微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 Android CameraX 拍摄的所有图像在其 EXIF 数据中的方向都不正确

如何解决使用 Android CameraX 拍摄的所有图像在其 EXIF 数据中的方向都不正确

我正在使用 CameraX https://developer.android.com/training/camerax 拍摄一些图像。但是,我所有的图像都旋转错误。它们都标有:ORIENTATION_ROTATE_90 是的,我已经检查以确保方向锁定未打开,并且清单中没有任何内容可以锁定屏幕方向,也没有覆盖任何方向方法

无论我如何通过模拟器或真实设备对其进行测试,方向似乎都被“锁定”了。唯一正确旋转的图片是设备处于纵向模式时。但是,它仍然被标记ORIENTATION_ROTATE_90

谁能看到我可能做错了什么?

     private var imageCapture: ImageCapture? = null
    private lateinit var cameraExecutor: ExecutorService
  
  //.. other methods removed for brievity
  
   override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // Request camera permissions

        cameraExecutor = Executors.newSingleThreadExecutor()
    }
        override fun onResume() {
        super.onResume()

            startCamera()

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

        cameraProviderFuture.addListener({
            // 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(binding.cameraPreview.surfaceProvider)
                }

            imageCapture = Builder().build()

            // Doesn't work
                // activity?.display.let { d ->
                // d.let {  imageCapture!!.targetRotation = d!!.rotation }
                //  }

            // Select back camera as a default
            val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA

            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(requireContext()))
    }
   
    private fun captureImage() {


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

        // this way the images will stay in order
        val id = System.currentTimeMillis().toString() 

        // Make directory if it doesn't exist,and build a file for the new image to go into
        val photoFile = File("${sharedviewmodel.fileDirectory}/${id}").apply {
            @Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
            parentFile.mkdirs()
        }

        // Create output options object which contains file + Metadata
        val outputoptions = OutputFileOptions.Builder(photoFile).build()

        // Set up image capture listener,which is triggered after photo has  been taken
        imageCapture.takePicture(
            outputoptions,ContextCompat.getMainExecutor(requireContext()),object : OnImageSavedCallback {
                override fun onError(exc: ImageCaptureException) {
                    Toast.makeText(requireContext(),"Photo capture Failed: ${exc.message}",Toast.LENGTH_LONG).show()
                    Log.e(TAG,exc)
                }

                override fun onImageSaved(output: OutputFileResults) {
                    fixRotation(photoFile.path)
                }
            })


    }

    private fun fixRotation(imageUri: String) {

        val bitmap = File(imageUri)
        if (!bitmap.exists()) return

        Uri.parse(imageUri)?.let{
            Coroutinescope(dispatchers.IO).launch { spinAndSave(it) }
        }

    }


    private suspend fun spinAndSave(imageURI: Uri) = withContext(dispatchers.IO) {

        val options = BitmapFactory.Options()
        options.inPreferredConfig = Bitmap.Config.ARGB_8888

        imageURI.path?.let { path ->
            ExifInterface(path).getAttributeInt(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_UNDEFINED).let { orientation ->
                debugOrientation(orientation)
                val rotatedBitmap = rotateBitmap( BitmapFactory.decodeFile(path,options),orientation)!!
                FileOutputStream(imageURI.path).use { fos ->
                    rotatedBitmap.compress(Bitmap.CompressFormat.JPEG,50,fos)
                    Log.i(TAG,"New Image Saved")
                }
            }
        }



    }

    private fun debugOrientation(orientation: Int) {

        val o = when (orientation) {
            ExifInterface.ORIENTATION_norMAL -> "ORIENTATION_norMAL"
            ExifInterface.ORIENTATION_FLIP_HORIZONTAL -> "ORIENTATION_FLIP_HORIZONTAL"
            ExifInterface.ORIENTATION_ROTATE_180 -> "ORIENTATION_ROTATE_180"
            ExifInterface.ORIENTATION_FLIP_VERTICAL -> "ORIENTATION_FLIP_VERTICAL"
            ExifInterface.ORIENTATION_TRANSPOSE -> "ORIENTATION_TRANSPOSE"
            ExifInterface.ORIENTATION_ROTATE_90 -> "ORIENTATION_ROTATE_90"
            ExifInterface.ORIENTATION_TRANsveRSE -> "ORIENTATION_TRANsveRSE"
            ExifInterface.ORIENTATION_ROTATE_270 -> "ORIENTATION_ROTATE_270"
            else -> "UKNONWN ORIENTATION"
        }

        Log.w(TAG,"ORIEntation int: $orientation is: $o")
    }


    private fun rotateBitmap(bitmap: Bitmap,orientation: Int): Bitmap? {
        val matrix = Matrix()
        when (orientation) {
            ExifInterface.ORIENTATION_norMAL -> return bitmap
            ExifInterface.ORIENTATION_FLIP_HORIZONTAL -> matrix.setScale(-1f,1f)
            ExifInterface.ORIENTATION_ROTATE_180 -> matrix.setRotate(180f)
            ExifInterface.ORIENTATION_FLIP_VERTICAL -> {
                matrix.setRotate(180f)
                matrix.postScale(-1f,1f)
            }
            ExifInterface.ORIENTATION_TRANSPOSE -> {
                matrix.setRotate(90f)
                matrix.postScale(-1f,1f)
            }
            ExifInterface.ORIENTATION_ROTATE_90 -> matrix.setRotate(90f)
            ExifInterface.ORIENTATION_TRANsveRSE -> {
                matrix.setRotate(-90f)
                matrix.postScale(-1f,1f)
            }
            ExifInterface.ORIENTATION_ROTATE_270 -> matrix.setRotate(-90f)
            else -> return bitmap
        }
        return try {
            val bmRotated = Bitmap.createBitmap(bitmap,bitmap.width,bitmap.height,matrix,true)
            bitmap.recycle()
            bmRotated
        } catch (e: OutOfMemoryError) {
            e.printstacktrace()
            null
        }
    }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。