Higher image size in CameraX as compared to Camera1

97 views
Skip to first unread message

Arun Rao

unread,
Jan 2, 2023, 5:57:05 AM1/2/23
to Android CameraX Discussion Group

We are working on updating our legacy Camera application to use CameraX APIs instead of Camera1 APIs. We have used same camera configurations in both Camera1 and CameraX, we read the JPEG image byte array from Camera, in-memory and then upload that to a server. However, we have noticed that the byte array length that is got from CameraX is around 2X that of the byte array that we get from Camera1. Does CameraX output has some additional data or metadata in the byte array that is got in the callback?

Camera Initialization in Camera1 along with setting target resolution, JPEG quality:

camera = Camera.open(cameraId); //cameraId is the ID of back camera

parameters = camera.getParameters();

//set target resolution to 1600 * 1200

parameters.setPictureSize(1600, 1200);

//set JPEG quality to 100

parameters.setJpegQuality(100);

//set image format to JPEG

parameters.setPictureFormat(ImageFormat.JPEG);


Camera Initliazation in CameraX along with setting target resolution, JPEG quality

//select back camera

CameraSelector cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;

//create preview

Preview preview = new Preview.Builder().build();

//create Image Capture use case, set JPEG quality to 100, target resolution to 1600*1200

ImageCapture imageCapture = new ImageCapture.Builder()

        .setJpegQuality(100)

        .setTargetResolution(new Size(1600, 1200))

        .build();


//start camera 

provider.bindToLifecycle(

        this, cameraSelector, preview, imageCapture

);


Callback method passed to takePicture method in Camera API.


camera.takePicture(shutterCallback, null, pictureTaken);


