YUV转RGB ISBN 1-878707-09-4 公式
RGB 的范围是 [0,255],Y 的范围是 [16,235] ,UV 的范围是 [16,239]
R=1.164(Y-16)+1.596(V-128)
G=1.164(Y-16)-0.813(V-128)-0.391(U-128)
B=1.164(Y-16)+2.018(U-128)
浮点运算比较慢,所以先干掉浮点,两边都乘以256
256R=297.984(Y-16)+408.576(V-128)
256G=297.984(Y-16)-208.128(V-128)-100.096(U-128)
256B=297.984(Y-16)+516.608(U-128)
取整
256R=298Y-4768+409V-52224
256G=298Y-4768-208V+26640-100U+12800
256B=298Y-4768+516U-66126
乘法运算转换为位移运算
R=(298Y+409V-56992)>>8
G=(298Y-208V-100U+34672)>>8
B=(298Y+516U-70894)>>8
注意加减运算优先级高于位移运算
R=((Y<<8)+(Y<<5)+(Y<<3)+(Y<<1)+(V<<8)+(V<<7)+(V<<4)+(V<<3)+V-56992)>>8
G=((Y<<8)+(Y<<5)+(Y<<3)+(Y<<1)-(V<<7)-(V<<6)-(V<<4)-(U<<6)-(U<<5)-(U<<2)+34672)>>8
B=((Y<<8)+(Y<<5)+(Y<<3)+(Y<<1)+(U<<9)+(U<<2)-70894)>>8
附上java代码
public static Bitmap yuv2Bitmap(byte[] data, int width, int height) {
long startTime = System.currentTimeMillis();
int frameSize = width * height;
int[] rgba = new int[frameSize];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int y = (0xff & ((int) data[i * width + j]));
int u = (0xff & ((int) data[frameSize + (i >> 1) * width + (j & ~1)]));
int v = (0xff & ((int) data[frameSize + (i >> 1) * width + (j & ~1) + 1]));
y = Math.max(y, 16);
/*
* ISBN 1-878707-09-4 公式
* RGB 的范围是 [0,255],Y 的范围是 [16,235] ,UV 的范围是 [16,239]
* R=1.164(Y-16)+1.596(V-128)
* G=1.164(Y-16)-0.813(V-128)-0.391(U-128)
* B=1.164(Y-16)+2.018(U-128)
*
* 256R=297.984(Y-16)+408.576(V-128)
* 256G=297.984(Y-16)-208.128(V-128)-100.096(U-128)
* 256B=297.984(Y-16)+516.608(U-128)
*
* 256R=298Y-4768+409V-52224
* 256G=298Y-4768-208V+26640-100U+12800
* 256B=298Y-4768+516U-66126
*
* R=(298Y+409V-56992)>>8
* G=(298Y-208V-100U+34672)>>8
* B=(298Y+516U-70894)>>8
*
* R=((Y<<8)+(Y<<5)+(Y<<3)+(Y<<1)+(V<<8)+(V<<7)+(V<<4)+(V<<3)+V-56992)>>8
* G=((Y<<8)+(Y<<5)+(Y<<3)+(Y<<1)-(V<<7)-(V<<6)-(V<<4)-(U<<6)-(U<<5)-(U<<2)+34672)>>8
* B=((Y<<8)+(Y<<5)+(Y<<3)+(Y<<1)+(U<<9)+(U<<2)-70894)>>8
*/
int temp = (y << 8) + (y << 5) + (y << 3) + (y << 1);
int r = (temp + (v << 8) + (v << 7) + (v << 4) + (v << 3) + v - 56992) >> 8;
int g = (temp - (v << 7) - (v << 6) - (v << 4) - (u << 6) - (u << 5) - (u << 2) + 34672) >> 8;
int b = (temp + (u << 9) + (u << 2) - 70894) >> 8;
//阈值矫正
r = r < 0 ? 0 : (Math.min(r, 255));
g = g < 0 ? 0 : (Math.min(g, 255));
b = b < 0 ? 0 : (Math.min(b, 255));
rgba[i * width + j] = 0xff000000 + (b << 16) + (g << 8) + r;
}
}
long yuvTime = System.currentTimeMillis() - startTime;
long bitmapTime = System.currentTimeMillis();
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bmp.setPixels(rgba, 0, width, 0, 0, width, height);
// Bitmap rotateBitmap = rotateBitmap(90f, bmp);
Log.d(TAG, "yuv2Bitmap yuv=" + yuvTime + " time=" + (System.currentTimeMillis() - bitmapTime));
return bmp;
}
测试时发现Java代码比Kotlin代码运行要快