How to get the Correct orientation of the image selected from the Default Image gallery

狂风中的少年 提交于 2019-11-26 02:53:26

问题


I have gone through some of the links to get the correct image orientation of the image selected from the default image gallery to be worked standard in all devices the exif tag always returns 0.

EXIF orientation tag value always 0 for image taken with portrait camera app android

Exif orientation tag returns 0

Exif data TAG_ORIENTATION always 0

http://mobisocial.stanford.edu/news/2011/08/rotating-images-in-android/

How to get an exact solution that will work on all devices?


回答1:


If the image(photo) was taken by a program made by you, you must set Parameters.setRotation with the correct rotation value.

This, depending of camera drive, rotates the image before save or save the rotation value to exif TAG_ORIENTATION.

Therefore, if TAG_ORIENTATION is null or zero, the image are in the correct orientation, otherwise you must rotate image according the value in TAG_ORIENTATION.

CODE

Get orientation from EXIF:

ExifInterface exif = null;
try {
    exif = new ExifInterface(path);
} catch (IOException e) {
    e.printStackTrace();
}  
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 
                                       ExifInterface.ORIENTATION_UNDEFINED);

Get bitmap rotated:

Bitmap bmRotated = rotateBitmap(bitmap, orientation);  

Method to rotate bitmap:

public static Bitmap rotateBitmap(Bitmap bitmap, int orientation) {

    Matrix matrix = new Matrix();
    switch (orientation) {
        case ExifInterface.ORIENTATION_NORMAL:
            return bitmap;
        case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
            matrix.setScale(-1, 1);
            break;
        case ExifInterface.ORIENTATION_ROTATE_180:
            matrix.setRotate(180);
            break;
        case ExifInterface.ORIENTATION_FLIP_VERTICAL:
            matrix.setRotate(180);
            matrix.postScale(-1, 1);
            break;
        case ExifInterface.ORIENTATION_TRANSPOSE:
            matrix.setRotate(90);
            matrix.postScale(-1, 1);
            break;
       case ExifInterface.ORIENTATION_ROTATE_90:
           matrix.setRotate(90);
           break;
       case ExifInterface.ORIENTATION_TRANSVERSE:
           matrix.setRotate(-90);
           matrix.postScale(-1, 1);
           break;
       case ExifInterface.ORIENTATION_ROTATE_270:
           matrix.setRotate(-90);
           break;
       default:
           return bitmap;
    }
    try {
        Bitmap bmRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        bitmap.recycle();
        return bmRotated;
    }
    catch (OutOfMemoryError e) {
        e.printStackTrace();
        return null;
    }
}



回答2:


For me ExifInterface worked quite well like this:

ExifInterface exifInterface = new ExifInterface(imagePath);
degree = Integer.parseInt(exifInterface.getAttribute(ExifInterface.TAG_ORIENTATION));

or you can try to get the details of image using MediaStore like this:

String[] orientationColumn = {MediaStore.Images.Media.ORIENTATION};
Cursor cur = managedQuery(imageUri, orientationColumn, null, null, null);
int orientation = -1;
if (cur != null && cur.moveToFirst()) {
    orientation = cur.getInt(cur.getColumnIndex(orientationColumn[0]));
} 

Similar Solution: ExifInterface always returns 1

Hope it helps.. :)




回答3:


I followed last answer and I tried hard to create a system to manage pictures, rotate, resize, cache and load into ImageViews and I can tell it is a hell. Even when all it was done it crashes sometimes cause OutOfMemory in some devices. Answer is correct but it is difficult to manage Bitmaps in Android.

My point is do not reinvent the wheel, it has a perfect design. Google itself encourage you to use Glide. It works in one line, super easy to use, lightweight in size and functions number, it manage EXIF by default, and it use memory like a charm.. It is simply black magic coded ;)

I'm not sure if Picasso also manages EXIF, but there is a quick intro to both of them:

