Android Training--Display Bitmaps Efficiently

翻译 2016年08月29日 15:38:49

Loading Large Bitmaps Efficiently

Images come in all shapes and sizes. In many cases they are larger than required for a typical application user interface (UI). For example, the system Gallery application displays photos taken using your Android devices’s camera which are typically much higher resolution than the screen density of your device.

Given that you are working with limited memory, ideally you only want to load a lower resolution version in memory. The lower resolution version should match the size of the UI component that displays it. An image with a higher resolution does not provide any visible benefit, but still takes up precious memory and incurs additional performance overhead due to additional on the fly scaling.

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

Read Bitmap Dimensions and Type

The BitmapFactory class provides several decoding methods (decodeByteArray(), decodeFile(), decodeResource(), etc.) for creating a Bitmap from various sources. Choose the most appropriate decode method based on your image data source. These methods attempt to allocate memory for the constructed bitmap and therefore can easily result in an OutOfMemory exception. Each type of decode method has additional signatures that let you specify decoding options via the BitmapFactory.Options class. Setting the inJustDecodeBounds property to true while decoding avoids memory allocation, returning null for the bitmap object but setting outWidth, outHeight and outMimeType. 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, unless you absolutely trust the source to provide you with predictably sized image data that comfortably fits within the available memory.

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. Here are some factors to consider:

Estimated memory usage of loading the full image in memory.
Amount of memory you are willing to commit to loading this image given any other memory requirements of your application.
Dimensions of the target ImageView or UI component that the image is to be loaded into.
Screen size and density of the current device.
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 true in 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 because the 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));

待续..

相关文章推荐

[Developer Android] Loading Large Bitmaps Efficiently

原文链接:https://developer.android.com/training/displaying-bitmaps/load-bitmap.html#load-bitmap 慢慢积累Goog...

Android有效的展示图片 (一) Loading Large Bitmaps Efficiently 有效的下载大图片

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

Loading Large Bitmaps Efficiently高效加载大图(Android开发文档翻译一)

Images come in all shapesand sizes. In many cases they are larger than required for a typicalapplica...

【Android Training - 09】高效地显示Bitmap图片 [ Lesson 2 - 在UI线程之外处理Bitmaps ]

Processing Bitmaps Off the UI Thread [在UI Thread之外处理Bitmap] 在上一课中有介绍一系列的BitmapFactory.decode* 方...

Displaying Bitmaps Efficiently

  • 2016年01月23日 20:38
  • 63KB
  • 下载

Displaying Bitmaps Efficiently

  • 2014年09月23日 17:15
  • 166KB
  • 下载

1Displaying Bitmaps Efficiently (位图有效显示)

英文不是很好,但是还是想强迫自己去阅读英文文档,毕竟android是外国人弄的。。。 翻译全凭词典,肯定很水,翻译不对的地方欢迎留言 Learn how to use common tec...

Loading Large Bitmaps Efficiently-高效的加载大位图

BitmapFactory类提供了一些解码方法 (decodeByteArray(), decodeFile(), decodeResource(), 等.) 从各种源来创建位图Bitmap。选择最合...
  • hil2000
  • hil2000
  • 2014年02月07日 19:30
  • 1203

Loading Large Bitmaps Efficiently 高效地加载大位图

Loading Large Bitmaps Efficiently 有效地加载大尺寸位图 图片有不同的形状与大小。在大多数情况下它们的实际大小都比需要呈现出来的要大很多。例如,系统的Galler...

2 Loading Large Bitmaps Efficiently(高效加载大尺寸位图)

Images come in all shapes and sizes. In many cases they are larger than required for a typical appli...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android Training--Display Bitmaps Efficiently
举报原因:
原因补充:

(最多只允许输入30个字)