Setting target resolution for CameraX not working as in documentation
Asked Answered
D

3

8

I want to capture photos with fixed resolution (i.e. 1200x1600) using CameraX library.

So according to documentation I can set target resolution for ImageCaptureConfig:

val imageCaptureConfig = ImageCaptureConfig.Builder()
    .setLensFacing(CameraX.LensFacing.BACK)
    .setCaptureMode(ImageCapture.CaptureMode.MAX_QUALITY)
    .setTargetResolution(Size(1200, 1600))
    .setTargetAspectRatio(Rational(3,4))
    .build()

Documentation describes setTargetResolution method as follows:

Sets the intended output target resolution.

The target resolution attempts to establish a minimum bound for the image resolution. The actual image resolution will be the closest available resolution in size that is not smaller than the target resolution, as determined by the Camera implementation. However, if no resolution exists that is equal to or larger than the target resolution, the nearest available resolution smaller than the target resolution will be chosen.

Correct me if I am wrong, but if device is able to take photos larger than 1200x1600 (e.g. 3024x4032), the output photo will be at least 1200x1600.

Unfortunately in many devices (e.g. Huawei P20 Pro, Samsung A5) the output photo is significantly smaller than 1200x1600, e.g. 480x640. Notice that these devices are able to take really large photos.

Is my ImageCaptureConfig badly configured or this is a bug?

Disario answered 29/7, 2019 at 13:30 Comment(3)
Any chances that there's a regression of this issue? We are seeing this right now with the front camera of an Alcatel, trying to set up 720 x 1280 with Camera X results in a weird lower resolutions, but the same device with other apps non based on Camera X can use 720 x 1280 with no issues it seems.Fulsome
@FranMarzoa Same issue happens here. Do you find any solutions?Kurzawa
@Kurzawa sorry, unfortunately no, I didn't. I only needed to capture one frame, so as a workaround I use lower resolution for preview and analysis, but then the last frame is taken with the image capture use case, which does higher resolution.Fulsome
C
2

It could be a bug that have been recently fixed at AOSP. refer https://android.googlesource.com/platform/frameworks/support/+/5c1aed8c4c502a74eb4ee6d30fe2089f4afcaf11

Cobweb answered 31/7, 2019 at 10:27 Comment(4)
Thanks! Do you know if this fix will be available in next version?Disario
@Wasim Ansari will you tell me in which class have solution in this repository?Pardon
Hi same issue happens here. Is it a regression or is that deployed?Kurzawa
Why is it so hard/difficult to just crop the image using the specified resolution after taking the picture, instead of ignoring what we pass to setTargetResolution? I swear, Google pisses me off sometimes.Censurable
S
3

The android documentation say this:

You cannot set both target aspect ratio and target resolution on the same use case. Doing so will throw an IllegalArgumentException when building the config object.

So decide what is mor important for you and choose only one.

Sodomy answered 29/7, 2020 at 16:17 Comment(1)
Thanks for response. It turned to be a bug, mentioned here: https://mcmap.net/q/1336028/-setting-target-resolution-for-camerax-not-working-as-in-documentation. FYI - at the time of writing this question, it wasn't an issue to set both aspect ratio and target resolution.Disario
D
3

When you use .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.

So this in Portait:

val imageCaptureConfig = ImageCaptureConfig.Builder()
    .setTargetResolution(Size(1200, 1600))

Became that in Landscape:

val imageCaptureConfig = ImageCaptureConfig.Builder()
    .setTargetResolution(Size(1600, 1200))

Be careful of the orientation of your device:

fun getTargetResolution(): Size {
    return when (resources.configuration.orientation) {
        Configuration.ORIENTATION_PORTRAIT -> Size(1200, 1600)
        Configuration.ORIENTATION_LANDSCAPE -> Size(1600, 1200)
        else -> Size(1600, 1200)
    }
}

fun setupCamera() {
    ...
    val resolution = getTargetResolution()
    val imageCaptureConfig = ImageCaptureConfig.Builder()
        .setTargetResolution(resolution)
    ...
}

It is the same thing with ImageAnalysis and ImagePreview

If you want some documentation, go here

Droit answered 4/10, 2022 at 11:34 Comment(2)
"size should be..."; do you mean must? What happens if you don't do that? Also, I find that in my app, I have to always pass the height/width backwards; otherwise the image gets saved with max resolutionSilvia
@Silvia It seems to be deprecated now, you may have to use ResolutionSelector with ResolutionStrategy. If you give him a badly formatted or a non existing resolution for your camera, it will set it to the default resolution if I remember. I wrote a code to list all handled resolutions from the camera and choose the nearest supported one from my target. But with the new way, I hope it's autoDroit
C
2

It could be a bug that have been recently fixed at AOSP. refer https://android.googlesource.com/platform/frameworks/support/+/5c1aed8c4c502a74eb4ee6d30fe2089f4afcaf11

Cobweb answered 31/7, 2019 at 10:27 Comment(4)
Thanks! Do you know if this fix will be available in next version?Disario
@Wasim Ansari will you tell me in which class have solution in this repository?Pardon
Hi same issue happens here. Is it a regression or is that deployed?Kurzawa
Why is it so hard/difficult to just crop the image using the specified resolution after taking the picture, instead of ignoring what we pass to setTargetResolution? I swear, Google pisses me off sometimes.Censurable

© 2022 - 2024 — McMap. All rights reserved.