简体   繁体   中英

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM