一、YUV
是一种颜色编码方法。通常使用在各个视频处理组件中。YUV的原理是把亮度与色度分离。
1、使用YUV的优点
- 彩色YUV图像转黑白YUV图像转换非常的简单,这一特性用在电视信号上。
- YUV数据总尺寸小于RGB格式。
2、各个字母代表的含义
Y 表示明亮度,即我们说的灰度值。
U 表示色度
V 表示浓度
值得一提的是,Y分量可以黑白电视机的所有影像信息。
3、常用的YUV格式
YUV的表示法称为A:B:C表示法:
- 4:4:4 表示完全取样。
- 4:2:2表示2:1的水平取样,没有垂直下采样。
- 4:2:0表示2:1的水平取样。
- 4:1:1表示4:1的水平取样,没用垂直下采样。
最常用Y:UV记录的比重通常为1:1或者2:1,DVD-Video是以YUV4:2:0的方式记录,也就是我们俗称的I420。
4、转换
YUV420P,Y,U,V三个分量都是平面格式,分为I420和YV12。I420格式和YV12格式的不同处在U平面和V平面的位置不同。在I420格式中,U平面紧跟在Y平面之后,然后才是V平面(即:YUV);但YV12则是相反(即:YVU)。
YUV420SP, Y分量平面格式,UV打包格式, 即NV12。 NV12与NV21类似,U 和 V 交错排列,不同在于UV顺序。
I420: YYYYYYYY UU VV =>YUV420P
YV12: YYYYYYYY VV UU =>YUV420P
NV12: YYYYYYYY UV UV =>YUV420SP
NV21: YYYYYYYY VU VU =>YUV420SP
1、NV21转NV12
private void swapNV21ToNV12(byte[] nv21, byte[] nv12, int width, int height){
if(nv21 == NULL || nv12 == NULL)
return ;
System.arraycopy(nv21 , 0 , nv12 , 0 , framezie);
for(int j = 0 ; j < framesize / 2 ; j += 2){
nv12[framesize + j + 1] = nv21[j + framesize];
nv12[framesize + j] = nv21[j + framesize + 1];
}
}
2、YV12转I420
private void swapYV12toI420(byte[] yv12bytes, byte[] i420bytes, int width, int height){
System.arraycopy(yv12bytes , 0 , i420bytes , 0 , width * height);
System.arraycopy(yu12bytes , width * height + widhth * height / 4 , i420bytes , width * height , width*height/4 );
System.arraycopy(yv12bytes, width*height, i420bytes,width*height+width*height/4,width*height/4);
}
3、yv12转nv12
void swapYV12toNV12(byte[] yv12bytes, byte[] nv12bytes, int width,int height){
int nLenV = width * height;
int nLenU = nLenY / 4;
System.arraycopy(yv12bytes , 0 , nv12bytes , 0 , width * height);
for(int i = 0 ; i < nLenU ; i++){
nv12bytes[nLenY + 2 * i + 1] = yv12bytes[nLenY + i];
nv12bytes[nLenY + 2 * i]=yv12bytes[nLenY + nLenU +i];
}
}
4、nv12转I420
void swapNV12toI420(byte[] nv12bytes, byte[] i420bytes, int width,int height){
int nLenY = width * height;
int nLenU = nLenY/4;
System.arraycopy(nv12bytes, 0, i420bytes, 0, width*height);
for(int i = 0 ; i < nLenU ; i++){
i420bytes[nLenY+i] = nv12bytes[nLenY+2*i+1];
i420bytes[nLenY+nLenU+i] = nv12bytes[nLenY+2*i];
}
}
4、YUV图解
- 图片来自网络
YUV 4:4:4采样,每一个Y对应一组UV分量。
YUV 4:2:2采样,每两个Y共用一组UV分量。
YUV 4:2:0采样,每四个Y共用一组UV分量。
1、NV12、NV21(属于YUV420)存储方式
NV12和NV21属于YUV420格式,是一种two-plane模式,即Y和UV分为两个Plane,但是UV(CbCr)为交错存储,而不是分为三个plane。其提取方式即Y’00、Y’01、Y’10、Y’11共用Cr00、Cb00。
YUV420 planar数据, 以720×488大小图象YUV420 planar为例,其存储格式是: 共大小为(720×480×3>>1)字节,分为三个部分:Y,U和V。
Y分量: (720×480)个字节
U(Cb)分量:(720×480>>2)个字节
V(Cr)分量:(720×480>>2)个字节
三个部分内部均是行优先存储,三个部分之间是Y,U,V 顺序存储。
即YUV数据的0--720×480字节是Y分量值,
720×480--720×480×5/4字节是U分量,
720×480×5/4 --720×480×3/2字节是V分量。
2、4 :2: 2 和4:2:0 转换
YUV4:2:2 —> YUV4:2:0 Y不变,将U和V信号值在行(垂直方向)在进行一次隔行抽样。 YUV4:2:0 —> YUV4:2:2 Y不变,将U和V信号值的每一行分别拷贝一份形成连续两行数据。
3、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。
4、旋转90度的算法
public static void rotateYUV24(byte[] src,byte[] des,int width,int height){
int wh = width * height;
//旋转
int k =0;
for(int i =0;i<width;i++){
for(int j=0;j<height;j++){
des[k] = src[width*j + i];
k++;
}
}
for(int i=0;i<width;i+=2){
for(int j=0;j<height/2;j++){
des[k]=src[wh + width*j +i];
des[k+1] = src[wh + width*j + i + 1];
k+=2;
}
}
}
5、NV21和NV12
NV21 颜色空间排列 :YYYYYYYY VUVU
NV12 颜色空间排列 :YYYYYYYY UVUV
YUV420SP颜色排列顺序为:YYYYYYY UVUV
YUV420 是与NV12对应的。
二、RGB
R代表Red
G代表Green
B代表Blue
1、RGB565 与RGB888的区别
RGB565 就是R-5bit,G-6bit,B-5bit
RGB555 就是R-5bit,G-5bit,B-5bit
RGB888 就是R-8bit,G-8bit,B-8bit ;其实这就是RGB24
RGB565 是16位的,2个字节,5+6+5,第一字节的前5位是R,后三位+第二字节前三位是G,第二字节后5位是B。
RGB555 也是16位的,2个字节,RGB各5位,有1位未用。
RGB888 是24位的,3个字节。
三、YUV和RGB的转换公式
1.小数形式,full range
R = Y + 1.4075 * (V-128);
G = Y - 0.3455 * (U-128) - 0.7169*(V-128);
B = Y + 1.779 * (U-128);
Y = 0.299R + 0.587G + 0.114B;
U = (B-Y)/1.772; (U~(-128-127))
V = (R-Y)/1.402;
或写为:
Y = 0.299R + 0.587G + 0.114B;
U = -0.169R - 0.331G + 0.5 B + 128; 注: +128 的含义是让UV的范围处于整数区间(0-255)
V = 0.5 R - 0.419G - 0.081B + 128;
2.整数形式(减少计算量)full range
R= Y + ((360 * (V - 128))>>8) ;
G= Y - (( ( 88 * (U - 128) + 184 * (V - 128)) )>>8) ;
B= Y +((455 * (U - 128))>>8) ;
Y = (77R + 150G + 29B)>>8;
U = ((131R - 110G - 21B)>>8) + 128 ;
V = ((-44R - 87G - 131*B)>>8) + 128;
3. 量化后的公式( Y~(16,235) U/V ~(16,240) ) tv range
yuv --> rgb
R = 1.155Y + 1.605 * V - 224
G = 1.168Y - 0.393 * U - 0.823 * V+ 135.7
B = 1.168Y + 2.028 * U- 277.8
rgb --> yuv
Y= ( 66R + 128G + 25B)>>8 + 16
U= (112R - 94G - 18B)>>8 + 128
V= (-38R - 74G + 112B)>>8 +128
四、图片尺寸
1、720P、1080P、2K、4K的区别
目前主流清晰度主要分为720P(高清)、1080i 、1080P(全高清)、2K、4K。
1、720P分辨率为1280*720,长宽比16:9,P是Progressive逐行扫描的的意思。720P是一种在逐行扫描下达到1280×720的分辨率的显示格式。视频网站这种分辨率的比较多,兼顾了清晰度和画质。
2、1080i分辨率是1920*1080,长宽比16:9,i是interlace,代表隔行扫描。这种清晰度的视频格式比较少见。
1080P分辨率是1920*1080,长宽比16:9,P是Progressive逐行扫描的的意思.这也是目前主流的全高清格式。
3、4K分辨率38402160;是全高清(FHD.19201080)的4倍;高清(HD.1280*720)的9倍。
2、根据分辨率计算图片的大小
x bit=2的x次方
1byte=8bit
1K=1024byte
1M=1024K
看图片格式,如果是图片无损格式,这样计算:
灰度分辨率小于8Bit黑白:水平像素垂直像素1byte
灰度分辨率大于8Bit黑白:水平像素垂直像素2byte
彩色就复杂点,一个像素存储了红绿蓝三色的信息,通场灰度级别为8bit,计算方式为:水平像素垂直像素3byte
例如: 256x256的图片
如果是8bit黑白 256x256x1byte=65536 byte=64Kb
如果是24bit彩色 256x256x3byte=192Kb