Custom raster processing and ALPHA_8

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.

+6
source share
3 answers

I had a similar problem. First of all, I used android RGBA_8888 format for infogray instead of A_8 (the original bitmap was created using the ARGB_8888 format). Then, if you use argb struct for the gray line instead of uint_8, you can fill the pixels like this:

 for (y = 0; y < infocolor.height; ++y) { argb* line = (argb*) pixelscolor; argb* grayline = (argb*) pixelsgray; for (x = 0; x < infocolor.width; ++x) { grayline[x].red = grayline[x].green = grayline[x].blue = 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; } 
+1
source

I had the same problems. I didn’t try very hard to make ALPHA_8 work, but the problem was fixed using ARGB_8888.

Btw, in response to @white_pawn's comment (sorry, I can not reply to comments)

The argb structure in IBM Example is in the wrong order. in my emulators or phone, converting it to RGBA fixes the problem (this is probably the reason your image looks blue because you use alpa for blue). Although I'm not sure that this order is hardware dependent.

 typedef struct { uint8_t red; uint8_t green; uint8_t blue; uint8_t alpha; } argb; 
+1
source

I had the same problem and it turned out what went wrong! When you use APHA_8, you need to change the background to #ffffffff ,

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ffffffff"> 
0
source

Source: https://habr.com/ru/post/898462/


All Articles