BitmapFactory.decodeByteArray() is returning NULL
Asked Answered
D

6

21

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"

Diaghilev answered 26/7, 2010 at 19:24 Comment(2)
I went back and clicked the checkmarks next to some of the answers I've gotten on here. Thanks for the informationDiaghilev
Possible duplicate of Getting frames from Video Image in AndroidIsaacson
L
43

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).

Latinalatinate answered 24/9, 2011 at 1:40 Comment(5)
Interesting; could you post a comparison of framerates?Ill
I could, but on an LG Optimus C the FPS was pretty much the same. On an HTC the FPS was the same. There is no noticeable lag.Latinalatinate
Is it really necessary to encode to jpeg (relatively slow operation) and decode back (slow as well)?Parik
@VioletGiraffe There's really no faster way to do it as of this answer's writing. Plus, it is a relatively fast operation if you try it ;) There's no other way to get it to a bitmap.Latinalatinate
@Qix I am getting bluer image.. i am using Samsung s4 tabCryoscopy
L
7

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 {
                        }
                    }
                }
Leta answered 31/10, 2013 at 8:42 Comment(0)
I
3

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.

Ill answered 26/8, 2010 at 22:57 Comment(1)
Using the NV21 decode in the link above, I was able to get the pixels but with a frame rate of about 1 frame / 10 seconds on an HTC Droid Incredible. However, I believe downsampling the pixels can get this frame rate up to speeds that may be usable for some applications.Ill
R
2

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;
}
Rationalism answered 27/11, 2018 at 9:52 Comment(0)
I
1

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).

Ill answered 24/9, 2011 at 19:57 Comment(0)
C
-1

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;
}
Corpulent answered 13/7, 2013 at 12:44 Comment(2)
Would you explain your approach in more details?Here
Why are you swallowing exceptions? Don't do that.Latinalatinate

© 2022 - 2024 — McMap. All rights reserved.