0

I want to apply the grayscale effect to image using NDK.

For that i have googled a lot but found the same result which returns the image in somewhat like negative(this is what i believe).

What i want ::

For example ::

I have this original image

enter image description here

After applying the grayscale effect it should be like this ::

enter image description here

What i have tried ::

I want to achieve this functionality using NDK,so that i have created one function in .cpp file

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] = 0.3 * line[x].red + 0.59 * line[x].green + 0.11*line[x].blue;
        }

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

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

The above function return me the result like this ::

enter image description here

This effect looks like something like negative of image.

Let me know if u need anything from my side.. Please help me to solve this issue as i have stuck into this from many hours.

Many Thanks in Advance...

EDIT ::

floppy12's Suggestion ::

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

Output ::

enter image description here

EDIT 2 ::

I have made the some simple modification to the image and it returns me the image what i wanted but the image lost its brightness.

This is the changes that i have made in native function..

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

Result(image is grayscaled but losing its brightness) ::

enter image description here

AndroidLearner
  • 4,500
  • 4
  • 31
  • 62
  • well here is how to convert any pixel to gray. Cause i think you are using constants numbers(?) to convert the colors. http://stackoverflow.com/questions/17117413/how-to-convert-pixels-to-gray-scale – adderly Apr 07 '14 at 14:46

1 Answers1

2

To obtain an image in grayscale, each pixel should have the same amount of red, green and blue

Maybe use the red component and affect it to both green and blue in your grayline computation

or use the formula (R+G+B)/3 = Gray

Negative images are normally obtained by by shifting each component :

NegR = 255 - grayR

and so on

So you could try to compute grayscal[x] = (255 - 0.3*line[x]) + ...

Edit for brightness: To obtain better brightness, try to add a fixed amount to your grayscale computation:

G += Bness;

Here it seems that Bness should be negative as long as you are going from 255(black) to 0(white) for some strange reason. You want to put a down limit to not go under 0 for your grascale value, then try :

G = max(0, G+Bness);

I recommend something like Bness = -25

Edit implementation brightness:

// Declare a global variable for your brightness - outside your class
static uint8_t bness = -25;

// In your grayscale computation function
for y...
 for x...
  grayscale[x] = ( (255-0.3*line[x].red) + ..... ) /3 ;
  int16_t gBright = grayscale[x] + bness;
  grayscale[x] = MAX( 0, gBright );
floppy12
  • 1,045
  • 6
  • 12
  • I have tried your suggestion it return me the gray scale images but the background of image still remain the same.Please check my edit.. – AndroidLearner Apr 08 '14 at 06:17
  • I have made some minor changes in native function as per your suggestion and it returned me an grayscaled image but it lost its brightness.Please check my EDIT2. – AndroidLearner Apr 08 '14 at 07:14
  • Well that looks better :) – floppy12 Apr 08 '14 at 08:44
  • image is losing its brightness,when i see the image in device,it grayscale without brihtness.Can you suggest me any changes in the current implementation of my native code to increase the brightness?Compare the image which i have posted in EDIT1,that image is bright(but background messed up) while in EDIT2 image get grayscaled but losing brightness. – AndroidLearner Apr 08 '14 at 08:51
  • I think that your background messed up because of an overflow in your computation maybe due to floating point arithmetic or something like... then part which should be black switched to white... and generally all your components are darker than they are – floppy12 Apr 08 '14 at 09:05
  • can you please help me how to implement this in my native code? – AndroidLearner Apr 08 '14 at 09:08
  • Does it suit your needs ? – floppy12 Apr 08 '14 at 11:44
  • 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,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:55
  • I think it's not related... You could have a look to this post for a working example : http://stackoverflow.com/questions/11846108/android-saving-bitmap-to-sd-card Maybe you have missed the permission WRITE_EXTERNAL_STORAGE in manifest ? – floppy12 Apr 08 '14 at 13:55
  • I have set the required permission and image is also getting saved in the SD Card at location which i have set.But the problem is saved image is totally blank with no display at all. – AndroidLearner Apr 08 '14 at 14:04
  • Maybe the config for bitmap is missing up, have you set a alpha component (transparency/opacity) ? It could explain the blank effect – floppy12 Apr 08 '14 at 15:12
  • for black image problem i have asked the new question,can you explain me here about your thought ? http://stackoverflow.com/questions/22953988/restoring-the-image-from-native-memory-using-ndk-returns-black-image-with-no-dis – AndroidLearner Apr 09 '14 at 05:58
  • The answers on this new question reflects my thought actually :) – floppy12 Apr 10 '14 at 11:50