Skip to content
Advertisement

Capture a picture in Android, and work with it using the ImageAnalyzer

I am trying to implement a solution that would be able to capture a picture from the phone’s camera, then operate the picture (do something with it) and repeat this process N times, quickly.

I have achieved this using the imageCapture.takePicture method, but when trying to implement the same process for N pictures, the onCaptureSuccess method is being called every ~500ms (on a solid Samsung device). The process of capturing and saving the picture lasts too long for me. I need it to be quicker than 500ms.

I was looking to implement it using the imageAnalyzer class, and used code similar to this:

private class CameraAnalyzer implements ImageAnalysis.Analyzer {
        
        @Override
        public void analyze(@NonNull ImageProxy image) {

            ByteBuffer bb = image.getPlanes()[0].getBuffer();
            byte[] buf = new byte[bb.remaining()];
            bb.get(buf);
            
            //raw - data container
            raw = buf;
            //runnable - operate the picture
            runnable.run();
            image.close();
        }
    }

But I am receiving NULL for buf and the picture is always empty. bb.rewind() did not help as well.

After being advised that the picture is coming in RAW format, and thus need to convert it to a Bitmap, I have done it with this code:

            ImageProxy.PlaneProxy[] planes = image.getPlanes();
            ByteBuffer buffer = planes[0].getBuffer();
            int pixelStride = planes[0].getPixelStride();
            int rowStride = planes[0].getRowStride();
            int rowPadding = rowStride - pixelStride * image.getWidth();
            Bitmap bitmap = Bitmap.createBitmap(image.getWidth()+rowPadding/pixelStride,
                    image.getHeight(), Bitmap.Config.ARGB_8888);

            bitmap.copyPixelsFromBuffer(buffer);

But while executing the copyPixelsFromBuffer I am encountering this issue:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.strujomeri, PID: 24466
    java.lang.RuntimeException: Buffer not large enough for pixels

How can I get the picture I want in imageAnalyzer, and also have it’s content in byte[] format to do with it what I want ?

Advertisement

Answer

The default image format is YUV_420_888 and as your buffer is only one plane (the Luminance(Y) plane ) the buffer is of pixels that are only a single byte in size.

copyPixelsFromBuffer assumes that the buffer is in the same colour space as the bitmap, so as you set the bitmap format to ARGB_8888 then it is looking for 4 bytes per pixel not 1 byte per pixel you are giving it.

I’ve not used this but this page has a ImageProxy.toBitmap example to convert a YUV to Bitmap via a Jpeg (if you just wanted a Jpeg you could skip the last step)

I’ve also seen another method not via Jpeg but to directly change the colorspace of YUV to a bitmap.

You can of course change to the only other colour space ImageAnalysis supports of ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888 which takes longer to be captured because it needs converting and is still not the right format for a Bitmap

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement