Search code examples
androidandroid-camera2

Camera2 CameraViewfinder Preview Stretched


I'm making a camera in my app using camera2 and I want to use CameraViewfinder as from what I understand it should handle correcting the orientation and aspect ratio. However, when I set its resolution and request the surface, the preview is vertically stretched. The resolution I'm using is 3072x4080 (3:4) and that aspect ratio doesn't match the viewfinder, so it doesn't look correct. However, I thought CameraViewfinder is supposed to correct that automatically? I'm using the fillCenter scale type and the documentation for it says the following:

This may cause the viewfinder to be cropped if the camera viewfinder aspect ratio does not match that of its container CameraViewfinder.

However, I don't see any cropping occurring to correct the aspect ratio. This is how I'm requesting the preview surface:

surfaceRequest = ViewfinderSurfaceRequest.Builder(
    resolution = resolution // Size(3072, 4080)
).build()
surfaceRequest?.let { request ->
    val surfaceListenableFuture: ListenableFuture<Surface> =
        binding.viewFinder.requestSurfaceAsync(request)

    Futures.addCallback(
        surfaceListenableFuture, object : FutureCallback<Surface> {
            override fun onSuccess(result: Surface?) {
                // use surface
            }

        },
        ContextCompat.getMainExecutor(requireContext())
    )
}

I have the viewfinder wrapped in a FrameLayout and defined in my XML as such:

<androidx.camera.viewfinder.CameraViewfinder
    android:id="@+id/view_finder"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginBottom="92dp"
    android:layout_marginTop="64dp"
    app:scaleType="fillCenter" />

I have margins on the view because I have top/bottom bars in my camera UI.

See my camera vs the Google camera.

I've tried getting the aspect ratio of the viewfinder and then finding the resolution with the closest aspect ratio, but the preview is still distorted. What do I need to do to correct the aspect ratio in my preview?


Solution

  • Figured out the issue. I needed to call populateFromCharacteristics(characteristics) on the ViewfinderSurfaceRequest.Builder so that it had all the characteristics for the camera to show the preview correctly. It would be nice if Google updated their documentation to show this as a necessary step. Full code below:

    surfaceRequest = ViewfinderSurfaceRequest.Builder(resolution)
        .populateFromCharacteristics(characteristics)
        .build()