https://inthecheesefactory.com/blog/get-to-know-glide-recommended-by-google/en

My Advice: do not waste your time and use them. You can solve your problem in one line:

Glide.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);



回答4:


For those who come along this post, make sure to use the exifinterface from the Android Support Library that was introduced in December 2016:

compile "com.android.support:exifinterface:25.1.0" // or newer

Details about this library can be found in the according Android Developers Blog post: Introducing the ExifInterface Support Library

They also included a sample code for dealing with rotation information stored in the exif interface:

int rotation = 0;
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);

switch (orientation) {
   case ExifInterface.ORIENTATION_ROTATE_90:
     rotation = 90;
     break;
  case ExifInterface.ORIENTATION_ROTATE_180:
     rotation = 180;
     break;
  case ExifInterface.ORIENTATION_ROTATE_270:
     rotation = 270;
     break;
}



回答5:


The solution for me was to create the ExifInterface from the input stream. Do not try to create it from a path, which maybe a content provider path and will fail to give the correct result. Convert the orientation into degrees and rotate image if required. Below is the key code for the solution when using the support library (e.g androidx.exifinterface.media.ExifInterface).

int orientation = 0;
InputStream input = mContext.getContentResolver().openInputStream(uri);
if (input != null){
    ExifInterface exif = new ExifInterface(input);
    orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
    input.close();
}

Here is my full code to obtain a correctly orientated bitmap selected from the Gallery, which also takes a maxsize. If using it make sure you check for the null return case.

public Bitmap getBitmapFromGalleryUri(Context mContext, Uri uri, Double maxSize)throws IOException {
    int orientation = 0;

    InputStream input = mContext.getContentResolver().openInputStream(uri);
    if (input != null){
        ExifInterface exif = new ExifInterface(input);
        orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
        //Log.d("Utils", "rotation value = " + orientation);
        input.close();
    }


    input = mContext.getContentResolver().openInputStream(uri);

    BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
    onlyBoundsOptions.inJustDecodeBounds = true;
    onlyBoundsOptions.inDither = true;//optional
    onlyBoundsOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional
    BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
    try {
        input.close();

    } catch (NullPointerException e) {
        e.printStackTrace();
    }

    if ((onlyBoundsOptions.outWidth == -1) || (onlyBoundsOptions.outHeight == -1)) {
        return null;
    }

    int originalSize = (onlyBoundsOptions.outHeight > onlyBoundsOptions.outWidth) ? onlyBoundsOptions.outHeight : onlyBoundsOptions.outWidth;

    double ratio = (originalSize > maxSize) ? (originalSize / maxSize) : 1.0;

    BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
    bitmapOptions.inSampleSize = getPowerOfTwoForSampleRatio(ratio);
    bitmapOptions.inDither = true; //optional
    bitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//
    input = mContext.getContentResolver().openInputStream(uri);
    Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
    try {
        input.close();

    } catch (NullPointerException e) {
        e.printStackTrace();
    }
    Matrix matrix = new Matrix();

    //Log.d("Utils", "rotation value = " + orientation);

    int rotationInDegrees = exifToDegrees(orientation);
    //Log.d("Utils", "rotationInDegrees value = " + rotationInDegrees);

    if (orientation != 0) {
        matrix.preRotate(rotationInDegrees);
    }

    int bmpWidth = 0;
    try {
        bmpWidth = bitmap.getWidth();
    } catch (NullPointerException e) {
        e.printStackTrace();
    }
    Bitmap adjustedBitmap = bitmap;
    if (bmpWidth > 0) {
        adjustedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    }

    return adjustedBitmap;

}
private static int getPowerOfTwoForSampleRatio(double ratio){
    int k = Integer.highestOneBit((int)Math.floor(ratio));
    if(k==0) return 1;
    else return k;
}

public 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; }
    return 0;
}


来源:https://stackoverflow.com/questions/20478765/how-to-get-the-correct-orientation-of-the-image-selected-from-the-default-image

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!