1

I am passing the Bitmap with ARGB_8888 config. I am able to apply the grayscale effect to the image but after applying that i am losing its brightness.

I have googled a lot but found the same implementation as i have.

Here is my native implmentation ::

JNIEXPORT void JNICALL Java_com_example_ndksampleproject_MainActivity_jniConvertToGray(JNIEnv * env, jobject  obj, jobject bitmapcolor,jobject bitmapgray)
{
    AndroidBitmapInfo  infocolor;
    void*              pixelscolor;
    AndroidBitmapInfo  infogray;
    void*              pixelsgray;
    int                ret;
    int             y;
    int             x;

    LOGI("convertToGray");
    if ((ret = AndroidBitmap_getInfo(env, bitmapcolor, &infocolor)) < 0) {
        LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
        return;
    }

    if ((ret = AndroidBitmap_getInfo(env, bitmapgray, &infogray)) < 0) {
        LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
        return;
    }

    LOGI("color image :: width is %d; height is %d; stride is %d; format is %d;flags is %d",infocolor.width,infocolor.height,infocolor.stride,infocolor.format,infocolor.flags);
    if (infocolor.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
        LOGE("Bitmap format is not RGBA_8888 !");
        return;
    }

    LOGI("gray image :: width is %d; height is %d; stride is %d; format is %d;flags is %d",infogray.width,infogray.height,infogray.stride,infogray.format,infogray.flags);
    if (infogray.format != ANDROID_BITMAP_FORMAT_A_8) {
        LOGE("Bitmap format is not A_8 !");
        return;
    }

    if ((ret = AndroidBitmap_lockPixels(env, bitmapcolor, &pixelscolor)) < 0) {
        LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
    }

    if ((ret = AndroidBitmap_lockPixels(env, bitmapgray, &pixelsgray)) < 0) {
        LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
    }

    LOGI("unlocking pixels height = %d",infocolor.height);

    // modify pixels with image processing algorithm

    for (y=0;y<infocolor.height;y++) {
        argb * line = (argb *) pixelscolor;
        uint8_t * grayline = (uint8_t *) pixelsgray;
        for (x=0;x<infocolor.width;x++) {
            grayline[x] = ((255-0.3 * line[x].red) + (255-0.59 * line[x].green) + (255-0.11*line[x].blue))/3;
        }

        pixelscolor = (char *)pixelscolor + infocolor.stride;
        pixelsgray = (char *) pixelsgray + infogray.stride;
    }

    LOGI("unlocking pixels");
    AndroidBitmap_unlockPixels(env, bitmapcolor);
    AndroidBitmap_unlockPixels(env, bitmapgray);
}

Result ::

enter image description here

Please let me know if you need anything from my side.. Please help me to get rid of this issue as i am stuck into this from many hours. Many thanks in Advance !!!

EDIT ::

After applying the Mark Setchell's Suggestion ::

enter image description here

EDITED

If you invert the image above, you get this - which looks correct to me:

enter image description here

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
AndroidLearner
  • 4,500
  • 4
  • 31
  • 62
  • Please take a look at my answer of http://stackoverflow.com/questions/16292146/android-how-to-apply-diffenernt-image-effects-on-bitmap-like-sepia-blackand-w/16292822#16292822 question – Chintan Rathod Apr 08 '14 at 08:18
  • @ChintanRathod Thanks for your quick response.Can you please guide about how to apply the same thing natively? – AndroidLearner Apr 08 '14 at 08:46
  • Hi, I don't know native coding of Android but i have seen some algorithm implementation. you can use http://www.johndcook.com/blog/2009/08/24/algorithms-convert-color-grayscale/ or http://www.tannerhelland.com/3643/grayscale-image-algorithm-vb6/ link and try to implement algorithm. I think only what you need is the changing algorithm of GrayScale. Just implement popular one. :) – Chintan Rathod Apr 08 '14 at 08:51
  • @ChintanRathod Thanks for link.I'll try and let you know the result. – AndroidLearner Apr 08 '14 at 08:53

2 Answers2

2

Don't divide by 3 on the line where you calculate grayline[x]. Your answer is already correctly weighted because 0.3 + 0.59 + 0.11 = 1

grayline[x] = (255-0.3 * line[x].red) + (255-0.59 * line[x].green) + (255-0.11*line[x].blue);
Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • I have tried your suggestion and it showed me the some strange result.Please check my EDIT. – AndroidLearner Apr 08 '14 at 09:58
  • Your image is exactly correct now, except it is inverted. I have corrected that. – Mark Setchell Apr 08 '14 at 10:27
  • If i remove the division by 3,the result remain same. – AndroidLearner Apr 08 '14 at 10:32
  • No. The image you have posted since using my code is exactly the correct brightness, it is just inverted. Please copy and paste the line of code above and try again - it definitely correct now. – Mark Setchell Apr 08 '14 at 10:34
  • If you remove the division by 3, like I said, the image MUST come out brighter! – Mark Setchell Apr 08 '14 at 10:35
  • Well right now m going with this `grayline[x] = (255- 0.3 * line[x].red) + (255- 0.59 * line[x].green) + (255-0.11*line[x].blue);`.I am checking that after saving the grayscaled image to SD card how does it looks on PC(may be you are correct),but image does not got saved in SD Card.does it because i am using the ALPHA_8 Config for bitmap to grayscale image?any clue? – AndroidLearner Apr 08 '14 at 11:56
  • Well,Mark thanks for your valuable suggestions.grayscale issue is solve upto some extent,but if i try to save the grayscale image in my sd card then it shows some black image(go to gallery and click on image). can you please help me on this ? http://stackoverflow.com/questions/22953988/restoring-the-image-from-native-memory-using-ndk-returns-black-image-with-no-dis – AndroidLearner Apr 09 '14 at 06:39
2

There are two problems with your current code.

1) As mentioned by others, do not divide the final result by three. If you were calculating grayscale using the average method (e.g. gray = (R + G + B) / 3), the division would be necessary. For the ITU conversion formula you are using, there is no need for this extra division, because the fractional amounts already sum to 1.

2) The inversion occurs because you are subtracting each color value from 255. There is no need to do this.

The correct grayscale conversion code for your current formula would be:

grayline[x] = ((0.3 * line[x].red) + (0.59 * line[x].green) + (0.11*line[x].blue));
Tanner H
  • 21
  • 3