I am trying to convert the image to grayscale through my own function using a piece of code taken from Android in action (2nd edition, you can also see it here ). Unfortunately, the returned bitmap object instead of shades of gray ends up empty.
This is how I upload an image (.png):
Bitmap original = BitmapFactory.decodeResource(this.getResources(), R.drawable.sample, options);
There are a number of security conditions with which a raster image passes (see below). Here's the definition of a native function in Java:
public native void convertToGray(Bitmap bitmapIn,Bitmap bitmapOut);
and call:
// Grayscale bitmap (initially empty) Bitmap gray = Bitmap.createBitmap(original.getWidth(),original.getHeight(),Config.ALPHA_8); // Native function call convertToGray(original,gray);
And here is the function:
JNIEXPORT void JNICALL Java_com_example_Preprocessor_convertToGray(JNIEnv * env, jobject obj, jobject bitmapcolor,jobject bitmapgray) { AndroidBitmapInfo infocolor; AndroidBitmapInfo infogray; void* pixelscolor; 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); } // 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("Done! Unlocking pixels..."); AndroidBitmap_unlockPixels(env, bitmapcolor); AndroidBitmap_unlockPixels(env, bitmapgray); }
The color bitmap is transmitted correctly, and part of the code processing works fine, but the bitmap remains empty. I guess I missed something important here.
Testing conditions: emulator, v2.2. With this version, the function works when native code is called from the main file. . On emulator 2.3, the function does not work , regardless of the thread that calls the C code or the way the bitmap is loaded. Android NDK: 4b and 6b.
UPDATE # 1: You will find the full source code here .
UPDATE # 2: RGB_565 instead of ALPHA_8 gives some results. It seems that even setPixels () in Java works for ALPHA_8, and I have problems finding information about this type of configuration. Any help would be much appreciated.