简体   繁体   中英

YUV_420_888 to RGB conversion

I am working with camera2 and in ImageReader i have YUV_420_888 format. I looked around and found some formulas for converting it to RGB. But i have problem with some colors. Here is the code that converts it to RGB:

ByteBuffer buffer0 = image.getPlanes()[0].getBuffer();
byte[] Y1 = new byte[buffer0.remaining()];
buffer0.get(Y1);
ByteBuffer buffer1 = image.getPlanes()[1].getBuffer();
byte[] U1 = new byte[buffer1.remaining()];
buffer1.get(U1);
ByteBuffer buffer2 = image.getPlanes()[2].getBuffer();
byte[] V1 = new byte[buffer2.remaining()];
buffer2.get(V1);
int Width = image.getWidth();
int Heigh = image.getHeight();
byte[] ImageRGB = new byte[image.getHeight()*image.getWidth()*4];

for(int i = 0; i<Heigh-1; i++){
    for (int j = 0; j<Width; j++){
        int Y = Y1[i*Width+j]&0xFF;
        int U = U1[(i/2)*(Width/2)+j/2]&0xFF;
        int V = V1[(i/2)*(Width/2)+j/2]&0xFF;
        U = U-128;
        V = V-128;
        int R,G,B;
        R = (int)(Y + 1.140*V);
        G = (int)(Y - 0.395*U - 0.581*V);
        B = (int)(Y + 2.032*U);
        if (R>255) {
            R = 255;
        } else if (R<0) {
            R = 0;
        }
        if (G>255) {
            G = 255;
        } else if (G<0) {
            G = 0;
        }
        if (B>255) {
            R = 255;
        } else if (B<0) {
            B = 0;
        }
        ImageRGB[i*4*Width+j*4] = (byte)R;
        ImageRGB[i*4*Width+j*4+1] = (byte)G;
        ImageRGB[i*4*Width+j*4+2] = (byte)B;
        ImageRGB[i*4*Width+j*4+3] = -1;
    }
}

And when i point camera towards some color this happens. Any idea why and how i can fix this?

EDIT: Here is code i used for posting on SurfaceView but i think its correct

Bitmap bm = Bitmap.createBitmap(image.getWidth(), image.getHeight(), 

Bitmap.Config.ARGB_8888);
bm.copyPixelsFromBuffer(ByteBuffer.wrap(ImageRGB));
Bitmap scaled = Bitmap.createScaledBitmap(bm, surfaceView.getWidth(), surfaceView.getHeight(), true);
Canvas c;
c = surfaceHolder.lockCanvas();
c.drawBitmap(scaled, 0, 0, null);
surfaceHolder.unlockCanvasAndPost(c);
image.close();

That doesn't look like the correct YUV->RGB transform. The camera2 API color space for YUV_420_888 from the camera device is the JFIF YUV colorspace (same as what's inside JPEG files). This is unfortunately not clearly documented currently.

The JFIF YUV->RGB transform is defined to be as follows in the JPEG JFIF specification :

R = Y + 1.402 (Cr-128)
G = Y - 0.34414 (Cb-128) - 0.71414 (Cr-128)
B = Y + 1.772 (Cb-128)

So try that to start with. And for full clarify, Cb = U, Cr = V.

There is an error in your code

    if (B>255) {
        B = 255; //was R = 255;
    } else if (B<0) {
        B = 0;
    }

And try to use both of variants

R = Y + 1.402 * V
G = Y - 0.34414 * U - 0.71414 * V
B = Y + 1.772 * U

Or from here :

R = yValue + (1.370705 * V);
G = yValue - (0.698001 * V) - (0.337633 * U);
B = yValue + (1.732446 * U);

The U,V planes have dimensions (x, y/2) so try

int offset = (i/2)*Width + j;
int U = U1[offset]&0xFF;
int V = V1[offset+1]&0xFF;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM