Bios90
Bios90

Reputation: 811

CameraX image rotation with fixed sreenOrientation

I added cameraX in my app as it described in this tutorial. The only problem i faced is image rotation. In app manifest file I use this settings for camera activity android:screenOrientation="portrait". My goal is to make this activity always in portrait mode, while captured images should have real rotation.

How can i achieve this? Is it possible for cameraX to detect different rotation while activity has fixed?

This is my code in camera activity

private lateinit var cameraProviderFuture: ListenableFuture<ProcessCameraProvider>
private lateinit var imageCapture: ImageCapture
private val executor = Executors.newSingleThreadExecutor()
private var camera: Camera? = null
...
override fun onCreate(savedInstanceState: Bundle?)
{
    ...
    cameraProviderFuture = ProcessCameraProvider.getInstance(this)
    preview_view.post(
        {
            startCamera()
        })
}
...
fun startCamera()
{
    preview = Preview.Builder().apply {
        setTargetAspectRatio(AspectRatio.RATIO_16_9)
        setTargetRotation(preview_view.display.rotation)
    }.build()

    imageCapture = ImageCapture.Builder().apply {
        setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
    }.build()

    val cameraSelector = CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build()
    cameraProviderFuture.addListener(Runnable {
        val cameraProvider = cameraProviderFuture.get()
        cameraProvider.unbindAll()
        camera = cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture)
        preview.setSurfaceProvider(preview_view.createSurfaceProvider(camera!!.cameraInfo))
    }, ContextCompat.getMainExecutor(this))
}
...
fun takePicture()
{
    val file = createFile(getOutputDirectory(), FILENAME, PHOTO_EXTENSION)
    val outputFileOptions = ImageCapture.OutputFileOptions.Builder(file).build()

    imageCapture.takePicture(outputFileOptions, executor, object : ImageCapture.OnImageSavedCallback
    {
        override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults)
        {
            val my_file_item = MyFileItem.createFromFile(file)
            imageCaptured(my_file_item)
        }

        override fun onError(exception: ImageCaptureException)
        {
            val msg = "Photo capture failed: ${exception.message}"
            preview_view.post({
                Toast.makeText(this@ActPhotoCapture2, msg, Toast.LENGTH_LONG).show()
            })
        }
    })
}

Upvotes: 1

Views: 4227

Answers (1)

Husayn Hakeem
Husayn Hakeem

Reputation: 4570

If your orientation is locked, you can probably use an orientation listener to listen for changes in the device's orientation, and each time its onOrientationChanged callback is invoked, you'd set the target rotation for the image capture use case.

val orientationEventListener = object : OrientationEventListener(context) {
    override fun onOrientationChanged(orientation: Int) {
        imageCapture.targetRotation = view.display.rotation
    }
}

The view you use to get the rotation can be any view, for example the root view if you're in fragment, or just the PreviewView. You can also enable/disable this listener in onResume and onPause.

ps: The way you're setting up your use cases can cause issues. The use cases shouldn't be initialized before the camera is started. You should build the use cases after this line val cameraProvider = cameraProviderFuture.get().

Upvotes: 6

Related Questions