使用BitmapFactory解码图片
解码本地图片
final BitmapFactory.Options option = new BitmapFactory.Options();
// inDensity表示当前的Bitmap的像素密度
option.inDensity = DensityUtil.densityDpi;
// 使用inScale=true, 表示解码图片时允许图片缩放
// option.inScaled = true;
// inTargetDensity 表示需要解成Bitmap的像素密度
final Bitmap bitmap = BitmapFactory.decodeFile(path, option);
这样解码仍然会存在问题,假如本地图片是3X图,那么解码完放在2X手机上会造成资源浪费,此时需要根据ImageView的大小动态调整Bitmap的大小,这样可以减少内存占用,同时避免OOM
使用inJustDecodeBounds进行测量Bitmap的宽高
使用inJustDecodeBounds=true, 然后使用BimapFactory.decodeXXX()这样不会造成真正的内存分配,但是此时通过Option可以拿到Bitmap的真实宽高
然后根据View的宽高调整Bitmap的宽高,即计算Bitmap的采样率(inSampleSize)
inSamplleSize的计算
inSampleSize必须是2的n次幂,这个inSampleSize的意思是宽高都缩减为这个值
计算规则如下:
reqWidth, reqHeight为View的需要宽高
option中携带Bitmap的宽高
/**
* Method allows to find out the scale which can be applied when loading image in order to save memory
*
* @param options preset and preloaded option of an image
* @param reqWidth required width of image
* @param reqHeight required height of image
* @return scaling of image to be applied while loading the image (as power of 2)
*/
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;
// 如果Bitmap的宽高大于View的宽高
if (height > reqHeight || width > reqWidth) {
// 均除2
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
inSampleSize *= 2;
}
}
return inSampleSize;
}
使用BitmapFactory进行解码的代码
public void parseDrawable(final List<Pair<View, String>> list, final OnLoadBitmapCallback callback) {
if (list == null || callback == null || list.isEmpty()) {
return;
}
final List<Pair<View, BitmapDrawable>> drawables = new ArrayList<>();
for (Pair<View, String> p : list) {
final BitmapFactory.Options option = new BitmapFactory.Options();
option.inJustDecodeBounds = true;
// just decode bound.
BitmapFactory.decodeFile(p.second, option);
// 计算真实图片图片比例
option.inSampleSize = calculateInSampleSize(option, p.first.getWidth(), p.first.getHeight());
option.inJustDecodeBounds = false;
// inPrefreredConfig表示优先选用的解码模式
// 但是RGB_565没有ALPHA通道,且只能表示65525中颜色
// 如果需要解码的图片含有ALPHA通道那么系统仍然会选用RGB_8888进行解码
// 忽略InPreferedConfig
option.inPreferredConfig = Bitmap.Config.RGB_565;
final Bitmap bitmap = BitmapFactory.decodeFile(p.second, option);
if (bitmap != null) {
BitmapDrawable bitmapDrawable = new BitmapDrawable(bitmap);
bitmapDrawable.setTargetDensity(DensityUtil.DISPLAY_METRICS);
bitmapDrawable.setTileModeXY(Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
drawables.add(new Pair<>(p.first, bitmapDrawable));
}
}
callback.onLoadBitmap(drawables);
});
}