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.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With