как автоматически повернуть изображение после захвата изображения с помощью библиотеки Camera X?

#android #android-jetpack #android-camerax

#Android #android-jetpack #android-camerax

Вопрос:

Я новичок в использовании библиотеки camera X. Я пытаюсь следовать кодовой таблице из Google здесь

Я могу показать предварительный просмотр и захватить изображение. но проблема в том……

когда я снимаю изображение в альбомной ориентации, результат изображения будет по-прежнему в портретной ориентации. Я хочу, чтобы оно автоматически вращалось. если я беру изображение в альбомной ориентации, то результат должен быть в альбомной ориентации, а если я беру его в портретной ориентации, то результат должен быть в портретной ориентации. как камера в приложении «Камера»

как это сделать?

Я использую Redmi Note 7, Android 10.

gradle, который я использую:

 implementation "androidx.camera:camera-camera2:1.0.0-beta11"
implementation "androidx.camera:camera-lifecycle:1.0.0-beta11"
implementation "androidx.camera:camera-view:1.0.0-alpha18"
  

вот мой код для отображения предварительного просмотра и захвата изображения

 class CameraFragment : Fragment() {

    private var imageCapture: ImageCapture? = null
    private lateinit var outputDirectory: File
    private lateinit var cameraExecutor: ExecutorService
    private var cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA

    companion object {
        private const val TAG = "CameraFragment"
        private const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS"
        private const val CAMERA_REQUEST_CODE_PERMISSIONS = 10
    }

    lateinit var mContext : Context
    lateinit var mActivity : FragmentActivity

   

    override fun onAttach(context: Context) {
        super.onAttach(context)

        mContext = context
        activity?.let { mActivity = it }

    }


    private fun getOutputDirectory(): File {
        val mediaDir = mActivity.externalMediaDirs.firstOrNull()?.let {
            File(it, resources.getString(R.string.app_name)).apply { mkdirs() }
        }
        return if (mediaDir != null amp;amp; mediaDir.exists())
            mediaDir else mActivity.filesDir
    }


    private fun startCamera() {
        val cameraProviderFuture = ProcessCameraProvider.getInstance(mContext)

        cameraProviderFuture.addListener(Runnable {
            // Used to bind the lifecycle of cameras to the lifecycle owner
            val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()

            // Preview
            val preview = Preview.Builder()
                    .build()
                    .also {
                        it.setSurfaceProvider(previewView.surfaceProvider)
                    }


            imageCapture = ImageCapture.Builder().build()


            try {
                // Unbind use cases before rebinding
                cameraProvider.unbindAll()

                // Bind use cases to camera
                cameraProvider.bindToLifecycle(
                        this, cameraSelector, preview, imageCapture)

            } catch (exc: Exception) {
                Log.e(TAG, "Use case binding failed", exc)
            }

        }, ContextCompat.getMainExecutor(mContext))
    }


    private fun takePhoto() {

        // Get a stable reference of the modifiable image capture use case
        val imageCapture = imageCapture ?: return


        // Create time-stamped output file to hold the image
        val photoFile = File(
                outputDirectory,
                SimpleDateFormat(FILENAME_FORMAT, Locale.US
                ).format(System.currentTimeMillis())   ".jpg")

        // Create output options object which contains file   metadata
        val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build()


        // Set up image capture listener, which is triggered after photo has
        // been taken
        imageCapture.takePicture(outputOptions, ContextCompat.getMainExecutor(mContext), object : ImageCapture.OnImageSavedCallback {

            override fun onError(exc: ImageCaptureException) {
                Log.d("agungxxx", "2: ${exc.localizedMessage}")
                Log.e(TAG, "Photo capture failed: ${exc.message}", exc)
            }

            override fun onImageSaved(output: ImageCapture.OutputFileResults) {
                cameraSharedViewModel.sendImageUriPathToPreviousDestination(photoFile)
                findNavController().navigateUp()
            }
        })

    }

}
  

Ответ №1:

Поворот захваченного изображения зависит от целевого поворота ImageCapture варианта использования. По умолчанию, когда оно не задано приложением, оно равно Display.getRotation() , где Display отображается по умолчанию на момент ImageCapture создания варианта использования.

Это означает, что вам необходимо обновлять ImageCapture целевой поворот каждый раз, когда меняется ориентация дисплея, например, когда устройство физически поворачивается с портретной на альбомную.

Я предполагаю, что ваша активность имеет заблокированную ориентацию (?). В этом случае вы можете использовать an OrientationEventListener для непрерывного получения обновлений о повороте устройства, а затем соответствующим образом обновлять целевой поворот варианта использования.

 val orientationEventListener = object : OrientationEventListener(this) {
    override fun onOrientationChanged(orientation: Int) {
        if (orientation == OrientationEventListener.UNKNOWN_ORIENTATION) {
            return
        }

        val rotation = when (orientation) {
            in 45 until 135 -> Surface.ROTATION_270
            in 135 until 225 -> Surface.ROTATION_180
            in 225 until 315 -> Surface.ROTATION_90
            else -> Surface.ROTATION_0
        }

        imageCapture.targetRotation = rotation
    }
}
  

Вы должны запускать / останавливать orientationEventListener , когда жизненный цикл действия запускается / останавливается, это также соответствует моменту запуска / остановки камеры. Вы можете увидеть пример этого здесь.

Вы также можете узнать больше о вариантах использования и поворота CameraX в официальной документации.

Комментарии:

1. @Husyan Большое вам спасибо, это решает мою проблему, я использую такой код i.stack.imgur.com/hcJGd.png , но не могли бы вы, пожалуйста, предоставить информацию о значении UNKNOWN_ORIENTATION здесь? поскольку я также не могу найти его в документации, это отрицательное целое число?

2. Рад это слышать. UNKNOWN_ORIENTATION равно -1, прослушиватель получает, когда поворот устройства не может быть определен.