Re: AndroidBitmap_lockPixels not working properly in Gingerbread

914 views
Skip to first unread message

David Turner

unread,
Jan 28, 2013, 3:38:06 AM1/28/13
to andro...@googlegroups.com
The most likely issue is that your bitmap is actually 16-bit RGB565 or RGBA4444, instead of 32-bit RGBA/RGBX.

The default bit depth of Bitmap surfaces is indeed platform-specific. You should use ABitmap_getInfo() to know exactly how to process your Bitmap. An alternative is to enforce the right format when creating the bitmap.

On Fri, Jan 25, 2013 at 1:16 AM, Stefan Anca <shtefa...@gmail.com> wrote:
Hi,

I am trying to port a Google Gallery Image Filter from the new Jelly Bean version of the Gallery App (see https://android.googlesource.com/platform/packages/apps/Gallery2 ) to my app and I want to make it available for Gingerbread as well (API 10). From what I understood, the native C code should run starting with API 9 (`APP_PLATFORM := android-9` in Application.mk). I have managed to cut out a special effect image filter and call it from my own App. This runs fine with Android 4.1 (Nexus S) and 4.2 (Galaxy Nexus) but it crashes with the infamous signal 11 (SIGSEV) error when I run it on an Android 2.3.5 device (HTC Wildfire S). The code looks like this:


void JNIFUNCF(ImageFilterFx, nativeApplyFilter, jobject bitmap, jint width, jint height, jobject lutbitmap,jint lutwidth, jint lutheight ) 

char* destination = 0; 
char* lut = 0; 
AndroidBitmap_lockPixels(env, bitmap, (void**) &destination); 
AndroidBitmap_lockPixels(env, lutbitmap, (void**) &lut); 

unsigned char * rgb = (unsigned char * )destination;
unsigned char * lutrgb = (unsigned char * )lut; 

int lutdim_r = lutheight;
int lutdim_g = lutheight;; 
int lutdim_b = lutwidth/lutheight;; 
int STEP = 4; 

float scale_R = (lutdim_r-1.f)/256.f;
float scale_G = (lutdim_g-1.f)/256.f; 
float scale_B = (lutdim_b-1.f)/256.f; 

int i;
int len = width * height * STEP; 

for (i = 0; i < len; i+=STEP)

    int r = rgb[i]; 
    int g = rgb[i+1]; 
    int b = rgb[i+2]; 

    float fb = b*scale_B;
    float fg = g*scale_G; 
    float fr = r*scale_R; 

    int lut_b = (int)fb;
    int lut_g = (int)fg; 
    int lut_r = (int)fr; 

    int p = lut_r+lut_b*lutdim_r+lut_g*lutdim_r*lutdim_b; 
    p*=STEP; 

    float dr = fr-lut_r;
    float dg = fg-lut_g; 
    float db = fb-lut_b; 

    rgb[i] = clamp(interp(lutrgb,p ,off,dr,dg,db));
    rgb[i+1] = clamp(interp(lutrgb,p+1,off,dr,dg,db)); 
    rgb[i+2] = clamp(interp(lutrgb,p+2,off,dr,dg,db)); 


AndroidBitmap_unlockPixels(env, bitmap);
AndroidBitmap_unlockPixels(env, lutbitmap); 
}

The arguments of the function are a bitmap and a transformation image (called lutbitmap), which is applied in a transformation on every pixel (in the for loop), for red(i), green(i+1) and blue(i+2). The segmentation fault appears on the line
      int r = rgb[i];
sometime in the middle of the image (for a 432 x 648 px image, it happens when i = 561144). I have tried it with a smaller resolution image (216 x 324 px) too and it still crashes during the run:

I/DEBUG   ( 7023): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG   ( 7023): Build fingerprint: 'htc_europe/htc_marvel/marvel:2.3.5/GRJ90/197017.3:user/release-keys'
I/DEBUG   ( 7023): pid: 7552, tid: 7552  >>> com.projecta.shirtagram <<<
I/DEBUG   ( 7023): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 45910000
I/DEBUG   ( 7023):  r0 0000001a  r1 be8f5254  r2 203af046  r3 80401e58
[......]
I/DEBUG   ( 7023):  d14 0000000000000000  d15 0000000000000000
I/DEBUG   ( 7023):  scr 60000012
I/DEBUG   ( 7023): 
I/DEBUG   ( 7023):          #00  pc 00001e5c  /data/data/com.projecta.shirtagram/lib/libjni_filtershow_filters.so
I/DEBUG   ( 7023):          #01  pc 00018374  /system/lib/libdvm.so
I/DEBUG   ( 7023):          #02  pc 00001624  /data/data/com.projecta.shirtagram/lib/libjni_filtershow_filters.so
I/DEBUG   ( 7023): 
I/DEBUG   ( 7023): code around pc:
I/DEBUG   ( 7023): 80401e3c ebfffd59 e59f7120 e1a03004 e51b1068 
[.......]
I/DEBUG   ( 7023): 
I/DEBUG   ( 7023): code around lr:
I/DEBUG   ( 7023): afa01194 00002044 1c0eb5f8 24091c15 dc0f2803 
[.......]
I/DEBUG   ( 7023): 
I/DEBUG   ( 7023): stack:
I/DEBUG   ( 7023):     be8f5238  00000000  
I/DEBUG   ( 7023):     be8f523c  afd11074  /system/lib/libc.so
I/DEBUG   ( 7023):     be8f5240  002dfeb8  
[................................................................]

I do not understand why this happens. The rgb pointer is set to the memory space allocated by the AndroidBitmap_lockPixels() method, so that space in memory should be safe to access. Is this a Gingerbread problem or maybe a device (HTC Wildfire S) problem? Has anyone ever since anything similar? I have searched all over the internet and haven't found anything that might indicate this code should not work under Gingerbread.

I would appreciate any help or advice on this problem.

Thank you,

Stefan

--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To post to this group, send email to andro...@googlegroups.com.
To unsubscribe from this group, send email to android-ndk...@googlegroups.com.
Visit this group at http://groups.google.com/group/android-ndk?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Stefan Anca

unread,
Jan 28, 2013, 5:01:45 AM1/28/13
to andro...@googlegroups.com
Hi David,

You are totally right, thanks! I used the following code and figured
out the config of my Bitmap was indeed RGB_565:

int ret;
AndroidBitmapInfo bitmapinfo;

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

LOGE("bitmap image :: width is %d; height is %d; stride is %d;
format is %d;flags is %d",
bitmapinfo.width,bitmapinfo.height,bitmapinfo.stride,bitmapinfo.format,bitmapinfo.flags);
if (bitmapinfo.format == ANDROID_BITMAP_FORMAT_RGBA_8888)
{
LOGE("Bitmap format is RGBA_8888 !");
} else if (bitmapinfo.format == ANDROID_BITMAP_FORMAT_RGB_565)
{
LOGE("Bitmap format is RGB_565 !");
} else if (bitmapinfo.format == ANDROID_BITMAP_FORMAT_RGBA_4444)
{
LOGE("Bitmap format is RGBA_4444 !");
}

I tried to copy the bitmap in Java code with the RGBA_8888 config (
Bitmap copy = originalImage.copy( Bitmap.Config.ARGB_8888, true ); )
and then make the call to native code and it doesn't crash anymore.
However, the image filter results are quite bad. Can it be that the
image taken by the device camera loses quality if it's transformed
from RGB_565 to RGBA_8888?

Stefan
Reply all
Reply to author
Forward
0 new messages