http://www.maxhis.info/androiding/bitmap-size-exceed/

完美解决java.lang.OutOfMemoryError: bitmap size exceeds VM budget
2011年6月17日 iStar 发表评论 阅读评论

当图片过大,或图片数量较多时使用BitmapFactory解码图片会出java.lang.OutOfMemoryError: bitmap size exceeds VM budget,要想正常使用则需分配更少的内存,具体的解决办法是修改采样值BitmapFactory.Options.inSampleSize,例如:

BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 4;
Bitmap bitmap = BitmapFactory.decodeFile(imageFile, opts);

如何设置恰当的inSampleSize

设置恰当的inSampleSize是解决该问题的关键之一。BitmapFactory.Options提供了另一个成员inJustDecodeBounds。

BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeFile(imageFile, opts);



设置inJustDecodeBounds为true后,decodeFile并不分配空间,但可计算出原始图片的长度和宽度,即opts.width和opts.height。有了这两个参数,再通过一定的算法,即可得到一个恰当的inSampleSize。

查看Android源码,Android提供了一种动态计算的方法。

public static int computeSampleSize(BitmapFactory.Options options,
int minSideLength, int maxNumOfPixels) {
int initialSize = computeInitialSampleSize(options, minSideLength,maxNumOfPixels);

int roundedSize;
if (initialSize <= 8 ) {
roundedSize = 1;
while (roundedSize < initialSize) {
roundedSize <<= 1;
}
} else {
roundedSize = (initialSize + 7) / 8 * 8;
}

return roundedSize;
}

private static int computeInitialSampleSize(BitmapFactory.Options options,int minSideLength, int maxNumOfPixels) {
double w = options.outWidth;
double h = options.outHeight;

int lowerBound = (maxNumOfPixels == -1) ? 1 :
(int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
int upperBound = (minSideLength == -1) ? 128 :
(int) Math.min(Math.floor(w / minSideLength),
Math.floor(h / minSideLength));

if (upperBound < lowerBound) {
// return the larger one when there is no overlapping zone.
return lowerBound;
}

if ((maxNumOfPixels == -1) &&
(minSideLength == -1)) {
return 1;
} else if (minSideLength == -1) {
return lowerBound;
} else {
return upperBound;
}
}



使用该算法,就可动态计算出图片的inSampleSize。

BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imageFile, opts);

opts.inSampleSize = computeSampleSize(opts, -1, 128*128);
opts.inJustDecodeBounds = false;
try {
Bitmap bmp = BitmapFactory.decodeFile(imageFile, opts);
imageView.setImageBitmap(bmp);
} catch (OutOfMemoryError err) {
}



另外,可以通过Bitmap.recycle()方法来释放位图所占的空间,当然前提是位图没有被使用。

更多相关文章

  1. Picasso网络图片加载 (毕加索)
  2. Android实现新手引导半透明蒙层效果
  3. Android(安卓)获取手机中所有图片
  4. Android(安卓)-对图片Drawable进行变色
  5. Android(安卓)圆角图片CircleImageView
  6. Android(安卓)加载本地图片 和 服务器图片
  7. android seekbar垂直滚动,滑块开始不在开端,滑块大小改变等相关问
  8. Android学习笔记之Button的点击事件切换点击图片
  9. android Bitmap类方法属性 详细说明

随机推荐

  1. 说说android下TV版本UC浏览器模拟鼠标的
  2. android:布局参数,控件属性及各种xml的作
  3. Android学习之Android广播机制
  4. Android8.1以及5.1版本识别sdcard和U盘并
  5. Qt仿Android带特效的数字时钟源码分析(滑
  6. Android(安卓)组件化架构概要
  7. 复制SqlServer数据库的方法
  8. 如何远程连接SQL Server数据库的图文教程
  9. MS SQL SERVER 数据库日志压缩方法与代码
  10. 在程序中压缩sql server2000的数据库备份