我一直在努力将JNI中的CV:Mat作为Java字节[]发送回去,以便可以使用BitmapFactory.decode()成功解码。当我第一次从Java端引入byte[]数组(使用来自Android位图的数据构造)时,我能够成功地在c++ OpenCV函数中使用它。我通过从传入的byte[]构建一个Mat并在Mat上调用cv::imdecode来实现这一点。
问题来了,当我回到Android,并试图使用BitmapFactory解码字节数组为Android位图。它返回null,这表明在解码中存在问题。在我从JNI返回之前,我是否错误地执行操作?我是否需要使用cv::imencode,因为我必须使用cv::imdecode对输入字节[]?
任何和所有的帮助感谢!代码示例如下,我从JNI中的Mat转换我需要的数据。
注我知道使用Apache Android_Bitmap函数,但使用字节数组是我目前正在工作的要求。
//inData is a char* pointer that is set to a char* cast of the jbyte* pointer for the
// incoming Array.
cv::Mat inMat = cv::Mat(rows, columns, CV_8UC4, inData);
cv::Mat decodedMat = cv::imdecode(inMat, 1);
//convertImage is a function that changes the color space from BGR to Gray and then Gray to
//RGB.
convertImage(decodedMat, decodedMat);
cv::cvtColor(decodedMat, decodedMat, CV_RGB2RGBA);
jbyteArray jDataArray = env->NewByteArray(pixelDataLength);
env->SetByteArrayRegion(jDataArray,0,pixelDataLength,(jbyte*)decodedMat.data);
env->SetObjectField(in,dataArray,jDataArray);
env->ReleaseByteArrayElements(pixelData, bytePointerForIn, 0);
BitmapFactory期望提供给它的数据是已知的文件格式,但是您传递给它的是原始像素。您可以通过调用cv::imencode来使其工作,但也许从原始像素数据加载图像的更自然的解决方案是将原始Java位图对象创建为可变的,然后调用copyPixelsToBuffer和copyPixelsFromBuffer方法来获取和设置该对象中的像素数据。
解决!这是我通过使用Bitmap.compress()发送字节的原始版本的组合,然后使用copyPixelsFromBuffer返回像素。谢谢Buddy给我指了正确的方向。
Android:
//input was the original bitmap that was used to construct the byte[] array. I then used input.compress() in JPEG format to a Byte. Very important for it to be compressed in a format that will be recognized in cv::imdecode.
ByteArrayOutputStream bos = new ByteArrayOutputStream();
input.compress(CompressFormat.JPEG, 100, bos);
data1.pixelData = bos.toByteArray();
...
//Reconstruction after JNI call
ByteBuffer buffer2 = ByteBuffer.wrap(data1.pixelData);
Bitmap returnFromConvert = Bitmap.createBitmap(input.getWidth(),
input.getHeight(),Bitmap.Config.ARGB_8888);
returnFromConvert.copyPixelsFromBuffer(buffer2);