JNI:来自 unsigned char* 的位图始终为 null
JNI: Bitmap from unsigned char* always null
我想将图像(通过 jni)从 C++ 传递到 android 应用程序。我从 unsigned char*
数组开始。这个数组没有任何损坏;我什至可以将它保存到 ppm
文件中并在我的笔记本电脑上正确显示它。
然后,我使用此函数将其转换为 jByteArray
:
jbyteArray imgByte=as_byte_array(env,imgRaw,img.getRawImageSize());
...
jbyteArray as_byte_array(JNIEnv *env, unsigned char* buf, int len) {
jbyteArray array = env->NewByteArray (len);
env->SetByteArrayRegion (array, 0, len, reinterpret_cast<jbyte*>(buf));
return array;
}
之后,我把这个jByteArray
发到java那边。该变量已正确填充,正如我通过在 LogCat:
上打印其十六进制值所见
07-01 18:02:45.941 7017-8238/com.myapp.myapp W/C++ side﹕ 798a95798b9677889371838d6b7d8664757e5d6e7860717b5e...
07-01 18:02:46.941 7017-8238/com.myapp.myapp W/Java side﹕ 798a95798b9677889371838d6b7d8664757e5d6e7860717b5e...
最后一步是在 ImageView 上显示它。为此,我做了以下代码(取自另一个关于 SO 的问题):
public void setImageViewWithByteArray(final ImageView view, byte[] data) {
final Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
if (bitmap==null) {
Log.e(TAG,"Bitmap is NULL!");
view.setImageResource(R.drawable.abc_btn_radio_material);
}
else {
view.setImageBitmap(bitmap);
}
}
});
}
但是 bitmap
变量总是 null
。我究竟做错了什么?有没有办法调试 decodeByteArray
?
BitmapFactor.decodeByteArray 用于解码压缩 图像数据,例如 PNG 文件的内容。
如果您的字节数组包含未压缩的 RGB 数据,那么您可以 create a mutable Bitmap of the correct width and height and then set the pixels using Bitmap.setPixels。但是,setPixels 采用具有 32 位 ARGB 值的整数数组,并且从您的日志看来,您的字节数组包含每像素 3 个字节的 RGB 数据。
因此您需要创建一个 int 数组,然后处理您的字节数组并为每个字节三元组将一个 int 值写入 int 数组,例如:
intArray[i] = 0xff000000 |
(((int)data[i*3] & 255) << 16) | (((int)data[i*3+1] & 255) << 8) | ((int)data[i*3+2] & 255);
然后传给setPixels。或者你可以在 JNI 端和 return 一个 jintArray.
我想将图像(通过 jni)从 C++ 传递到 android 应用程序。我从 unsigned char*
数组开始。这个数组没有任何损坏;我什至可以将它保存到 ppm
文件中并在我的笔记本电脑上正确显示它。
然后,我使用此函数将其转换为 jByteArray
:
jbyteArray imgByte=as_byte_array(env,imgRaw,img.getRawImageSize());
...
jbyteArray as_byte_array(JNIEnv *env, unsigned char* buf, int len) {
jbyteArray array = env->NewByteArray (len);
env->SetByteArrayRegion (array, 0, len, reinterpret_cast<jbyte*>(buf));
return array;
}
之后,我把这个jByteArray
发到java那边。该变量已正确填充,正如我通过在 LogCat:
07-01 18:02:45.941 7017-8238/com.myapp.myapp W/C++ side﹕ 798a95798b9677889371838d6b7d8664757e5d6e7860717b5e...
07-01 18:02:46.941 7017-8238/com.myapp.myapp W/Java side﹕ 798a95798b9677889371838d6b7d8664757e5d6e7860717b5e...
最后一步是在 ImageView 上显示它。为此,我做了以下代码(取自另一个关于 SO 的问题):
public void setImageViewWithByteArray(final ImageView view, byte[] data) {
final Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
if (bitmap==null) {
Log.e(TAG,"Bitmap is NULL!");
view.setImageResource(R.drawable.abc_btn_radio_material);
}
else {
view.setImageBitmap(bitmap);
}
}
});
}
但是 bitmap
变量总是 null
。我究竟做错了什么?有没有办法调试 decodeByteArray
?
BitmapFactor.decodeByteArray 用于解码压缩 图像数据,例如 PNG 文件的内容。
如果您的字节数组包含未压缩的 RGB 数据,那么您可以 create a mutable Bitmap of the correct width and height and then set the pixels using Bitmap.setPixels。但是,setPixels 采用具有 32 位 ARGB 值的整数数组,并且从您的日志看来,您的字节数组包含每像素 3 个字节的 RGB 数据。
因此您需要创建一个 int 数组,然后处理您的字节数组并为每个字节三元组将一个 int 值写入 int 数组,例如:
intArray[i] = 0xff000000 |
(((int)data[i*3] & 255) << 16) | (((int)data[i*3+1] & 255) << 8) | ((int)data[i*3+2] & 255);
然后传给setPixels。或者你可以在 JNI 端和 return 一个 jintArray.