JNI:RGB565位图到灰度 - 如何将JNI更改的数据传递回Java
JNI: RGB565 Bitmap to Grayscale - how to pass in JNI changed data back to Java?
在JNI中,我有一个指向8位整数数组(uint8_t*)的指针。我想将其数据传递给 Java 部分。
我的问题是,数组中的数据必须是uint_8格式,因为我从格式为 RGB565 的位图中实现了它的颜色信息,我想将其更改为灰度:
爪哇部分:
private void loadJPEG(String fileName) {
Bitmap old = BitmapFactory.decodeFile(fileName);
Bitmap bmp = old.copy(Config.RGB_565, false);
byte[] grayScaledBitmap = new byte[]{};
if (bmp != null && bmp.getConfig() == Bitmap.Config.RGB_565) {
ShortBuffer rgbBuf = ShortBuffer.allocate(bmp.getWidth() * bmp.getHeight());
bmp.copyPixelsToBuffer(rgbBuf);
grayScaledBitmap = convertToLum(rgbBuf.array(), bmp.getWidth(), bmp.getHeight());
}
}
private native byte[] convertToLum(short[] data, int w, int h);
C++部分:
void convertRGB565ToGrayScale(JNIEnv* env, uint8_t* src, unsigned int srcWidth, unsigned int srcHeight, uint8_t* dst) {
unsigned int size = srcWidth * srcHeight;
uint16_t rgb;
uint16_t r;
uint16_t g;
uint16_t b;
for (unsigned int i = 0; i < size; i++) {
rgb = ((uint16_t*) src)[i];
uint16_t tmp = (uint16_t) (rgb & 0xF800);
tmp = tmp >> 8;
r = (uint16_t) ((rgb & 0xF800) >> 8); //to rgb888
g = (uint16_t) ((rgb & 0x07E0) >> 3);
b = (uint16_t) ((rgb & 0x001F) << 3);
dst[i] = (uint8_t) (((r << 1) + (g << 2) + g + b) >> 3); //to grayscale
}
}
JNIEXPORT jbyteArray JNICALL Java_com_qualcomm_loadjpeg_LoadJpeg_convertToLum(JNIEnv* env, jobject obj, jshortArray img, jint w, jint h) {
jshort* jimgData = NULL;
jboolean isCopy = 0;
jbyte* grayScaled;
jbyteArray arrayToJava
DPRINTF("%s %dn", __FILE__, __LINE__);
if (img != NULL) {
// Get data from JNI
jimgData = env->GetShortArrayElements(img, &isCopy);
uint8_t* lum = (uint8_t*) fcvMemAlloc(w * h, 16);
convertRGB565ToGrayScale(env, (uint8_t*) jimgData, w, h, lum);
grayScaled = (jbyte*) lum;
arrayToJava = env->NewByteArray(w*h);
env->SetByteArrayRegion(arrayToJava, 0, w*h, grayScaled);
env->ReleaseShortArrayElements(img, jimgData, JNI_ABORT);
fcvMemFree(lum);
DPRINTF("%s %d Donen", __FILE__, __LINE__);
}
return arrayToJava;
}
该错误与 SetShortArrayRegion 函数有关:
No source available for memcpy() at [hexadecimal adress]
No source available for ioctl() at ...
编辑>>上面的错误不再出现,它是由于通过 fcvmemfree 释放内存错误引起的,代码被重新编辑。我仍然有一个问题,用convertRGB565ToGrayScale的数据填充jbyteArray arrayToJava,在SetByteArrayRegion调用后它总是空的。问题仍然是:
我应该如何将更改的数据传递给 Java 部分?
jshort
相当于 16 位整数。 uint8_t
是 8 位无符号字符类型:
http://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/types.html
http://en.cppreference.com/w/c/types/integer
因此,您不能只将一种指针类型转换为另一种指针类型,尤其是不同大小类型的指针类型。 有一个严格的混叠规则的问题,可能会发挥作用:
什么是严格的混叠规则?
因此,您应该尝试使用int16_t
作为类型。 根据上述链接中的 JNI 文档,这与jshort
的定义相匹配。
您的问题不在于转换数据类型,而在于您过早释放缓冲区。 convertRGB565ToGrayScale
不会为输出分配任何新缓冲区,而是将输出数据写入调用方提供的缓冲区。convertRGB565ToGrayScale
返回后,grayScaled
指向与 lum
相同的缓冲区。由于grayScaled
使用时间较晚,因此请将fcvMemFree
调用移至 SetShortArrayRegion
之后。
其次,不要在 C++ 函数中创建新的 arrayToJava
对象,而是使用您传入的对象。(然后你需要在java端为正确的大小分配它,如grayScaledBitmap = new byte[bmp.getWidth() * bmp.getHeight()]
)。当您覆盖一个函数中的变量时,它不会在调用函数时更改同一变量。
- 防止主数据类型C++的隐式转换
- 用于访问容器<T>数据成员的正确 API
- 嵌套在类中时无法设置成员数据
- 使用流处理接收到的数据
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 在cuda线程之间共享大量常量数据
- C++将文本文件中的数据读取到结构数组中
- 通过JNI传递数据数组的最快方法是什么
- 如何将两个 jlong 数据类型转换为 jstring,然后将两个字符串连接在一起以便从 JNI 将字符串返回给 jav
- 将 JSON 对象作为参数在 JNI 中传递给 CPP,并在 CPP 中检索 JSON 对象的数据
- 准备要传递给 jni 的位图字节 [] 数据
- 如何使用JNI将数据传递到构造函数
- 如何使用JNI + OpenCV + NDK获取原始的android相机传感器图像数据
- 使用 JNI 通过从C++到 Java 的指针返回数据
- JNI:如何将一组数据从c++转换为Java
- JNI:RGB565位图到灰度 - 如何将JNI更改的数据传递回Java
- 通过 JNI 的数据未正确传递
- Android & JNI 如何将 Byte[] 数据数组传递给 JNI 并取回 Byte []
- 如何使用jni在c++中将数据从javaInputStream移动到char*