高效的加载大分辨率的图片 bitmap

在实际项目中,会遇到很多需要处理各种图片的地方。在很多情况下,图片的分辨率会特别高。特别是现在手机发展速度快速,拍摄出来的照片动辄10多M,当我们查看这些照片的时候,如果不经过任何处理,不仅在加载速度会很感人,而且耗费的内存很可能导致内存超出应用的可用内存,所以在加载大分辨率图片之前进行适当的处理十分有必要。

处理的步骤主要分为如下两部分:

读取带加载图片的尺寸和类型

我们知道,BitmapFactory提供了几种解码方式来将图片转化为Bitmap格式,比如(decodeByteArray(), decodeFile(), decodeResource()等等),这些方式分别对应来源和存放位置不同的图片资源。我们应当选择合适的方法来加载相应的图片。但是这些方法会为了构造Bitmap而直接分配内存,这样很容易因为图片资源分辨率过大而造成OOM。Google官方也考虑这些方法的缺陷,做出了相应的弥补。构建一个BitmapFactory.options实例,然后将它其中的一个参数inJustDecodeBounce置为true,传入到上述方法中:

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;

这样的话,decodeResource方法就暂时不会创建Bitmap对象,也不会消耗内存。而我们可以通过options拿到图片你的长宽以及类型,这些属性对后面处理图片有很重要的作用。

根据图片的尺寸与控件尺寸对图片进行缩放

现在我们知道了源图片的尺寸参数,就可以根据尺寸参数来决定是直接加载原图还是预处理缩小后在加载图片。做出选择主要需要考虑一下的因素:

  • 预估直接加载图片的内存消耗
  • 考虑你可以接受的内存消耗
  • 加载图片的ImageView或者其他控件的实际尺寸
  • 屏幕大小和分辨率

举个例子,没有必要向一个尺寸只有128*96的ImageView传入一个分辨率为1024*768的图片。

如果确定需要缩小当前的图片资源,那么我们得搞清楚到底该缩小多少。在options中有一个参数inSampleSize,他是确定最后实际生成的Bitmap和原图之间分辨率的一个比例。比如,原图为2048*1536而inSampleSize为4的话,最后通过上述解码方法生成的Bitmap的实际分辨率就是512*384. 同时内存消耗也从12MB减少到了0.75MB(假设Bitmap的设置是ARGB_8888).下面是一个计算inSampleSize的参考方法:

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;

        // 计算最大inSampleSize,使其始终是2的倍数
        // 保证图片尺寸是大于要求尺寸
        while ((halfHeight / inSampleSize) >= reqHeight
                && (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

代码很简单,此处就不赘述了。
下面是调用这一方法的代码:

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

需要注意的是,你必须根据图片的来源来调整decode方法的类型。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值