Bitmap的高效加载

时间:2021-01-31 20:56:55

1 加载方式

BitmaFactory 类提供了四类的加载方法:

  1. decodeFile:从系统文件加载
  2. decodeResource:从资源文件加载
  3. decodeStream:从输入流加载
  4. decodeByteArray:从字节数组中加载

前二者最终都是调用第三者进行加载的。


2 加载核心

加载的核心就是采用 BitmapFactory.Options 来加载所需尺寸的图片,其中用到的一个重要的参数为 inSampleSize(采样率)。

1 inSampleSize介绍

  1. 当其为2的时候,采样后的图片的宽/高均变为原来的1/2, 即整体变为了原来的 1/4
  2. 当其小于1的时候,起作用相当于1,无缩放作用;
  3. 一般情况下,inSampleSize 的取值都是2的指数。若不为2的指数,那么系统就会向下取整并选择一个最接近2的指数来代替;

2 inSampleSize的获取

  1. BitmapFactory.OptionsinJustDecodeBounds 参数设置为true,并加载图片。(此时 BitmapFactory 只会解析图片的宽/高信息,并不会真正加载图片)
  2. BitmapFactory.Options 中获取图片的原始宽/高信息,对应于outWidthoutHeight的方法。
  3. 根据目标图片的所需大小计算出inSampleSize
  4. BitmapFactory.OptionsinJustDecodeBounds 参数设置为false,重新加载图片。

3 代码实现

仅以第二种加载方式举例,其余的处理方式也类似,但第三种会复杂些。

/**
 * 加载图片的工具类</br>
 * Created by Administrator on 2016/5/12.
 */
public class LoadBitmapUtil {
    /**
     * 加载资源图片
     *
     * @param res       资源
     * @param resId     资源图片Id
     * @param reqWidth  请求的宽度
     * @param reqHeight 请求的高度
     * @return 处理后的Bitmap
     */
    public static Bitmap decodeBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
        //First decode whit inJustDecodeBounds=true to check dimention
        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);
    }

    /**
     * 计算inSampleSize
     */
    private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        //Raw height an 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 keep both height and width larger than the requested
            // height and width.
            while ((halfHeight / inSampleSize) > reqHeight &&
                    (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize = inSampleSize << 2;
            }
        }
        return inSampleSize;
    }

}

方法的调用:

mImageView.setImageBitmap(LoadBitmapUtil.decodeBitmapFromResource(getResources(), R.drawable.test, 100, 100));