Android CameraX(Java)Image转Bitmap数组越界问题求助
Hey there, let's break down why you're hitting that ArrayIndexOutOfBoundsException and fix it with reliable Java solutions.
What's Causing the Issue?
Your current toBitmap method assumes the image uses the YUV_420_888 format (which has 3 separate planes), but CameraX might be returning a single-plane format like JPEG depending on your ImageCapture setup. That’s why image.getPlanes().length is 1 instead of 3—your code tries to access indexes 1 and 2 which don’t exist, triggering the error.
Solution 1: Handle Multiple Image Formats in toBitmap
Update your conversion method to check the image format first, then handle both YUV_420_888 and JPEG formats properly:
private Bitmap toBitmap(Image image) { if (image.getFormat() == ImageFormat.YUV_420_888) { // Process 3-plane YUV_420_888 format 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]; // Copy Y plane data yBuffer.get(nv21, 0, ySize); // Swap and copy V/U planes for NV21 compatibility 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, image.getWidth(), image.getHeight()), 75, out); byte[] imageBytes = out.toByteArray(); return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); } else if (image.getFormat() == ImageFormat.JPEG) { // Process single-plane JPEG format ByteBuffer buffer = image.getPlanes()[0].getBuffer(); byte[] imageBytes = new byte[buffer.remaining()]; buffer.get(imageBytes); return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); } else { // Fallback for unsupported formats throw new IllegalArgumentException("Unsupported image format: " + image.getFormat()); } }
Critical Reminder: Always Close ImageProxy
After processing the image, call image.close() to release system resources and avoid memory leaks. Update your onCaptureSuccess method:
@Override public void onCaptureSuccess(ImageProxy image, int rotationDegrees) { try { Bitmap bitmap = rotateImage(toBitmap(image.getImage()), (float) rotationDegrees); ImageView takenImage.setImageBitmap(bitmap); } finally { // Mandatory: Close the ImageProxy to free resources image.close(); } super.onCaptureSuccess(image, rotationDegrees); }
Alternative Solution: File-Based Capture (Simpler)
If you don’t need in-memory image processing right away, use CameraX’s file-based capture to skip manual format handling entirely. This is more efficient and avoids format-related bugs:
private void takePicture() { // Create a temporary file to store the photo File photoFile = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "photo_" + System.currentTimeMillis() + ".jpg"); ImageCapture.OutputFileOptions outputOptions = new ImageCapture.OutputFileOptions.Builder(photoFile).build(); imageCapture.takePicture(outputOptions, ContextCompat.getMainExecutor(this), new ImageCapture.OnImageSavedCallback() { @Override public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) { // Load bitmap from the saved file Bitmap bitmap = BitmapFactory.decodeFile(photoFile.getAbsolutePath()); // Rotate bitmap to match device orientation Bitmap rotatedBitmap = rotateImage(bitmap, getScreenRotationDegrees()); takenImage.setImageBitmap(rotatedBitmap); } @Override public void onError(@NonNull ImageCaptureException exception) { Log.e("CameraX", "Capture failed: " + exception.getMessage()); } }); } // Helper to get correct rotation based on screen orientation private float getScreenRotationDegrees() { int rotation = getWindowManager().getDefaultDisplay().getRotation(); return rotation * 90f; }
内容的提问来源于stack exchange,提问作者Prajwal Bhat

