YUV,分为三个分量,“Y”表示明亮度(Luminance或Luma),也就是灰度值;
而“U”和“V”表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。
一、YUV 采样
有一种表示法可用来描述 U 和 V 与 Y 的采样频率比例,这个表示法称为 A:B:C 表示法:
例如4:2:0
× × × ×
。 。 。
× × × ×
× × × ×
。 。 。
× × × ×
YUV420(4:2:0)为每个像素点对应一个Y分量,每4个像素点共用一组UV分量。所以分辨率为width*height的YUV420格式图像的数据量为:
yBytes = width*height;
uBytes = width*height/4; // width*height>>2;
vBytes = width*height/4; // width*height>>2;
yuvBytes = width*height*3/2;// width*height*3>>1;
YUV420按照UV分量的存储方式分为YUV420p
和YUV420sp
两类。
YUV420p
为Y、U、V三平面依次存储,YUV420sp
为Y和UV两平面,且UV分量交叉存储。
stride:
/*
* YUV420p
*/
yStride = width;
uStride = width/2; // width>>1;
vStride = width/2; // width>>1;
/*
* YUV420sp
*/
yStride = width;
uvStride = width;
stride(考虑字节对齐):
#define ALIGN(x, align) (x+(align-1))&~(align-1)
/*
* YUV420p
*/
yStride = ALIGN(width, 16);
uStride = ALIGN(width>>1, 16);
vStride = ALIGN(width>>1, 16);
/*
* YUV420sp
*/
yStride = ALIGN(width, 16);
uvStride = ALIGN(width, 16);
参考文档:
YUV420p
:
YUV420sp
:
YUV420p又分为I420和YV12两类。
分辨率为4X2的图像,I420格式数据存储为:YYYY YYYY UU VV,YV12格式数据存储为:YYYY YYYY VV UU。
I420即android.ImageFormat.YUV_420_888
YUV420sp又分为NV12和NV21两类。
分辨率为4X2的图像,NV12格式数据存储为:YYYY YYYY UV UV,NV21格式数据存储为:YYYY YYYY VU VU。
参考文档:
二、YUV与YCbCr
2.1 YUV与YCbCr的区别:
YUV色彩模型来源于RGB模型,该模型的特点是将亮度和色度分离开,适合于图像处理领域。
应用:模拟领域,basic color model used in analogue color TV broadcasting.
YCbCr模型来源于YUV模型。YCbCr is a scaled and offset version of the YUV color space.
应用:数字视频,ITU-R BT.601 recommendation
note:U和Cb对应,V和Cr对应。(通常接触到的数字图像像素格式为YCbCr,简单理解为YUV)
YCbCr分量图:
参考文档:
2.2 YUV、YCbCr转RGB公式:
RGB -> YCbCr
Y’ = 0.257*R' + 0.504*G' + 0.098*B' + 16
Cb' = -0.148*R' - 0.291*G' + 0.439*B' + 128
Cr' = 0.439*R' - 0.368*G' - 0.071*B' + 128
RGB -> YCbCr 代码实现(参考:Android加载图片小结->11. Bitmap转yuv420sp(NV21))
int R, G, B;
...
int Y = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
int Cb = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
int Cr = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128;
Y = ((Y < 0) ? 0 : ((Y > 255) ? 255 : Y));
Cb = ((Cb < 0) ? 0 : ((Cb > 255) ? 255 : Cb));
Cr = ((Cr < 0) ? 0 : ((Cr > 255) ? 255 : Cr));
YCbCr -> RGB
R' = 1.164*(Y’-16) + 1.596*(Cr'-128)
G' = 1.164*(Y’-16) - 0.813*(Cr'-128) - 0.392*(Cb'-128)
B' = 1.164*(Y’-16) + 2.017*(Cb'-128)
参考文档:
三、YUV420 旋转90
void turnRotation(int width, int height, byte[] src, byte[] dest) {
final int SUM = width * height;
int h = SUM;
// Y
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
dest[--h] = src[j * width + i];
}
}
h = SUM * 3 / 2;
// UV
for (int i = 0; i < width; i += 2) {
for (int j = 0; j < height / 2; j++) {
dest[--h] = src[SUM + j * width + i + 1];
dest[--h] = src[SUM + j * width + i];
}
}
}
void turnRotationBack(int width, int height, byte[] src, byte[] dest) {
final int SUM = width * height;
int h = SUM;
// Y
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
dest[j * width + i] = src[--h];
}
}
h = SUM * 3 / 2;
int x = SUM * 3 / 2;
// UV
for (int i = 0; i < width; i += 2) {
for (int j = 0; j < height / 2; j++) {
dest[--x] = src[--h];
dest[--x] = src[--h];
}
}
}
参考网址: