小知识:
RGB
与
YUV
----
摘自《
DirectShow
实务精选》
作者:陆其明
计算机彩色显示器显示色彩的原理与彩色电视机一样,都是采用 R ( Red )、 G ( Green )、 B ( Blue )相加混色的原理:通过发射出三种不同强度的电子束,使屏幕内侧覆盖的红、绿、蓝磷光材料发光而产生色彩。这种色彩的表示方法称为 RGB 色彩空间表示(它也是多媒体计算机技术中用得最多的一种色彩空间表示方法)。
根据三基色原理,任意一种色光 F 都可以用不同分量的 R 、 G 、 B 三色相加混合而成。
F = r [ R ] + g [ G ] + b [ B ]
其中, r 、 g 、 b 分别为三基色参与混合的系数。当三基色分量都为 0 (最弱)时混合为黑色光;而当三基色分量都为 k (最强)时混合为白色光。调整 r 、 g 、 b 三个系数的值,可以混合出介于黑色光和白色光之间的各种各样的色光。
那么 YUV 又从何而来呢?在现代彩色电视系统中,通常采用三管彩色摄像机或彩色 CCD 摄像机进行摄像,然后把摄得的彩色图像信号经分色、分别放大校正后得到 RGB ,再经过矩阵变换电路得到亮度信号 Y 和两个色差信号 R - Y (即 U )、 B - Y (即 V ),最后发送端将亮度和色差三个信号分别进行编码,用同一信道发送出去。这种色彩的表示方法就是所谓的 YUV 色彩空间表示。
采用 YUV 色彩空间的重要性是它的亮度信号 Y 和色度信号 U 、 V 是分离的。如果只有 Y 信号分量而没有 U 、 V 分量,那么这样表示的图像就是黑白灰度图像。彩色电视采用 YUV 空间正是为了用亮度信号 Y 解决彩色电视机与黑白电视机的兼容问题,使黑白电视机也能接收彩色电视信号。
YUV 与 RGB 相互转换的公式如下( RGB 取值范围均为 0-255 ):
Y = 0.299R + 0.587G + 0.114B
U = -0.147R - 0.289G + 0.436B
V = 0.615R - 0.515G - 0.100B
R = Y + 1.14V
G = Y - 0.39U - 0.58V
B = Y + 2.03U
在 DirectShow 中,常见的 RGB 格式有 RGB1 、 RGB4 、 RGB8 、 RGB565 、 RGB555 、 RGB24 、 RGB32 、 ARGB32 等;常见的 YUV 格式有 YUY2 、 YUYV 、 YVYU 、 UYVY 、 AYUV 、 Y41P 、 Y411 、 Y211 、 IF09 、 IYUV 、 YV12 、 YVU9 、 YUV411 、 YUV420 等。 作为视频媒体类型的辅助说明类型( Subtype ),它们对应的 GUID 见表 2.3 。
表 2.3 常见的 RGB 和 YUV 格式
GUID 格式描述
MEDIASUBTYPE_RGB1 2 色,每个像素用 1 位表示,需要调色板
MEDIASUBTYPE_RGB4 16 色,每个像素用 4 位表示,需要调色板
MEDIASUBTYPE_RGB8 256 色,每个像素用 8 位表示,需要调色板
MEDIASUBTYPE_RGB565 每个像素用 16 位表示, RGB 分量分别使用 5 位、 6 位、 5 位
MEDIASUBTYPE_RGB555 每个像素用 16 位表示, RGB 分量都使用 5 位(剩下的 1 位不用)
MEDIASUBTYPE_RGB24 每个像素用 24 位表示, RGB 分量各使用 8 位
MEDIASUBTYPE_RGB32 每个像素用 32 位表示, RGB 分量各使用 8 位(剩下的 8 位不用)
MEDIASUBTYPE_ARGB32 每个像素用 32 位表示, RGB 分量各使用 8 位(剩下的 8 位用于表示 Alpha 通道值)
MEDIASUBTYPE_YUY2 YUY2 格式,以 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 格式
MEDIASUBTYPE_Y41P Y41P 格式,以 4:1:1 方式打包
MEDIASUBTYPE_Y411 Y411 格式(实际格式与 Y41P 相同)
MEDIASUBTYPE_Y211 Y211 格式
MEDIASUBTYPE_IF09 IF09 格式
MEDIASUBTYPE_IYUV IYUV 格式
MEDIASUBTYPE_YV12 YV12 格式
MEDIASUBTYPE_YVU9 YVU9 格式
计算机彩色显示器显示色彩的原理与彩色电视机一样,都是采用 R ( Red )、 G ( Green )、 B ( Blue )相加混色的原理:通过发射出三种不同强度的电子束,使屏幕内侧覆盖的红、绿、蓝磷光材料发光而产生色彩。这种色彩的表示方法称为 RGB 色彩空间表示(它也是多媒体计算机技术中用得最多的一种色彩空间表示方法)。
根据三基色原理,任意一种色光 F 都可以用不同分量的 R 、 G 、 B 三色相加混合而成。
F = r [ R ] + g [ G ] + b [ B ]
其中, r 、 g 、 b 分别为三基色参与混合的系数。当三基色分量都为 0 (最弱)时混合为黑色光;而当三基色分量都为 k (最强)时混合为白色光。调整 r 、 g 、 b 三个系数的值,可以混合出介于黑色光和白色光之间的各种各样的色光。
那么 YUV 又从何而来呢?在现代彩色电视系统中,通常采用三管彩色摄像机或彩色 CCD 摄像机进行摄像,然后把摄得的彩色图像信号经分色、分别放大校正后得到 RGB ,再经过矩阵变换电路得到亮度信号 Y 和两个色差信号 R - Y (即 U )、 B - Y (即 V ),最后发送端将亮度和色差三个信号分别进行编码,用同一信道发送出去。这种色彩的表示方法就是所谓的 YUV 色彩空间表示。
采用 YUV 色彩空间的重要性是它的亮度信号 Y 和色度信号 U 、 V 是分离的。如果只有 Y 信号分量而没有 U 、 V 分量,那么这样表示的图像就是黑白灰度图像。彩色电视采用 YUV 空间正是为了用亮度信号 Y 解决彩色电视机与黑白电视机的兼容问题,使黑白电视机也能接收彩色电视信号。
YUV 与 RGB 相互转换的公式如下( RGB 取值范围均为 0-255 ):
Y = 0.299R + 0.587G + 0.114B
U = -0.147R - 0.289G + 0.436B
V = 0.615R - 0.515G - 0.100B
R = Y + 1.14V
G = Y - 0.39U - 0.58V
B = Y + 2.03U
在 DirectShow 中,常见的 RGB 格式有 RGB1 、 RGB4 、 RGB8 、 RGB565 、 RGB555 、 RGB24 、 RGB32 、 ARGB32 等;常见的 YUV 格式有 YUY2 、 YUYV 、 YVYU 、 UYVY 、 AYUV 、 Y41P 、 Y411 、 Y211 、 IF09 、 IYUV 、 YV12 、 YVU9 、 YUV411 、 YUV420 等。 作为视频媒体类型的辅助说明类型( Subtype ),它们对应的 GUID 见表 2.3 。
表 2.3 常见的 RGB 和 YUV 格式
GUID 格式描述
MEDIASUBTYPE_RGB1 2 色,每个像素用 1 位表示,需要调色板
MEDIASUBTYPE_RGB4 16 色,每个像素用 4 位表示,需要调色板
MEDIASUBTYPE_RGB8 256 色,每个像素用 8 位表示,需要调色板
MEDIASUBTYPE_RGB565 每个像素用 16 位表示, RGB 分量分别使用 5 位、 6 位、 5 位
MEDIASUBTYPE_RGB555 每个像素用 16 位表示, RGB 分量都使用 5 位(剩下的 1 位不用)
MEDIASUBTYPE_RGB24 每个像素用 24 位表示, RGB 分量各使用 8 位
MEDIASUBTYPE_RGB32 每个像素用 32 位表示, RGB 分量各使用 8 位(剩下的 8 位不用)
MEDIASUBTYPE_ARGB32 每个像素用 32 位表示, RGB 分量各使用 8 位(剩下的 8 位用于表示 Alpha 通道值)
MEDIASUBTYPE_YUY2 YUY2 格式,以 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 格式
MEDIASUBTYPE_Y41P Y41P 格式,以 4:1:1 方式打包
MEDIASUBTYPE_Y411 Y411 格式(实际格式与 Y41P 相同)
MEDIASUBTYPE_Y211 Y211 格式
MEDIASUBTYPE_IF09 IF09 格式
MEDIASUBTYPE_IYUV IYUV 格式
MEDIASUBTYPE_YV12 YV12 格式
MEDIASUBTYPE_YVU9 YVU9 格式
下面分别介绍各种
RGB
格式。
¨ RGB1 、 RGB4 、 RGB8 都是调色板类型的 RGB 格式,在描述这些媒体类型的格式细节时,通常会在 BITMAPINFOHEADER 数据结构后面跟着一个调色板(定义一系列颜色)。它们的图像数据并不是真正的颜色值,而是当前像素颜色值在调色板中的索引。以 RGB1 ( 2 色位图)为例,比如它的调色板中定义的两种颜色值依次为 0x000000 (黑色)和 0xFFFFFF (白色),那么图像数据 001101010111 …(每个像素用 1 位表示)表示对应各像素的颜色为:黑黑白白黑白黑白黑白白白…。
¨ RGB565 使用 16 位表示一个像素,这 16 位中的 5 位用于 R , 6 位用于 G , 5 位用于 B 。程序中通常使用一个字( WORD ,一个字等于两个字节)来操作一个像素。当读出一个像素后,这个字的各个位意义如下:
高字节 低字节
R R R R R G G G G G G B B B B B
可以组合使用屏蔽字和移位操作来得到 RGB 各分量的值:
#define RGB565_MASK_RED 0xF800
#define RGB565_MASK_GREEN 0x07E0
#define RGB565_MASK_BLUE 0x001F
R = (wPixel & RGB565_MASK_RED) >> 11; // 取值范围 0-31
G = (wPixel & RGB565_MASK_GREEN) >> 5; // 取值范围 0-63
B = wPixel & RGB565_MASK_BLUE; // 取值范围 0-31
¨ RGB555 是另一种 16 位的 RGB 格式, RGB 分量都用 5 位表示(剩下的 1 位不用)。使用一个字读出一个像素后,这个字的各个位意义如下:
高字节 低字节
X R R R R G G G G G B B B B B ( X 表示不用,可以忽略)
可以组合使用屏蔽字和移位操作来得到 RGB 各分量的值:
#define RGB555_MASK_RED 0x7C00
#define RGB555_MASK_GREEN 0x03E0
#define RGB555_MASK_BLUE 0x001F
R = (wPixel & RGB555_MASK_RED) >> 10; // 取值范围 0-31
G = (wPixel & RGB555_MASK_GREEN) >> 5; // 取值范围 0-31
B = wPixel & RGB555_MASK_BLUE; // 取值范围 0-31
¨ RGB1 、 RGB4 、 RGB8 都是调色板类型的 RGB 格式,在描述这些媒体类型的格式细节时,通常会在 BITMAPINFOHEADER 数据结构后面跟着一个调色板(定义一系列颜色)。它们的图像数据并不是真正的颜色值,而是当前像素颜色值在调色板中的索引。以 RGB1 ( 2 色位图)为例,比如它的调色板中定义的两种颜色值依次为 0x000000 (黑色)和 0xFFFFFF (白色),那么图像数据 001101010111 …(每个像素用 1 位表示)表示对应各像素的颜色为:黑黑白白黑白黑白黑白白白…。
¨ RGB565 使用 16 位表示一个像素,这 16 位中的 5 位用于 R , 6 位用于 G , 5 位用于 B 。程序中通常使用一个字( WORD ,一个字等于两个字节)来操作一个像素。当读出一个像素后,这个字的各个位意义如下:
高字节 低字节
R R R R R G G G G G G B B B B B
可以组合使用屏蔽字和移位操作来得到 RGB 各分量的值:
#define RGB565_MASK_RED 0xF800
#define RGB565_MASK_GREEN 0x07E0
#define RGB565_MASK_BLUE 0x001F
R = (wPixel & RGB565_MASK_RED) >> 11; // 取值范围 0-31
G = (wPixel & RGB565_MASK_GREEN) >> 5; // 取值范围 0-63
B = wPixel & RGB565_MASK_BLUE; // 取值范围 0-31
¨ RGB555 是另一种 16 位的 RGB 格式, RGB 分量都用 5 位表示(剩下的 1 位不用)。使用一个字读出一个像素后,这个字的各个位意义如下:
高字节 低字节
X R R R R G G G G G B B B B B ( X 表示不用,可以忽略)
可以组合使用屏蔽字和移位操作来得到 RGB 各分量的值:
#define RGB555_MASK_RED 0x7C00
#define RGB555_MASK_GREEN 0x03E0
#define RGB555_MASK_BLUE 0x001F
R = (wPixel & RGB555_MASK_RED) >> 10; // 取值范围 0-31
G = (wPixel & RGB555_MASK_GREEN) >> 5; // 取值范围 0-31
B = wPixel & RGB555_MASK_BLUE; // 取值范围 0-31
¨ RGB24
使用
24
位来表示一个像素,
RGB
分量都用
8
位表示,取值范围为
0-255
。注意在内存中
RGB
各分量的排列顺序为:
BGR BGR BGR
…。通常可以使用
RGBTRIPLE
数据结构来操作一个像素,它的定义为:
typedef struct tagRGBTRIPLE {
BYTE rgbtBlue; // 蓝色分量
BYTE rgbtGreen; // 绿色分量
BYTE rgbtRed; // 红色分量
} RGBTRIPLE;
¨ RGB32 使用 32 位来表示一个像素, RGB 分量各用去 8 位,剩下的 8 位用作 Alpha 通道或者不用。( ARGB32 就是带 Alpha 通道的 RGB32 。)注意在内存中 RGB 各分量的排列顺序为: BGRA BGRA BGRA …。通常可以使用 RGBQUAD 数据结构来操作一个像素,它的定义为:
typedef struct tagRGBQUAD {
BYTE rgbBlue; // 蓝色分量
BYTE rgbGreen; // 绿色分量
BYTE rgbRed; // 红色分量
BYTE rgbReserved; // 保留字节(用作 Alpha 通道或忽略)
} RGBQUAD;
typedef struct tagRGBTRIPLE {
BYTE rgbtBlue; // 蓝色分量
BYTE rgbtGreen; // 绿色分量
BYTE rgbtRed; // 红色分量
} RGBTRIPLE;
¨ RGB32 使用 32 位来表示一个像素, RGB 分量各用去 8 位,剩下的 8 位用作 Alpha 通道或者不用。( ARGB32 就是带 Alpha 通道的 RGB32 。)注意在内存中 RGB 各分量的排列顺序为: BGRA BGRA BGRA …。通常可以使用 RGBQUAD 数据结构来操作一个像素,它的定义为:
typedef struct tagRGBQUAD {
BYTE rgbBlue; // 蓝色分量
BYTE rgbGreen; // 绿色分量
BYTE rgbRed; // 红色分量
BYTE rgbReserved; // 保留字节(用作 Alpha 通道或忽略)
} RGBQUAD;
下面介绍各种
YUV
格式。
YUV
格式通常有两大类:打包(
packed
)格式和平面(
planar
)格式。前者将
YUV
分量存放在同一个数组中,通常是几个相邻的像素组成一个宏像素(
macro-pixel
);而后者使用三个数组分开存放
YUV
三个分量,就像是一个三维平面一样。表
2.3
中的
YUY2
到
Y211
都是打包格式,而
IF09
到
YVU9
都是平面格式。(注意:在介绍各种具体格式时,
YUV
各分量都会带有下标,如
Y0
、
U0
、
V0
表示第一个像素的
YUV
分量,
Y1
、
U1
、
V1
表示第二个像素的
YUV
分量,以此类推。)
¨ YUY2 (和 YUYV )格式为每个像素保留 Y 分量,而 UV 分量在水平方向上每两个像素采样一次。一个宏像素为 4 个字节,实际表示 2 个像素。( 4:2:2 的意思为一个宏像素中有 4 个 Y 分量、 2 个 U 分量和 2 个 V 分量。)图像数据中 YUV 分量排列顺序如下:
Y0 U0 Y1 V0 Y2 U2 Y3 V2 …
¨ YVYU 格式跟 YUY2 类似,只是图像数据中 YUV 分量的排列顺序有所不同:
Y0 V0 Y1 U0 Y2 V2 Y3 U2 …
¨ UYVY 格式跟 YUY2 类似,只是图像数据中 YUV 分量的排列顺序有所不同:
U0 Y0 V0 Y1 U2 Y2 V2 Y3 …
¨ AYUV 格式带有一个 Alpha 通道,并且为每个像素都提取 YUV 分量,图像数据格式如下:
A0 Y0 U0 V0 A1 Y1 U1 V1 …
¨ Y41P (和 Y411 )格式为每个像素保留 Y 分量,而 UV 分量在水平方向上每 4 个像素采样一次。一个宏像素为 12 个字节,实际表示 8 个像素。图像数据中 YUV 分量排列顺序如下:
U0 Y0 V0 Y1 U4 Y2 V4 Y3 Y4 Y5 Y6 Y8 …
¨ Y211 格式在水平方向上 Y 分量每 2 个像素采样一次,而 UV 分量每 4 个像素采样一次。一个宏像素为 4 个字节,实际表示 4 个像素。图像数据中 YUV 分量排列顺序如下:
Y0 U0 Y2 V0 Y4 U4 Y6 V4 …
¨ YVU9 格式为每个像素都提取 Y 分量,而在 UV 分量的提取时,首先将图像分成若干个 4 x 4 的宏块,然后每个宏块提取一个 U 分量和一个 V 分量。图像数据存储时,首先是整幅图像的 Y 分量数组,然后就跟着 U 分量数组,以及 V 分量数组。 IF09 格式与 YVU9 类似。
¨ IYUV 格式为每个像素都提取 Y 分量,而在 UV 分量的提取时,首先将图像分成若干个 2 x 2 的宏块,然后每个宏块提取一个 U 分量和一个 V 分量。 YV12 格式与 IYUV 类似。
¨ YUV411 、 YUV420 格式多见于 DV 数据中,前者用于 NTSC 制,后者用于 PAL 制。 YUV411 为每个像素都提取 Y 分量,而 UV 分量在水平方向上每 4 个像素采样一次。 YUV420 并非 V 分量采样为 0 ,而是跟 YUV411 相比,在水平方向上提高一倍色差采样频率,在垂直方向上以 U/V 间隔的方式减小一半色差采样,如图 2.12 所示。
¨ YUY2 (和 YUYV )格式为每个像素保留 Y 分量,而 UV 分量在水平方向上每两个像素采样一次。一个宏像素为 4 个字节,实际表示 2 个像素。( 4:2:2 的意思为一个宏像素中有 4 个 Y 分量、 2 个 U 分量和 2 个 V 分量。)图像数据中 YUV 分量排列顺序如下:
Y0 U0 Y1 V0 Y2 U2 Y3 V2 …
¨ YVYU 格式跟 YUY2 类似,只是图像数据中 YUV 分量的排列顺序有所不同:
Y0 V0 Y1 U0 Y2 V2 Y3 U2 …
¨ UYVY 格式跟 YUY2 类似,只是图像数据中 YUV 分量的排列顺序有所不同:
U0 Y0 V0 Y1 U2 Y2 V2 Y3 …
¨ AYUV 格式带有一个 Alpha 通道,并且为每个像素都提取 YUV 分量,图像数据格式如下:
A0 Y0 U0 V0 A1 Y1 U1 V1 …
¨ Y41P (和 Y411 )格式为每个像素保留 Y 分量,而 UV 分量在水平方向上每 4 个像素采样一次。一个宏像素为 12 个字节,实际表示 8 个像素。图像数据中 YUV 分量排列顺序如下:
U0 Y0 V0 Y1 U4 Y2 V4 Y3 Y4 Y5 Y6 Y8 …
¨ Y211 格式在水平方向上 Y 分量每 2 个像素采样一次,而 UV 分量每 4 个像素采样一次。一个宏像素为 4 个字节,实际表示 4 个像素。图像数据中 YUV 分量排列顺序如下:
Y0 U0 Y2 V0 Y4 U4 Y6 V4 …
¨ YVU9 格式为每个像素都提取 Y 分量,而在 UV 分量的提取时,首先将图像分成若干个 4 x 4 的宏块,然后每个宏块提取一个 U 分量和一个 V 分量。图像数据存储时,首先是整幅图像的 Y 分量数组,然后就跟着 U 分量数组,以及 V 分量数组。 IF09 格式与 YVU9 类似。
¨ IYUV 格式为每个像素都提取 Y 分量,而在 UV 分量的提取时,首先将图像分成若干个 2 x 2 的宏块,然后每个宏块提取一个 U 分量和一个 V 分量。 YV12 格式与 IYUV 类似。
¨ YUV411 、 YUV420 格式多见于 DV 数据中,前者用于 NTSC 制,后者用于 PAL 制。 YUV411 为每个像素都提取 Y 分量,而 UV 分量在水平方向上每 4 个像素采样一次。 YUV420 并非 V 分量采样为 0 ,而是跟 YUV411 相比,在水平方向上提高一倍色差采样频率,在垂直方向上以 U/V 间隔的方式减小一半色差采样,如图 2.12 所示。