关于YUV格式的讲解,网上有很多,主要有以下几种格式:
1)打包(packed)格式.将YUV分量存放在同一个数组中,通常是几个相邻的像素组成一个宏像素(macro-pixel):
MEDIASUBTYPE_YUY2 YUY2格式,以4:2:2方式打包(比较常用的,默认的4:2:2的格式)
MEDIASUBTYPE_YUYV YUYV格式(实际格式与YUY2相同)
MEDIASUBTYPE_YVYU YVYU格式,以4:2:2方式打包
MEDIASUBTYPE_UYVY UYVY格式,以4:2:2方式打包
MEDIASUBTYPE_AYUV ,带Alpha通道的4:4:4 YUV格式
2)平面(planar)格式。后者使用三个数组分开存放YUV三个分量
MEDIASUBTYPE_IF09 IF09格式
MEDIASUBTYPE_IYUV IYUV格式
MEDIASUBTYPE_YV12 YV12格式
MEDIASUBTYPE_YVU9 YVU9格式
YUV 采样
YUV 的优点之一是,色度频道的采样率可比 Y 频道低,同时不会明显降低视觉质量。有一种表示法可用来描述 U 和 V 与 Y 的采样频率比例,这个表示法称为 A:B:C 表示法(其实就是Y:U:V):
- 4:4:4 表示色度频道没有下采样, 每一个Y分量都对应一个UV分量,最简单容易理解。
srcY = Buf_yuv444;srcU = srcY + width * height;srcV = srcU + width * height;
- 4:2:2 表示 2:1 的水平下采样,没有垂直下采样。相对于4:4:4,就是每隔一列删去一列U(或者V)分量,只保留第0,2,4,6....列的U(V)分量。
srcY = Buf_yuv422;srcU = srcY + width * height;srcV = srcU + width/2 * height;
- 4:2:0 表示 2:1 的水平下采样,2:1 的垂直下采样。相对于4:2:2,再继续每隔一行删去一行U(或者V)分量,只保留第0,2,4,6....行的U(V)分量。
srcY = Buf_yuv420;srcU = srcY + width * height;srcV = srcU + width/2 * height/2;
- 4:1:1 表示 4:1 的水平下采样,没有垂直下采样。对于每个 U 样例或 V 样例,每个扫描行都包含四个 Y 样例。不常见。
YUV444 TO YUV420:(packed)(BYTE)
void YUV444To420(BYTE* yuv444, BYTE* yuv420, DWORD width, DWORD height){ int ynum=width*height; DWORD i, j, k; BYTE *dstY = yuv420; BYTE *dstU = dstY + ynum; BYTE *dstV = dstU + ynum / 4; BYTE *srcY = yuv444; BYTE *srcU = srcY + ynum; BYTE *srcV = srcU + ynum; k = 0; for (i = 0; i < height; i ++){ for (j = 0; j < width; j ++){ dstY[k++] = srcY[i * width + j]; } } k = 0; for(i = 0;i < height;i += 2){ for(j = 0;j < width; j += 2){ dstU[k++] = srcU[i * width + j]; } } k = 0; for(i = 0;i < height;i += 2){ for(j = 0;j < width;j += 2){ dstV[k++] = srcV[i * width + j]; } } }
YUV422 TO YUV420:(packed) (Int16_t)
void YUV422To420_10bit(int16_t* yuv422, int16_t* yuv420, DWORD width, DWORD height){ int ynum = width*height; DWORD i, j, k; SHORT *dstY = yuv420; SHORT *dstU = dstY + ynum; SHORT *dstV = dstU + ynum / 4; SHORT *srcY = yuv422; SHORT *srcU = srcY + ynum; SHORT *srcV = srcU + ynum / 2; memcpy(dstY, srcY, ynum * 2); k = 0; width /= 2; for (i = 0; i < height; i += 2){ for (j = 0; j < width; j += 1){ dstU[k++] = srcU[i * width + j]; } } k = 0; for (i = 0; i < height; i += 2){ for (j = 0; j < width; j += 1){ dstV[k++] = srcV[i * width + j]; } }}