How to pass a bitmap from Java to C++ with JNI in Android Development?

android, c++, java-native-interface

Solution

This line:

fwrite(img + (w * (h - i - 1)*3), 3, w, f);

You are assuming the input BITMAP has 24 bites (3 bytes) per pixel. But there is no such pixel format in android.

You also are assuming the width is exactly 640 pixels and the height is exactly 480 pixels. This can be truth in your case, but you should read this information, not hardcode the values.

All these values are provided by the function `AndroidBitmap_getInfo()`. Why are you not using them? Just check the structure `AndroidBitmapInfo`:

typedef struct {
    uint32_t    width;
    uint32_t    height;
    uint32_t    stride;
    int32_t     format;
    uint32_t    flags;      // 0 for now
} AndroidBitmapInfo;

You can directly read the dimensions of your bitmap. Additionally you should check the parameter `format`, which can be one of these values:

enum AndroidBitmapFormat {
    ANDROID_BITMAP_FORMAT_NONE      = 0,
    ANDROID_BITMAP_FORMAT_RGBA_8888 = 1,
    ANDROID_BITMAP_FORMAT_RGB_565   = 4,
    ANDROID_BITMAP_FORMAT_RGBA_4444 = 7,
    ANDROID_BITMAP_FORMAT_A_8       = 8,
};

You see? There is no `RGB_888` format. You should ensure you are sending the bitmap in `RGBA_8888` pixel format from Java co C++ and modify your algorithm accordingly. I think it would be easier to change the output pixel format to 32 bits (instead of 24 bits).

Problem

I would like to pass a bitmap from Android to C++ using JNI for Android Development. In Java, I call this function to send a Bitmap from Java to C++: ``` public native int sendMyBitmap(Bitmap bitmap); ``` in JNI, I have done it like this: ``` JNIEXPORT void JNICALL sendMyBitmap(JNIEnv * env, jobject obj, jobject bitmap) { AndroidBitmapInfo androidBitmapInfo ; void* pixels; AndroidBitmap_getInfo(env, bitmap, &androidBitmapInfo); AndroidBitmap_lockPixels(env, bitmap, &pixels); unsigned char* pixelsChar = (unsigned char*) pixels; saveImage(pixelsChar); } void saveImage(unsigned char* img) { FILE *f; int w = 640, h = 480; int filesize = 54 + 3*w*h; //w is your image width, h is image height, both int unsigned char bmpfileheader[14] = {'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0}; unsigned char bmpinfoheader[40] = {40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0}; unsigned char bmppad[3] = {0,0,0}; bmpfileheader[ 2] = (unsigned char)(filesize ); bmpfileheader[ 3] = (unsigned char)(filesize>> 8); bmpfileheader[ 4] = (unsigned char)(filesize>>16); bmpfileheader[ 5] = (unsigned char)(filesize>>24); bmpinfoheader[ 4] = (unsigned char)( w ); bmpinfoheader[ 5] = (unsigned char)( w>> 8); bmpinfoheader[ 6] = (unsigned char)( w>>16); bmpinfoheader[ 7] = (unsigned char)( w>>24); bmpinfoheader[ 8] = (unsigned char)( h ); bmpinfoheader[ 9] = (unsigned char)( h>> 8); bmpinfoheader[10] = (unsigned char)( h>>16); bmpinfoheader[11] = (unsigned char)( h>>24); f = fopen("/storage/test.png","wb"); fwrite(bmpfileheader,1,14,f); fwrite(bmpinfoheader,1,40,f); for(int i=0; i<h; i++) { fwrite(img+(w*(h-i-1)*3),3,w,f); fwrite(bmppad,1,(4-(w*3)%4)%4,f); } fflush(f); fclose(f); } ``` After saving the bitmap in C++ JNI, the bitmaps in Java and in C++ are different. I am struggling to find out what is the problem and how can I find the problem.

Original source