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