新生代农民工的主页

简单了解 iOS CVPixelBuffer(中)

字数统计: 1.8k阅读时长: 7 min
2022/02/27

前言:

「简单了解 iOS CVPixelBuffer (上)」)中,我们了解了CVPixelBuffer如何创建、修改、以及检查CVPixelBuffer相关的参数。在上篇文末我们有讲到在这篇文章中,我们将了解颜色空间RGB和YUV的区别以及相关的背景知识,然后回过头来再看CVPixelBuffer中的kCVPixelFormatType相关的类型。

相信大家对于RGB都不陌生吧,那么YUV大家是否了解呢,它为我们做了些什么?

在开篇我先提出一个问题:为什么要使用YUV呢? 这个问题在我们了解了颜色空间之后,相信大家心中就已经有了答案。接下来开始我们的正文。

颜色空间

颜色空间一词源于英文的Color Space,在色彩学中,人们建立了多种颜色模型,以一维、二维、三维甚至四维空间坐标来表示某一色彩,这种用坐标系统来定义的颜色范围即颜色空间。

我们经常用到的颜色空间主要有RGB、YUV、CMYK、HSB、HSL等,其中RGBYUV是视频中使用较多的两种色彩空间。

RGB

RGB 是由红(Red)、绿(Green)、蓝(Blue)三种颜色组成,我们称为三原色。每个颜色可以取值不同,将三种颜色相混合后,会组成其他的不同的颜色。使用 RGB 表示的图像中,每个像素都有红、绿、蓝三种颜色,每个颜色占8 bit,即1 byte。所以一个像素占用3 byte

红、绿、蓝三个颜色通道每种颜色各分为256阶亮度,取值为0-255

在存储时,我们常常以R G B或者B G R的顺序进行排列,所以在前文中,我们有看到pixelFormatType有kCVPixelFormatType_32RGBAkCVPixelFormatType_32BGRA两种相似的类型(这里的A指的是AlphaAlpha 通道一般用作不透明度参数),其实这两个类型只是它们的编码上的顺序不同;

接下来我们熟悉下另一个颜色空间。

YUV

YUV 是 Y’UV、YUV、YCbCr、YPbPr 等色彩空间的统称

YUV是由 Y 和 UV组成,前者表示明亮度 (Luminance、Luma),后者表示色度(Chrominance、Chroma),色度包括两个⽅面:色调、饱和度

使用YUV的图像,每个像素点都包含 Y、U、V 分量,YUV分量是分离的,如果只有Y没有UV,那么图像就像以前的黑白电视机一样。为了兼容老式电视机,彩色电视机采用的也是 YUV 的颜色空间,不过UV是存在的。

采样格式

YUV采样格式是个重点,YUV采样格式有三种:

  • YUV 4:4:4
  • YUV 4:2:2
  • YUV 4:2:0

采样格式.png

YUV444

YUV444代表每个Y分量分别对应一个U分量和一个V分量。
以4个像素为例:
[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
存放的码流为:
Y0 U0 V0 Y1 U1 V1 Y2 U2 V2 Y3 U3 V3

YUV422

YUV422代表每两个Y分量分别共用一个U分量和一个V分量。
以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]

YUV420

