YUV422 YUV420 Planar \ Semi-Planar \ Interleaved格式详解

很多人对YUV数据格式不清楚,以至于在做视频的时候出现了一些不可预知的错误(比如说图像带有点、颜色不对等)。今晚是周末放假,我就抽点时间来给大家介绍一下。

       提示: 读下面的文字时,希望大家结合图片看,这样更易理解
       在YUV420中,一个像素点对应一个Y,一个2X2的小方块对应一个U和V。对于所有YUV420图像,它们的Y值排列是完全相同的,因为只有Y的图像就是灰度图像。YUV420sp与YUV420p的数据格式它们的UV排列在原理上是完全不同的。420p它是先把U存放完后,再存放V,也就是说UV它们是连续的。而420sp它是UV、UV这样交替存放的。(见下图)
有了上面的理论,我就可以准确的计算出一个YUV420在内存中存放的大小。
width * hight =Y(总和)
U = Y / 4  
V = Y / 4

所以YUV420 数据在内存中的长度是 width * hight * 3 / 2,

假设一个分辨率为8X4的YUV图像,它们的格式如下图:

                                   YUV420sp格式如下图                                                                    YUV420p数据格式如下图

                         

有了上边的理论,我们可以对Android摄像头采集的YUV420sp数据做很多的转换,下面我写一个旋转90度的算法。

代码如下:

[java] view plain copy

  1. public static void rotateYUV240SP(byte[] src,byte[] des,int width,int height)  
  2.     {  
  3.          
  4.         int wh = width * height;  
  5.         //旋转Y  
  6.         int k = 0;  
  7.         for(int i=0;i<width;i++) {  
  8.             for(int j=0;j<height;j++)   
  9.             {  
  10.                   des[k] = src[width*j + i];              
  11.                   k++;  
  12.             }  
  13.         }  
  14.           
  15.         for(int i=0;i<width;i+=2) {  
  16.             for(int j=0;j<height/2;j++)   
  17.             {     
  18.                   des[k] = src[wh+ width*j + i];      
  19.                   des[k+1]=src[wh + width*j + i+1];  
  20.                   k+=2;  
  21.             }  
  22.         }  
  23.           
  24.           
  25.     }  


 

结合上面的旋转算法,我在Android平台写了一个测试项目。

运行结果效果如下:

上边视频是摄像头的预览数据(预览数据的图像截图看不见,郁闷啊),所以我为了能让大家看到效果,专门拍了一张照片。

                                                                                   

===========================================================================

关于yuv 格式

YUV 格式通常有两大类:打包(packed)格式和平面(planar)格式。前者将 YUV 分量存放在同一个数组中,
通常是几个相邻的像素组成一个宏像素(macro-pixel);而后者使用三个数组分开存放 YUV 三个分量,就像
是一个三维平面一样。

几种常见的yuv格式

1.YUV422 Planar

这里,Y\U\V数据是分开存放的,每两个水平Y采样点,有一个Cb和一个Cr采样点,如下图

ffmpeg 中的定义  PIX_FMT_YUV422P,   ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)  

android  OMX  中的定义  OMX_COLOR_FormatYUV422Planar     //*  YUV422Planar           : Three arrays Y,U,V.

2. YUV420 Planar

这个格式跟YUV422 Planar 类似,但对于Cb和Cr的采样在水平和垂直方向都减少为2:1,如下图

ffmpeg 中定义  PIX_FMT_YUV420P    //< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)

android OMX 中定义  OMX_COLOR_FormatYUV420Planar     //  *  YUV420Planar           : Three arrays Y,U,V   

3.YUV422 Semi-Planar                                         Semi 是’半‘的意思 我的理解这个半平面模式

   这个格式的数据量跟YUV422 Planar的一样,但是U、V是交叉存放的,如下图。

ffmpeg 中 未找到定义

android  OMX  中 OMX_COLOR_FormatYUV422SemiPlanar    ////YUV422SemiPlanar       : Two arrays, one is all Y, the other is U and V

4.YUV420 Semi-Planar

 这个格式的数据量跟YUV420 Planar的一样,但是U、V是交叉存放的,如下图。

 ffmpeg 中定义  

PIX_FMT_NV12,      ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V)

android   OMX  中定义 OMX_COLOR_FormatYUV420SemiPlanar    //YUV420SemiPlanar       : Two arrays, one is all Y, the other is U and V 

5.YUV422 Interleaved        Interleaved -- 交错   

这个格式的数据量跟YUV422 Planar的一样,但是Y、U、V是交叉存放的,如下图。 这个是打包(packed)模式的

ffmpeg  中  PIX_FMT_UYVY422   ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1

android  OMX 中  OMX_COLOR_FormatCbYCrY    //CbYCrY                 : Organized as 16bit UYVY (i.e. CbYCrY)

 24bit RGB888 -> 16bit RGB565 的转换

 24ibt RGB888 R7 R6 R5 R4 R3 R2 R1 R0 G7 G6 G5 G4 G3 G2 G1 G0 B7 B6 B5 B4 B3 B2 B1 B0

 16bit RGB656 R7 R6 R5 R4 R3 G7 G6 G5 G4 G3 G2 B7 B6 B5 B4 B3

猜你喜欢

转载自blog.csdn.net/taotongning/article/details/86472354