在JNI中,我有一个指向8位整数数组(uint8_t *)的指针。我想将其数据传递给Java部分。
我的问题是,数组中的数据必须是uint_8格式,因为我是从格式为RGB565的位图中将其作为颜色信息实现的,我想将其转换为灰度:
Java部分:
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 %d\n", __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 Done\n", __FILE__, __LINE__);
}
return arrayToJava;
}
错误与SetShortArrayRegion函数一致:
No source available for memcpy() at [hexadecimal adress]
No source available for ioctl() at ...
编辑&gt;&gt;上面的错误不再出现,它是由于通过fcvmemfree释放内存不足造成的,代码是重新编辑的。使用convertRGB565ToGrayScale中的数据填充jbyteArray arrayToJava时仍然存在问题,在SetByteArrayRegion调用后它始终为空。问题仍然是:
我应该如何将更改的数据传递给Java部分?
答案 0 :(得分:0)
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
因此,您不能仅仅将一个指针类型转换为另一个指针类型,尤其是不同大小类型。存在严格别名规则的问题:
What is the strict aliasing rule?
所以你应该尝试使用int16_t
作为类型。根据上述链接中的JNI文档,这与jshort
定义的匹配。
答案 1 :(得分:0)
您的问题不在于转换数据类型,而在于您过早释放缓冲区这一事实。 convertRGB565ToGrayScale
不为输出分配任何新缓冲区,但将输出数据写入调用方提供的缓冲区。 convertRGB565ToGrayScale
返回后,grayScaled
指向与lum
相同的缓冲区。由于grayScaled
的使用时间较晚,因此请将fcvMemFree
来电转移到SetShortArrayRegion
之后。
其次,不要在C ++函数中创建一个新的arrayToJava
对象,而是使用你传入的对象。(然后你需要在java端分配正确的大小,如{ {1}})。当您在一个函数中覆盖变量时,它不会在调用函数时更改相同的变量。