原文链接:https://developer.android.com/training/displaying-bitmaps/load-bitmap.html#load-bitmap
慢慢积累Google官方的文档,以后方便快速查阅。
更高效的加载并使用Bitmap对象
1.首先获取Bitmap的尺寸与类型
BitmapFactory类根据不同图片资源类型提供了
decodeByteArray(), decodeFile(), decodeResource()等解码方法。
可以根据图片的类型选择合适的方法获取Bitmap对象。然而,构建Bitmap对象容易在分配内存的时候出现OOM。因此在调用各种解码方法前都可以通过设置
BitmapFactory.Options 的inJustDecodeBounds 属性为true来避免内存分配、并使其构建的Bitmap对象返回null,以方便获取option对象中图片的宽高。这里有几个参数可以获取要加载的图片的宽高及其类型。
( outWidth, outHeight and outMimeType.)
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;
2.缩放后再加载到内存中
图片尺寸获取之后,就可以决定是否将图加载到内存中还是经过二次缩放后再加载。这里有几点需要考虑的因素:
~预估整个图加载到内存中所需的内存
~加载到分配的内存后是否应用程序有使用到
~图片要加载到哪个ImageView、UI组件。
~屏幕尺寸和当前设备的密度
介于第三点,比如,加载一张1024X768px的图片到内存后,却只用128X96px的ImageView来显示,这是非常不值得的。
因此就需要进行N次缩放后再将其加载到内存中。可以通过设置BitmapFactory.Options对象的 inSampleSize 属性来进行分辨率的缩放。比如一张分辨率为2048X1536的图(加载到内存需要12MB)经过4次压缩后大概变成512X384(加载到内存需要0.75MB)。
这里有个计算压缩次数的方法:
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;
}
综合上面两点,首先要设置inJustDecodeBounds为true,再计算出需要压缩的次数之后,再设置为false。
public static Bitmap decodeSampledBitmapFromResource(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);
}
举例:项目中假设有一张100X100px的图片,
mImageView.setImageBitmap(
decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));
PS:不对之处,以及有其他好的处理方式,多多指教了。