RedApparat / Fotoapparat

Making Camera for Android more friendly. 📸
Apache License 2.0
3.81k stars 405 forks source link

java.lang.OutOfMemoryError in .whenDone() #322

Closed MrSilverstein closed 5 years ago

MrSilverstein commented 5 years ago

Not always, but from time to time, I get:

 E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.debug, PID: 26609
    java.lang.OutOfMemoryError: Failed to allocate a 46476300 byte allocation with 16777216 free bytes and 30MB until OOM
        at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
        at android.graphics.Bitmap.nativeCreate(Native Method)
        at android.graphics.Bitmap.createBitmap(Bitmap.java:831)
        at android.graphics.Bitmap.createBitmap(Bitmap.java:808)
        at android.graphics.Bitmap.createBitmap(Bitmap.java:739)
        at com.example.CameraEngine$2.whenDone(CameraEngine.java:99)
        at com.example.CameraEngine$2.whenDone(CameraEngine.java:87)
        at io.fotoapparat.result.PendingResult$whenDone$1.invoke(PendingResult.kt:90)
        at io.fotoapparat.result.PendingResult$whenDone$1.invoke(PendingResult.kt:16)
        at io.fotoapparat.result.PendingResultKt$notifyCallbackOnMainThread$1.invoke(PendingResult.kt:111)
        at io.fotoapparat.result.PendingResultKt$notifyCallbackOnMainThread$1.invoke(PendingResult.kt)
        at io.fotoapparat.hardware.ExecutorKt$executeMainThread$1.run(Executor.kt:28)

comapred to other similar reports, it is often casused during the Bitmap creation process. I am cropping a part out of the original image and rotating this. SO the new image should be smaller than the original image,

fotoapparat.takePicture()
    .toBitmap()
    .whenDone(new WhenDoneListener<BitmapPhoto>() {
        @Override
        public void whenDone(@Nullable BitmapPhoto photo) {
            if (photo != null){
                int widthBitmap = photo.bitmap.getWidth();
                int heightBitmap = photo.bitmap.getHeight();
                int resizedWidth = heightBitmap / 4 * 3;
                int offsetX = (widthBitmap - resizedWidth) / 2;

                Matrix matrix = new Matrix();
                matrix.postRotate(90);

                Bitmap resizedBitmap = Bitmap.createBitmap(photo.bitmap, offsetX, 0, resizedWidth, heightBitmap, matrix, true);
                bitmapPhoto = new BitmapPhoto(resizedBitmap, 0);
            }
        }
    });
dmitry-zaitsev commented 5 years ago

Calling createBitmap is a memory intensive operation. Consider rotating the image by using view transformation methods instead.