Как получить правильную ориентацию изображения, выбранного из галереи изображений по умолчанию

Я просмотрел некоторые ссылки, чтобы получить правильную ориентацию изображения, выбранную из галереи изображений по умолчанию, которая будет работать стандартно во всех устройствах, тег exif всегда возвращает 0.

Значение тега ориентации EXIF ​​всегда 0 для изображения, сделанного с помощью приложения для портфолио с вертикальной камерой

Тег ориентации Exif возвращает 0

Данные Exif TAG_ORIENTATION всегда 0

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

Как получить точное решение, которое будет работать на всех устройствах?

Ответ 1

Если изображение (фотография) было выполнено программой, сделанной вами, вы должны установить Parameters.setRotation с правильным значением вращения.

Это, в зависимости от привода камеры, поворачивает изображение перед сохранением или сохраняет значение вращения в exif TAG_ORIENTATION.

Поэтому, если TAG_ORIENTATION имеет значение null или ноль, изображение находится в правильной ориентации, иначе вы должны повернуть изображение в соответствии со значением в 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;
    }
}

Ответ 2

Для меня 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

Надеюсь, это поможет..:)

Ответ 3

Я последовал за последним ответом, и я попытался создать систему для управления изображениями, поворота, изменения размера, кеширования и загрузки в ImageViews, и я могу сказать, что это ад. Даже когда все это было сделано, сбои иногда вызывают OutOfMemory в некоторых устройствах. Ответ правильный, но управлять Bitmaps в Android сложно.

Моя задача - не изобретать колесо, он имеет идеальный дизайн. Google сам рекомендует вам использовать Glide. Он работает в одной строке, супер прост в использовании, имеет легкий размер и количество функций, он управляет EXIF ​​по умолчанию, и он использует память как шарм. Это просто закодированная черная магия;)

Я не уверен, что Picasso также управляет 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);

Ответ 4

Для тех, кто приходит на этот пост, обязательно используйте exifinterface из Библиотеки поддержки Android, которая была представлена ​​в декабре 2016 года:

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