Масштабирование изображений в Android вызывает исключение OutOfMemory

1

Я разрабатываю Android-игру, состоящую из многих изображений как спрайтов.

Когда я загружаю изображения следующим образом:

public static Bitmap loadBitmap(int resId) {  
    return BitmapFactory.decodeResource(getResources(), resId, options);
}

все работает отлично.

Когда я пытаюсь масштабировать down- или up- масштабировать растровое изображение с помощью этого кода:

public static Bitmap loadBitmap(int resId) {
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resId, options);
    Matrix matrix = new Matrix();
    matrix.postScale(0.8f, 0.8f);
    Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    bitmap.recycle();
    bitmap = null;
    return scaledBitmap;
}

приложение вылетает со следующим исключением:

2211840-byte external allocation too large for this process.  
Out of memory: Heap Size=4935KB, Allocated=2549KB, Bitmap Size=18463KB  
VM won't let us allocate 2211840 bytes

Почему масштабирование вызывает исключение OutOfMemory? Я даже пытаюсь переработать исходное изображение, чтобы сохранить некоторое пространство. Я не использую Bitmap.createScaledBitmap(...) намеренно, так как этот метод делает утечку памяти внутренне (как объясняется в других онлайн-ресурсах).

Спасибо заранее,
Златко

Теги:
image-scaling
out-of-memory
bitmap

3 ответа

1

Вероятно, вы очень близко к пределу памяти. Похоже, вы создаете довольно большой растровый рисунок (и я не уверен, почему вы делаете его того же размера, что и исходное растровое изображение). Из журнала вы использовали 25 МБ распределений Java и 18 МБ распределений растровых изображений, поэтому вы в основном правы против предела кучи 48 МБ.

Также я думаю, что очень маловероятно, что createScaledBitmap() утечки. Все, что он делает, это в основном то, что вы здесь делаете.

  • 0
    Почему первый фрагмент кода никогда не приводит к исключению OOM? На самом деле, во втором фрагменте я масштабирую исходное растровое изображение до 80% его размера. Выделено, есть 2,5 МБ, а не 25 МБ
0

Вам следует попытаться использовать переменную "inSampleSized" в классе BitmapFactory.Options. Это будет масштабироваться без использования избыточной памяти.

http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inSampleSize

  • 0
    «inSampleSize» является переменной int> = 1, поэтому у меня нет точного контроля над коэффициентом масштабирования. В игре требуются специальные коэффициенты увеличения и уменьшения, например 0,7688
  • 0
    Требуется ли сохранение растрового изображения при изменении размера? Почему бы вам просто не применить матрицу к холсту, на котором вы рисуете при рисовании растрового изображения. Битовая карта большего размера будет находиться в памяти, но при этом она может использовать меньше памяти, поскольку другую битовую карту не нужно выделять.
0

Я думаю, вы действительно близки к пределу кучи. В вашей функции вы в основном создаете второй битмап, что примерно приводит к удвоению вашей памяти (битмапы очень большие). Если вы находитесь на ОС раньше, чем Honeycomb, это также вводит в заблуждение, чтобы посмотреть на значения памяти, которые где-то распечатываются. iirc, битмапы хранятся непосредственно в куче системной памяти, тогда как все остальные хранятся на куче vm (и это значения, которые вы видите → 2,5 МБ). Тем не менее, память для распределений битмапа также учитывается для ограничения кучи памяти.:/

Я предлагаю вам ознакомиться с этим сеансом ввода-вывода Google: http://www.youtube.com/watch?v=_CruQY55HOk

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

  • 0
    Спасибо за ссылку. Это действительно познавательно. Что касается проблемы, я не могу снизить разрешение, поскольку оно должно быть строго определено. Также я попробовал решение с кэшированием всех уже загруженных ресурсов. Когда я не занимаюсь переработкой изображений, я получаю OutOfMemory. Когда я перерабатываю, то я получаю ошибку SIGNAL 11 (WIN_DEATH), которую трудно отладить. Это действительно расстраивает ...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню