Reputation: 609
It is known that Android has issues with storing bitmap data in RAM memory. I need to load an image (a photo from 13Mpx camera) on the View and then I need to be able to zoom-in and zoom-out the image. The Image should be mutable. Now it is implemented this way:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inMutable = true;
_bitmap = BitmapFactory.decodeFile(_path, options);
When I take a large photo (13 or 8 Mpx) programm crushed with "Out of memory" error. I need some solution for this problem. I need some class that can load and operate (scaling it) with big images. It's needed to be equal or less than API-8.
I tried Universall Image Loader, but it has no scaling option. Does someone know any ideas how to solve this problem?
Upvotes: 1
Views: 1135
Reputation: 609
Thanks a lot to all for all of ur answers.
I thought that I should use inJustDecodeBounds option and load resized bitmap, but In need a fresh view to this problem of more experienced persons.
I also thought about using Universal Image Loader for loading and caching large images and something like ScaleImageView for Zooming it.
There is something that can solve my problem. Load bitmap partially.
Upvotes: 0
Reputation: 3679
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
To avoid java.lang.OutOfMemory
exceptions, check the dimensions of a bitmap before decoding it, unless you absolutely trust the source to provide you with predictably sized image data that comfortably fits within the available memory. Reference
Upvotes: 1
Reputation: 14435
A bitmap takes up 4 bytes per pixel ==> 13MP equals 52MB of memory.
You should use BitmapFactory.Options to get the size only first. By using inJustDecodeBounds
you get the Bitmap object with all its meta data, but without the actual image.
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
then calculate the scale size that your screen needs:
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
and use that to load a scaled version of your bitmap:
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
This is all explained in the Developer Guide
Upvotes: 2
Reputation: 6925
Try this for scaling the bitmap
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
/*
* If set to a value > 1, requests the decoder to
* subsample the original image, returning a smaller
* image to save memory. The sample size is the
* number of pixels in either dimension that
* correspond to a single pixel in the decoded
* bitmap. For example, inSampleSize == 4 returns an
* image that is 1/4 the width/height of the
* original, and 1/16 the number of pixels. Any
* value <= 1 is treated the same as 1. Note: the
* decoder uses a final value based on powers of 2,
* any other value will be rounded down to the
* nearest power of 2.
*/
options.inSampleSize = 2;
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeFile(path, options);
Upvotes: 1
Reputation: 5020
I would recommend to use Picasso library from Square. And PhotoView for image zooming.
Upvotes: 1