Martin Seal Martin Seal - 4 months ago 45
Android Question

Get rotation of an image selected from the gallery on activity result on android

this question seems to come up often, I've read a lot on this subject my question is when i select an image from the gallery and pass it to on activity result the orientation is wrong, so i want to read it and correct it so it is always portrait,
I've implemented methods that work for launching the camera, taking a picture, and checking the Exif data to make sure its always portrait but this doesn't seem to work for selecting images for the gallery my rotation variable will always return 0

ExifInterface exifInterface = new ExifInterface(imgFile.getAbsolutePath());
int rotation =
exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
int rotationInDegrees = exifToDegrees(rotation);
System.out.println(rotation);
Matrix matrix = new Matrix();

if (rotation != 0f) {

matrix.preRotate(rotationInDegrees);
Bitmap bitmap2 = Bitmap.createBitmap(bitmap, 0,
0, bitmap.getWidth(), bitmap.getHeight(),
matrix,false);
imgView.setImageBitmap(bitmap2);
path = saveToInternalStorage(imageFileName,bitmap2,getApplicationContext());
}
else
path = saveToInternalStorage(imageFileName,bitmap,getApplicationContext());
}
catch (IOException e) {
e.printStackTrace();
}


ExifToDegrees method

private static int exifToDegrees(int exifOrientation) {
if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) {
return 90;
}
else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) {
return 180; }
else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {
return 270; }
else if (exifOrientation == 6) {
return 90; }
else if (exifOrientation == 3) {
return 180; }
else if (exifOrientation == 8) {
return 270; }
return 0;
}


As mentioned I've read a lot about this, some say its a bug with android some say its down to the new recent's file picker and we should use

getAbsolutePath()


and be checking for each SDK version and be saving the image first, I've done all of these with no joy some say we don't need to be using Exif at all and that

MediaStore.Images.ImageColumns.ORIENTATION


should work, but again this hasn't worked.

I'm targeting devices from ICS to M (I have all permissions I need granted) I'm saving the image to my folder

File directory = cw.getDir("SimpleAAC", Context.MODE_PRIVATE);


and saving the path in a database, i load the images from that folder, using the path from my database and using universal image loader,
after asking for permission i launch gallery with this

Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,
"Select A Picture"), PICK_IMAGE_REQUEST);
dialog.dismiss();


here is my onActivityResult code for the gallery

if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data !=
null && data.getData() != null) {

Uri uri = data.getData();

BitmapFactory.Options bitmapOptions = new
BitmapFactory.Options();
bitmapOptions.inSampleSize = 4;
InputStream inputStream = null;
try {
inputStream = getContentResolver().openInputStream(uri);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Bitmap scaledBitmap = BitmapFactory.decodeStream(inputStream,
null, bitmapOptions);
String timeStamp = new
SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = timeStamp + ".jpg";

ContextWrapper cw = new ContextWrapper(getApplicationContext());
File directory = cw.getDir("SimpleAAC", Context.MODE_PRIVATE);
File mypath = new File(directory,imageFileName);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mypath);
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}

//the relevant parts of this method(setThumbNailImageAndSave ) are
// included above


finalPath = setThumbnailImageAndSave(imageView,mypath);
ImageLoader imageLoader = ImageLoader.getInstance();
DisplayImageOptions options = new
DisplayImageOptions.Builder().cacheInMemory(true)
.cacheOnDisc(true).resetViewBeforeLoading(true)
.showImageForEmptyUri(R.drawable.ic_insert_photo_black_24dp)
.showImageOnFail(R.drawable.ic_insert_photo_black_24dp)
.showImageOnLoading(R.drawable.ic_insert_photo_black_24dp).build();

imageLoader.displayImage(finalPath, imageView, options);
System.out.println(finalPath);
}


So to conclude this question I'm looking for clarification, is this a bug? can i get around this using MediaStore.Images.ImageColumns.ORIENTATION and if so how? is it the intent.setAction(intent.ACTION_GET_CONTENT)? is it the post kitkat file changes?

Honestly I've read so much contradicting information on this and nothing i seem to try works, thanks for any and all replies

Answer

is this a bug?

In your code? Possibly. It is unclear how imgFile in your first code snippet relates to your last code snippet. But you are stripping all the EXIF headers by decoding the bitmap, then encoding it, in that last code snippet. If that is the file that you are examining via ExifInterface in your first code snippet, that's your problem.

can i get around this using MediaStore.Images.ImageColumns.ORIENTATION and if so how?

No, because your image may not come from the MediaStore.

Instead, given your uri, call openInputStream() on a ContentResolver. Then, pass that openInputStream() to a better ExifInterface, one that can read from streams rather than requiring a file. This sample app demonstrates the process, including having a copy of the better ExifInterface code, though I happen to use an InputStream from assets rather than from a ContentResolver.

If you want to make a local copy of the image for other reasons, then get rid of the decode-and-encode the bitmap logic in that last code snippet. Instead, openInputStream() with that uri, open a FileOutputStream on your desired file, and copy the bytes using normal Java I/O. This will keep the EXIF headers intact.

Also, in either scenario, please do all this Uri work on a background thread.

Comments