BitmapFactory.decodeByteArray() 返回 NULL

发布于 2024-09-11 15:27:28 字数 1174 浏览 7 评论 0原文

我正在使用相机的预览回调来尝试抓取图像。这是我使用的代码,

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 returned null”

I am using the previewCallback from the camera to try and grab images. Here is the code I am using

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" );

        }
};

the length of the data always comes otu the same as 576000.

Also I have tried changing the parameters of the camera so the image comes back as different formats. Here is what it looks like when I do that.

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

However both when I change the preview format and when I leave it as its default of NV21, BitmapFactory.decodeByteArray comes back as null. I have also tried changing the preview format to JPEG type. I even get a debug statement in the ddms, this is what I get

"D/skia (14391): --- SkImageDecoder::Factory returned null"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

单挑你×的.吻 2024-09-18 15:27:29

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

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

此功能从 Android 2.1 开始运行

感谢 的 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 质量(100 中的 0,100 最好)。

Alright, hopefully this will help.

Scoured the internet looking for a fast solution, and found the perfect thing.

This works as of Android 2.1

Thanks to off3nsiv3 from this page.

// 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);

Just a little modification to off3nsiv3's code and you're set. The FPS is still incredibly high compared to manual decoding.

For the above code, the 80 is the jpeg quality (0 from 100, 100 being best).

(り薆情海 2024-09-18 15:27:29

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

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

you can try this and it is working...

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 {
                        }
                    }
                }
夏末 2024-09-18 15:27:29

我正在尝试做同样的事情。基于此处的讨论以及这里,听起来人们没有运气得到< code>decodeByteArray() 来处理 Android 2.1/2.2 起的 NV21 格式。它绝对无法在我的模拟器或我的 Droid Incredible 上工作,尽管我认为这会调用本机代码,因此它可能会在某些手机上工作,具体取决于驱动程序?

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

显然,在尝试处理 CameraPreview 时,由于竞争条件也存在稳定性问题,尽管我自己还没有确认这个问题。我认为您可以避免这种情况,并通过使用 Android 2.1/2.2 中添加的缓冲预览回调方法 setPreviewCallbackWithBuffer() 来提高帧速率。这是在 2.1 中添加的,但一直隐藏到 2.2 为止。 要在 2.1 中使用它,你需要绕过隐藏。

有些人建议使用 MediaRecorder 而不是 CameraPreview。不幸的是,MediaRecorder 提供的获取预览帧的功能似乎比 CameraPreview 还要少,因此我不能推荐该路线。

I'm trying to do the same thing. Based on the discussions here and here, it sounds like people have not had luck getting decodeByteArray() to handle NV21 format as of Android 2.1/2.2. It definitely doesn't work in my emulator or on my Droid Incredible, although I think this calls native code so it may work on some phones depending on the drivers?

As an alternative, you can try to decode the NV21 yourself in Java (see link above for an example), although this is apparently too slow to be useful for most cases. I haven't had much luck trying to get CameraPreview to send a different format either, and I would expect this to be problematic for trying to write code that is portable across different hardware. If you wrote the NV21 decode methods in NDK you might get the framerate up a bit.

Apparently there are stability problems due to race conditions in trying to process the CameraPreview too, although I haven't confirmed this issue myself. I think you might avoid this and also get your framerate up a bit by using the buffered preview callback method setPreviewCallbackWithBuffer() that was added in Android 2.1/2.2. This was added in 2.1 but was left hidden until 2.2. To use it in 2.1 you need to hack around the hiding.

Some people have suggested using MediaRecorder instead of CameraPreview. Unfortunately, MediaRecorder appears to have even less provided for getting preview frames than CameraPreview, so I can't recommend that route.

允世 2024-09-18 15:27:29

这对我有用......

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

This is working for me...

 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;
}
寂寞美少年 2024-09-18 15:27:29

更新了我之前的答案,但请注意 Qix 的答案,它看起来更简单

实际上,我在纯 Java 中进行解码得到了不错的结果。只要预览尺寸不太大,帧速率约为 10-15 fps。遗憾的是,我的 Droid Inc 的 Android 2.3 更新似乎取消了一些较小的预览尺寸选项:(。我也尝试使用从另一个项目中提取的本机代码来完成此操作,但这有问题,而且似乎并没有更快对于我正在做的相对简单的处理,所以我没有进一步追求它的源代码。 (Java 和本机)。

Update from my earlier answer, but note Qix's answer, which looks simpler

I've actually had decent results with decoding in pure Java. Framerates around 10-15 fps as long as the preview size is not too big. Sadly the Android 2.3 update to my Droid Inc seems to have taken away some of the smaller preview size options :(. I also tried doing it in native code that I pulled from another project, but this was buggy and didn't seem any faster for relatively simple processing I was doing, so I didn't pursue it further. See my Github for the source (both Java and native).

┊风居住的梦幻卍 2024-09-18 15:27:29

尝试如下:

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

try it like follow:

    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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文