Android OpenCV中传出byte []需要cv :: imencode吗?

时间:2014-03-28 21:44:31

标签: android c++ opencv java-native-interface bitmapfactory

我一直在努力发回CV:JNI中的Mat作为Java字节[],以便可以使用BitmapFactory.decode()成功解码。当我第一次从Java端引入我的byte []数组(使用来自Android Bitmap的数据构建)时,我能够在C ++ OpenCV函数中成功使用它。我是通过在byte []中构建一个Mat并在Mat上调用cv :: imdecode来实现的。

当我返回Android并尝试使用BitmapFactory将字节数组解码为Android Bitmap时,问题就出现了。它返回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);

2 个答案:

答案 0 :(得分:1)

BitmapFactory期望提供给它的数据是已知的文件格式,但是你传递的是原始像素。您可以通过调用cv :: imencode使其工作,但是从原始像素数据加载图像的更自然的解决方案是将原始Java Bitmap对象创建为可变,然后调用copyPixelsToBuffer和copyPixelsFromBuffer方法来获取和设置该对象中的像素数据。

答案 1 :(得分:0)

解决!它是我使用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);