问题
Basically, My camera app is set to Portrait Mode. However, user can take photos in Potrait or landscape by rotating the phone accordingly (The app doesnt rotate).
So my question is, how can we find the captured image orientation?
I tried using DisplayManager.DisplayListener
, however, it works only when orientation of app happens. Since I have blocked the orientation of app to portrait mode, it doesnt get any callbacks here.
I even tried using ExifInterface
, however, it always gives 6 as rotation.
I am looking for solution using CameraX apis.
回答1:
I had this problem also. What solved it is by using the device sensor data to get the correct orientation, then set it in my imageCapture
object. See snippet below.
orientationEventListener = object : OrientationEventListener(context) {
override fun onOrientationChanged(orientation: Int) {
// Monitors orientation values to determine the target rotation value
val rotation = if (orientation >= 45 && orientation < 135) {
Surface.ROTATION_270
} else if (orientation >= 135 && orientation < 225) {
Surface.ROTATION_180
} else if (orientation >= 225 && orientation < 315) {
Surface.ROTATION_90
} else {
Surface.ROTATION_0
}
imageCapture?.setTargetRotation(rotation)
}
}
This is also the recommended approach from a similar issue in the Google Issue Tracker: https://issuetracker.google.com/issues/144944155
回答2:
Please follow the Official documentation of camerax:
By default, the camera rotation is set to match the default display's rotation during the creation of the use case. In this default case, CameraX produces outputs to allow the app to easily match what you would expect to see in the preview. You can change the rotation to a custom value to support multi-display devices by passing in the current display orientation when configuring use case objects or dynamically after they have been created.
You can use the default display rotation and/or the camerax metadata output combinations from Preview.PreviewOutput() to create transforms for GLSurfaceView
display.
val previewConfig = PreviewConfig.Builder()
.setTargetRotation(windowManager.defaultDisplay.rotation)
.build()
Based on the set rotation, each use case will either rotate the image data directly or provide rotation metadata to the consumers of the non-rotated image data.
Preview: Metadata output is provided to create the right transforms for a GLSurfaceView display using Preview.PreviewOutput.getRotationDegrees().
ImageAnalysis: Metadata output is provided so that image buffer coordinates are known relative to display coordinates. The analyze() method provides a rotationDegrees parameter representing the rotation that needs to be applied to the image analysis data to match the viewfinder.
ImageCapture: The image Exif metadata will be altered to note the rotation setting.
回答3:
Try out this same in our case ExifInterface did't work.
private int getImgimageOrientation(){
final String[] imageColumns = { MediaStore.Images.Media._ID, MediaStore.Images.ImageColumns.ORIENTATION };
final String imageOrderBy = MediaStore.Images.Media._ID+" DESC";
Cursor cursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
imageColumns, null, null, imageOrderBy);
if(cursor.moveToFirst()){
int orientation = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.ImageColumns.ORIENTATION));
cursor.close();
return orientation;
} else {
return 0;
}
}
来源:https://stackoverflow.com/questions/59572176/how-do-we-detect-the-orientation-of-image-captured-using-camerax-if-application