Android: BitmapFactory.decodeStream() out of memory with a 400KB file with 2MB free heap
Android library is not so smart for loading images, so you have to create workarounds for this.
In my tests, Drawable.createFromStream
uses more memory than BitmapFactory.decodeStream
.
You may change the Color scheme to reduce memory (RGB_565), but the image will lose quality too:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Config.RGB_565;
Bitmap bitmap = BitmapFactory.decodeStream(stream, null, options);
Reference: http://developer.android.com/reference/android/graphics/Bitmap.Config.html
You can also load a scaled image, which will decrease a lot the memory usage, but you have to know your images to not lose too much quality of it.
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
Bitmap bitmap = BitmapFactory.decodeStream(stream, null, options);
Reference: http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html
To define the inSampleSize dynamically, you may want to know the image size to take your decision:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
bitmap = BitmapFactory.decodeStream(stream, null, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
options.inJustDecodeBounds = false;
// recreate the stream
// make some calculation to define inSampleSize
options.inSampleSize = ?;
Bitmap bitmap = BitmapFactory.decodeStream(stream, null, options);
You can customize the inSampleSize according to the screen size of the device. To get the screen size, you can do:
DisplayMetrics metrics = new DisplayMetrics();
((Activity) activity).getWindowManager().getDefaultDisplay().getMetrics(metrics);
int screenWidth = metrics.widthPixels;
int screenHeight =metrics.heightPixels;
Other tutorials: - http://developer.android.com/training/displaying-bitmaps/load-bitmap.html - http://developer.android.com/training/displaying-bitmaps/index.html
Please see this for a guide on loading large Bitmaps more efficiently:
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
A 400 KB image file can easily take up 5-10 MB of RAM.
The size of the file on disk doesn't necessarily coincide with the size of the file in memory. Chances are likely that the file is compressed, which they won't be when decoded. You need to account for that in your calculation.
Multiply the size of the image (width x height) by the color depth of the image to get the in-memory size of the image.