[Developer Android] Loading Large Bitmaps Efficiently

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

慢慢积累Google官方的文档,以后方便快速查阅。

更高效的加载并使用Bitmap对象

1.首先获取Bitmap的尺寸与类型

    BitmapFactory类根据不同图片资源类型提供了

decodeByteArray()decodeFile()decodeResource()等解码方法。

可以根据图片的类型选择合适的方法获取Bitmap对象。然而,构建Bitmap对象容易在分配内存的时候出现OOM。因此在调用各种解码方法前都可以通过设置

BitmapFactory.Options inJustDecodeBounds 属性为true来避免内存分配、并使其构建的Bitmap对象返回null,以方便获取option对象中图片的宽高。这里有几个参数可以获取要加载的图片的宽高及其类型。

 outWidthoutHeight and outMimeType.

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;

2.缩放后再加载到内存中

图片尺寸获取之后,就可以决定是否将图加载到内存中还是经过二次缩放后再加载。这里有几点需要考虑的因素:

~预估整个图加载到内存中所需的内存

~加载到分配的内存后是否应用程序有使用到

~图片要加载到哪个ImageViewUI组件。

~屏幕尺寸和当前设备的密度

介于第三点,比如,加载一张1024X768px的图片到内存后,却只用128X96pxImageView来显示,这是非常不值得的。

因此就需要进行N次缩放后再将其加载到内存中。可以通过设置BitmapFactory.Options对象的 inSampleSize 属性来进行分辨率的缩放。比如一张分辨率为2048X1536的图(加载到内存需要12MB)经过4次压缩后大概变成512X384(加载到内存需要0.75MB)。

这里有个计算压缩次数的方法:

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

综合上面两点,首先要设置inJustDecodeBoundstrue,再计算出需要压缩的次数之后,再设置为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);
}

举例:项目中假设有一张100X100px的图片,

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

PS:不对之处,以及有其他好的处理方式,多多指教了。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值