BitmapFactory.decodeByteArray()返回NULL

时间:2010-07-26 19:24:23

标签: java android image format camera

我正在使用相机中的previewCallback尝试抓取图像。这是我正在使用的代码

private Camera.PreviewCallback mPrevCallback = new Camera.PreviewCallback() 
{
        public void onPreviewFrame( byte[] data, Camera Cam ) {
                Log.d("CombineTestActivity", "Preview started");
                Log.d("CombineTestActivity", "Data length = " 
                        + data.length );
                currentprev = BitmapFactory.decodeByteArray( data, 0, 
                        data.length );

               if( currentprev == null )
                   Log.d("CombineTestActivity", "currentprev is null" );

                Log.d("CombineTestActivity", "Preview Finished" );

        }
};

数据的长度总是与576000相同。

此外,我尝试更改相机的参数,以便图像以不同的格式返回。这就是我这样做的样子。

mCamera = Camera.open();
camParam = mCamera.getParameters();
camParam.setPreviewFormat( ImageFormat.RGB_565 );
mCamera.setParameters( camParam );
    mCamera.setPreviewCallback( mPrevCallback );

然而,当我更改预览格式并将其保留为NV21的默认格式时,BitmapFactory.decodeByteArray将返回null。我也尝试将预览格式更改为JPEG类型。我甚至在ddms中得到了一个调试语句,这就是我得到的

“D / skia(14391):--- SkImageDecoder :: Factory返回null”

6 个答案:

答案 0 :(得分:41)

好的,希望这会有所帮助。

搜索互联网寻找快速解决方案,并找到了完美的东西。

适用于Android 2.1

感谢来自this page的off3nsiv3。

// Convert to JPG
Size previewSize = camera.getParameters().getPreviewSize(); 
YuvImage yuvimage=new YuvImage(data, ImageFormat.NV21, previewSize.width, previewSize.height, null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvimage.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 80, baos);
byte[] jdata = baos.toByteArray();

// Convert to Bitmap
Bitmap bmp = BitmapFactory.decodeByteArray(jdata, 0, jdata.length);

对off3nsiv3的代码稍作修改就可以了。与手动解码相比,FPS仍然非常高。

对于上面的代码,80是jpeg质量(0表示100,100表示​​最佳)。

答案 1 :(得分:7)

你可以尝试这个并且它正在工作......

mCamera.setOneShotPreviewCallback(new Camera.PreviewCallback() {
                @Override
                public void onPreviewFrame(byte[] data, Camera camera) {
                    Camera.Parameters parameters = camera.getParameters();
                    int format = parameters.getPreviewFormat();
                    //YUV formats require more conversion
                    if (format == ImageFormat.NV21 || format == ImageFormat.YUY2 || format == ImageFormat.NV16) {
                        int w = parameters.getPreviewSize().width;
                        int h = parameters.getPreviewSize().height;
                        // Get the YuV image
                        YuvImage yuv_image = new YuvImage(data, format, w, h, null);
                        // Convert YuV to Jpeg
                        Rect rect = new Rect(0, 0, w, h);
                        ByteArrayOutputStream output_stream = new ByteArrayOutputStream();
                        yuv_image.compressToJpeg(rect, 100, output_stream);
                        byte[] byt = output_stream.toByteArray();
                        FileOutputStream outStream = null;
                        try {
                            // Write to SD Card
                            File file = createFileInSDCard(FOLDER_PATH, "Image_"+System.currentTimeMillis()+".jpg");
                            //Uri uriSavedImage = Uri.fromFile(file);
                            outStream = new FileOutputStream(file);
                            outStream.write(byt);
                            outStream.close();
                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        } finally {
                        }
                    }
                }

答案 2 :(得分:3)

我正在尝试做同样的事情。基于讨论herehere,听起来人们从Android 2.1 / 2.2开始就没有幸运decodeByteArray()来处理NV21格式。它绝对不适用于我的模拟器或我的Droid Incredible,虽然我认为这会调用本机代码,因此它可能会在某些手机上运行,​​具体取决于驱动程序?

作为替代方案,您可以尝试使用Java自己解码NV21(请参阅上面的链接以获取示例),尽管这对于大多数情况来说显然太慢而无法使用。我没有太多运气试图让CameraPreview发送不同的格式,我希望这对于尝试编写可在不同硬件上移植的代码是有问题的。如果你在NDK中编写了NV21解码方法,你可能会稍微提高帧速率。

显然,在尝试处理CameraPreview时,由于竞争条件存在稳定性问题,尽管我自己没有证实这个问题。我认为您可以通过使用Android 2.1 / 2.2中添加的缓冲预览回调方法setPreviewCallbackWithBuffer()来避免这种情况并提高帧速率。这是在2.1中添加的,但保持隐藏直到2.2。 To use it in 2.1 you need to hack around the hiding.

有些人建议使用MediaRecorder代替CameraPreview。不幸的是,MediaRecorder似乎提供的预览图片比CameraPreview更少,所以我不推荐这条路线。

答案 3 :(得分:1)

从我之前的回答中更新,但请注意Qix的答案,看起来更简单

我实际上在纯Java中解码效果不错。只要预览大小不是太大,帧速率大约为10-15 fps。可悲的是,我的Droid公司的Android 2.3更新似乎已经取消了一些较小的预览尺寸选项:(。我也试过在我从另一个项目中提取的本机代码中执行此操作,但这是错误的,似乎没有任何更快对于我正在进行的相对简单的处理,所以我没有进一步追求它。请参阅my Github获取源代码(包括Java和本机)。

答案 4 :(得分:0)

这对我有用...

 private Camera.PreviewCallback getPreviewCallback() {
    Log.d("TAG", "previewCallBack ==> " + "getPreviewCallback");
    Camera.PreviewCallback previewBitmap = new Camera.PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            Camera.Size previewSize = camera.getParameters().getPreviewSize();
            YuvImage yuvimage=new YuvImage(data, ImageFormat.NV21, previewSize.width, previewSize.height, null);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            yuvimage.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 80, baos);
            byte[] jdata = baos.toByteArray();
            // Convert to Bitmap
            Bitmap bitmap = BitmapFactory.decodeByteArray(jdata, 0, jdata.length);
            Log.d("TAG", "BITMAP ==> " + bitmap);
            runModelInference(bitmap);
        }
    };

    return previewBitmap;
}

答案 5 :(得分:-1)

尝试如下:

    public Bitmap stringtoBitmap(String string) {
    Bitmap bitmap = null;
    try {
        YuvImage yuvimage = new YuvImage(base64.getBytes(),ImageFormat.YUY2, 120, 30, null);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        yuvimage.compressToJpeg(new Rect(0, 0, 20, 20), 100, baos);
        byte[] jdata = baos.toByteArray();
        bitmap = BitmapFactory.decodeByteArray(jdata, 0, jdata.length);
    } catch (Exception e) {

    }
    return bitmap;
}
相关问题