1

This is an issue that has plagued me for MONTHS. I've seen all the SO posts there are about rotating an image chosen from the gallery or taken via image capture intent, but none have worked. The big offender is, of course, Samsung devices, but I've even seen some funky behavior on my Nexus.

I'm using intents to choose images from gallery and camera, but it seems that landscape photos always seem to come in rotated 90 degrees. The first step is always ExifInterface, something like this:

ExifInterface exif = new ExifInterface(imageUri.getLastPathSegment();
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
int rotationNeeded = getRotationFromExifData(orientation);
Matrix matrix = new Matrix();
matrix.setRotate(rotationNeeded);

Where getRotationFromExifData(orientation) is:

private static int getRotationFromExifData(int orientation) {
    Log.d(LOG_TAG, "Orientation: " + orientation);
    switch (orientation) {
        case ExifInterface.ORIENTATION_ROTATE_90:
            Log.d(LOG_TAG, "Exif returned 90");
            return 90;
        case ExifInterface.ORIENTATION_ROTATE_180:
            Log.d(LOG_TAG, "Exif returned 180");
            return 180;
        case ExifInterface.ORIENTATION_ROTATE_270:
            Log.d(LOG_TAG, "Exif returned 270");
            return 270;
        default: // Normal or 0
            Log.d(LOG_TAG, "Exif returned 0");
            return 0;
    }
}

This doesn't work, ExifInterface (from what I'm seeing) always returns 0 (or normal), especially on Samsung devices.

Other steps include querying the MediaStore and other junk that doesn't work. Can somebody please tell me what the exact way to get proper image rotation using all native Intents, so all images are displayed correctly? Thanks in advance.

Community
  • 1
  • 1
Brandon
  • 1,886
  • 2
  • 17
  • 28

1 Answers1

0

Not sure about the photos selected from gallery but for that taken directly from camera, you can try this:

In your activity/fragment to capture a photo, try adding and enabling an OrientationEventListener in onResume(), and disabling it in onPause().

Here is the onResume()

@Override
public void onResume() {
    super.onResume();
    orientationListener = new OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL) {
            @Override
            public void onOrientationChanged(int angle) {
                if (angle > 315 || angle <= 45) {
                    rotation = 90;
                } else if (angle > 45 && angle <= 135) {
                    rotation = 180;
                } else if (angle > 135 && angle <= 225) {
                    rotation = 270;
                } else if (angle > 225 && angle <= 315) {
                    rotation = 0;
                } else {
                    rotation = -1;// UNKNOWN
                }

                if (currentFacing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                    rotation = (360 - rotation) % 360;
                }

                Log.i("Orientation", "rotation = " + rotation);
            }
        };

        if (orientationListener.canDetectOrientation()) {
            orientationListener.enable();
        }
}

Here is the onPause()

@Override
public void onPause() {
    //...
    orientationListener.disable();
    super.onPause();
}

When you take the photo using your camera, use that rotation to rotate the bitmap accordingly, as following:

       camera.takePicture(null, null, null, new PictureCallback() {

            @Override
            public void onPictureTaken(byte[] data, Camera camera) {

                Bitmap theBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

                if (rotation != -1) {
                    Matrix matrix = new Matrix();
                    matrix.postRotate(rotation);

                    theBitmap = Bitmap.createBitmap(theBitmap, 0, 0, theBitmap.getWidth(), theBitmap.getHeight(), matrix, false);
                }

                // Save the bitmap here...
            }
        }

Hope this helps.

Nguyen Tuan Anh
  • 1,036
  • 8
  • 14