YUV420代表每四个Y分量分别共用一个U分量和一个V分量。
以8个像素为例:
[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
[Y5 U5 V5] [Y6 U6 V6] [Y7 U7 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] [Y7 U2 V7] [Y8 U2 V7]

综上来看,YUV444的存储的数据量和RGB相同,YUV422是RGB的2/3,YUV420是RGB的1/2。

存储方式

YUV有两种存储方式,一种是打包(packed),一种是平面(planar).

  • packed: 先连续存储所有Y分量,然后交叉存储U、V分量;
  • planar:先连续存储所有Y分量,然后在连续存储U、V分量(保证了每个区块连续);

在懂得这些颜色空间的编码格式以及存储方式之后,我们再来看上文中的这些类型的定义,就可以依据这些理论推导出来这些类型代表什么了;

比如说:
444、422、420 表示不同的采样格式(压缩比)
8、10、16 表示bit位数
Planar、BiPlanar 表示平面、双平面
VideoRange、FullRange 其意义是YUV颜色空间中亮度部分 Y 的取值范围,fullRange的取值范围为luma=[0,255] chroma=[1,255],而videoRange的取值范围为luma=[16,235] chroma=[16,240]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
kCVPixelFormatType_422YpCbCr8     = '2vuy',     /* Component Y'CbCr 8-bit 4:2:2, ordered Cb Y'0 Cr Y'1 */
  kCVPixelFormatType_4444YpCbCrA8   = 'v408',     /* Component Y'CbCrA 8-bit 4:4:4:4, ordered Cb Y' Cr A */
  kCVPixelFormatType_4444YpCbCrA8R  = 'r408',     /* Component Y'CbCrA 8-bit 4:4:4:4, rendering format. full range alpha, zero biased YUV, ordered A Y' Cb Cr */
  kCVPixelFormatType_4444AYpCbCr8   = 'y408',     /* Component Y'CbCrA 8-bit 4:4:4:4, ordered A Y' Cb Cr, full range alpha, video range Y'CbCr. */
  kCVPixelFormatType_4444AYpCbCr16  = 'y416',     /* Component Y'CbCrA 16-bit 4:4:4:4, ordered A Y' Cb Cr, full range alpha, video range Y'CbCr, 16-bit little-endian samples. */
  kCVPixelFormatType_444YpCbCr8     = 'v308',     /* Component Y'CbCr 8-bit 4:4:4 */
  kCVPixelFormatType_422YpCbCr16    = 'v216',     /* Component Y'CbCr 10,12,14,16-bit 4:2:2 */
  kCVPixelFormatType_422YpCbCr10    = 'v210',     /* Component Y'CbCr 10-bit 4:2:2 */
  kCVPixelFormatType_444YpCbCr10    = 'v410',     /* Component Y'CbCr 10-bit 4:4:4 */
  kCVPixelFormatType_420YpCbCr8Planar = 'y420',   /* Planar Component Y'CbCr 8-bit 4:2:0.  baseAddr points to a big-endian CVPlanarPixelBufferInfo_YCbCrPlanar struct */
  kCVPixelFormatType_420YpCbCr8PlanarFullRange    = 'f420',   /* Planar Component Y'CbCr 8-bit 4:2:0, full range.  baseAddr points to a big-endian CVPlanarPixelBufferInfo_YCbCrPlanar struct */
  kCVPixelFormatType_422YpCbCr_4A_8BiPlanar = 'a2vy', /* First plane: Video-range Component Y'CbCr 8-bit 4:2:2, ordered Cb Y'0 Cr Y'1; second plane: alpha 8-bit 0-255 */
  kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange = '420v', /* Bi-Planar Component Y'CbCr 8-bit 4:2:0, video-range (luma=[16,235] chroma=[16,240]).  baseAddr points to a big-endian CVPlanarPixelBufferInfo_YCbCrBiPlanar struct */
  kCVPixelFormatType_420YpCbCr8BiPlanarFullRange  = '420f', /* Bi-Planar Component Y'CbCr 8-bit 4:2:0, full-range (luma=[0,255] chroma=[1,255]).  baseAddr points to a big-endian CVPlanarPixelBufferInfo_YCbCrBiPlanar struct */ 
  kCVPixelFormatType_422YpCbCr8BiPlanarVideoRange = '422v', /* Bi-Planar Component Y'CbCr 8-bit 4:2:2, video-range (luma=[16,235] chroma=[16,240]).  baseAddr points to a big-endian CVPlanarPixelBufferInfo_YCbCrBiPlanar struct */
  kCVPixelFormatType_422YpCbCr8BiPlanarFullRange  = '422f', /* Bi-Planar Component Y'CbCr 8-bit 4:2:2, full-range (luma=[0,255] chroma=[1,255]).  baseAddr points to a big-endian CVPlanarPixelBufferInfo_YCbCrBiPlanar struct */
  kCVPixelFormatType_444YpCbCr8BiPlanarVideoRange = '444v', /* Bi-Planar Component Y'CbCr 8-bit 4:4:4, video-range (luma=[16,235] chroma=[16,240]).  baseAddr points to a big-endian CVPlanarPixelBufferInfo_YCbCrBiPlanar struct */
  kCVPixelFormatType_444YpCbCr8BiPlanarFullRange  = '444f', /* Bi-Planar Component Y'CbCr 8-bit 4:4:4, full-range (luma=[0,255] chroma=[1,255]).  baseAddr points to a big-endian CVPlanarPixelBufferInfo_YCbCrBiPlanar struct */
  kCVPixelFormatType_422YpCbCr8_yuvs = 'yuvs',     /* Component Y'CbCr 8-bit 4:2:2, ordered Y'0 Cb Y'1 Cr */
  kCVPixelFormatType_422YpCbCr8FullRange = 'yuvf', /* Component Y'CbCr 8-bit 4:2:2, full range, ordered Y'0 Cb Y'1 Cr */

写在最后

看到这里,为什么要使用YUV呢? 我想每个人心中都已经有了答案。
YUV的优势基本上也已经一目了然,因为压缩率比RGB要高很多,所占的数据存储量相对较小,所以适用于内存中传输视频数据或者处理图像等等一系列的操作。

下一章:「简单了解 iOS CVPixelBuffer (下)」

CATALOG
  1. 1. 前言:
  2. 2. 颜色空间
    1. 2.1. RGB
    2. 2.2. YUV
      1. 2.2.1. 采样格式
        1. 2.2.1.1. YUV444
        2. 2.2.1.2. YUV422
        3. 2.2.1.3. YUV420
      2. 2.2.2. 存储方式
  3. 3. 写在最后