安卓 Bitmap 高效加载

博客: 安卓之家
微博: 追风917
CSDN: 蒋朋的家
简书: 追风917

理论


Bitmap 的高效加载会利用 BitmapFactory.Options 来加载所需尺寸的图片,也就是可以按一定的采样率来加载所需图片(一般就是缩小后的图片)。采样率的设置就是 BitmapFactory.Options 的inSampleSize 参数。

  • inSampleSize 小于1时,无缩放效果,相当于 inSampleSize = 1;
  • inSampleSize 为1时,采样后图片为原始图片大小
  • inSampleSize 为2时,采样后图片的宽高均为原始图片的一半,那么像素值为原始图片的1/4, 占内存大小也是原图的1/4,也就是说缩放比例是 1/(inSampleSize 的2次方),比如inSampleSize 为 4, 缩放比例就是 1/16
  • 最新官方文档指出,inSampleSize 的取值应该是2的指数,比如1,2,4,8,16…如果inSampleSize不为2的指数,会向下取整选择一个最接近的2的指数来代替,比如3,系统会选择2来代替,但是验证发现该结论并非所有的安卓系统版本都成立,因此这只是一个开发建议咯。

步骤


  1. 把 BitmapFactory.Options 的inJustDecodeBounds 参数设置为 true,此时BitmapFactory 只会解析原始图片的宽高信息,不会真正加载图片
  2. 从 BitmapFactory.Options 中取出图片宽高信息,它们对应于outWidth 和 outHeight 参数
  3. 根据采样率的规则并结合目标View所需大小计算采样率 inSampleSize
  4. 把 BitmapFactory.Options 的inJustDecodeBounds 参数设置为 false, 重新加载图片

具体代码实现


计算分辨率

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;
}

加载图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static Bitmap decodeBitmapFromResource(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);
}

我写到了这个 Gist

使用


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

参考内容:
任书记的《Android 开发艺术探索》第 12 章
google开发指南

分享是一种美德,更是一种生活方式!!

也许你会说我是一个梦想者,但我不是唯一的一个。

悦分享,越快乐^_^

欢迎交流,转载请注明出处,谢谢!

文章目錄
  1. 1. 理论
  2. 2. 步骤
  3. 3. 具体代码实现
  4. 4. 使用
,
Fork me on GitHub