在做图片处理的时候最常遇到的问题估计就是Out Of Memory (内存溢出)了

网上对这种问题的解决方案很多,原来无非就是压缩图片大小

本不该重复造轮子,但实际中却遇见了问题,写出来希望后来者能引以为戒,并给出一个自我感觉不错的方案

常用的一种解决方案:

FileInputStream f = new FileInputStream(file);
BitmapFactory.Options options = new BitmapFactory.Options();   
options.inSampleSize = 2;//将图片大小改为原来的1/4
Bitmap bm = BitmapFactory.decodeStream(f, null, options);

其中options.inSampleSize定义如下:

If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save memory. The sample size is the number of pixels in either dimension that correspond to a single pixel in the decoded bitmap. For example, inSampleSize == 4 returns an image that is 1/4 the width/height of the original, and 1/16 the number of pixels. Any value <= 1 is treated the same as 1. Note: the decoder will try to fulfill this request, but the resulting bitmap may have different dimensions that precisely what has been requested. Also, powers of 2 are often faster/easier for the decoder to honor.

也就是说options.inSampleSize = 2就是将原图片的高和宽都设为1/2(单位为像素),整体图片也就缩小成原来的1/4之一了

这当然是一种很好的解决方案,只需根据自己的需要设置缩放比就行。

但这仅仅解决了一部分问题

试想一下,如果每张图片的大小都不一样,而要显示在相同的控件中,这时的缩放比(options.inSampleSize)该设置成多少呢?

如果设置缩放基本不够小,对于大像素图片的处理依然会出现内存溢出,设置得太大又会导致图片失真

这真是个头疼的问题。

如果能够根据图片大小自动计算缩放比那该多好啊!

别急,google已经为我们提供了这么一个方法(出自源码 暂且保存为BitmapUtiles.java 方便以后使用):

public class BitmapUtils
{
  
 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; 
     } 
 } 
}

我们只需要这样使用就好了:

FileInputStream f = new FileInputStream(file);
FileDescriptor fd = f.getFD();
   
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFileDescriptor(fd, null, options);

options.inSampleSize = BitmapUtils.computeSampleSize(options, 80, 128*128);

options.inJustDecodeBounds = false;
Bitmap bm = BitmapFactory.decodeStream(f, null, options);

其中需要注意的是options.inJustDecodeBounds这个属性,API解释如下:

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.

在设置为true的情况下不会返回bitmap,即不会占用内存,但可以计算bitmap的size大小(BitmapFactory.decodeFileDescriptor(fd, null, options) 由options带回宽、高)

此时的操作就是为了得到高、宽用于后面缩放比的计算

BitmapUtils.computeSampleSize(options, 80, 128*128)中

80是最小边长,128*128是期望得到的图像像素

特别注意的是,计算完宽高后一定要将改属性设置为false,否则BitmapFactory.decodeStream会一直返回null

OK,讲得够详细了

转自:http://blog.csdn.net/lovehong0306/article/details/7741436#comments

