雷霄骅在 https://blog.csdn.net/leixiaohua1020/article/details/40266503 一文中提到了yuv转rgb的代码,通过简单的改造,就可以直观的看出yuv的模样。
测试rgb的渲染。
改动CONVERT_YUV420PtoRGB24 的代码如下。
void CONVERT_YUV420PtoRGB24(unsigned char* yuv_src, unsigned char* rgb_dst, int nWidth, int nHeight)
{
unsigned char Y, U, V, R, G, B;
unsigned char* y_planar, * u_planar, * v_planar;
int offSet = 0;
int rgb_width = nWidth * 3;
int ypSize = nWidth * nHeight;
int upSize = (ypSize >> 2);
y_planar = yuv_src;
u_planar = yuv_src + ypSize;
v_planar = u_planar + upSize;
for (int i = 0; i < nHeight; i++)
{
for (int j = 0; j < nWidth; j++)
{
R = 255;
G = 0;
B = 0;
offSet = rgb_width * i + j * 3;
rgb_dst[offSet] = B;
rgb_dst[offSet + 1] = G;
rgb_dst[offSet + 2] = R;
}
}
}
期待的结果为整个窗口为红色。
只渲染yuv中的y数据。
改动CONVERT_YUV420PtoRGB24 的代码如下。
void CONVERT_YUV420PtoRGB24(unsigned char* yuv_src, unsigned char* rgb_dst, int nWidth, int nHeight)
{
unsigned char Y, U, V, R, G, B;
unsigned char* y_planar, * u_planar, * v_planar;
int offSet = 0;
int rgb_width = nWidth * 3;
int ypSize = nWidth * nHeight;
int upSize = (ypSize >> 2);
y_planar = yuv_src;
u_planar = yuv_src + ypSize;
v_planar = u_planar + upSize;
for (int i = 0; i < nHeight; i++)
{
for (int j = 0; j < nWidth; j++)
{
Y = *(y_planar + nWidth * i + j);
R = Y;
G = Y;
B = Y;
offSet = rgb_width * i + j * 3;
rgb_dst[offSet] = B;
rgb_dst[offSet + 1] = G;
rgb_dst[offSet + 2] = R;
}
}
}
运行后的结果为:
可以看出,Y代表的就是亮度信息。
添加uv数据
改动CONVERT_YUV420PtoRGB24 的代码如下。值得注意的是,雷兄给的第一种方法,颜色有些许偏差,查资料可以看出来,第二种方法更加主流。https://stackoverflow.com/questions/1737726/how-to-perform-rgb-yuv-conversion-in-c-c
void CONVERT_YUV420PtoRGB24(unsigned char* yuv_src, unsigned char* rgb_dst, int nWidth, int nHeight)
{
unsigned char Y, U, V, R, G, B;
unsigned char* y_planar, * u_planar, * v_planar;
int offSet = 0;
int rgb_width = nWidth * 3;
int ypSize = nWidth * nHeight;
int upSize = (ypSize >> 2);
int u_width = (nWidth >> 1);
y_planar = yuv_src;
u_planar = yuv_src + ypSize;
v_planar = u_planar + upSize;
for (int i = 0; i < nHeight; i++)
{
for (int j = 0; j < nWidth; j++)
{
Y = *(y_planar + nWidth * i + j);
offSet = (i >> 1) * (u_width)+(j >> 1);
U = *(v_planar + offSet);
V = *(u_planar + offSet);
int C, D, E;
C = Y - 16;
D = U - 128;
E = V - 128;
R = CONVERT_ADJUST((298 * C + 409 * E + 128) >> 8);
G = CONVERT_ADJUST((298 * C - 100 * D - 208 * E + 128) >> 8);
B = CONVERT_ADJUST((298 * C + 516 * D + 128) >> 8);
offSet = rgb_width * i + j * 3;
rgb_dst[offSet] = B; // 如果不想再调用CHANGE_ENDIAN_PIC,可以直接调换 b和r的赋值位置。
rgb_dst[offSet + 1] = G;
rgb_dst[offSet + 2] = R;
}
}
}