Search code examples
android-camerax

Images taken with CameraX are not of high resolution output size produced by device camera


I was trying to get high resolution images with cameraX implementation. With below code I was able to see that for back camera of the device I tested an entry with resolution of 4000x3000.

    @RequiresApi(Build.VERSION_CODES.M)
fun getPossibleOutputSizes(id: String) {
    val cameraManager = context?.getSystemService(Context.CAMERA_SERVICE) as CameraManager
    val sizes = cameraManager?.getCameraCharacteristics(id)?.get(SCALER_STREAM_CONFIGURATION_MAP)?.getHighResolutionOutputSizes(ImageFormat.JPEG)
    if (sizes != null) {
        println("got possible resolutions:")
        println(sizes.joinToString("\n"))
    }
}

Below is the code for setting up camera. This is a sample app I used to check the output resolution provided by cameraX takePhoto calls.

/** Declare and bind preview, capture and analysis use cases */
@SuppressLint("RestrictedApi", "ServiceCast", "UnsafeOptInUsageError")
private fun bindCameraUseCases() {

    // Get screen metrics used to setup camera for full screen resolution
    val metrics = windowManager.getCurrentWindowMetrics().bounds
    Log.d(TAG, "Screen metrics: ${metrics.width()} x ${metrics.height()}")

    val screenAspectRatio = aspectRatio(metrics.width(), metrics.height())
    Log.d(TAG, "Preview aspect ratio: $screenAspectRatio")

    val rotation = fragmentCameraBinding.viewFinder.display.rotation

    // CameraProvider
    val cameraProvider = cameraProvider
            ?: throw IllegalStateException("Camera initialization failed.")

    // CameraSelector
    var cameraSelector = CameraSelector.Builder().requireLensFacing(lensFacing).build()

    selectExternalOrBestCamera(cameraProvider)?.let { returnedCameraSelector ->
        cameraSelector = returnedCameraSelector


    }
    // Preview
    preview = Preview.Builder()
            // We request aspect ratio but no resolution
            .setTargetAspectRatio(screenAspectRatio)//either RATIO_4_3 or RATIO_16_9
            // Set initial target rotation
            .setTargetRotation(rotation)
            .build()

    // ImageCapture
    imageCapture = ImageCapture.Builder()
            .setCaptureMode(ImageCapture.CAPTURE_MODE_ZERO_SHUTTER_LAG)
            // We request aspect ratio but no resolution to match preview config, but letting
            // CameraX optimize for whatever specific resolution best fits our use cases
            // Set initial target rotation, we will have to call this again if rotation changes
            // during the lifecycle of this use case
            //.setTargetAspectRatio(AspectRatio.RATIO_4_3)//tried both RATIO_4_3 and RATIO_16_9
            .setTargetResolution(Size(3000, 4000))//tried 4000 * 3000 too..
            .setTargetRotation(rotation)
            //.setDefaultCaptureConfig(config)
            .build()
    // Must unbind the use-cases before rebinding them
    cameraProvider.unbindAll()

    try {
        // A variable number of use-cases can be passed here -
        // camera provides access to CameraControl & CameraInfo
        camera = cameraProvider.bindToLifecycle(
                this, cameraSelector, preview, imageCapture)

        // Attach the viewfinder's surface provider to preview use case
        preview?.setSurfaceProvider(fragmentCameraBinding.viewFinder.surfaceProvider)
        observeCameraState(camera?.cameraInfo!!)
    } catch (exc: Exception) {
        Log.e(TAG, "Use case binding failed", exc)
    }
}

I tried to play around with the available configurations present in cameraX and was not able to get the high resolution output with same resolution I get in getPossibleOutputSizes. This seems to be the case in all the devices I tested. But device camera was able to provide images in that resolution and so is camera2 based implementation.

Is this a limitation in cameraX or I have missed something?


Solution

  • Unfortunately, as of January 2023, using a high resolution that was returned by getHighResolutionOutputSizes cannot be used together with CameraX. I do not know any workaround. Bug report and current status can be found here: https://issuetracker.google.com/issues/162121234 Current outlook is that the feature should come with CameraX 1.3 version.

    Edit 20.04.23: With yesterday's release of Version 1.3.0-alpha06 , this should now be available: https://developer.android.com/jetpack/androidx/releases/camera#1.3.0-alpha06