【问题标题】:BitmapFactory.decodeByteArray() is returning NULLBitmapFactory.decodeByteArray() 返回 NULL
【发布时间】:2011-03-21 06:36:46
【问题描述】:

我正在使用相机的 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 返回为空。我还尝试将预览格式更改为 JPEG 类型。我什至在 ddms 中得到了一个调试语句,这就是我得到的

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

【问题讨论】:

标签: java android image format camera


【解决方案1】:

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

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

这适用于 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 最好)。

【讨论】:

  • 有趣;你能发布帧率的比较吗?
  • 我可以,但在 LG Optimus C 上,FPS 几乎相同。在 HTC 上,FPS 是一样的。没有明显的滞后。
  • 真的有必要编码成jpeg(比较慢的操作)和解码回来(也慢)吗?
  • @VioletGiraffe 在撰写此答案时,确实没有更快的方法可以做到这一点。另外,如果您尝试一下,这是一个相对较快的操作;)没有其他方法可以将其转换为位图。
  • @Qix 我的图像变蓝了.. 我正在使用三星 s4 选项卡
【解决方案2】:

你可以试试这个,它正在工作......

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 {
                        }
                    }
                }

【讨论】:

    【解决方案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 提供的预览帧更少,所以我不能推荐这条路线。

    【讨论】:

    • 使用上面链接中的 NV21 解码,我能够获得像素,但在 HTC Droid Incredible 上的帧速率约为 1 帧/10 秒。但是,我相信对像素进行下采样可以使该帧速率达到某些应用程序可能可用的速度。
    【解决方案4】:

    这对我有用...

     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】:

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

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

      【讨论】:

        【解决方案6】:

        尝试如下:

            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;
        }
        

        【讨论】:

        • 您能更详细地解释您的方法吗?
        • 你为什么要吞下异常?不要那样做。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多