Android BitmapFactory decodeResource Исключение из памяти

Я новичок в Android и разрабатываю приложение, которое сохраняет большие изображения из папки с возможностью рисования в хранилище телефона. Эти файлы имеют разрешение 2560x2560, и я хочу сохранить эти файлы без потери качества изображения.

Я использую следующий метод для сохранения изображений, и он дает мне Исключение нехватки памяти. Я видел много ответов, как эффективно загружать большие растровые изображения. Но я не могу найти ответ на эту проблему.

В моем коде я использую

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), imageId);
File file = new File(root.getAbsolutePath() + "/Pictures/" + getResources().getString(R.string.app_name) + "/" + timeStamp + ".jpg");
file.createNewFile();
FileOutputStream oStream = new FileOutputStream(file);
bitmap.compress(CompressFormat.JPEG, 100, oStream);
oStream.close();
bitmap.recycle();

Что-то не так с моим кодом? Это работает без каких-либо исключений для небольших изображений.

Если я использую android:largeHeap="true", это не вызывает никаких исключений. Но я знаю, что использовать android:largeHeap="true" не рекомендуется.

Есть ли какой-либо эффективный способ без исключения сохранять большие изображения из папки с возможностью рисования?

Заранее спасибо.


person Vajira Lasantha    schedule 10.01.2016    source источник


Ответы (1)


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

Вы можете скопировать необработанный файл ресурсов, например:

InputStream in = getResources().openRawResource(imageId);
String path = root.getAbsolutePath() + "/Pictures/" + getResources().getString(R.string.app_name) + "/" + timeStamp + ".jpg";
FileOutputStream out = new FileOutputStream(path);
try {
    byte[] b = new byte[4096];
    int len = 0;
    while ((len = in.read(b)) > 0) {
        out.write(b, 0, len);
    }
}
finally {
    in.close();
    out.close();
}

Обратите внимание, что вы должны хранить изображение в каталоге res/raw/, а не в каталоге res/drawable/.

person Floern    schedule 10.01.2016
comment
Согласованный. Или сохраните их как активы (например, в src/main/assets/ модуля Android Studio) и скопируйте их оттуда (вызовите open() в AssetManager, который вы получите, вызвав getAssets()). - person CommonsWare; 11.01.2016
comment
@Floern Похоже, это хорошая идея. Но я загружаю те же изображения в ImageView моего приложения (используя внешнюю библиотеку под названием Subsampling Scale Image View от davemorrissey). Поэтому, если я помещу эти изображения в необработанную папку, приложение просто снова выйдет из строя с исключением Out of Memory (в android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:500)). - person Vajira Lasantha; 11.01.2016
comment
@VajiraLasantha происходит сбой, потому что на вашем устройстве недостаточно оперативной памяти для хранения вашего изображения. Ваш ImageView должен быть меньше вашего экрана, поэтому вы можете изменить размер изображения, чтобы он соответствовал вашему ImageView, а затем отобразить его. Вот полезная ссылка: developer.android.com/training/displaying-bitmaps / - person mr.icetea; 11.01.2016
comment
@Floern исправил. Использованы параметры Bitmap.Config.RGB_565 и inDither = true при декодировании растрового изображения из необработанного файла изображения для отображения в ImageView, и теперь все работает нормально. Спасибо за ваш ответ. - person Vajira Lasantha; 11.01.2016