[英]How to rotate image to its default orientation selected from gallery in Android?
[英]How to get the Correct orientation of the image selected from the Default Image gallery
我已經瀏覽了一些鏈接,以獲得從默認圖像庫中選擇的圖像的正確圖像方向,以便在所有設備中正常工作,exif 標簽始終返回 0。
對於使用人像相機應用程序 android 拍攝的圖像,EXIF 方向標簽值始終為 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.