I'm exploring CameraX API of android using Java and trying to build capture image use-case. Here is the code for
private void takePicture() {
imageCapture.takePicture(new ImageCapture.OnImageCapturedListener() {
@Override
public void onCaptureSuccess(ImageProxy image, int rotationDegrees) {
Bitmap bitmap = rotateImage(toBitmap(image.getImage()), (float) rotationDegrees);
ImageView takenImage.setImageBitmap(bitmap);
super.onCaptureSuccess(image, rotationDegrees);
}
});
}
and to convert the image captured to bitmap. I'm trying to implement @Ahwar's answer in the following question which is written in Java: Converting ImageProxy to Bitmap Here is the code answer given there:
private Bitmap toBitmap(Image image) {
Image.Plane[] planes = image.getPlanes();
ByteBuffer yBuffer = planes[0].getBuffer();
ByteBuffer uBuffer = planes[1].getBuffer();
ByteBuffer vBuffer = planes[2].getBuffer();
int ySize = yBuffer.remaining();
int uSize = uBuffer.remaining();
int vSize = vBuffer.remaining();
byte[] nv21 = new byte[ySize + uSize + vSize];
//U and V are swapped
yBuffer.get(nv21, 0, ySize);
vBuffer.get(nv21, ySize, vSize);
uBuffer.get(nv21, ySize + vSize, uSize);
YuvImage yuvImage = new YuvImage(nv21, ImageFormat.NV21, image.getWidth(), image.getHeight(), null);
ByteArrayOutputStream out = new ByteArrayOutputStream();
yuvImage.compressToJpeg(new Rect(0, 0, yuvImage.getWidth(), yuvImage.getHeight()), 75, out);
byte[] imageBytes = out.toByteArray();
return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
}
My issue: When I call toBitmap(image) function, I'm getting ArrayIndexOutOfBoundsException, and after debugging, I understood that size of image planes is just 1 rather than 3. I have attached exception received here,
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.camerax3, PID: 17342
java.lang.ArrayIndexOutOfBoundsException: length=1; index=1
at com.example.camerax3.activity.MainActivity.toBitmap(MainActivity.java:210)
at com.example.camerax3.activity.MainActivity.access$100(MainActivity.java:45)
at com.example.camerax3.activity.MainActivity$2.onCaptureSuccess(MainActivity.java:239)
at androidx.camera.core.ImageCapture$ImageCaptureRequest.dispatchImage(ImageCapture.java:1341)
at androidx.camera.core.ImageCapture$10.onImageAvailable(ImageCapture.java:657)
at androidx.camera.core.MetadataImageReader$3.run(MetadataImageReader.java:279)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7099)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)
Could anyone suggest a way to solve this ?. I have read many answers in Kotlin but I'm trying to implement the same in Java. Any alternative method to convert image to bitmap in java is appreciated as well.
This code worked for me, try it.
private Bitmap getBitmap(ImageProxy image) {
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
buffer.rewind();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
byte[] clonedBytes = bytes.clone();
return BitmapFactory.decodeByteArray(clonedBytes, 0, clonedBytes.length);
}