How can I find the orientation of a picture taken with Intent MediaStore.ACTION_IMAGE_CAPTURE?
Solution 1
I found the answer. The Exif of the image has an indicator of the orientation. Just in case, Exif can be viewed in Android like this:
ExifInterface exif = new ExifInterface("filepath");
exif.getAttribute(ExifInterface.TAG_ORIENTATION);
Solution 2
Read from Exif if available, otherwise read from MediaStore
public static int getImageOrientation(Context context, String imagePath) {
int orientation = getOrientationFromExif(imagePath);
if(orientation <= 0) {
orientation = getOrientationFromMediaStore(context, imagePath);
}
return orientation;
}
private static int getOrientationFromExif(String imagePath) {
int orientation = -1;
try {
ExifInterface exif = new ExifInterface(imagePath);
int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
switch (exifOrientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
orientation = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
orientation = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
orientation = 90;
break;
case ExifInterface.ORIENTATION_NORMAL:
orientation = 0;
break;
default:
break;
}
} catch (IOException e) {
Log.e(LOG_TAG, "Unable to get image exif orientation", e);
}
return orientation;
}
private static int getOrientationFromMediaStore(Context context, String imagePath) {
Uri imageUri = getImageContentUri(context, imagePath);
if(imageUri == null) {
return -1;
}
String[] projection = {MediaStore.Images.ImageColumns.ORIENTATION};
Cursor cursor = context.getContentResolver().query(imageUri, projection, null, null, null);
int orientation = -1;
if (cursor != null && cursor.moveToFirst()) {
orientation = cursor.getInt(0);
cursor.close();
}
return orientation;
}
private static Uri getImageContentUri(Context context, String imagePath) {
String[] projection = new String[] {MediaStore.Images.Media._ID};
String selection = MediaStore.Images.Media.DATA + "=? ";
String[] selectionArgs = new String[] {imagePath};
Cursor cursor = context.getContentResolver().query(IMAGE_PROVIDER_URI, projection,
selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
int imageId = cursor.getInt(0);
cursor.close();
return Uri.withAppendedPath(IMAGE_PROVIDER_URI, Integer.toString(imageId));
}
if (new File(imagePath).exists()) {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, imagePath);
return context.getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
}
return null;
}
Solution 3
For a quick fix, you can check if the image's width is bigger than the image's height. It means it's landscape and you can change it to portrait.
private Bitmap fromGallery(final Uri selectedImageUri) {
try {
Bitmap bm = MediaStore.Images.Media.getBitmap(this.getContentResolver(), selectedImageUri);
ExifInterface exif = new ExifInterface(selectedImageUri.getPath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
int angle = 0;
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
angle = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
angle = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
angle = 270;
break;
default:
angle = 0;
break;
}
Matrix mat = new Matrix();
if (angle == 0 && bm.getWidth() > bm.getHeight())
mat.postRotate(90);
else
mat.postRotate(angle);
return Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), mat, true);
}
catch (IOException e) {
Log.e("", "-- Error in setting image");
}
catch (OutOfMemoryError oom) {
Log.e("", "-- OOM Error in setting image");
}
return null;
}
Solution 4
I used a file provider and nothing worked except making a temporary copy and reading the data from it.
public static int getOrientation(Context context, Uri uri) {
int rotate = 0;
try {
ParcelFileDescriptor parcelFileDescriptor =
context.getContentResolver().openFileDescriptor(uri, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
FileInputStream input = new FileInputStream(fileDescriptor);
File tempFile = File.createTempFile("exif", "tmp");
String tempFilename = tempFile.getPath();
FileOutputStream output = new FileOutputStream(tempFile.getPath());
int read;
byte[] bytes = new byte[4096];
while ((read = input.read(bytes)) != -1) {
output.write(bytes, 0, read);
}
input.close();
output.close();
ExifInterface exif = new ExifInterface(tempFile.getAbsolutePath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
}
} catch (Exception e) {
Log.i(TAG, e.getLocalizedMessage());
}
return rotate;
}
bonus rotate function
public static Bitmap rotateImage(Context context, Uri uri, int orientation) throws IOException {
ParcelFileDescriptor parcelFileDescriptor =
context.getContentResolver().openFileDescriptor(uri, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
if (orientation > 0) {
Matrix matrix = new Matrix();
matrix.postRotate(orientation);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
return bitmap;
}
Arcantos
Updated on July 09, 2022Comments
-
Arcantos almost 2 years
When I take a picture with Android's camera app, it detects the phone's orientation and saves the picture accordingly. So if I take a picture of a building, the roof will be on the topside, whether I hold the phone in landscape position or portrait.
However, when I use
Intent imageCaptureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
to get a picture, the camera app doesn't react to the orientation. If I hold the phone vertically (portrait), the resulting picture will be rotated, with said building's roof to the left of the screen.
How can I set the intent so that the camera will take the orientation into account?
Or can I deduce in some way in what orientation the picture was taken and rotate it myself afterwards?
Or is there another way?
-
Andrew Mackenzie almost 13 yearsOnly available from API Level 10 and on... I'm using this method, but would like a method that would work on lower API versions
-
Stan Kurdziel over 12 yearsAll the orientation stuff looks like API Level 5 to me: developer.android.com/reference/android/media/… That's Android 2.0: developer.android.com/guide/appendix/api-levels.html I'm using it in 2.1 / Api level 7 successfully.
-
Manoj Kumar about 12 yearsI have implement this feature in our application for image issue. Really Good Feature for image orientation display and manage in developing application........
-
Andras Balázs Lajtha about 12 yearsNo exif information for me in HTC Widfire S, Android 2.3.6 :(
-
valerybodak over 9 yearsWhat is IMAGE_PROVIDER_URI constant? Thank you.
-
gts13 over 4 yearsIMAGE_PROVIDER_URI is missing
-
TatiOverflow about 4 yearswhy is it telling me that MediaStore.Images.ImageColumns.ORIENTATION field Requires Api level Q? I used to use this field w/o any issues before.