I am trying to find an efficient way to load a Bitmap
from a file containing an arbitrarily large image, place a watermark (a logo) over it, and save it back to fil
Using BitmapFactory.decodeFile(File) leads to OutOfMemory issues when decoding large pictures
OutOfMemoryError
occurs because there is no single block of heap space big enough for your request. The Dalvik garbage collector is a non-compacting collector, and so the heap will get fragmented into lots of smaller blocks of memory.
If all of the pictures will be the same resolution, and your minSdkVersion
is 11 or higher, then allocate the Bitmap
for it when your process starts up (e.g., in onCreate()
of a custom Application
class), and use that with inBitmap
on your BitmapFactory.Options
. Your attempt to allocate the Bitmap
should succeed early on, before your heap gets fragmented, if the image can fit in the heap in the first place.
If they will not all be the same resolution, but you know the maximum resolution, and your minSdkVersion
is 19 or higher, then do the same thing as I describe above. Android 4.4 extended inBitmap
to support a Bitmap
that is the same size or bigger than the image you are loading, whereas before it had to match the size exactly.
If none of that is possible:
Use android:largeHeap="true"
to get a larger heap on API Level 11+ devices, or
Move your image-processing logic to the NDK, as native memory allocations do not count against the Dalvik heap limit, or
Move your image-processing logic to a dedicated short-lived process, so you get a clean separate heap at the point in time when you need to process a particular image
Those latter three options have costs to the user in terms of the system RAM consumption of your app and other effects.