oli*_*dev 6 c++ java-native-interface android
我想使用JNI for Android Development将位图从Android传递到C++.
在Java中,我调用此函数将Bitmap从Java发送到C++:
public native int sendMyBitmap(Bitmap bitmap);
Run Code Online (Sandbox Code Playgroud)
在JNI中,我这样做了:
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);
}
Run Code Online (Sandbox Code Playgroud)
在C++ JNI中保存位图后,Java和C++中的位图是不同的.我正在努力找出问题所在,我该如何找到问题所在.
这行:
fwrite(img + (w * (h - i - 1)*3), 3, w, f);
Run Code Online (Sandbox Code Playgroud)
您假设输入 BITMAP 每个像素有 24 位(3 字节)。但android中没有这种像素格式。
您还假设宽度恰好为 640 像素,高度恰好为 480 像素。对于您的情况来说,这可能是事实,但您应该阅读此信息,而不是对值进行硬编码。
所有这些值均由函数提供AndroidBitmap_getInfo()。你为什么不使用它们?只需检查结构AndroidBitmapInfo:
typedef struct {
uint32_t width;
uint32_t height;
uint32_t stride;
int32_t format;
uint32_t flags; // 0 for now
} AndroidBitmapInfo;
Run Code Online (Sandbox Code Playgroud)
您可以直接读取位图的尺寸。此外,您应该检查参数format,它可以是以下值之一:
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,
};
Run Code Online (Sandbox Code Playgroud)
你看?没有RGB_888格式。您应该确保从 Java co C++ 以像素格式发送位图RGBA_8888,并相应地修改您的算法。我认为将输出像素格式更改为 32 位(而不是 24 位)会更容易。