从字节数组转换位图(byte []) - 位图仍为空

时间:2015-02-05 00:32:17

标签: android bitmap java-native-interface bytearray decode

我从我的应用程序的JNI部分检索了一个字节数组。 JNI的输入也是ARGB8888格式的摄像机位图图像的字节数组。 C ++使用FastCV函数将我的位图修改为灰度。这是我的代码:

爪哇:

private void fcvTest(String fileName) { //path to stored image 

        Bitmap bmp = BitmapFactory.decodeFile(fileName);
        //we are going from 32bit integer (ARGB8888) to 8bit byte (grayscale) => 4 * number of pixels:
        ByteBuffer argbBuf = ByteBuffer.allocate(bmp.getWidth() * bmp.getHeight() * 4); 
        bmp.copyPixelsToBuffer(argbBuf);
         byte[] grayBuffer = new byte[]{};
        grayBuffer = fcvGrayScale(argbBuf.array(), bmp.getWidth(), bmp.getHeight());


        Bitmap grayScaledPic = BitmapFactory.decodeByteArray(grayBuffer, 0, grayBuffer.length);

    }

private native byte[] fcvGrayScale(byte[] data, int w, int h);

C ++:

JNIEXPORT jbyteArray JNICALL Java_com_qualcomm_loadjpeg_LoadJpeg_fcvGrayScale(JNIEnv* env, jobject obj, jbyteArray img, uint32_t w, uint32_t h) {

    jbyte* jImg;
    jboolean isCopy;
    jbyteArray grayToJava;
    jbyte* jbyteGray;

    jImg = env->GetByteArrayElements(img, &isCopy);
    uint8_t* uint8Gray = (uint8_t*) fcvMemAlloc(w*h*4, 16);

    fcvColorRGB888ToGrayu8((uint8_t*) jImg, w, h, 0, uint8Gray, 0);

    jbyteGray = (jbyte*) uint8Gray;
    grayToJava = env->NewByteArray(w*h); //no need for 4-more space for grayscale
    env->SetByteArrayRegion(grayToJava, 0, w*h, jbyteGray);

    env->ReleaseByteArrayElements(img, jImg, JNI_ABORT);
    fcvMemFree(uint8Gray);

    return grayToJava;
}

此处可以看到FastCV函数fcvColorRGB888ToGrayu8的文档: fcvColorRGB888ToGrayu8 doc

正如您在标题中看到的,我无法从JNI设置新的位图grayScaledPic。 Log cat给了我这个通常的陈述:

SkImageDecoder::Factory returned null

我的新数组grayBuffer中的字节似乎不合适,或者我忽略了一些问题,例如通过BitmapFactory.Options设置正确的位图格式。或者输入数组甚至可能是错误的,因为fcvColorRGB888ToGrayu8期望RGB888作为输入,但Android不支持这种格式。我是否必须先移除Alpha通道?

有人知道吗,还有什么意义呢?

已解决>>看到接受的答案

问题在于通过BitmapFactory.decodeByteArray解码字节数组 - 仅适用于压缩位图(JPEG,PNG)

1 个答案:

答案 0 :(得分:1)

问题在于您的Java代码:

Bitmap grayScaledPic = BitmapFactory.decodeByteArray(grayBuffer, 0, grayBuffer.length);

BitmapFactor.decodeByteArray()解码压缩图像,例如已加载到字节数组中的JPG或PNG文件。它不适用于原始未压缩数据。

要从灰度字节数组设置,您必须使用不同的方法。您可以转换为int数组,然后使用Bitmap.createBitmap()创建位图,例如:

final int pixCount = bmp.getWidth() * bmp.getHeight();
int[] intGreyBuffer = new int[pixCount];
for(int i=0; i < pixCount; i++)
{
    int greyValue = (int)greyBuffer[i] & 0xff;
    intGreyBuffer[i] = 0xff000000 | (greyValue << 16) | (greyValue << 8) | greyValue;
}
Bitmap grayScaledPic = Bitmap.createBitmap(intGreyBuffer, bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888);

另一种方法是从JNI代码而不是字节数组返回一个int数组,然后直接用Java从它创建位图。