Страницы

Поиск по вопросам

пятница, 24 января 2020 г.

Как избавиться от ООМ при работе с Bitmap?

#java #android #bitmap


Я работаю с Bitmap и рабочий процесс выглядит так

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

Таким образом юзер делает 5 фото.

Так вот после первой фото и все хорошо. Фото показывается юзеру и проходит 2 этапа
подтверждения.

Но на втором фото юзеру показывается фото , он ее подтверждает и получает ошибку

FATAL EXCEPTION: AsyncTask #2
    Process: com.fittingroom.newtimezone, PID: 7196
            java.lang.RuntimeException: An error occurred while executing doInBackground()
                at android.os.AsyncTask$3.done(AsyncTask.java:309)
                at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
                at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
                at java.util.concurrent.FutureTask.run(FutureTask.java:242)
                at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
                at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
                at java.lang.Thread.run(Thread.java:818)
            Caused by: java.lang.OutOfMemoryError: Failed to allocate a 63489036
byte allocation with 16777216 free bytes and 60MB until OOM
                at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
                at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
                at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:882)
                at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:858)
                at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:478)
                at com.fittingroom.newtimezone.presenters.PresenterActivityAcceptNotAccept.getCroppedBitmapFromPath(PresenterActivityAcceptNotAccept.java:65)
                at com.fittingroom.newtimezone.presenters.PresenterActivityAcceptNotAccept.access$200(PresenterActivityAcceptNotAccept.java:16)
                at com.fittingroom.newtimezone.presenters.PresenterActivityAcceptNotAccept$1.doInBackground(PresenterActivityAcceptNotAccept.java:41)
                at com.fittingroom.newtimezone.presenters.PresenterActivityAcceptNotAccept$1.doInBackground(PresenterActivityAcceptNotAccept.java:31)
                at android.os.AsyncTask$2.call(AsyncTask.java:295)
                at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) 
                at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
                at java.lang.Thread.run(Thread.java:818)


вот код в котором появляется ошибка

private Bitmap getCroppedBitmapFromPath(String path) {
    final File photo = new File(path);
    final BitmapFactory.Options options = new BitmapFactory.Options();
    final Bitmap bitmap = BitmapFactory.decodeFile(photo.getAbsolutePath(), options);
    int height = bitmap.getHeight();

    Bitmap result;
    final Matrix matrix = new Matrix();
    matrix.postRotate(90);
    final double centerX = height * 0.5;
    final double centerY = height / 447 * 480;
    final double widthAndHeight = height / 447 * 160;
    final int pointY = (int) (centerX - widthAndHeight / 2);
    final int pointX = (int) (bitmap.getWidth() - centerY - widthAndHeight / 2);
    final int widthAndHeightResult = (int) widthAndHeight;
    result = Bitmap.createBitmap(bitmap, pointX, pointY, widthAndHeightResult, widthAndHeightResult,
matrix, false);

    return result;
}


Вот в этой строчке 

final Bitmap bitmap = BitmapFactory.decodeFile(photo.getAbsolutePath(), options);


может как то нужно освобождать байты с которыми Bitmap работает? 

или может как то уменьшить размер картинки?
    


Ответы

Ответ 1



Можно, если это например jpeg или png работать с картинкой меньшего качества, а потом уже приводить ее к нормально виду, когда закончили работу. А как менять качество: BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 8; final Bitmap bitmap = BitmapFactory.decodeFile(selectedImageUri.getPath(), options); Да и в плюс данного метода: наверняка эта картинка маленькая, результирующая нет смысла показывать хорошее качество

Комментариев нет:

Отправить комментарий