Displaying Bitmaps Efficiently (一)-----Loading Large Bitmaps Efficiently

This lesson walks you throughdecoding large bitmaps without exceeding the per application memory limit by loading a smaller subsampled version in memory.

1>Read Bitmap Dimensions and Type

TheBitmapFactory class provides several decoding methods (decodeByteArray(),decodeFile(),decodeResource(), etc.) for creating aBitmap from various sources. 

Each type of decode method has additional signatures that let you specify decoding options via theBitmapFactory.Options class.

Setting theinJustDecodeBounds property totrue while decoding avoids memory allocation, returning null for the bitmap object but setting outWidth,outHeight andoutMimeType. This technique allows you to read the dimensions and type of the image data prior to construction (and memory allocation) of the bitmap.


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.

2>Load a Scaled Down Version into Memory

Now that the image dimensions are known, they can be used to decide if the full image should be loaded into memory or if a subsampled version should be loaded instead. 

For example, it’s not worth loading a 1024x768 pixel image into memory if it will eventually be displayed in a 128x96 pixel thumbnail in an ImageView.

To tell the decoder to subsample the image, loading a smaller version into memory, set inSampleSize to truein your BitmapFactory.Options object. 

For example, an image with resolution 2048x1536 that is decoded with an inSampleSize of 4 produces a bitmap of approximately 512x384. Loading this into memory uses 0.75MB rather than 12MB for the full image (assuming a bitmap configuration of ARGB_8888). 

Here’s a method to calculate a sample size value that is a power of two based on a target width and height:

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;
}


Note:  A power of two value is calculated becausethe decoder uses a final value by rounding down to the nearest power of two, as per the  inSampleSize  documentation.

To use this method, first decode with inJustDecodeBounds set to true, pass the options through and then decode again using the new inSampleSize value and inJustDecodeBounds set to false:

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 method makes it easy to load a bitmap of arbitrarily large size into an ImageView that displays a 100x100 pixel thumbnail, as shown in the following example code:

mImageView.setImageBitmap(
    decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));

You can follow a similar process to decode bitmaps from other sources, by substituting the appropriate  BitmapFactory.decode*  method as needed.


http://developer.android.com/training/displaying-bitmaps/load-bitmap.html#load-bitmap

你可能感兴趣的:(bitmap)