(转)解决 bitmap size exceeds VM budget (Out Of Memory 内存溢出)的问题的更多相关文章

  1. java.lang.OutOfMemoryError: bitmap size exceeds VM budget解决方法

    1 BitmapFactory.decodeFile(imageFile); 用BitmapFactory解码一张图片时,有时会遇到该错误.这往往是由于图片过大造成的.要想正常使用,则需要分配更少的内 ...

  2. android报错及解决1--Bitmap加载时,报bitmap size exceeds VM budget

    报错描述: 用Bitmap加载图片资源时,报错java.lang.OutOfMemoryError: bitmap size exceeds VM budget 原因分析: android系统限制,只 ...

  3. 【Android】Bitmap加载图片错误 java.lang.OutOfMemoryError: bitmap size exceeds VM budget

    今天测试程序的时候出现下面的错误日志信息,程序当场挂掉 07-09 14:11:25.434: W/System.err(4890): java.lang.OutOfMemoryError: bitm ...

  4. bitmap size exceeds VM budget

    bitmap size exceeds VM budget we can avoid this error by the following parts:1  its not how much ima ...

  5. Android解决java.lang.OutOfMemoryError: bitmap size exceeds VM budget(转)

    昨天遇到这个问题就是从一个输入流里调用BitmapFactory.decodeStream(this.getContentResolver().openInputStream(uri))得到一个bit ...

  6. 【android错误】bitmap size exceeds 32bits

    使用图片缩放时遇到这么个问题: java.lang.IllegalArgumentException: bitmap size exceeds 32bits 后来一行行查代码,发现原来是 scale ...

  7. 解决 SqlServer执行脚本,文件过大,内存溢出问题

    原文:解决 SqlServer执行脚本,文件过大,内存溢出问题 执行.sql脚本文件,如果文件较大时,执行会出现内存溢出问题,可用命令替代 cmd 中输入 osql -S 127.0.0.1,8433 ...

  8. 图片_ _Android有效解决加载大图片时内存溢出的问题 2

    Android有效解决加载大图片时内存溢出的问题 博客分类: Android Android游戏虚拟机算法JNI 尽量不要使用setImageBitmap或 setImageResource或 Bit ...

  9. Android开发中如何解决加载大图片时内存溢出的问题

    Android开发中如何解决加载大图片时内存溢出的问题    在Android开发过程中,我们经常会遇到加载的图片过大导致内存溢出的问题,其实类似这样的问题已经屡见不鲜了,下面将一些好的解决方案分享给 ...

随机推荐

  1. Git 简易使用指南及补充

    Git最简易的使用指南 助你开始使用 git 的简易指南,木有高深内容,;) 安装 下载 git OSX 版 下载 git Windows 版 下载 git Linux 版 创建新仓库 创建新文件夹, ...

  2. Redis哨兵模式主从同步不可以绑定127.0.0.1或者0.0.0.0,不然无法进行主从同步

    Redis哨兵模式主从同步不可以绑定127.0.0.1或者0.0.0.0,不然无法进行主从同步,一定要绑定内网IP,而对于跨机房的问题,可以使用iptables进行nat转发来解决.

  3. ASP.NET Web Api 实现数据的分页

    前言 这篇文章我们将使用不同的方式实现手动分页(关于高端大气上档次的OData本文暂不涉及,但有可能会在系列的后期介绍,还没确定...),对于分页的结果,我们将采用2种不同的方式响应给客户端(1.将分 ...

  4. MVC实现文件下载

    □ 思路 点击一个链接,把该文件的Id传递给控制器方法,遍历文件夹所有文件,根据ID找到对应文件,并返回FileResult类型. 与文件相关的Model: namespace MvcApplicat ...

  5. 通过使用第三方开源jar包sigar.jar我们可以获得本地的信息

    1.下载sigar.jar sigar官方主页 sigar-1.6.4.zip 2.按照主页上的说明解压包后将相应的文件copy到java路径.比如windows32位操作系统需要将lib中sigar ...

  6. 在MyEclipse中修改类不重启tomcat

    今天因为在调试一个程序,因为工程中用到spring,每次修改类代码时都要重启服务器,搞得很郁闷,于是上网找找有没有可以让java代码每次修改之后 直接加载到服务器的,找了一些还果真有,不过有些方法我试 ...

  7. tomcat配置manager

    tomcat-users.xml配置 <role rolename="manager-gui"/><user username="tomcat" ...

  8. 常见的Hadoop十大应用误解

    常见的Hadoop十大应用误解 1.        (误解) Hadoop什么都可以做 (正解) 当一个新技术出来时,我们都会去思考它在各个不同产业的应用,而对于平台的新技术来说,我们思考之后常会出现 ...

  9. 兼容的动态加载JS【原】

    兼容的动态加载JS 屌丝就是悲剧,五一还得宅家里写程序专研技术. 说起动态加载JS,搞web的肯定不陌生,著名的YUI库就有强大的模块化的动态加载JS机制.在代码量不断庞大的今天,动态加载JS作用还是 ...

  10. 《深入理解C#(第3版)》

    <深入理解C#(第3版)> 基本信息 原书名:C# in depth 作者: (英)Jon Skeet 译者: 姚琪琳 丛书名: 图灵程序设计丛书 出版社:人民邮电出版社 ISBN:978 ...