RGB与YUV
RGB色彩空间
RGB是以颜色发光的原理设计:三原色光模式(RGB color model),又称RGB颜色模型或红绿蓝颜色模型,是一种加色模型,将红(Red)、绿(Green)、蓝(Blue)三原色的色光以不同的比例相加,以合成产生各种色彩光。 from wikipedia
索引格式(已废弃)
- 索引格式是计算机早期的一种格式,它的优点比较节省空间,缺点是表现的色彩有限,目前格式基本被抛弃了,不再被使用,这里只做简单介绍。
- 索引格式中的bit存储的并非是实际的R,G, B值,而是对应点的像素在调色板中的索引。
- 调色板,可以简单理解为通过编号映射到颜色的一张二维表。如01索引,表示红色。采用索引格式的RGB,红色的像素对应存储的值便是索引01。就像指针一样,存储的是值的地址,而不是真正的值。
RGB1
每个像素用1个bit表示,可表示的颜色范围为双色,即最传统的黑和白。1个bit只能表示0,1两种值。需要调色板,不过调色板只包含两种颜色。
RGB4
每个像素用4个bit表示,4个bit所能够表示的索引范围是0-15,共16个。也就是可以表示16种颜色。即调色板中包含16中颜色。
RGB8
每个像素用8个bit表示。8个bit所能够表示的索引范围是0-255,共256个。也就是可以表示256中颜色。即调色板中包含256中颜色。
像素格式
RGB像素格式中的bit存储的是每一个像素点的R,G,B值
RGB565
一个像素用16个bit = 2个byte表示 ,R=5 G=6 B=5
R = color & 0xF800; //获取高字节的5个bit
G = color & 0x07E0; //获取中间6个bit
B = color & 0x001F; //获取低字节5个bit
为什么绿色为6位?
RGB555
一个像素用16个bit = 2个byte,但是最高位不用,R=5 G=5 B=5
R = color & 0x7C00;
G = color & 0x03E0;
B = color & 0x001F;
RGB24格式(BGR)
RGB24图像每个像素用8个bit,共24个位表示,共3个字节,注意:在内存中RGB各分量的排列顺序为:BGR
R = color & 0x0000FF00;
G = color & 0x00FF0000;
B = color & 0xFF000000;
RGB32格式(BGR)
RGB32图像每个像素用32个bit表示,占4个byte,R,G,B分量分别用8个bit表示,存储顺序为B,G,R,最后8个字节保留。注意:在内存中RGB各分量的排列顺序为:BGR
R = color & 0x0000FF00;
G = color & 0x00FF0000;
B = color & 0xFF000000;
A = color & 0x000000FF;
ARGB32格式(BGRA)
RGB32图像每个像素用32个bit表示,占4个字节,R,G,B分量分别用8个bit表示,存储顺序为B,G,R,最后8个为透明像素。注意:在内存中RGB各分量的排列顺序为:BGRA
R = color & 0x0000FF00;
G = color & 0x00FF0000;
B = color & 0xFF000000;
A = color & 0x000000FF;
Android平台下的常用的RGB格式
Bitmap.Config.ALPHA_8
每个像素用8比特位表示,占1个字节,只有透明度,没有颜色。
Bitmap.Config.RGB_565
每个像素用16比特位表示,占2个字节,RGB分量分别使用5位、6位、5位,见上图。
Bitmap.Config.ARGB_4444
每个像素用16比特位表示,占2个字节,由4个4位组成,ARGB分量都是4位。
Bitmap.Config.ARGB_8888
每个像素用32比特位表示,占4个字节,由4个8位组成,ARGB分量都是8位。
注意:java默认使用大端字节序,c/c++默认使用小端字节序,android平台下Bitmap.config.ARGB_8888的Bitmap默认是大端字节序,当需要把这个图片内存数据给小端语言使用的时候,就需要把大端字节序转换为小端字节序。例如:java层的ARGB_565传递给jni层使用时,需要把java层的ARGB_565的内存数据转换为BGRA565。
详细验证请看:Android Bitmap像素排列与JNI操作
YUV
YUV,是一种颜色编码方法。常使用在各个影像处理组件中。 YUV在对照片或视频编码时,考虑到人类的感知能力,允许降低色度的带宽。
YUV有很多变种,我们常说的YUV指的是YCbCr,YUV三个字母中,其中”Y”表示明亮度(Lumina nce或Luma),也就是灰阶值;而”U”和”V”表示的则是色度(Chrominance或Chroma)作用是描述影像色彩及饱和度,用于指定像素的颜色。Cb指蓝色色度分量,而Cr指红色色度分量,是标准 YUV 的一个翻版(还有YPbPr等),此文中,我们就用 YUV 指代 YCbCr 了。
分类标准
首先,YUV按照数据大小分为三个格式,YUV420,YUV422,YUV444。由于人眼对Y的敏感度远超于对U和V的敏感,所以可以多个Y分量共用一组UV,这样既可以极大的节省空间,又可以不太损失质量。
- YUV420,由4个Y分量共用一套UV分量
- YUV422,由2个Y分量共用一套UV分量
- YUV444,不共用,一个Y分量使用一套UV分量
按照多个 Y 分量共用一个 UV 的方式,我们可以把 YUV 分为 420,422,444 三种类型,而在这三种类型之下,我们又可以按照 YUV 的排列储存顺序,将其细分为好多种格式,这些格式数量繁多,又不好记忆,这为我们学习过程中造成了不少困难。下面我就为大家一一介绍。
首先,我们将可以按照 YUV 的排列方式,再次将 YUV 分成三个大类,Planar,Semi-Planar 和 Packed。
Planar YUV 三个分量分开存放
Semi-Planar Y 分量单独存放,UV 分量交错存放
Packed YUV 三个分量全部交错存放
按照这三种方式,我们就可以将 YUV 格式进行比较细致的分类了。
YUV的所有格式列表
一张从上到下分别为原图、Y、U 和 V:
YUV采样格式
YUV444采样格式
YUV 4:4:4 采样,意味着 Y、U、V 三个分量的采样比例相同,因此在生成的图像里,每个像素的三个分量信息完整,都是 8 bit,也就是一个字节。
如下图所示:
其中,Y 分量用叉表示,UV 分量用圆圈表示。
举个例子 :
假如图像像素为:[Y0 U0 V0]、[Y1 U1 V1]、[Y2 U2 V2]、[Y3 U3 V3]
那么采样的码流为:Y0 U0 V0 Y1 U1 V1 Y2 U2 V2 Y3 U3 V3
最后映射出的像素点依旧为 [Y0 U0 V0]、[Y1 U1 V1]、[Y2 U2 V2]、[Y3 U3 V3]
假如图像像素为:[Y0 U0 V0]、[Y1 U1 V1]、[Y2 U2 V2]、[Y3 U3 V3]
那么采样的码流为:Y0 U0 V0 Y1 U1 V1 Y2 U2 V2 Y3 U3 V3
最后映射出的像素点依旧为 [Y0 U0 V0]、[Y1 U1 V1]、[Y2 U2 V2]、[Y3 U3 V3]
可以看到这种采样方式的图像和 RGB 颜色模型的图像大小是一样,并没有达到节省带宽的目的,当将 RGB 图像转换为 YUV 图像时,也是先转换为 YUV 4:4:4 采样的图像。
YUV422采样格式
YUV 4:2:2 采样,意味着 UV 分量是 Y 分量采样的一半,Y 分量和 UV 分量按照 2 : 1 的比例采样。如果水平方向有 10 个像素点,那么采样了 10 个 Y 分量,而只采样了 5 个 UV 分量。
如下图所示:
举个例子 :
假如图像像素为:[Y0 U0 V0]、[Y1 U1 V1]、[Y2 U2 V2]、[Y3 U3 V3] 那么采样的码流为:Y0 U0 Y1 V1 Y2 U2 Y3 V3
其中,每采样过一个像素点,都会采样其 Y 分量,而 U、V 分量就会间隔一个采集一个。
最后映射出的像素点为 [Y0 U0 V1]、[Y1 U0 V1]、[Y2 U2 V3]、[Y3 U2 V3]
假如图像像素为:[Y0 U0 V0]、[Y1 U1 V1]、[Y2 U2 V2]、[Y3 U3 V3]
那么采样的码流为:Y0 U0 Y1 V1 Y2 U2 Y3 V3 其中,每采样过一个像素点,都会采样其 Y 分量,而 U、V 分量就会间隔一个采集一个。
最后映射出的像素点为 [Y0 U0 V1]、[Y1 U0 V1]、[Y2 U2 V3]、[Y3 U2 V3]
采样的码流映射为像素点,还是要满足每个像素点有 Y、U、V 三个分量。但是可以看到,第一和第二像素点公用了 U0、V1 分量,第三和第四个像素点公用了 U2、V3 分量,这样就节省了图像空间。
一张 1280 * 720 大小的图片,在 YUV 4:2:2 采样时的大小为:
(1280 _ 720 _ 8 + 1280 _ 720 _ 0.5 _ 8 _ 2)/ 8 / 1024 / 1024 = 1.76 MB 。
可以看到 YUV 4:2:2 采样的图像比 RGB 模型图像节省了三分之一的存储空间,在传输时占用的带宽也会随之减少。
YUV420采样格式
YUV 4:2:0 采样,并不是指只采样 U 分量而不采样 V 分量。而是指,在每一行扫描时,只扫描一种色度分量(U 或者 V),和 Y 分量按照 2 : 1 的方式采样。比如,第一行扫描时,YU 按照 2 : 1 的方式采样,那么第二行扫描时,YV 分量按照 2:1 的方式采样。对于每个色度分量来说,它的水平方向和竖直方向的采样和 Y 分量相比都是 2:1 。
如下图所示:
假设第一行扫描了 U 分量,第二行扫描了 V 分量,那么需要扫描两行才能够组成完整的 UV 分量。
举个例子 :
假设图像像素为:[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其中,每采样过一个像素点,都会采样其 Y 分量,而 U、V 分量就会间隔一行按照 2 : 1 进行采样。
最后映射出的像素点为:[Y0 U0 V5]、[Y1 U0 V5]、[Y2 U2 V7]、[Y3 U2 V7][Y5 U0 V5]、[Y6 U0 V5]、[Y7 U2 V7]、[Y8 U2 V7]
假设图像像素为:[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其中,每采样过一个像素点,都会采样其 Y 分量,而 U、V 分量就会间隔一行按照 2 : 1 进行采样。
最后映射出的像素点为:[Y0 U0 V5]、[Y1 U0 V5]、[Y2 U2 V7]、[Y3 U2 V7][Y5 U0 V5]、[Y6 U0 V5]、[Y7 U2 V7]、[Y8 U2 V7]
从映射出的像素点中可以看到,四个 Y 分量是共用了一套 UV 分量,而且是按照 2*2 的小方格的形式分布的,相比 YUV 4:2:2 采样中两个 Y 分量共用一套 UV 分量,这样更能够节省空间。
一张 1280 * 720 大小的图片,在 YUV 4:2:0 采样时的大小为:
(1280 _ 720 _ 8 + 1280 _ 720 _ 0.25 _ 8 _ 2)/ 8 / 1024 / 1024 = 1.32 MB 。
可以看到 YUV 4:2:0 采样的图像比 RGB 模型图像节省了一半的存储空间,因此它也是比较主流的采样方式。
YUV存储格式
YUV 的存储格式,有两种:
- planar 平面格式
指先连续存储所有像素点的 Y 分量,然后存储 U 分量,最后是 V 分量。 - packed 打包模式
指每个像素点的 Y、U、V 分量是连续交替存储的。
YUV422存储格式
YUYV 格式
YUYV 格式是采用打包格式进行存储的,指每个像素点都采用 Y 分量,但是每隔一个像素采样它的 UV 分量,排列顺序如下:
Y0 UO Y1 V0 Y2 U2 Y3 V2
UYVY 格式
UYVY 格式也是采用打包格式进行存储,它的顺序和 YUYV 相反,先采用 U 分量再采样 Y 分量,排列顺序如下:
U0 Y0 V0 Y1 U2 Y2 V2 Y3
YUV422P 格式
YUV 422P 格式,又叫做 I422,采用的是平面格式进行存储,先存储所有的 Y 分量,再存储所有的 U 分量,再存储所有的 V 分量。
Y0 Y1 Y2 Y3
U0 U1
V0 V1
YUV420存储格式
基于 YUV 4:2:0 采样的格式主要有 YUV 420P 和 YUV 420SP 两种类型,每个类型又对应其他具体格式。
- YUV 420P 类型
- YU12 格式
- YV12 格式
- YUV 420SP 类型
- NV12 格式
-
NV21 格式
I420 格式
I420 的单帧结构示意图如下(Planar 方式)
这幅图的上面一幅可以看出 Y1、Y2、Y7、Y8 共用 U1 和 V1。后面的线性数组为其存储顺序,可以看出 Y、U 和 V 都是顺序存储的,往外写的时候,先按顺序将 Y 分量写出,然后再根据 U、V 分别将它们依次写出即可。
NV12 格式
NV12的单帧结构示意图如下(Planar 方式)
可以看出与 YV12 不同的时,它的 Y 虽然也是顺序存储,但 U、V 却是交错存储的,这种方式存储在往外写出时则先直接顺序写出 Y,然后对 UV 分别依次写出。
PS:Android的Camera Preview默认图像格式为NV21。
RGB和YUV的优缺点对比
- RGB缺乏与早期黑白显示系统的良好兼容性。因此,许多电子电器厂商普遍采用的做法是,将RGB转换成YUV颜色空间,以维持兼容,再根据需要换回RGB格式,以便在电脑显示器上显示彩色图形。
- YUV主要用于优化彩色视频信号的传输,使其向后相容老式黑白电视。与RGB视频信号传输相比,它最大的优点在于只需占用极少的频宽(RGB要求三个独立的视频信号同时传输)。
- 采用YUV色彩空间的重要性是它的亮度信号Y和色度信号U、V是分离的。如果只有Y信号分量而没有U、V分量,那么这样表示的图像就是黑白灰度图像。彩色电视采用YUV空间正是为了用亮度信号Y解决彩色电视机与黑白电视机的兼容问题,使黑白电视机也能接收彩色电视信号。
YUV与RGB互转
把RGB和YUV的范围都缩放到[0,255]
YUV转RGB
R = Y + 1.403 × (V-128)
G = Y - 0.343 × (U-128) - 0.714 × (V-128)
B = Y + 1.770 × (U-128)
RGB转YUV
Y = 0.299R + 0.587G + 0.114B
Cr = V = 0.500R - 0.419G - 0.081B + 128
Cb = U = -0.169R - 0.331G + 0.500B + 128
参考资料:
图片RGB数据格式
一文读懂 YUV 的采样与格式
视音频数据处理入门:RGB、YUV像素数据处理
Android Bitmap像素排列与JNI操作
YUV420_SVG