实验目的
将取样结构为4:2:0的yuv文件通过C语言转成rgb文件
方法解释
存储格式
我们用W和H来表示图像的宽和高
(4:2:0)YUV存储格式
4:2:0取样结构的yuv文件数据存储方式为WH个亮度信号Y顺序存放,尾部连接0.25WH个色差信号U顺序存放,再尾部连接0.25W*H个色差信号V顺序存放。
RGB存储格式
构成同一像素的三种彩色信号,按照GBR顺序依次存放,重复W*H次。
算法说明
4:2:0 yuv信号构成像素方式,如下图
一个2x2正方形像素由同样的U、Y信号构成,所以在转换成RGB格式时,也要让一个2x2正方形像素由同样的U、Y信号转换成RGB信号。因此需要将W*H/4的U、V进行如下图的扩充
代码实现如下
for (j = 0; j < y_dim / 2; j ++) //y_dim为图像高度
{
psu = sub_u_buf + j * x_dim / 2;//sub_u_buf为原U信号序列
psv = sub_v_buf + j * x_dim / 2;//sub_v_buf为原V信号序列
pu1 = u + 2 * j * x_dim;//u为扩充后U信号序列
pu2 = u + (2 * j + 1) * x_dim;
pv1 = v + 2 * j * x_dim;//v为扩充后V信号序列
pv2 = v + (2 * j + 1) * x_dim;
for (i = 0; i < x_dim/2; i ++)//x_dim为图像宽度
{
*pu1 = *(pu1 + 1) = *pu2 = *(pu2 + 1) = *psu;
*pv1 = *(pv1 + 1) = *pv2 = *(pv2 + 1) = *psv;
psu ++;
psv ++;
pu1 += 2;
pu2 += 2;
pv1 += 2;
pv2 += 2;
}
}
扩充后的U、Y信号数量等于Y信号,而且顺序关系一一对应。此时可以通过转换公式
// R = 1.164 *(Y - 16) + 1.596 *(V- 128) //
// G = 1.164 *(Y - 16) - 0.392 *(U - 128) - 0.812 *(V - 128)//
// B = 1.164 *(Y - 16) + 2.016 *(U - 128) //
进行依次带入扩充后的YUV信序列转换,如下
for (i = 0; i < size ; i ++)
{
inter_var = ( YUVRGB1164_16[*py] - YUVRGB0392_128[*cb] - YUVRGB0812_128[*cr]);
FixPixel(inter_var);//防止向unsigned char型指针赋值时
/*void FixPixel(float &inter_var) 由于超出0-255,而乱码
{
if(inter_var < 0)
inter_var = 0;
else if(inter_var > 255)
inter_var = 255;
}*/
*g = (unsigned char)inter_var;
inter_var = ( YUVRGB1164_16[*py] + YUVRGB2016_128[*cb] );
FixPixel(inter_var);
*b = (unsigned char)inter_var;
inter_var = ( YUVRGB1164_16[*py] + YUVRGB1596_128[*cr] );
FixPixel(inter_var);
*r = (unsigned char)inter_var;
py ++;
cb ++;
cr ++;
g ++;
b ++;
r ++;
}
为了防止信号变动造成过载,在256级上下端各留16级作为保护带
for (i = 0; i < frameWidth*frameHeight; i++)
{
if (gBuf[i] < 16) gBuf[i] = 16;
if (gBuf[i] > 240) gBuf[i] = 240;
}
for (i = 0; i < frameWidth*frameHeight; i++)
{
if (bBuf[i] < 16) bBuf[i] = 16;
if (bBuf[i] > 240) bBuf[i] = 240;
if (rBuf[i] < 16) rBuf[i] = 16;
if (rBuf[i] > 240) rBuf[i]