0

I'm willing to implement zoom feature in my app with CameraX API. I followed this medium post to implement pinch to zoom and it works.

The problem is when I retrieve the captured image in onCaptureSuccess callback, The image is not zoomed.

Here is the code I use to implement zoom on Camera in onCreate():

  //ZOOM
    val listener = object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
        override fun onScale(detector: ScaleGestureDetector): Boolean {
            val zoomRatio = camera?.cameraInfo?.zoomState?.value?.zoomRatio ?: 0f
            val scale = zoomRatio * detector.scaleFactor
            camera?.cameraControl?.setZoomRatio(scale)
            return true
        }
    }

    scaleDetector = ScaleGestureDetector(context, listener)

And in method "bindCameraUseCases()" :

   previewCamera.setOnTouchListener { _, event ->
            scaleDetector.onTouchEvent(event)
        }

The full method if needed :

 /** Declare and bind preview, capture and analysis use cases */
fun bindCameraUseCases() {
    // Get screen metrics used to setup camera for full screen resolution
    val metrics = DisplayMetrics().also { previewCamera.display.getRealMetrics(it) }
    Log.d(TAG, "Screen metrics: ${metrics.widthPixels} x ${metrics.heightPixels}")

    val rotation = previewCamera.display.rotation

    // Bind the CameraProvider to the LifeCycleOwner
    val cameraSelector = CameraSelector.Builder().requireLensFacing(lensFacing).build()
    val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext())
    cameraProviderFuture.addListener(Runnable {

        // CameraProvider
        val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()

        // Preview
        preview = Preview.Builder()
            .setTargetRotation(rotation)
            .build()

        previewCamera.preferredImplementationMode =
            PreviewView.ImplementationMode.TEXTURE_VIEW  // when setting to TEXTURE_VIEW, preview doesnt take full screen on back pressed

        previewCamera.setOnTouchListener { _, event ->
            scaleDetector.onTouchEvent(event)
        }

        // Default PreviewSurfaceProvider
        preview?.setSurfaceProvider(previewCamera.createSurfaceProvider(camera?.cameraInfo))


        val screenAspectRatio = aspectRatio(metrics.widthPixels, metrics.heightPixels)


        // ImageCapture
        imageCapture = ImageCapture.Builder()
            .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
            .setTargetAspectRatio(screenAspectRatio)
            .setTargetRotation(rotation)
            .build()

        // ImageAnalysis
        imageAnalyzer = ImageAnalysis.Builder()
            .setTargetAspectRatio(screenAspectRatio)
            .setTargetRotation(rotation)
            .build()

        cameraProvider.unbindAll()
        try {
            camera = cameraProvider.bindToLifecycle(
                this as LifecycleOwner, cameraSelector, preview, imageCapture, imageAnalyzer
            )
        } catch (exc: Exception) {
            Log.e(TAG, "Use case binding failed", exc)
        }

    }, mainExecutor)
}

As I mentionned, zoom is working but then in onCaptureSucess, ImageProxy is not zoomed.

override fun onCaptureSuccess(image: ImageProxy) {
                        image.use { image ->
                            savedBitmap = image.imageProxyToBitmap()
                            ///...

                }
            }

Here is the extension function to retrieve bitmap from imageProxy :

fun ImageProxy.imageProxyToBitmap(): Bitmap {

val buffer = this.planes[0].buffer
buffer.rewind()
val bytes = ByteArray(buffer.capacity())
buffer.get(bytes)
val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
val matrix = Matrix()
matrix.postRotate(90f)

return Bitmap.createBitmap(bitmap, 0, 0,bitmap.width,bitmap.height, matrix, true)

}

Here are my dependencies :

    // CameraX core library
def camerax_version = "1.0.0-beta02"
implementation "androidx.camera:camera-core:$camerax_version"

// CameraX Camera2 extensions
implementation "androidx.camera:camera-camera2:$camerax_version"

// CameraX Lifecycle library
implementation "androidx.camera:camera-lifecycle:$camerax_version"

// CameraX View class
implementation "androidx.camera:camera-view:1.0.0-alpha09"

Thank you for your help

1 Answers1

0

not sure why this happens but we are unable to reproduce the issue. In my test, ImageCapture always captures the image with zoom applied.

Currently I suspect this could a device issue. It could be helpful if you can provide the device name. It will also be helpful if you can verify it on other devices.

Scott Nien
  • 51
  • 1
  • Hi @Scott. Thank you for your feedback. I have a OnePlus 5T, version 9.0.11 of Oxygen OS. I'll try to have a test on other brand. I'll let you know. Can you confirm me that code I pasted seems ok ? Thanks again for your time ! – Fanny Demey Pluvinage Apr 10 '20 at 19:03
  • The codes looks fine but it is not complete, so I am not sure if something wrong somewhere. By the way, how do you make sure the image is not zoomed ? Zoomed image has the same resolution as non-zoomed images and it is just the FoV (Field of View) of the image is changed. – Scott Nien Apr 12 '20 at 05:26
  • Thanks for mentioning Field of View, that made me realized I had to add android:adjustViewBounds="true" in my ImageView displaying the bitmap result . Sorry for the trouble and thanks again for your support. – Fanny Demey Pluvinage Apr 13 '20 at 07:52
  • Not a problem. Always happy to see the issue resolved. – Scott Nien Apr 14 '20 at 16:19