cats-oss / android-gpuimage

Android filters based on OpenGL (idea from GPUImage for iOS)
9k stars 2.27k forks source link

the color is changed when rendered by GPUImage Sample #140

Open hoozh opened 9 years ago

hoozh commented 9 years ago

I work on a microscopic software project, so the color of image is important.

Recently, i find that the colors of image previewed by gpuimage sample and Android Camera App is different.

screenshots is attached

Android 4.2 Camera camera

GPUImage Sample gpuimage_sample

hoozh commented 9 years ago

debug all day, I get some results

  1. Use GPUImage Sample “Gallery” button to open a captured picture, the color is right, it's green
  2. the image color is already blue before GPUImageView.setImage, so the problem is not caused by GPUImageRender.
  3. In my project, I use libyuv to convert NV21 image data to Bitmap, then send the Bitmap to GPUImage for rendering. so I capture a yuv frame before YUV-RGB convertion, and manually convert the yuv frame to RGB24 with two formulas, two formulas results DIFFERENT color. I think it is the problem.

       // formula 1, the color is green
       int r = y + 1.13983 * (v - 128);
       int g = y - 0.39465*(u - 128) - 0.58060 * (v - 128);
       int b = y + 2.03211*(u - 128);
    
       // formula 2, the color is blue
       int r = (int)(1.164f * (y - 16) + 1.596f * (v - 128));
       int g = (int)(1.164f * (y - 16) - 0.813f * (v - 128) - 0.391f * (u - 128));
       int b = (int)(1.164f * (y - 16) + 2.018f * (u - 128));

I guess the GPUImage working with Android Camera may be using formula 2,

        GPUImageNativeLibrary.YUVtoRBGA
hoozh commented 9 years ago

Problem Solved

in file yuv-decoder.c, method Javajp..._YUVtoRBGA(), line 39

                 R = Y + Cr + (Cr >> 2) + (Cr >> 3) + (Cr >> 5);
                 if(R < 0) R = 0; else if(R > 255) R = 255;
                 G = Y - (Cb >> 2) + (Cb >> 4) + (Cb >> 5) - (Cr >> 1) + (Cr >> 3) + (Cr >> 4) + (Cr >> 5);
                 if(G < 0) G = 0; else if(G > 255) G = 255;
                 B = Y + Cb + (Cb >> 1) + (Cb >> 2) + (Cb >> 6);
                 if(B < 0) B = 0; else if(B > 255) B = 255;

Change to

                 R = Y + Cr + (Cr >> 3) + (Cr >> 6);
                 if(R < 0) R = 0; else if(R > 255) R = 255;
                 G = Y - (Cb >> 1) + (Cb >> 4) + (Cb >> 5) - Cr + (Cr >> 2) + (Cr >> 3) + (Cr >> 5) + + (Cr >> 6);
                 if(G < 0) G = 0; else if(G > 255) G = 255;
                 B = Y + (Cb << 1) + (Cb >> 5);
                 if(B < 0) B = 0; else if(B > 255) B = 255;
wasabeef commented 9 years ago

thank you.

I hope to 1.2.2-SNAPSHOT to try out weekend.

wasabeef commented 9 years ago

Just pushed to 1.2.2-SNAPSHOT.

hoozh commented 9 years ago

Thanks wasabeef, I'm sorry i made a mistake, the code I provided make the color better, but the color is still inaccurate,

The code below is OK

//Method 4 //============================== //R = 1.164Y + 2.018Cr; //G = 1.164Y - 0.813Cb - 0.391Cr; //B = 1.164Y + 1.596Cb; //============================== //===== Approximation ========== // R = 1.1640625Y + 2.015625Cr // G = 1.1640625Y - 0.8125Cb - 0.375Cr // B = 1.1640625Y + 1.59375Cb //============================== Y = Y + (Y >> 3) + (Y >> 5) + (Y >> 7); R = Y + (Cr << 1) + (Cr >> 6); if(R < 0) R = 0; else if(R > 255) R = 255; G = Y - Cb + (Cb >> 3) + (Cb >> 4) - (Cr >> 1) + (Cr >> 3); if(G < 0) G = 0; else if(G > 255) G = 255; B = Y + Cb + (Cb >> 1) + (Cb >> 4) + (Cb >> 5); if(B < 0) B = 0; else if(B > 255) B = 255;

wasabeef commented 9 years ago

ok, Please pull-request.