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

待续..

roaringbitmap 源码(4)序列化和反序化以及分布式应用

迭代器和序列化和反序列化serialize:都很简单。 ArrayContainer@Override public void serialize(DataOutput out) throws IO...
  • chenfenggang
  • chenfenggang
  • 2017年07月08日 15:03
  • 507

Loading Large Bitmaps Efficiently [有效率的加载大尺寸的位图]

Loading Large Bitmaps Efficiently[有效率的加载大尺寸的位图] 图片有不同的形状与大小。在大多数情况下它们的实际大小都比需要呈现出来的要大很多。例如,系统的Gall...
  • gg137608987
  • gg137608987
  • 2013年07月02日 14:51
  • 762

使用Redis bitmaps进行快速、简单、实时统计

原文:Fast, easy, realtime metrics using Redis bitmaps  (http://blog.getspool.com/2011/11/29/fast-...
  • u011547353
  • u011547353
  • 2014年03月28日 17:43
  • 803

高效使用Bitmaps(二) 后台加载Bitmap

文章来源:http://my.oschina.net/rengwuxian/blog/183802 摘要 有没有过这种体验:你在Android手机上打开了一个带有含图片的ListView...
  • l_215851356
  • l_215851356
  • 2016年05月24日 14:03
  • 299

Caching Bitmaps缓存bitmaps(Android官方文档翻译三)

原文目录如下: Displaying Bitmaps Efficiently Loading Large Bitmaps EfficientlyProcessing Bitmaps...
  • liujinmou
  • liujinmou
  • 2014年06月01日 16:49
  • 677

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

http://developer.android.com/training/displaying-bitmaps/load-bitmap.html#read-bitmap
  • domyself918
  • domyself918
  • 2014年04月18日 23:41
  • 713

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

Images come in all shapesand sizes. In many cases they are larger than required for a typicalapplica...
  • liujinmou
  • liujinmou
  • 2014年06月01日 16:30
  • 1021

Bitmaps与其优化

一, 位图重新采样1, 有效的处理较大的位图 图像有各种不同的形状和大小。在很多情况下,他们往往比一个典型应用程序的用户界面(UI)所需要的资源更大。 读取一个位图的尺寸和类型:   为了从多...
  • u013144863
  • u013144863
  • 2016年05月30日 15:04
  • 982

如何使用Createjs来编写HTML5游戏(三)使用EaselJS中的制作Sprite类制作

动画的制作原理据说是由于人的视觉残留效应,连续播放一系列的静止图片,即可获得一段动画,每张图片可以称作动画的一帧,在EaselJS中,提供了一个Sprites类,可以用来创建动画。创建Sprite同创...
  • lanix516
  • lanix516
  • 2015年08月05日 19:47
  • 4150

Android Studio lint工具所提示的需要注意的内容简要记录

Android lint部分:Duplicated icons under different names 相同的icon 用了不同的名字 FrameLayout can be replaced ...
  • u012760183
  • u012760183
  • 2016年12月22日 18:55
  • 897
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android Training--Display Bitmaps Efficiently
举报原因:
原因补充:

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