Question

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

Was it helpful?

Solution

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);

OTHER TIPS

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));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top