2013-07-14 4 views
6
public static boolean rotateBitmapByExifAndSave(File targetFile){ 

    if (targetFile==null || !targetFile.exists() || !targetFile.canRead() || !targetFile.canWrite()) 
     return false; 

    boolean isSucceed = false; 
    // detect if photo is need to be rotated 
    try { 
     final Matrix matrix = new Matrix(); 

     ExifInterface exifReader = new ExifInterface(targetFile.getAbsolutePath()); 

     int orientation = exifReader.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1); 
     boolean isRotationNeeded = true; 

     switch (orientation) { 
     case ExifInterface.ORIENTATION_ROTATE_90: 
      matrix.postRotate(90); 
      break; 

     case ExifInterface.ORIENTATION_ROTATE_180: 
      matrix.postRotate(180); 
      break; 

     case ExifInterface.ORIENTATION_ROTATE_270: 
      matrix.postRotate(270); 
      break; 

     default: // ExifInterface.ORIENTATION_NORMAL 
      // Do nothing. The original image is fine. 
      isRotationNeeded = false; 
      isSucceed = true; 
      break; 
     } 

     if (isRotationNeeded){ 
      BitmapFactory.Options bmfOtions = new BitmapFactory.Options(); 
      Bitmap bitmap = null; 
      FileInputStream fileInputStream = null; 
      try { 
       fileInputStream = new FileInputStream(targetFile); 
       bitmap = BitmapFactory.decodeStream(fileInputStream,null,bmfOtions); 
      } catch (FileNotFoundException e){ 
       isSucceed = false; 
      } 
      finally { 
       if (fileInputStream != null) 
        try { 
         fileInputStream.close(); 
        } catch (IOException e) {} 
      } 
      if (bitmap!=null){ 
       bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); 
       isSucceed = ImageUtils.saveBitmapToFile(bitmap, targetFile, 100); 
       bitmap.recycle(); 
      } 
     } 

    } catch (IOException e) { 
     Log.e("ImageUtils", e); 
    } catch (Exception e) { 
     // like there is no EXIF support? 
     Log.e("ImageUtils", e); 
    } catch (Throwable e) { 
     // stupid Out of VM's memory 
     Log.e("ImageUtils", e.toString()); 
    } 

    return isSucceed; 
} 

Этот метод используется для поворота исходных фотографий, сделанных камерой устройства. В настоящее время камера может быть больше 8MPix (Samsung Galaxy S4 имеет 13 мегапиксельную камеру). И даже с меньшей камерой MPix (мой 5 MP, 2592 x 1944 пикселей, что в сочетании с ARGB_888 принимает 19Mb ОЗУ в соответствии с официальными документами) Я уже получил OutOfMemory. Итак, вопрос в том, как повернуть фотографию БЕЗ потери первоначального разрешения и, таким образом, качества?Как избежать OutOfMemory ex во время поворота изображения?

+0

Вы решили эту проблему? @Stan – bentzy

+0

Эй, Стэн Мне нужен этот вопрос. Помогите мне, если сможете! спасибо – therealprashant

ответ

2

Поскольку ответа не было, я полагаю, что ответа нет или, может быть, я просто задал вопрос немного неправильно. Похоже, что единственный вариант здесь to increase the app's heap size
UPDATE:
Существует также другой вариант - работать с растровыми изображениями через НДК/JNI как here или использовать Android Image-Magic lib. Image Magic Lib довольно прохладно, чтобы повернуть изображение все, что вам нужно:

ImageInfo imageInfo = new ImageInfo(imageFile.getAbsolutePath()); 
MagickImage magickImage = new MagickImage(imageInfo); 
magickImage.setCompression(100); // to minimize loss 
magickImage.rotateImage(90.0f).writeImage(imageInfo); 

MagickImage имеет много других вариантов изображения манипулирования, а также. Размытие, матовый, масштаб, древесный уголь и многие другие. Однако размер их библиотек примечателен. Авторы отлично поработали, и они охватывали все возможные форматы: arm64-v8a, armeabi, armeabi-v7a, mips, mips64, x86, x86_64 и конечный размер всех этих libs - более 36 Мб. Поэтому вы должны подумать, прежде чем добавлять все библиотеки в один apk, возможно, упаковка 6 различных версий, использующих манифест для фильтрации по набору микросхем/платформы, является правильным способом.
UPDATE
Другим вариантом является convert Immutable Bitmap into Mutable (wrap bitmaps into MappedByteBuffer)

+1

Ваш прецедент, по-видимому, не оправдывает декодирование/кодирование JPEG в первую очередь. Это не только проблема с памятью (как указывает ваш принятый ответ, существует множество способов избежать OOM), это также влияет на производительность и качество изображения. Вы можете выполнить без потерь вращение изображения JPEG в соответствии с флагом EXIF, как показано [здесь] (http://stackoverflow.com/questions/706665/lossless-jpeg-rotate-90-180-270-degrees-in-java) , Библиотеку Android можно найти на ** [GitHub] (https://github.com/bkhall/AndroidMediaUtil) ** –

+1

Я попробовал решение LLJTran/AndroidMediaUtil, и он не работает! Я попытался повернуть очень большое изображение в формате JPEG (2400x4200). Он работает медленно, и он создает OOM без JPEG. – Stan

+0

Btw, AndroidMediaUtil имеет раздражающую «функцию» - они включали XML-файл (makernote.xml) в ресурсы и, таким образом, они создали боль в @ss, потому что проект lib/jar не может содержать никаких ресурсов (исключая формат аара). Даже если вы импортируете его как модуль в AndroidStudio, это не поможет. Так что мне пришлось жестко кодировать информацию из этого xml в String, чтобы заставить его работать. Также 2400x4200 не так уж и велика, так как моя камера снимает 2400x3200. – Stan

-1

Сделать имя метода декодирования файла:

public static Bitmap decodeFile(File f,int WIDTH,int HIGHT){ 
     try { 
      //Decode image size 
      BitmapFactory.Options o = new BitmapFactory.Options(); 
      o.inJustDecodeBounds = true; 
      BitmapFactory.decodeStream(new FileInputStream(f),null,o); 

      //The new size we want to scale to 
      final int REQUIRED_WIDTH=WIDTH; 
      final int REQUIRED_HIGHT=HIGHT; 
      //Find the correct scale value. It should be the power of 2. 
      int scale=1; 
      while(o.outWidth/scale/2>=REQUIRED_WIDTH && o.outHeight/scale/2>=REQUIRED_HIGHT) 
       scale*=2; 

      //Decode with inSampleSize 
      BitmapFactory.Options o2 = new BitmapFactory.Options(); 
      o2.inSampleSize=scale; 
      return BitmapFactory.decodeStream(new FileInputStream(f), null, o2); 
     } catch (FileNotFoundException e) {} 
     return null; 
    } 

затем вызвать этот метод, как это (Вы можете вызвать этот метод нажатия кнопки слушателя)

Bitmap bi = decodeFile(new File(path),1280,800); 

Где путь - путь к изображению, где вы сохраняете свое изображение .. в моем случае это

String path = Environment.getExternalStorageDirectory().toString() + "/nature.jpg"; 

В случае возникновения проблем - спросите :) Надеюсь, это поможет.

+0

Эта ошибка возникает из-за нехватки памяти, поэтому вам нужно установить ее высоту и ширину, передать ее в этом методе –

+1

Вы прочитали это: Итак, вопрос в том, как повернуть фотографию БЕЗ потери первоначального размера и, таким образом, качества? – Stan

+0

вы можете установить одинаковый размер изображения в этом и чуваке. –

Смежные вопросы