使用android提供的BitmapFactory解码图片时,往往会因为图片过大而遇到OutOfMemoryError的异常。要想正常使用,一种简便的方式是分配更少的内存空间来存储,即在载入图片的时候以牺牲图片质量为代价,将图片进行放缩,这是一种避免OOM所采用的解决方法。但是,这种方法是得不偿失的,牺牲了图片质量。
在BitmapFactory中有一个内部类BitmapFactory.Options,其中值得我们注意的是inSampleSize和inJustDecodeBounds两个属性:
inSampleSize是以2的指数的倒数被进行放缩
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.
inJustDecodeBounds为Boolean型
设置inJustDecodeBounds为true后,decodeFile并不分配空间,但可计算出原始图片的长度和宽度,即options.outWidth和options.outHeight。
要对图片进行缩放,最大的问题就是怎么在运行时动态的改变inSampleSize的值,通过上面的inJustDecodeBounds可以知道图片原始的大小,那么这样以来就可以通过算法来得到一个恰当的inSampleSize值。其动态算法可参考下面的,网上也很多,大体都一样:
/**
* compute Sample Size
*
* @param options
* @param minSideLength
* @param maxNumOfPixels
* @return
*/
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;
}
/**
* compute Initial Sample Size
*
* @param options
* @param minSideLength
* @param maxNumOfPixels
* @return
*/
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;
}
}
有了上面的算法,我们就可以轻易的get到Bitmap了:
/**
* get Bitmap
*
* @param imgFile
* @param minSideLength
* @param maxNumOfPixels
* @return
*/
public static Bitmap tryGetBitmap(String imgFile, int minSideLength,
int maxNumOfPixels) {
if (imgFile == null || imgFile.length() == 0)
return null;
try {
FileDescriptor fd = new FileInputStream(imgFile).getFD();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
// BitmapFactory.decodeFile(imgFile, options);
BitmapFactory.decodeFileDescriptor(fd, null, options);
options.inSampleSize = computeSampleSize(options, minSideLength,
maxNumOfPixels);
try {
// 这里一定要将其设置回false,因为之前我们将其设置成了true
// 设置inJustDecodeBounds为true后,decodeFile并不分配空间,即,BitmapFactory解码出来的Bitmap为Null,但可计算出原始图片的长度和宽度
options.inJustDecodeBounds = false;
Bitmap bmp = BitmapFactory.decodeFile(imgFile, options);
return bmp == null ? null : bmp;
} catch (OutOfMemoryError err) {
return null;
}
} catch (Exception e) {
return null;
}
}
分享到:
相关推荐
Android不支持将Bitmap转换成单色的Bmp图片,所以参考Bmp格式说明,自己写了一个转换类。亲测有效!!!
android中对Bitmap图片设置任意角为圆角
Android图片Bitmap和字符串String之间相互转换的工具类,外加项目代码,封装好的,直接可以用,
android bitmap outofMemory 用来解决android中常见的bitmap outOfMemory
主要介绍了 Android canvas drawBitmap方法详解及实例的相关资料,需要的朋友可以参考下
一个基于android平台Bitmap 工具类,一个基于android平台Bitmap 工具类,一个基于android平台Bitmap 工具类,一个基于android平台Bitmap 工具类,一个基于android平台Bitmap 工具类,一个基于android平台Bitmap 工具...
主要介绍了Android 实现把bitmap图片的某一部分的颜色改成其他颜色,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
感觉Uri 、File、bitmap 比较混乱,这里进行记载,方便以后查看.下面话不多说了,来一起看看详细的介绍吧 Bitmap、File与Uri 1、将一个文件路径path转换成File String path ; File file = new File(path) 2...
Android bitmap Android Bitmap相关
Android上解析24位深度Bitmap文件示例
Android Bitmap详解及Bitmap的内存优化 一、Bitmap: Bitmap是Android系统中的图像处理的最重要类之一。用它可以获取图像文件信息,进行图像剪切、旋转、缩放等操作,并可以指定格式保存图像文件。 常用方法: ...
android Bitmap相关知识介绍~~~
软件开发网在此之前给大家介绍过图片加载框架Glide的基本用法介绍,大家可以先参考一下,本篇内容更加深入的分析了Glide获取图片Path、Bitmap用法,以及实现的代码分析。 1. 获取Bitmap: 1)在图片下载缓存好之后...
Android中bitmap转化成string格式的工具类,主要用于联网操作传递数据情境中
android 画图 bitmap drawable canvas paint
NULL 博文链接:https://chen592969029.iteye.com/blog/749100
Android—BitMap与Canvas学习笔记
Android下使用Canvas生成验证码Bitmap
android 通过surfacetexture绘制Bitmap,使用ISurfaceComposerClient创建新图层
本文实例讲述了Android中Bitmap用法。分享给大家供大家参考,具体如下: 一般在android程序中把图片文件放在res/drawable目录下就可以通过R.drawable.id来使用,但在存储卡中的图片怎样引用呢?下面通过实现这个功能...