簡體   English   中英

如何獲得從默認圖像庫中選擇的圖像的正確方向

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

我已經瀏覽了一些鏈接,以獲得從默認圖像庫中選擇的圖像的正確圖像方向,以便在所有設備中正常工作,exif 標簽始終返回 0。

對於使用人像相機應用程序 android 拍攝的圖像,EXIF 方向標簽值始終為 0

Exif 方向標簽返回 0

Exif 數據 TAG_ORIENTATION 始終為 0

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

如何獲得適用於所有設備的精確解決方案?

如果圖像(照片)是由您制作的程序拍攝的,您必須使用正確的旋轉值設置 Parameters.setRotation。

這取決於相機驅動器,在保存之前旋轉圖像或將旋轉值保存到 exif TAG_ORIENTATION。

因此,如果 TAG_ORIENTATION 為空或零,則圖像處於正確的方向,否則您必須根據 TAG_ORIENTATION 中的值旋轉圖像。

代碼

從 EXIF 獲取方向:

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

獲取位圖旋轉:

Bitmap bmRotated = rotateBitmap(bitmap, orientation);  

旋轉位圖的方法:

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;
    }
}

對我來說 ExifInterface 工作得很好,就像這樣:

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

或者您可以嘗試使用MediaStore獲取圖像的詳細信息,如下所示:

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]));
} 

類似的解決方案: ExifInterface 總是返回 1

希望它有幫助.. :)

對於那些看到這篇文章的人,請確保使用 2016 年 12 月推出的 Android 支持庫中的 exifinterface:

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

有關此庫的詳細信息可以在相應的 Android 開發者博客文章中找到: ExifInterface 支持庫介紹

他們還包括一個示例代碼,用於處理存儲在 exif 界面中的旋轉信息:

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;
}

我遵循了最后一個答案,我努力創建一個系統來管理圖片、旋轉、調整大小、緩存和加載到 ImageViews 中,我可以說這是一個地獄。 即使完成了所有操作,它有時也會在某些設備中導致 OutOfMemory 崩潰。 答案是正確的,但在 Android 中很難管理位圖。

我的觀點是不要重新發明輪子,它有一個完美的設計。 Google 本身鼓勵您使用Glide 它在一行中工作,超級易於使用,體積和功能數量輕巧,默認情況下管理 EXIF ,並且它像魅力一樣使用內存......它只是黑魔法編碼;)

我不確定畢加索是否也管理 EXIF,但有一個對它們的快速介紹:

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

我的建議:不要浪費你的時間並使用它們。 您可以在一行中解決您的問題:

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

我的解決方案是從輸入流創建 ExifInterface。 不要嘗試從路徑創建它,這可能是內容提供者路徑,並且無法給出正確的結果。 如果需要,將方向轉換為度數並旋轉圖像。 以下是使用支持庫(例如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();
}

這是我的完整代碼,用於獲取從 Gallery 中選擇的正確方向的位圖,它也需要一個 maxsize。 如果使用它,請確保檢查空返回情況。

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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM