代码之家  ›  专栏  ›  技术社区  ›  Alexa289

如何使用Camera X库在捕获图像后自动旋转图像?

  •  0
  • Alexa289  · 技术社区  · 4 年前

    我是使用X相机库的新手。我试着跟随谷歌的代码实验室 here

    我可以显示预览并捕获图像。但问题是。。。。。。

    当我在风景中捕捉图像时,图像结果将仍然是肖像。我想让它自动旋转。如果我在风景中拍摄图像,那么结果应该是风景,如果我在肖像中拍摄,那么结果也应该是肖像。就像“相机”应用程序中的相机

    怎么做?

    我使用的是红米Note 7和安卓10。

    我使用的刻度:

    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 && 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()
                }
            })
    
        }
    
    }
    
    0 回复  |  直到 4 年前
        1
  •  2
  •   Husayn Hakeem    4 年前

    捕获图像的旋转取决于 the target rotation ImageCapture 用例。默认情况下,当应用程序没有设置它时,它等于 Display.getRotation() ,在哪里 Display 是当时的默认显示 图像捕捉 创建用例。

    这意味着您需要更新 图像捕捉 每次显示器方向改变时,例如当设备从纵向旋转到横向时,的目标旋转。

    我假设你的活动有一个锁定的方向(?)。在这种情况下,您可以使用 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 当“活动”的生命周期启动/停止时,这也与相机的启动/停止时间相匹配。你可以看到一个例子 here .

    您还可以了解有关CameraX用例和旋转的更多信息 in the official documentation .