/*

主要的采样格式有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

 #define uint8_t BYTE
void YUY2toI420(int inWidth, int inHeight, uint8_t *pSrc, uint8_t *pDest)
{
int i, j;
//首先对I420的数据整体布局指定
uint8_t *u = pDest + (inWidth * inHeight);
uint8_t *v = u + (inWidth * inHeight) / ; for (i = ; i < inHeight/; i++)
{
/*采取的策略是:在外层循环里面,取两个相邻的行*/
uint8_t *src_l1 = pSrc + inWidth***i;//因为4:2:2的原因,所以占用内存,相当一个像素占2个字节,2个像素合成4个字节
uint8_t *src_l2 = src_l1 + inWidth*;//YUY2的偶数行下一行
uint8_t *y_l1 = pDest + inWidth**i;//偶数行
uint8_t *y_l2 = y_l1 + inWidth;//偶数行的下一行
for (j = ; j < inWidth/; j++)//内层循环
{
// two pels in one go//一次合成两个像素
//偶数行,取完整像素;Y,U,V;偶数行的下一行,只取Y
*y_l1++ = src_l1[];//Y
*u++ = src_l1[];//U
*y_l1++ = src_l1[];//Y
*v++ = src_l1[];//V
//这里只有取Y
*y_l2++ = src_l2[];
*y_l2++ = src_l2[];
//YUY2,4个像素为一组
src_l1 += ;
src_l2 += ;
}
}
}
05-20 14:42