Bitmap加载

Bitmap是Android系统中的图像处理的最重要的类之一。通常对于一般小的图片的加载时没有什么问题的,但是如果如果加载比较的大的图片,就很容易发生OOM问题,就是所谓的内存溢出,所以我们就要对图片进行加载管理,就是通过缩放来加载图片。
首先,Bitmap的加载是通过BitmapFactory类提供的一些方法,decodeFile(),decodeResoure(),decodeStream(),decodeByteArray(),decodeFileDescriptor()
其中decodeFile()和decodeResource()最终是调用了decodeStream(),这从源码可以看出:

public static Bitmap decodeFile(String pathName, Options opts) {
    Bitmap bm = null;
    InputStream stream = null;
    try {
        stream = new FileInputStream(pathName);
        bm = decodeStream(stream, null, opts);
    }
    ........
    return bm;
}
public static Bitmap decodeResource(Resources res, int id, Options opts) {
.....
        bm = decodeResourceStream(res, value, is, null, opts);
      .....
    return bm;
}
public static Bitmap decodeResourceStream(Resources res, TypedValue value,
        InputStream is, Rect pad, Options opts) {
    ........
    return decodeStream(is, pad, opts);
}

如何加载Bitmap,就是通过缩放。通常,ImageView要显示的图片大小没有那么大,但是如果一开始就整张图片加载进来再进行设置,这就很浪费资源了,我们就可以根据ImageView的宽高需求进行加载。这时候就要通过BitmapFactory.Options来加载大小,这里面还涉及一个采样率inSampleSize。
当inSampleSize为1的时候,图片不进行缩放;当inSampleSize为2的时候,加载的图片均为原来的1/2,整张图片就是原来的1/4大小了,假如原始图片是4M,那么加载进来就只有1M,大大节省空间。

通过采样率加载图片通常有以下四步:

  1. 设置BitmapFactory.Options的inJustDecodeBounds值为true,此时BitmapFactory只会解析图片的原始高度
  2. 根据BitmapFactory.Options获取图片的原始高度和宽度信息
  3. 根据图片的原始高度计算出采样率options.inSampleSize
  4. 设置BitmapFactory.Options的inJustDecodeBounds值为false,此时BitmapFactory会根据采样率加载图片
public Bitmap decodeSampleFromResource(Resources res,int resId,int reqWidth,int reqHeight){
    BitmapFactory.Options options = new BitmapFactory.Options();
    //此时,BitmapFactory只会解析图片的原始高度和宽度
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res,resId,options);

    options.inSampleSize = calculateInSampleSize(options,reqWidth,reqHeight);
    //此时就会根据inSample来加载
    options.inJustDecodeBounds = false;

    return BitmapFactory.decodeResource(res,resId,options);

}

public 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 halfWidth = width / 2;
        final int halfHeight = height / 2;
        while ((halfWidth / inSampleSize)>=reqWidth && (halfHeight / inSampleSize)>=reqHeight){
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

注意

有些情况下,ImageView宽度和高度是100*100,而原始图片是200*200,当采样率为2的时候,图片就会刚好缩放到100*100。当原始图片是200*300的时候,采样率同为2,图片会缩放到100*150,也是可以的,当采样率为3的时候,就是66*100,那么图片就会被拉伸而变得模糊,为了防止这种情况发生,缩放的时候,必须缩放后的宽度和高度都要大于等于需求的高度,所以:

while ((halfWidth / inSampleSize)>=reqWidth && (halfHeight / inSampleSize)>=reqHeight)

猜你喜欢

转载自blog.csdn.net/lihuanxing/article/details/52225981
今日推荐