我正在为希望解压缩数据块的 Android 编写本机代码。我正在从本机 JNI 函数调用 Java 方法。这个 Java 方法调用 BitmapFactory,然后尝试分配一些内存:
int[] pixels = new int[width * height];
当程序似乎崩溃或停止或其他情况时,给我“spin on suspend”,然后在 VM 关闭之前在 logcat 中喷出很多东西。
只是为了在深入了解细节之前给出大图,我试图将压缩图像的字节数组转换为width*height*bpp
未压缩的图像以返回给本机代码。我正在尝试使用 Android Java BitmapFactory 进行似乎可以正常工作的解压缩。压缩的字节块是之前加载到本机代码中的 JPG 或 PNG 图像(在我的系统中无法从磁盘读取)。
序列有点复杂,我不确定什么是相关的,所以我会全部说出来:
class MyRenderer implements GLSurfaceView.Renderer
方法onSurfaceCreated
调用原生init()
,它在MyRenderer
类中定义:
static {System.loadLibrary("glprog");
}
public native void init(int dummy_variable);
在本机代码中,这是调用的函数:
JNIEXPORT void JNICALL Java_com_pitransviewersingleimageres_MyRenderer_init(JNIEnv * env, jobject obj, jint dummy_variable) {
glprog_init(dummy_variable);
}
然后调用另一个本机函数char glprog_init(int dummy_variable)
,该函数本身调用本机 wrapper_uncompress_image_by_os(overlay_compressed_data,overlay_compressed_data_len,... 这是本机函数:
char wrapper_uncompress_image_by_os(unsigned char *compressed_data, int compressed_len, //input compressed data
char *data_name_string, char *suffix, //name and type
int slot_num) {
jstring jnamestring = (*preset_env)->NewStringUTF(preset_env,data_name_string);
jstring jsuffix = (*preset_env)->NewStringUTF(preset_env,suffix);
//create byte[] and copy data in
jbyteArray retArray = (*preset_env)->NewByteArray(preset_env, compressed_len);
if(retArray==NULL) {__android_log_write(ANDROID_LOG_INFO, "NATIVE","ERROR wrapper_uncompress_image_by_os: calling NewByteArray()");return-1;}
jbyte *javaptr = (*preset_env)->GetPrimitiveArrayCritical(preset_env, (jarray)retArray, 0);
if(javaptr==NULL) {__android_log_write(ANDROID_LOG_INFO, "NATIVE","ERROR wrapper_uncompress_image_by_os: calling GetPrimitiveArrayCritical()");return-1;}
memcpy(javaptr,compressed_data,compressed_len);
(*preset_env)->ReleasePrimitiveArrayCritical(preset_env, retArray, javaptr, 0);
if((preset_javaobject!=NULL)&&(preset_method_id_convertimagefromnative!=NULL))
{
jthrowable exception;
//call java function
(*preset_env)->CallVoidMethod(preset_env, preset_javaobject,preset_method_id_convertimagefromnative,
retArray,compressed_len,
jnamestring,jsuffix,slot_num);
它调用了与nativeconvertImageFromNative()
相同的 Java 类中的方法。 MyRenderer
init()
public void convertImageFromNative(final byte[] data, int data_len, final String data_name_string, final String suffix, final int slot_num) {
//writeFile(data,data_name_string);
Bitmap bitmapqq=bytes2bitmap(data);
}
到目前为止,这似乎有效,如果我取消注释writeFile()
它会将所有数据正常写入我的 SD 卡。我有问题是在里面bytes2bitmap()
。
可以在“常规”Java 中调用该类bytes2bitmap()
,但是当从本机调用的 this 调用时,它会在该int[] pixels = new int[width * height];
行崩溃。
所以最后这里是导致崩溃的代码:
Bitmap bytes2bitmap(byte[] bytes) {
Log.d("startup", "Entered MyRenderer.bytes2bitmap()");
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inDither = true;
opt.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap=BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opt);
if(bitmap==null) Log.d("running", "ERROR: GLESActivity.java: BitmapFactory() returns null");
int width = bitmap.getWidth();
int height = bitmap.getHeight();
bytes=null; //not sure if I should be freeing memory here, but it seems to work
int[] pixels = new int[width * height]; //crash happens here
//crashes before doing the following
bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
pixels=null;
return bitmap;
}
我还没有完成将未压缩的数据正确地传递回本机代码的部分,但我认为我应该首先解决这个问题。
我可以在本机代码中创建一个int[]
数组来传递,问题是我不知道未压缩的图像大小。
在此先感谢,马克