YUV与RGB彩色空间转换
YUV与RGB转换公式
Y=0.2990R+0.5870G+0.1140B
U=-0.1684R-0.3316G+0.5B
V=0.5R-0.4187G-0.0813B
R = Y+1.4075V
G = Y-0.3455U-0.7169V
B = Y+1.7790U
YUV转RGB实现算法
主函数
分配缓冲区
/* get an output buffer for a frame */
rgbBuf = (u_int8_t*)malloc(frameWidth * frameHeight * 3);
/* get the input buffers for a frame */
yuvBuf = (u_int8_t*)malloc(frameWidth * frameHeight * 3 / 2);
yBuf = yuvBuf;
uBuf = yuvBuf + (frameWidth * frameHeight);
vBuf = yuvBuf + (frameHeight * frameWidth * 5 / 4);
读出与写入图像
while (fread(yuvBuf, 1, frameWidth * frameHeight * 3 / 2, yuvFile))
{
if(YUV2RGB(frameWidth, frameHeight, yBuf, uBuf, vBuf, rgbBuf, flip))
{
printf("error");
return 0;
}
fwrite(rgbBuf, 1, frameWidth * frameHeight * 3, rgbFile);
printf("\r...%d", ++videoFramesWritten);
}
printf("\n%u %ux%u video frames written\n",
videoFramesWritten, frameWidth, frameHeight);
部分查找表
static float YUVRGB14075[256], YUVRGB03455[256];
static float YUVRGB07169[256], YUVRGB17790[256];
void InitLookupTable()
{
int i;
for (i = 0; i < 256; i++) YUVRGB14075[i] = (float)1.4075 * (i - 128);
for (i = 0; i < 256; i++) YUVRGB03455[i] = (float)0.3455 * (i - 128);
for (i = 0; i < 256; i++) YUVRGB07169[i] = (float)0.7169 * (i - 128);
for (i = 0; i < 256; i++) YUVRGB17790[i] = (float)1.7790 * (i - 128);
}
YUV到RGB转换函数
分配内存
y_buffer = (unsigned char *)y_in;
u_buffer = (unsigned char *)u_in;
v_buffer = (unsigned char *)v_in;
rgb = (unsigned char*)malloc(3 * size * sizeof(unsigned char));
if (!(rgb))
{
free(rgb);
return 2;
}
rgb_buffer = (unsigned char *)rgb_out;
YUV转换为RGB,分别求出B、G、R的值,求得的电平低于0时为0,高于255时为255,以此作为保护
for (j = 0; j < (y_dim / 2); j++)
for (i = 0; i < (x_dim / 2); i++)
{
/* B */
if ((y_buffer[2 * j * x_dim + 2 * i] + YUVRGB17790[*u_buffer]) > 255)
rgb[2 * j * 3 * x_dim + 6 * i] = 255;
else if ((y_buffer[2 * j * x_dim + 2 * i] + YUVRGB17790[*u_buffer]) < 0)
rgb[2 * j * 3 * x_dim + 6 * i] = 0;
else
rgb[2 * j * 3 * x_dim + 6 * i] = (unsigned char)(y_buffer[2 * j * x_dim + 2 * i] + YUVRGB17790[*u_buffer]);
if ((y_buffer[(2 * j + 1) * x_dim + 2 * i] + YUVRGB17790[*u_buffer]) > 255)
rgb[(2 * j + 1) * 3 * x_dim + 6 * i] = 255;
else if ((y_buffer[(2 * j + 1) * x_dim + 2 * i] + YUVRGB17790[*u_buffer]) < 0)
rgb[(2 * j + 1) * 3 * x_dim + 6 * i] = 0;
else
rgb[(2 * j + 1) * 3 * x_dim + 6 * i] = (unsigned char)(y_buffer[(2 * j + 1) * x_dim + 2 * i] + YUVRGB17790[*u_buffer]);
if ((y_buffer[2 * j * x_dim + 2 * i + 1] + YUVRGB17790[*u_buffer]) > 255)
rgb[2 * j * 3 * x_dim + 6 * i + 3] = 255;
else if ((y_buffer[2 * j * x_dim + 2 * i + 1] + YUVRGB17790[*u_buffer]) < 0)
rgb[2 * j * 3 * x_dim + 6 * i + 3] = 0;
else
rgb[2 * j * 3 * x_dim + 6 * i + 3] = (unsigned char)(y_buffer[2 * j * x_dim + 2 * i + 1] + YUVRGB17790[*u_buffer]);
if ((y_buffer[(2 * j + 1) * x_dim + 2 * i + 1] + YUVRGB17790[*u_buffer]) > 255)
rgb[(2 * j + 1) * 3 * x_dim + 6 * i + 3] = 255;
else if ((y_buffer[(2 * j + 1) * x_dim + 2 * i + 1] + YUVRGB17790[*u_buffer]) < 0)
rgb[(2 * j + 1) * 3 * x_dim + 6 * i + 3] = 0;
else
rgb[(2 * j + 1) * 3 * x_dim + 6 * i + 3] = (unsigned char)(y_buffer[(2 * j + 1) * x_dim + 2 * i + 1] + YUVRGB17790[*u_buffer]);
/* G */
if ((y_buffer[2 * j * x_dim + 2 * i] - YUVRGB03455[*u_buffer] - YUVRGB07169[*v_buffer]) > 255)
rgb[2 * j * 3 * x_dim + 6 * i + 1] = 255;
else if ((y_buffer[2 * j * x_dim + 2 * i] - YUVRGB03455[*u_buffer] - YUVRGB07169[*v_buffer]) < 0)
rgb[2 * j * 3 * x_dim + 6 * i + 1] = 0;
else
rgb[2 * j * 3 * x_dim + 6 * i + 1] = (unsigned char)(y_buffer[2 * j * x_dim + 2 * i] - YUVRGB03455[*u_buffer] - YUVRGB07169[*v_buffer]);
if ((y_buffer[(2 * j + 1) * x_dim + 2 * i] - YUVRGB03455[*u_buffer] - YUVRGB07169[*v_buffer]) > 255)
rgb[(2 * j + 1) * 3 * x_dim + 6 * i + 1] = 255;
else if ((y_buffer[(2 * j + 1) * x_dim + 2 * i] - YUVRGB03455[*u_buffer] - YUVRGB07169[*v_buffer]) < 0)
rgb[(2 * j + 1) * 3 * x_dim + 6 * i + 1] = 0;
else
rgb[(2 * j + 1) * 3 * x_dim + 6 * i + 1] = (unsigned char)(y_buffer[(2 * j + 1) * x_dim + 2 * i] - YUVRGB03455[*u_buffer] - YUVRGB07169[*v_buffer]);
if ((y_buffer[2 * j * x_dim + 2 * i + 1] - YUVRGB03455[*u_buffer] - YUVRGB07169[*v_buffer]) > 255)
rgb[2 * j * 3 * x_dim + 6 * i + 4] = 255;
else if ((y_buffer[2 * j * x_dim + 2 * i + 1] - YUVRGB03455[*u_buffer] - YUVRGB07169[*v_buffer]) < 0)
rgb[2 * j * 3 * x_dim + 6 * i + 4] = 0;
else
rgb[2 * j * 3 * x_dim + 6 * i + 4] = (unsigned char)(y_buffer[2 * j * x_dim + 2 * i + 1] - YUVRGB03455[*u_buffer] - YUVRGB07169[*v_buffer]);
if ((y_buffer[(2 * j + 1) * x_dim + 2 * i + 1] - YUVRGB03455[*u_buffer] - YUVRGB07169[*v_buffer]) > 255)
rgb[(2 * j + 1) * 3 * x_dim + 6 * i + 4] = 255;
else if ((y_buffer[(2 * j + 1) * x_dim + 2 * i + 1] - YUVRGB03455[*u_buffer] - YUVRGB07169[*v_buffer]) < 0)
rgb[(2 * j + 1) * 3 * x_dim + 6 * i + 4] = 0;
else
rgb[(2 * j + 1)* 3 * x_dim + 6 * i + 4] = (unsigned char)(y_buffer[(2 * j + 1) * x_dim + 2 * i + 1] - YUVRGB03455[*u_buffer] - YUVRGB07169[*v_buffer]);
/* R */
if ((y_buffer[2 * j * x_dim + 2 * i] + YUVRGB14075[*v_buffer]) > 255)
rgb[2 * j * 3 * x_dim + 6 * i + 2] = 255;
else if ((y_buffer[2 * j * x_dim + 2 * i] + YUVRGB14075[*v_buffer]) < 0)
rgb[2 * j * 3 * x_dim + 6 * i + 2] = 0;
else
rgb[2 * j * 3 * x_dim + 6 * i + 2] = (unsigned char)(y_buffer[2 * j * x_dim + 2 * i] + YUVRGB14075[*v_buffer]);
if ((y_buffer[(2 * j + 1) * x_dim + 2 * i] + YUVRGB14075[*v_buffer]) > 255)
rgb[(2 * j + 1) * 3 * x_dim + 6 * i + 2] = 255;
else if ((y_buffer[(2 * j + 1) * x_dim + 2 * i] + YUVRGB14075[*v_buffer]) < 0)
rgb[(2 * j + 1) * 3 * x_dim + 6 * i + 2] = 0;
else
rgb[(2 * j + 1) * 3 * x_dim + 6 * i + 2] = (unsigned char)(y_buffer[(2 * j + 1) * x_dim + 2 * i] + YUVRGB14075[*v_buffer]);
if ((y_buffer[2 * j * x_dim + 2 * i + 1] + YUVRGB14075[*v_buffer]) > 255)
rgb[2 * j * 3 * x_dim + 6 * i + 5] = 255;
else if ((y_buffer[2 * j * x_dim + 2 * i + 1] + YUVRGB14075[*v_buffer]) < 0)
rgb[2 * j * 3 * x_dim + 6 * i + 5] = 0;
else
rgb[2 * j * 3 * x_dim + 6 * i + 5] = (unsigned char)(y_buffer[2 * j * x_dim + 2 * i + 1] + YUVRGB14075[*v_buffer]);
if ((y_buffer[(2 * j + 1) * x_dim + 2 * i + 1] + YUVRGB14075[*v_buffer]) > 255)
rgb[(2 * j + 1) * 3 * x_dim + 6 * i + 5] = 255;
else if ((y_buffer[(2 * j + 1) * x_dim + 2 * i + 1] + YUVRGB14075[*v_buffer]) < 0)
rgb[(2 * j + 1) * 3 * x_dim + 6 * i + 5] = 0;
else
rgb[(2 * j + 1) * 3 * x_dim + 6 * i + 5] = (unsigned char)(y_buffer[(2 * j + 1) * x_dim + 2 * i + 1] + YUVRGB14075[*v_buffer]);
u_buffer++;
v_buffer++;
}
上下翻转图像
if (flip) {
for (j = 0; j < y_dim; j++)
for (i = 0; i < x_dim * 3; i++) {
*rgb_buffer = rgb[(y_dim - j - 1) * x_dim * 3 + i];
rgb_buffer++;
}
}
else {
rgb_buffer=rgb;
}
实验结果
用YUV Viewer播放器查看结果,与原始图像一致