/*
主要的采样格式有YCbCr 4:2:0、YCbCr 4:2:2、YCbCr 4:1:1和 YCbCr 4:4:4。
其中YCbCr 4:1:1 比较常用,其含义为:每个点保存一个 8bit 的亮度值(也就是Y值),
每 2x2 个点保存一个 Cr 和Cb 值, 图像在肉眼中的感觉不会起太大的变化。
所以, 原来用 RGB(R,G,B 都是 8bit unsigned) 模型, 1个点需要 8x3=24 bits(如下图第一个图),
(全采样后,YUV仍各占8bit)。按4:1:1采样后,而现在平均仅需要 8+(8/4)+(8/4)=12bits(4个点,8*4(Y)+8(U)+8(V)=48bits),
平均每个点占12bits(如下图第二个图)。这样就把图像的数据压缩了一半。
上边仅给出了理论上的示例,在实际数据存储中是有可能是不同的,下面给出几种具体的存储形式:
(1) YUV 4:4:4
YUV三个信道的抽样率相同,因此在生成的图像里,每个象素的三个分量信息完整(每个分量通常8比特),
经过8比特量化之后,未经压缩的每个像素占用3个字节。
下面的四个像素为: [Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
存放的码流为: Y0 U0 V0 Y1 U1 V1 Y2 U2 V2 Y3 U3 V3
(2) YUV 4:2:2
每个色差信道的抽样率是亮度信道的一半,所以水平方向的色度抽样率只是4:4:4的一半。
对非压缩的8比特量化的图像来说,每个由两个水平方向相邻的像素组成的宏像素需要占用4字节内存。
下面的四个像素为:[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
存放的码流为:Y0 U0 Y1 V1 Y2 U2 Y3 V3
映射出像素点为:[Y0 U0 V1] [Y1 U0 V1] [Y2 U2 V3] [Y3 U2 V3]
(3) YUV 4:1:1
4:1:1的色度抽样,是在水平方向上对色度进行4:1抽样。对于低端用户和消费类产品这仍然是可以接受的。
对非压缩的8比特量化的视频来说,每个由4个水平方向相邻的像素组成的宏像素需要占用6字节内存。
下面的四个像素为: [Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
存放的码流为: Y0 U0 Y1 Y2 V2 Y3
映射出像素点为:[Y0 U0 V2] [Y1 U0 V2] [Y2 U0 V2] [Y3 U0 V2]
(4)YUV4:2:0
4:2:0并不意味着只有Y,Cb而没有Cr分量。它指得是对每行扫描线来说,只有一种色度分量以2:1的抽样率存储。
相邻的扫描行存储不同的色度分量,也就是说,如果一行是4:2:0的话,下一行就是4:0:2,再下一行是4:2:0...
以此类推。对每个色度分量来说,水平方向和竖直方向的抽样率都是2:1,所以可以说色度的抽样率是4:1。
对非压缩的8比特量化的视频来说,每个由2x2个2行2列相邻的像素组成的宏像素需要占用6字节内存。
下面八个像素为:[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
[Y5 U5 V5] [Y6 U6 V6] [Y7U7 V7] [Y8 U8 V8]
存放的码流为:Y0 U0 Y1 Y2 U2 Y3
Y5 V5 Y6 Y7 V7 Y8
映射出的像素点为:[Y0 U0 V5] [Y1 U0 V5] [Y2 U2 V7] [Y3 U2 V7]
[Y5 U0 V5] [Y6 U0 V5] [Y7U2 V7] [Y8 U2 V7]
转自:http://blog.csdn.net/yiheng_l/article/details/3789586
*/
/*
简单的说,YUV的格式在存储上有两类布局: Packed和Plannar。
Packed的方式就是把相邻几个象素打包起来。比如把水平方向2个象素打包到一个DWORD里。
Planner方式则相反。Y分量和UV分量完全分开来保存。
YUY2和YV12是最常用的两个代表。
YUY2是packed方式的。水平方向两个像素打包到一个DWORD,并且UV采样率只有Y的一半,
这符合人的视觉特征能有效的压缩数据,具体布局为[Y0, U0,Y1,V0]。 这种格式常见于MPEG1的解码器。
YV12则常见于H.264的解码器,它属于plannar方式。
对于一个MxN大小的视频来说,数据布局为[Y:M x N] [U:M/2 x N/2] [V:M/2 x N/2].
也就是说UV的采样率在水平和垂直方向上都只有Y的一半。
*/
/*
YUYV和YUY2格式的保存格式
+--------+--------+--------+--------+--------
| Y1 | U | Y2 | V | ....
+--------+--------+--------+--------+--------
1 Byte 2Byte 3Byte 4Byte
这种格式,每4个字节为一组。每组保存2个像素的数据,也就是连续的两个像素使用同一个UV。
*/
转自:http://www.cnblogs.com/cplusplus/archive/2012/04/17/2453315.html
1 #define uint8_t BYTE 2 void YUY2toI420(int inWidth, int inHeight, uint8_t *pSrc, uint8_t *pDest) 3 { 4 int i, j; 5 //首先对I420的数据整体布局指定 6 uint8_t *u = pDest + (inWidth * inHeight); 7 uint8_t *v = u + (inWidth * inHeight) / 4; 8 9 for (i = 0; i < inHeight/2; i++) 10 { 11 /*采取的策略是:在外层循环里面,取两个相邻的行*/ 12 uint8_t *src_l1 = pSrc + inWidth*2*2*i;//因为4:2:2的原因,所以占用内存,相当一个像素占2个字节,2个像素合成4个字节 13 uint8_t *src_l2 = src_l1 + inWidth*2;//YUY2的偶数行下一行 14 uint8_t *y_l1 = pDest + inWidth*2*i;//偶数行 15 uint8_t *y_l2 = y_l1 + inWidth;//偶数行的下一行 16 for (j = 0; j < inWidth/2; j++)//内层循环 17 { 18 // two pels in one go//一次合成两个像素 19 //偶数行,取完整像素;Y,U,V;偶数行的下一行,只取Y 20 *y_l1++ = src_l1[0];//Y 21 *u++ = src_l1[1];//U 22 *y_l1++ = src_l1[2];//Y 23 *v++ = src_l1[3];//V 24 //这里只有取Y 25 *y_l2++ = src_l2[0]; 26 *y_l2++ = src_l2[2]; 27 //YUY2,4个像素为一组 28 src_l1 += 4; 29 src_l2 += 4; 30 } 31 } 32 }