theroom101
theroom101

Reputation: 609

Load big Images in Android

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

Answers (5)

theroom101
theroom101

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

kAnNaN
kAnNaN

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

dumazy
dumazy

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

Jitender Dev
Jitender Dev

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

makovkastar
makovkastar

Reputation: 5020

I would recommend to use Picasso library from Square. And PhotoView for image zooming.

Upvotes: 1

Related Questions