Android Camera Intent Saving Image Landscape When Taken Portrait [duplicate]
Asked Answered
A

2

41

I have had a look around but there doesn't seem to be a solid answer/solution to the, very irritating, problem.

I take a picture in portrait orientation and when I hit save/discard the buttons are in the correct orientation also. The problem is when I then retrieve the image later on it is in landscape orientation (the picture has been rotated 90 degrees anti-clockwise)

I don' want to force the user to use the camera in a certain orientation.

Is there a way to maybe detect whether the photo was taken in portrait mode and then decode the bitmap and flip it the correct way up?

Avulsion answered 17/10, 2012 at 11:16 Comment(0)
U
89

The picture is always taken in the orientation the camera is built into the device. To get your image rotated correctly you'll have to read the orientation information that is stored into the picture (EXIF meta data). There it is stored how the device was oriented, when the image was taken.

Here is some code that reads the EXIF data and rotates the image accordingly: file is the name of the image file.

BitmapFactory.Options bounds = new BitmapFactory.Options();
bounds.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file, bounds);

BitmapFactory.Options opts = new BitmapFactory.Options();
Bitmap bm = BitmapFactory.decodeFile(file, opts);
ExifInterface exif = new ExifInterface(file);
String orientString = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
int orientation = orientString != null ? Integer.parseInt(orientString) :  ExifInterface.ORIENTATION_NORMAL;

int rotationAngle = 0;
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) rotationAngle = 90;
if (orientation == ExifInterface.ORIENTATION_ROTATE_180) rotationAngle = 180;
if (orientation == ExifInterface.ORIENTATION_ROTATE_270) rotationAngle = 270;

Matrix matrix = new Matrix();
matrix.setRotate(rotationAngle, (float) bm.getWidth() / 2, (float) bm.getHeight() / 2);
Bitmap rotatedBitmap = Bitmap.createBitmap(bm, 0, 0, bounds.outWidth, bounds.outHeight, matrix, true);

UPDATE 2017-01-16

With the release of the 25.1.0 Support Library, an ExifInterface Support Library was introduced, which should perhaps make the access to the Exif attributes easier. See the Android Developer's Blog for an article about it.

Upstart answered 17/10, 2012 at 11:49 Comment(16)
+1 many thanks! Shame no way to do without the (sometimes) creation of second bitmap. Damn Android and its tiny VMsSmalley
Where do you initialize opts and resizedBitmap?Jibheaded
@lschessinger, good catch (after 2 years). I've updated the code.Upstart
please see hereFanchette
rotatedBitmap is never used..Fanchette
rotatedBitmap is the result of the whole operation. It contains the corrected image (rotated according to EXIF information)Upstart
setRotate seems to be removed by Android. This code does not work anymoreRemanent
@SrujanBarai I don't think so: developer.android.com/reference/android/graphics/…Upstart
what is the first decode doing here? It is not returning any bitmap but as per documentation "the out... fields will still be set" with bounds.inJustDecodeBounds = true; What does this mean?Colporteur
@SudipBhandari the first decode() just reads the size of the bitmap into the bounds variable. It is used later on.Upstart
can we get exif from bitmap directly without writing it to a file? @RidicullyColporteur
@SudipBhandari No you can't. EXIF is part of the JPEG file, not part of the bitmap. The bitmap is just raw, uncompressed image data.Upstart
hey its taking too much time any solution on that?,Sandpaper
this code not working at all on my samsung galaxy s7. can you help me? it makes me so crazyPathogenic
@Pathogenic try to run in debugger and see what orientation you read from the file. Also, if possible try the ExifInterface Support Library I mentioned.Upstart
@Pathogenic also see answer by D. Scott below, about Samsung devicesUpstart
F
1

The selected answer uses the most common method answered to this and similar questions. However, it did not work for me with both front and back cameras on Samsung. For those needing another solution which works across both front and back cameras for Samsung and other major manufacturers, this answer by nvhausid is awesome:

https://mcmap.net/q/50206/-controlling-the-camera-to-take-pictures-in-portrait-doesn-39-t-rotate-the-final-images

For those who don't want to click through, the relevant magic is to use the CameraInfo rather then relying on EXIF or a Cursor over the media files.

Bitmap realImage = BitmapFactory.decodeByteArray(data, 0, data.length);
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(mCurrentCameraId, info);
Bitmap bitmap = rotate(realImage, info.orientation);

Full code in the link.

Furore answered 30/10, 2016 at 3:2 Comment(2)
It is not working too.............Pathogenic
Where does mCurrentCameraId come from?Taliped

© 2022 - 2024 — McMap. All rights reserved.