YUV和RGB格式的转化
1.二者的转化关系
由配色方程我们可以知道其转化关系如下
R = Y + 1.4075 * (V-128);
G = Y - 0.3455 * (U-128) - 0.7169*(V-128);
B = Y + 1.779 * (U-128);
Y = 0.299R + 0.587G + 0.114*B;
U = (B-Y)/1.772;
V = (R-Y)/1.402; (U~(-128-127))
或写为:
Y = 0.299R + 0.587G + 0.114*B;
U = -0.169R - 0.331G + 0.5 *B ;
V = 0.5 R - 0.419G - 0.081*B;
在进行量化并将0电平调制128后我们将方程转化为
Y=0.299R+0.5870G+0.1140B
U=−0.1684R−0.3316G+0.5B+128
V=0.5R−0.4187G−0.0813B+128
2.代码实现
//
#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
const int width = 256;
const int height = 256;
int main(int argc, char *argv[])
{
FILE* rgb = NULL;
FILE* yuv = NULL;
rgb = fopen("C:\\Users\\Jack\\Desktop\\新建文件夹 (2)\\rgb2yuv\\down.rgb", "rb");
yuv = fopen("C:\\Users\\Jack\\Desktop\\新建文件夹 (2)\\rgb2yuv\\down.yuv", "wb");
//建立缓冲区
unsigned char* buffer_rgb = (unsigned char*)malloc(sizeof(unsigned char) * 3 * width * height);
unsigned char* buffer_y = (unsigned char*)malloc(sizeof(unsigned char) * width * height);
unsigned char* buffer_u = (unsigned char*)malloc(sizeof(unsigned char) * width * height / 4);
unsigned char* buffer_v = (unsigned char*)malloc(sizeof(unsigned char) * width * height / 4);
fread(buffer_rgb, sizeof(unsigned char), 3 * width * height, rgb);
//y分量
for (int i = 0; i < width * height; i++)
{
buffer_y[i] = 0.299 * buffer_rgb[3 * i + 2] + 0.587 * buffer_rgb[3 * i + 1] + 0.114 * buffer_rgb[3 * i];
if (buffer_y[i] > 235)
buffer_y[i] = 235;
else if (buffer_y[i] < 16)
buffer_y[i] = 16;
}
//u分量
int k = 0;
for (int i = 0; i < height; i++)
for (int j = 0; j < width; j++)
{
if (i % 2 == 0 && j % 2 == 0)
{
buffer_u[k] = -0.1684 * buffer_rgb[3 * (i * width + j) + 2] - 0.3316 * buffer_rgb[3 * (i * width + j) + 1] + 0.5 * buffer_rgb[3 * (i * width + j)] + 128;
if (buffer_u[k] > 240)
buffer_u[k] = 240;
else if (buffer_u[k] < 16)
buffer_u[k] = 16;
k++;
}
}
//v分量
k = 0;
for (int i = 0; i < height; i++)
for (int j = 0; j < width; j++)
{
if (i % 2 == 0 && j % 2 == 0)
{
buffer_v[k] = 0.5 * buffer_rgb[3 * (i * width + j) + 2] - 0.4187 * buffer_rgb[3 * (i * width + j) + 1] - 0.0813 * buffer_rgb[3 * (i * width + j)] + 128;
if (buffer_v[k] > 240)
buffer_v[k] = 240;
else if (buffer_v[k] < 16)
buffer_v[k] = 16;
k++;
}
}
//写文件
fwrite(buffer_y, sizeof(unsigned char), width * height, yuv);
fwrite(buffer_u, sizeof(unsigned char), width * height / 4, yuv);
fwrite(buffer_v, sizeof(unsigned char), width * height / 4, yuv);
//释放
if (buffer_rgb != NULL)
free(buffer_rgb);
if (buffer_y != NULL)
free(buffer_y);
if (buffer_u != NULL)
free(buffer_u);
if (buffer_v != NULL)
free(buffer_v);
if (rgb != NULL)
fclose(rgb);
if (yuv != NULL)
fclose(yuv);
return 0;
}
将结果用yuv打开效果如下
将yuv转化为rgb
#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
const int width = 256;
const int height = 256;
int main(int argc, char *argv[])
{
FILE* rgb = NULL;
FILE* yuv = NULL;
rgb = fopen("C:\\Users\\Jack\\Desktop\\新建文件夹 (2)\\yuv2rgb\\down.rgb", "wb");
yuv = fopen("C:\\Users\\Jack\\Desktop\\新建文件夹 (2)\\yuv2rgb\\down.yuv", "rb");
//建立缓冲区
unsigned char* buffer_rgb = (unsigned char*)malloc(sizeof(unsigned char) * 3 * width * height);
unsigned char* buffer_y = (unsigned char*)malloc(sizeof(unsigned char) * width * height);
unsigned char* buffer_u = (unsigned char*)malloc(sizeof(unsigned char) * width * height / 4);
unsigned char* buffer_v = (unsigned char*)malloc(sizeof(unsigned char) * width * height / 4);
fread(buffer_y, sizeof(unsigned char), width * height, yuv);
fread(buffer_u, sizeof(unsigned char), width * height / 4, yuv);
fread(buffer_v, sizeof(unsigned char), width * height / 4, yuv);
unsigned char y[width][height] = { 0 };
for (int i = 0; i < height; i++)
for (int j = 0; j < width; j++)
y[i][j] = buffer_y[i * width + j];
unsigned char u[width][height] = { 0 };
unsigned char v[width][height] = { 0 };
int k = 0;
for (int i = 0; i<height; i++)
for (int j = 0; j < width; j++)
{
if (i % 2 == 0 && j % 2 == 0)
{
u[i][j] = buffer_u[k];
v[i][j] = buffer_v[k];
k++;
}
else if (i % 2 == 0 && j % 2 == 1)
{
u[i][j] = u[i][j - 1];
v[i][j] = v[i][j - 1];
}
else if (i % 2 == 1 && j % 2 == 0)
{
u[i][j] = u[i - 1][j];
v[i][j] = v[i - 1][j];
}
else if (i % 2 == 1 && j % 2 == 1)
{
u[i][j] = u[i - 1][j - 1];
v[i][j] = v[i - 1][j - 1];
}
}
for (int i = 0; i<height; i++)
for (int j = 0; j < width; j++)
{
buffer_rgb[3 * (i * width + j)] = y[i][j] + 1.7718 * (u[i][j] - 128) - 0.0013 * (v[i][j] - 128);
buffer_rgb[3 * (i * width + j) + 1] = y[i][j] - 0.3441 * (u[i][j] - 128) - 0.7139 * (v[i][j] - 128);
buffer_rgb[3 * (i * width + j) + 2] = y[i][j] + 1.4020 * (v[i][j] - 128);
}
fwrite(buffer_rgb, sizeof(unsigned char), 3 * width * height, rgb);
if (buffer_rgb != NULL)
free(buffer_rgb);
if (buffer_y != NULL)
free(buffer_y);
if (buffer_u != NULL)
free(buffer_u);
if (buffer_v != NULL)
free(buffer_v);
if (rgb != NULL)
fclose(rgb);
if (yuv != NULL)
fclose(yuv);
return 0;
}