private Camera.PictureCallback pictureTaken = new Camera.PictureCallback() {

   @Override

   public void onPictureTaken(final byte[] data, final Camera camera){

   Log.d(“Data byte array length”, data.length); // for same image this is around 400000 bytes

   ///Logic to upload data to server    

   }


Callback method passed to takePicture method in CameraX API.


imageCapture.takePicture(ContextCompat.getMainExecutor(this), 

   new ImageCapture.OnImageCapturedCallback() {

             @Override

             public void onCaptureSuccess(@NonNull ImageProxy imageProxy) {

           //convert imageProxy to byte array

           ByteBuffer buffer = imageProxy.getPlanes()[0].getBuffer();

                        buffer.rewind();

                        byte[] data = new byte[buffer.capacity()];

                        buffer.get(data); 

           Log.d(“Data byte array length”, data.length); //for same image this is around 600000 bytes

       })

   


Final image size is also considerably higher in CameraX implementation. In Camera1 its around 400kb and in CameraX its around 700kb. Is there any configuration we are missing or is there any metadata in the byte array that we need to strip off ?

Charcoal Chen

unread,
Jan 2, 2023, 8:51:13 PM1/2/23
to Arun Rao, Android CameraX Discussion Group
Hi,

It's great to hear that your app will use CameraX to replace the original Camera1 implementation.

It should be caused by the specified target resolution being incorrect. Please see the following Javadoc description of ImageCapture.Builder#setTargetResolution(Size):

The resolution Size should be expressed in the coordinate frame after rotating the supported sizes by the target rotation. For example, a device with portrait natural orientation in natural target rotation requesting a portrait image may specify 480x640, and the same device, rotated 90 degrees and targeting landscape orientation may specify 640x480.

In your case, you might need to specify the target resolution as new Size(1200, 1600) when the app is running on phone devices.


--
You received this message because you are subscribed to the Google Groups "Android CameraX Discussion Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to camerax-develop...@android.com.
To view this discussion on the web visit https://groups.google.com/a/android.com/d/msgid/camerax-developers/5374ccae-fd41-41f7-b8b8-c1ba43ccac96n%40android.com.

Arun Rao

unread,
Jan 3, 2023, 1:22:23 AM1/3/23
to Android CameraX Discussion Group, charco...@google.com, Android CameraX Discussion Group, Arun Rao
Hi,

Thanks for you inputs. 
I do set the target resolution based on the orientation and if its landscape I use Size(1600, 1200) and if it's portrait then I use Size(1200, 1600). Also the output ImageProxy's resolution matches to what is set in ImageCapture use case, so I doubt target resolution might be the reason for the mismatch.

Charcoal Chen

unread,
Jan 3, 2023, 3:02:11 AM1/3/23
to Android CameraX Discussion Group, arun...@gmail.com, Charcoal Chen, Android CameraX Discussion Group
Thanks for your clarification.

So, the case is that, your app can successfully obtain 1600x1200 still images no matter using Camera1 or CameraX API. But size of the image captured by CameraX (700kb) is larger than size of the image captured by Camera1 (400kb).

The plane byte buffer retrieved by the following code is provided by the Camera2 camera capture pipeline. CameraX doesn't change anything on it. I don't know whether the device manufacturer might do something different for JPEG compression between Camera1 and Camera2 pipeline. 

             public void onCaptureSuccess(@NonNull ImageProxy imageProxy) {

                 //convert imageProxy to byte array

                 ByteBuffer buffer = imageProxy.getPlanes()[0].getBuffer();

                        ...

             }

To clarify this, could you help to do some more checks for the following questions:
1. Could you try the Camera2Basic sample app, specify the 1600x1200 still image size here and specify JPEG quality 100 here? Then, please check whether the captured JPEG image still has larger size?
2. Does this issue happen on specific devices or all devices? Could you provide the information (device name, model name, Android version) of some devices which can reproduce the issue?

Arun Rao

unread,
Jan 3, 2023, 7:19:27 AM1/3/23
to Android CameraX Discussion Group, charco...@google.com, Arun Rao, Android CameraX Discussion Group
HI,

I tried Camera2Basic sample app, with 1600*1200 resolution and 100 JPEG quality. It seems that the output from Camera2 itself is of higher size. Image size was around 1MB. For JPEG quality 90 image size was around 500KB and for 80 quality it was around 300KB.
Also, i verified this in Pixel 4 and Pixel 6a devices both running Android 13(API 33).

Arun Rao

unread,
Jan 6, 2023, 7:13:39 AM1/6/23
to Android CameraX Discussion Group, Arun Rao, charco...@google.com, Android CameraX Discussion Group
Hi,

In Camera2, we have an option to disable Edge enhancement during capture phase. When I tried capturing images with edge enhancement turned OFF, the output image's size is comparable to what we get in Camera1. So, is it possible that edge enhancement is causing the image size to be bigger in Camera2? Any idea if image taken from Camera1 is edge enhanced?

Thanks.

Charcoal Chen

unread,
Jan 9, 2023, 2:59:56 AM1/9/23
to Arun Rao, Android CameraX Discussion Group
Hi,

I tried to use the timing test app to capture still images under Camera1 and CameraX modes. I modified the code to make them capture the same size of images with Jpeg quality 100. I found that the images captured by Camera1 are close to (but larger than) the images by CameraX. Please refer to the attachment including the captured images on Pixel 5a and Pixel 6a. The similar results are also on the other Pixel 6 and Samsung Note 10+ devices. I don't know what might cause the different results between yours and mine.

Different OEMs may have their own different implementations under the camera2 architecture. Therefore, it is difficult to say that disabling the Edge enhancement setting can work for all devices. When I did the test on  the timing test app, I also found that different devices might have or have no thumbnail in the images captured by the Camera1 or CameraX API. This might also affect the output image size.

Usually, apps might set the JPEG quality as 100 when they really care about the output image quality. Even if the Edge enhancement setting might increase the output size, it should also provide better output image quality for some aspects. I'm not quite sure that disabling Edge enhancement setting is a proper solution for this issue for your app. If your apps care more about the image size, maybe you need to consider decreasing the JPEG quality setting. CameraX sets JPEG quality as 95 for ImageCapture's default capture mode (JPEG_QUALITY_MINIMIZE_LATENCY_MODE) which also provides images of good enough quality. Or you can further consider to reduce it to 90 and then the output image might only have half image size compared to image of quality 100.

Camera1-vs-CameraX.zip

Arun Rao

unread,
Jan 9, 2023, 10:12:58 AM1/9/23
to Charcoal Chen, Android CameraX Discussion Group
Thanks Charcoal for detailed analysis!

I agree that disabling Edge enhancement is not the right solution for the issue. If CameraX does edge enhancements and other improvements which were not being done by Camera1 then it justifies the increase in output image size. 

Charcoal Chen

unread,
Jan 9, 2023, 9:21:02 PM1/9/23
to Arun Rao, Android CameraX Discussion Group
I searched the CameraX code base and confirmed that CameraX doesn't  set the CaptureRequest.EDGE_MODE setting. If EDGE_MODE is still enabled, it might be that OEMs enable EDGE_MODE according to some other conditions. As your previous test result - "When I tried capturing images with edge enhancement turned OFF, the output image's size is comparable to what we get in Camera1", EDGE_MODE is turned on by OEM implementation when taking still images on those devices to cause the result.
Reply all
Reply to author
Forward
0 new messages