MyException - 我的异常网
当前位置:我的异常网» Android » Android Bitmap 内存占用太多的有关问题

Android Bitmap 内存占用太多的有关问题

www.MyException.Cn  网友分享于:2013-07-04  浏览:447次
Android Bitmap 内存占用太多的问题
有时会发现由于内存不够而导致错误,大都来源于Image太大造成的。下面给出一个简单有效的方法:

BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 4;
Bitmap bitmap = BitmapFactory.decodeFile(imageFile, opts);
设置恰当的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 <= {        
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()方法来释放位图所占的空间,当然前提是位图没有被使用。
在开发图片浏览器等软件是,很多时候要显示图片的缩略图,而一般情况下,我们要将图片按照固定大小取缩略图,一般取缩略图的方法是使用BitmapFactory的decodeFile方法,然后通过传递进去BitmapFactory.Option类型的参数进行取缩略图,在Option中,属性值inSampleSize表示缩略图大小为原始图片大小的几分之一,即如果这个值为2,则取出的缩略图的宽和高都是原始图片的1/2,图片大小就为原始大小的1/4。
然而,如果我们想取固定大小的缩略图就比较困难了,比如,我们想将不同大小的图片去出来的缩略图高度都为200px,而且要保证图片不失真,那怎么办?我们总不能将原始图片加载到内存中再进行缩放处理吧,要知道在移动开发中,内存是相当宝贵的,而且一张100K的图片,加载完所占用的内存何止100K?
经过研究,发现,Options中有个属性inJustDecodeBounds,研究了一下,终于明白是什么意思了,SDK中的E文是这么说的 If set to true, the decoder will return null (no bitmap), but the out... fields will still be set, allowing the caller to query the bitmap without having to allocate the memory for its pixels.
哦,明白了,那么相应的方法也就出来了,通过设置inJustDecodeBounds为true,获取到outHeight(图片原始高度)和outWidth(图片的原始宽度),
然后计算一个inSampleSize(缩放值),然后就可以取图片了,这里要注意的是,inSampleSize可能小于1,必须做判断,同时由于inSampleSize为Int类型,而图片的高度和宽度也为int类型,通过精度的转换,可能会存在失真的问题,那么,我这样进行那个判断(实例代码中为取高度为200PX的缩略图)
int be = options.outHeight / 20;
//应该直接除200的,但这里出20是为了增加一位数的精度
if(be%10 !=0) be+=10;
//尽量取大点图片,否则会模糊
be=be/10;
if (be <= 0)
//判断200是否超过原始图片高度
be = 1;
//如果超过,则不进行缩放
options.inSampleSize = be;
整体代码如下
BitmapFactory.Options options = new BitmapFactory.Options();
//options.inSampleSize = 3; options.outHeight = 200;
options.inJustDecodeBounds = true;
//options.
if (position < 0) {
position = position + mImageDirs.size();
}
// 获取这个图片的宽和高
Bitmap bm = BitmapFactory.decodeFile(this.mImageDirs .get(position % mImageDirs.size()), options);
//此时返回bm为空
options.inJustDecodeBounds = false;
int be = options.outHeight / 20;
if(be%10 !=0) be+=10; be=be/10;
if (be <= 0) be = 1;
options.inSampleSize = be;
bm = BitmapFactory.decodeFile(this.mImageDirs.get(position % mImageDirs.size()), options);
int w = bm.getWidth(); int h = bm.getHeight(); w = w *200 /h;
i.setImageBitmap(bm);
1 楼 yahier 2012-02-22  
好像明白了点 好像还是不会真实的操作

文章评论

5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
漫画:程序员的工作
漫画:程序员的工作
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
程序员必看的十大电影
程序员必看的十大电影
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
中美印日四国程序员比较
中美印日四国程序员比较
程序员的鄙视链
程序员的鄙视链
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
程序员都该阅读的书
程序员都该阅读的书
如何成为一名黑客
如何成为一名黑客
我是如何打败拖延症的
我是如何打败拖延症的
为什么程序员都是夜猫子
为什么程序员都是夜猫子
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
代码女神横空出世
代码女神横空出世
老程序员的下场
老程序员的下场
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
程序员和编码员之间的区别
程序员和编码员之间的区别
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
10个调试和排错的小建议
10个调试和排错的小建议
每天工作4小时的程序员
每天工作4小时的程序员
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
我的丈夫是个程序员
我的丈夫是个程序员
一个程序员的时间管理
一个程序员的时间管理
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
编程语言是女人
编程语言是女人
程序员应该关注的一些事儿
程序员应该关注的一些事儿
那些争议最大的编程观点
那些争议最大的编程观点
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有