一种根据ImageView的大小缩放Bitmap的方法

     Bitmap是Android应用程序引起OOM的罪魁祸首之一,当我们从网络上下载图片的时候无法知道网络图片的准确大小,所以为了节约内存,一般会在服务器上缓存 一个缩略图,提升下载速度。除此之外,我们还可以在本地显示图片前将图片进行压缩,使其完全符合imageview的大小,这样可以最大限度避免内存浪费。
本文基本思路:
 (1)获取ImageView的宽和高。
 (2)使用inJustDecodeBounds获取bitmap的长和宽。
 (3)根据bitmap的长款和ImageView的长和宽,计算出压缩比例inSampleSize的大小。
 (4)使用inSampleSize,加载一个比ImageView稍大一点的缩略图a。
 (5)使用Bitmap.createScaseBitmap再次压缩A,将缩略图A生成需要的缩略图B。

1.计算ImageView的宽高
   int ImageView.getWidth()
   int ImageView.getHeight()
这两个方法可以得到ImageView的实际大小,单位为pix,需要在view加载完之后再调用。如果不知道什么时候加载完,可以使用下面方法在run()中获取:
final ImageView iv = new ImageView(context);
   iv.post(new Runnable() {
       @Override
       public void run() {
         int w = iv.getWidth();
         int h = iv.getHeight();
       }
   })

 

2.通过BitmapFactory计算得到压缩后的bitmap对象。

2.1 BitmapFactory.Options介绍
  BitmapFactory提供了多种方式根据不同的图片源来创建Bitmap对象:
  (1)Bitmap BitmapFactory.decodeFile(String pathName, Options opts): 读取SD卡上的图片。
  (2)Bitmap BitmapFactory.decodeResource(Resources res, int id, Options opts) : 读取网络上的图片。
  (3)Bitmap BitmapFactory.decodeResource(Resources res, int id, Options opts) : 读取资源文件中的图片。
  这三个函数默认会直接为bitmap分配内存,我们通过第二个参数Options来控制,让它不分配内存,同时可以得到图片的相关信息。具体参考:
  BitmapFactory.Options options = new BitmapFactory.Options();
  options.inJustDecodeBounds = true;
  BitmapFactory.decodeFile(pathName,options);
  int imageHeight = options.outHeight;
  int imageWidth = options.outWidth;

这样就可以在不分配内存的情况下直接得到图片的宽高。

2.2 计算图片压缩比例(采样率)
  通常如果图片是针对某种分辨率设计的,直接decode图片不会有什么问题。但是,如果图片不是特定设计,且比较大的话,容易造成OOM。
  假设,一个ImageView大小为512*384,有一张2048*1536的图片需要显示,那么如果加载整张图片,那就造成了浪费,这时候就需要采用不同的采样率对原图片进行一定的压缩。
  计算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 heightRatio = Math.round((float) height / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);
        // 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高
        // 一定都会大于等于目标的宽和高。
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }
    return inSampleSize;
  }
  方法二:
 
 private 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;
   }
需要注意的是,inSampleSize只能是2的整数次幂,如果不是的话,向下取得最大的2的整数次幂。因为按照2的次方进行压缩会比较高效和方便。 方法一计算出来的inSampleSize值可能不是2的整数次幂,不如计算出来的值是inSampleSize=7,这时会被decode函数向下取为 inSampleSize=4。所以我们一般采用方法二进行计算。
   此时,将设置了inSampleSize的options传给BitmapFactory.decode函数去获取图片,得到的会是一张比ImageView稍大的图片,不过这个图片要比原图小了。
 public static Bitmap decodeSampledBitmapFromFile(String pathName, int reqWidth, int reqHeight) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(pathName, options);
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
        options.inJustDecodeBounds = false;
        Bitmap src = BitmapFactory.decodeFile(pathName, options);
        return createScaleBitmap(src, reqWidth, reqHeight);
    }

2.3 得到符合ImageView大小的图片
这是通过Bitmap Bitmap.createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)函数来实现的。
这个函数返回一个按要求进行拉伸或者缩小后的bitmap.
    private static Bitmap createScaleBitmap(Bitmap src, int dstWidth, int dstHeight, int inSampleSize) {
    // 如果是放大图片,filter决定是否平滑,如果是缩小图片,filter无影响,我们这里是缩小图片,所以直接设置为false
        Bitmap dst = Bitmap.createScaledBitmap(src, dstWidth, dstHeight, false);
        if (src != dst) { // 如果没有缩放,那么不回收
            src.recycle(); // 释放Bitmap的native像素数组
        }
        return dst;
    }

 

转载于:https://www.cnblogs.com/Jackwen/p/5879454.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值