Alex Rivera | Logout

Handling large Bitmaps

Asked 2010-02-08T10:40:52.580
32

I have a bunch of image URLs. I have to download these images and display them in my application one-by-one. I am saving the images in a Collection using SoftReferences and also on Sdcard to avoid refetches and improve user experience.

The problem is I dont know anything about the size of the bitmaps. And as it turns out, I am getting OutOfMemoryExceptions sporadically, when I am using BitmapFactory.decodeStream(InputStream) method. So, I chose to downsample the images using BitmapFactory Options(sample size=2). This gave a better output: no OOMs, but this affects the quality of smaller images.

How should I handle such cases? Is there a way to selectively downsample only high resolution images?

Edit
Report

1 Answer

14

After a few days struggling to avoid all OutOfMemory errors that I was getting with different devices, I create this:

private Bitmap getDownsampledBitmap(Context ctx, Uri uri, int targetWidth, int targetHeight) {
    Bitmap bitmap = null;
    try {
        BitmapFactory.Options outDimens = getBitmapDimensions(uri);

        int sampleSize = calculateSampleSize(outDimens.outWidth, outDimens.outHeight, targetWidth, targetHeight);

        bitmap = downsampleBitmap(uri, sampleSize);

    } catch (Exception e) {
        //handle the exception(s)
    }

    return bitmap;
}

private BitmapFactory.Options getBitmapDimensions(Uri uri) throws FileNotFoundException, IOException {
    BitmapFactory.Options outDimens = new BitmapFactory.Options();
    outDimens.inJustDecodeBounds = true; // the decoder will return null (no bitmap)

    InputStream is= getContentResolver().openInputStream(uri);
    // if Options requested only the size will be returned
    BitmapFactory.decodeStream(is, null, outDimens);
    is.close();

    return outDimens;
}

private int calculateSampleSize(int width, int height, int targetWidth, int targetHeight) {
    int inSampleSize = 1;

    if (height > targetHeight || width > targetWidth) {

        // Calculate ratios of height and width to requested height and
        // width
        final int heightRatio = Math.round((float) height
                / (float) targetHeight);
        final int widthRatio = Math.round((float) width / (float) targetWidth);

        // Choose the smallest ratio as inSampleSize value, this will
        // guarantee
        // a final image with both dimensions larger than or equal to the
        // requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }
    return inSampleSize;
}

private Bitmap downsampleBitmap(Uri uri, int sampleSize) throws FileNotFoundException, IOException {
    Bitmap resizedBitmap;
    BitmapFactory.Options outBitmap 
answered 2013-06-15T16:54:00.870

Your Answer