如何解决使用 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 举报,一经查实,本站将立刻删除。