BitMap高效显示策略(一):大图的缩放和加载

来源:互联网 发布:sql select嵌套查询 编辑:程序博客网 时间:2024/04/30 01:35

Android对不同屏幕和dpi的设备有单个应用程序运行内存的限制。在有的设备上,最严格的限制甚至可以小到只有16MB内存。

Bitmap会消耗很多内存,如果一个手机能够拍摄2592x1936 pixels (5 MB)的图片,bitmap的配置是使用ARGB_8888 (从Android 2.3开始的默认配置) ,那么加载这张照片到内存会大概需要19MB(2592*1936*4 bytes) 的内存, 如果在只有16MB上限的设备上运行的话,会迅速消耗掉设备的整个内存。

BitmapFactory提供一系列加载BitMap的方法,这些方法在调用时会尝试分配内存,如果加载一个图片所需内存过大,就有可能抛OutOfMemory异常。

BitmapFactory.Options提供一些附加属性来指定decode的选项,解析Bitmap时用到2个重要参数:

1.inJustDecodeBounds

设置为true后,decode方法解析Bitmap时会返回一个null,只讲这个图片的原始大小(单位是像素)存入BitmapFactory.Options对象的options.outHeight和options.outWidth中,这样可以在不分配内存的情况下得到图片的尺寸信息。

2.inSampleSize

这个参数代表缩小比例,如果是1,代表原始尺寸,如果>1,假设为2,则缩小后图片像素值为原图的1/4(长1/2,宽1/2),同等格式下,占用内存也变为原来的1/4。decoder以2的幂作为系数,接近2的幂的数值都会被处理为最接近的2的幂值,3.4~4,2.1~2,这样。

缩小图片会降低图像质量,所以加载图片前,是否缩放,缩放比例等应综合考虑以下因素:

1.加载完整图片所需要耗费的内存

2.显示这张图片的组件的尺寸大小

3.屏幕大小与当前设备的屏幕密度

如下方法计算出长宽都小于给定长宽时需要缩小的比例值。

public static int calculateInSampleSize(            BitmapFactory.Options options, int reqWidth, int reqHeight) {    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;        while ((halfHeight / inSampleSize) > reqHeight                && (halfWidth / inSampleSize) > reqWidth) {            inSampleSize *= 2;        }    }    return inSampleSize;}
在调用以上方法前,记得设置options.inJustDecodeBounds = true;

调用后算出比例后,则调用

BitmapFactory.decodexxxx(res, resId, options);
解析。

示例代码:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,        int reqWidth, int reqHeight) {    final BitmapFactory.Options options = new BitmapFactory.Options();    options.inJustDecodeBounds = true;    BitmapFactory.decodeResource(res, resId, options);    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);    options.inJustDecodeBounds = false;    return BitmapFactory.decodeResource(res, resId, options);}
mImageView.setImageBitmap(    decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));


注意BitmapFactory.decodeStream解析网络流的时候情况比较特殊,参考这篇:

BitmapFactory.decodeStream使用inJustDecodeBounds参数解析网络流的问题

0 0
原创粉丝点击