public byte[] rgb2YCbCr422(int[] pixels, int width, int height) {
int len = width * height;
int index = 0;
//yuv格式数组大小,y亮度占len长度,u,v各占len/4长度。
byte[] yuv = new byte[len * 2];
int y, u, v, y1, u1, v1;
int rgb, b, g, r, a;
for (int i = 0; i < height * width; i++) {
a = pixels[i] >>> 24;
//屏蔽ARGB的透明度值
rgb = pixels[i] & 0x00FFFFFF;
//像素的颜色顺序为bgr,移位运算。
b = rgb & 0xFF;
g = (rgb >> 8) & 0xFF;
r = (rgb >> 16) & 0xFF;
//套用公式
y = ((66 * r + 129 * g + 25 * b + 128) >> 8) + 16;
u = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128;
v = ((112 * r - 94 * g - 18 * b + 128) >> 8) + 128;
//调整
/* y = (y > 255 ? 255 : y);
u = u < 0 ? 0 : (u > 255 ? 255 : u);
v = v < 0 ? 0 : (v > 255 ? 255 : v);*/
rgb = pixels[i++] & 0x00FFFFFF;
b = rgb & 0xFF;
g = (rgb >> 8) & 0xFF;
r = (rgb >> 16) & 0xFF;
y1 = ((66 * r + 129 * g + 25 * b + 128) >> 8) + 16;
u1 = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128;
v1 = ((112 * r - 94 * g - 18 * b + 128) >> 8) + 128;
//调整
y1 = (y1 > 255 ? 255 : y1);
u1 = u1 < 0 ? 0 : (u1 > 255 ? 255 : u1);
v1 = v1 < 0 ? 0 : (v1 > 255 ? 255 : v1);
yuv[index++] = (byte) y;
if(a==0)
{
yuv[index++] = 0;
}
else
{
//两个rgb像素点的u分量合并除以2得出新的yuv的U分量
yuv[index++] = (byte) ((u + u1) >> 1);
}
yuv[index++] = (byte) y1;
//屏蔽透明色,因为yuv是没有透明色的,所以要把argb的透明色给屏蔽掉。
//屏蔽透明色还有点问题,需要处理。
if(a==0)
{
yuv[index++] = 0;
}
else
{
yuv[index++] = (byte) v;
}
}
return yuv;
}
上面之所以一次算出2个int的argb里的RGB值,转换成4个byte的yuv值,是因为一个ARGB值,可以分别得出一个R、G、B数值出来。这个R、G、B可以转成对应的Y、U、V的值,但是一个rgb的像素点,对应两个yuv的字节,这里有3个值,一次填不下,所以就算出两个rgb像素点出来,然后将其中的两个u合并,再丢掉一个相临的V值,就可以得到2个yuv像素点的4个字节了。
使用上面函数的方法:
这个bitmap是读取的一张jpg的图片,保存在bitmap变量里。
bitmap.getPixels(regaArr[i], 0 , w, i * w, 0, w, h);
byte [] yuv = rgb2YCbCr422_3(regaArr[i], w, h);
yuv颜色编码的详细解析,有一篇博客 说得不错,大家可以参考下:
https://www.jianshu.com/p/a91502c00fb0