YUV转RGB优化

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代码运行要快

猜你喜欢

转载自blog.csdn.net/jerry872235631/article/details/115949985
今日推荐