6

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.

arungiri_10
  • 988
  • 1
  • 11
  • 23
  • you can use `ImageAnalysis.setTargetRotation()` and `Preview.PreviewOutput()` to decide the rotation of the photo taken using camerax api – Sudheesh R Jan 03 '20 at 01:51
  • How do I get to know about the rotation degree to set in `ImageAnalysis.setTargetRotation()`. As mentioned in the question, the app is fixed to portrait mode and Display Manager doesnt give rotation Degree since the display doesnt rotate. – arungiri_10 Jan 03 '20 at 04:54
  • From the documentation: "You might use this when the app is locked to portrait mode—and so no reconfiguration occurs on rotation—but the photo or analysis use case needs to be aware of the current rotation of the device. For example, rotation awareness may be needed so faces are oriented correctly for face detection, or photos are set to landscape or portrait. Although data for captured images is stored without rotating it, the Exif data contains rotation information so that gallery applications can show the image in the correct orientation after saving." – Sudheesh R Jan 03 '20 at 05:52
  • Yes you are right. `but the photo or analysis use case needs to be aware of the current rotation of the device`. So how do I get to know the current rotation? – arungiri_10 Jan 03 '20 at 05:56
  • I understood your problem, could you check out this [answer](https://stackoverflow.com/a/9022405/6630837), I think this may help you. And try [this](https://stackoverflow.com/a/26735408/6630837) too if you are concerned about battery optimizations. – Sudheesh R Jan 03 '20 at 06:12

3 Answers3

6

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

Karl Jamoralin
  • 1,240
  • 1
  • 14
  • 27
0

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;
}
}
haresh
  • 1,424
  • 2
  • 12
  • 18
-1

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.

Sudheesh R
  • 1,767
  • 3
  • 23
  • 43