Bitmap—— BitmapFactory.decodeFile
来源:互联网 发布:菲拉格慕蓝色经典 知乎 编辑:程序博客网 时间:2024/06/05 16:58
转自http://www.cnblogs.com/zgz345/archive/2013/01/08/2851204.html
在android设备上(where you have only 16MB memory available),如果使用BitmapFactory解码一个较大文件,程序立刻蹦出了java.lang.OutOfMemoryError: bitmap size exceeds VM budget的OOM错误!
解决办法:
方法一:将载入的图片缩小,这种方式以牺牲图片的质量为代价。在BitmapFactory中有一个内部类BitmapFactory.Options,其中当options.inSampleSize值>1时,
根据文档:
If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save memory. (1 -> decodes full size; 2 -> decodes 1/4th size; 4 -> decode 1/16th size). Because you rarely need to show and have full size bitmap images on your phone. For manipulations smaller sizes are usually enough.
也就是说,options.inSampleSize是以2的指数的倒数被进行放缩。这样,我们可以依靠inSampleSize的值的设定将图片放缩载入,这样一般情况也就不会出现上述的OOM问题了。现在问题是怎么确定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提供了一种动态计算的方法。如下:
public Bitmap getBitmapFromFile(File dst, int width, int height) { if (null != dst && dst.exists()) { BitmapFactory.Options opts = null; if (width > 0 && height > 0) { opts = new BitmapFactory.Options();<br><br> //设置inJustDecodeBounds为true后,decodeFile并不分配空间,此时计算原始图片的长度和宽度 opts.inJustDecodeBounds = true; BitmapFactory.decodeFile(dst.getPath(), opts); // 计算图片缩放比例 final int minSideLength = Math.min(width, height); opts.inSampleSize = computeSampleSize(opts, minSideLength, width * height);<br><br> //这里一定要将其设置回false,因为之前我们将其设置成了true opts.inJustDecodeBounds = false; opts.inInputShareable = true; opts.inPurgeable = true; } try { return BitmapFactory.decodeFile(dst.getPath(), opts); } catch (OutOfMemoryError e) { e.printStackTrace(); } } return null;} 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; }}
这样,在BitmapFactory.decodeFile执行处,也就不会报出上面的OOM Error。
如前面提到的,这种方式在一定程度上是以牺牲图片质量为代价的。如何才能更加优化的实现需求?
当在android设备中载入较大图片资源时,可以创建一些临时空间,将载入的资源载入到临时空间中。
BitmapFactory.Options bfOptions=new BitmapFactory.Options();bfOptions.inTempStorage=newbyte[12 * 1024];
以上创建了一个12kb的临时空间。然后使用
Bitmap bitmapImage = BitmapFactory.decodeFile(path,bfOptions);
但是我在程序中却还是出现以上问题!以下使用BitmapFactory.decodeFileDescriptor解决了以上问题:
BitmapFactory.Options bfOptions=new BitmapFactory.Options(); bfOptions.inDither=false; bfOptions.inPurgeable=true; bfOptions.inTempStorage=newbyte[12 * 1024]; bfOptions.inJustDecodeBounds = true; File file = new File(pePicFile.getAbsolutePath() + "/"+info.getImage()); FileInputStream fs=null; Bitmap bmp = null; try { fs = new FileInputStream(file); if(fs != null) bmp = BitmapFactory.decodeFileDescriptor(fs.getFD(), null, bfOptions); } catch (Exception e) { e.printStackTrace(); }
当然要将取得图片进行放缩显示等处理也可以在以上得到的bmp进行。
图片处理后记得回收内存
if(!bmp.isRecycle() ){ bmp.recycle() //回收图片所占的内存 system.gc() //提醒系统及时回收}
- Bitmap—— BitmapFactory.decodeFile
- BitmapFactory.decodeFile
- Bitmap——BitmapFactory.Options
- BitmapFactory 方法:decodeFileDescriptor()、decodeFile()
- BitmapFactory.decodeFile返回NULL
- Android入门——Bitmap和BitmapFactory
- Bitmap——BitmapFactory.Options的使用
- BitMapFactory.decodeFile always returns null.
- Android学习之——图形图像处理(Bitmap、BitmapFactory)(一)
- Android学习之——图形图像处理(Bitmap、BitmapFactory)(一)
- Android——Bitmap及其BitmapFactory的常用方法
- android BitmapFactory.decodeFile out of memory 崩溃
- android BitmapFactory.decodeFile()返回为null问题
- BitmapFactory.decodeFile图片过大内存溢出
- BitmapFactory.decodeFile内存溢出和变相解决方案
- (Bitmap OOM) BitmapFactory.nativeDecodeStream
- Bitmap,BitmapDrawable,BitmapFactory用法
- Bitmap与BitmapFactory.Options
- java的初始化顺序
- 关于UPnP Device Architecture 2.0的阅读笔记(三)
- iOS动画大全
- linux下快速安装nginx
- unicode转码
- Bitmap—— BitmapFactory.decodeFile
- serialVersionUID的作用
- Ajax网页实现异步更新----理解
- mockito简单教程
- 经典问题总结
- HDU5823(2016多校第八场)——color II (状压dp,独立集)
- 线段树 扫描线
- HDU 5093 Battle ships [二分图匹配] [匈牙利算法]
- hdu 2013