Android官方教程中提到如何通过加载一个缩小版本的图片到内存,从而避免超出程序的内存限制。(点击打开链接)
其中,通过设置inJustDecodeBounds=true,可以避免加载过大的原始图片,从而避免内存溢出。
以下代码片段给出解释:
<span style="white-space:pre"> </span>final BitmapFactory.Options options = new BitmapFactory.Options();
// 在解码的时候避免内存的分配,它会返回一个null的Bitmap
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// 获取到原始图片的尺寸
final int imageHeight = options.outHeight;
final int imageWidth = options.outWidth;
Log.d(TAG, "calculateInSampleSize: 原始图片的尺寸width=" + imageWidth + "\t height=" + imageHeight);
取得原始图片尺寸后,可以通过判断与ImageView尺寸的宽高,按比例缩小图片并将其加载到内存中:
<span style="white-space:pre"> </span>
以上是Android官方给出的实例代码,可以看到第一步是将int inSampleSize 赋值为 1 。
最后需要设置options.inJustDecodeBounds = false;得到缩放后的图像。
<span style="white-space:pre"> </span>int inSampleSize = 1;
// 原始图片比较大的情况,如果原始比较小,则inSampleSize=1会将原始图片放大2倍
if (imageWidth > reqWidth || imageHeight > reqHeight) {
final int halfWidth = imageWidth / 2;
final int halfHeight = imageHeight / 2;
// 计算出最大的inSampleSize的值(2的幂),并保持图片宽高比请求的宽高大。
while ((halfWidth / inSampleSize) > reqWidth
&& (halfHeight / inSampleSize) > reqHeight) {
inSampleSize *= 2;
}
long totalPixels = imageWidth * imageHeight;
// Anything more than 2x the requested pixels we'll sample down further
final long totalReqPixelsCap = reqWidth * reqHeight * 2;
while (totalPixels >= totalReqPixelsCap) {
inSampleSize *= 2;
totalPixels /= 2;
}
}
本人在实践过程中,发现如果原始图像尺寸比较小,则inSampleSize=1会将原始图片放大2倍:
原因是使用inSampleSize要保证压缩出来的宽高要大于等于请求的宽高。
目前本人的解决办法是如果原始图像比ImageView的宽高其中之一小就不缩放原始图像。