图片的分辨率会比我们手机屏幕的分辨率高得多。大家应该知道,我们编写的应用程序都是有一定内存限制的,程序占用了过高的内存就容易出现OOM(Out Of Memory)异常。我们可以通过下面的代码看出每个应用程序最高可用内存是多少。
因此在展示高分辨率图片的时候,最好先将图片进行压缩。压缩后的图片大小应该和用来展示它的控件大小相近,在一个很小的ImageView上显示一张超大的图片不会带来任何视觉上的好处,但却会占用我们相当多宝贵的内存,而且在性能上还可能会带来负面影响。下面我们就来看一看,如何对一张大图片进行适当的压缩,让它能够以最佳大小显示的同时,还能防止OOM的出现。
BitmapFactory这个类提供了多个解析方法
(decodeByteArray, decodeFile, decodeResource,decodeStream等)用于创建Bitmap对象,
我们应该根据图片的来源选择合适的方法。比如SD卡中的图片可以使用decodeFile方法,
网络上的图片可以使用decodeStream方法,
资源文件中的图片可以使用decodeResource方法。
这些方法会尝试为已经构建的bitmap分配内存,这时就会很容易导致OOM出现。为此每一种解析方法都提供了一个可选的BitmapFactory.Options参数,将这个参数的inJustDecodeBounds属性设置为true就可以让解析方法禁止为bitmap分配内存,返回值也不再是一个Bitmap对象,而是null。虽然Bitmap是null了,但是BitmapFactory.Options的outWidth、outHeight和outMimeType属性都会被赋值。这个技巧让我们可以在加载图片之前就获取到图片的长宽值和MIME类型,从而根据情况对图片进行压缩。
一.如何加载一张图片
二.加载图片的核心思想
采用BitmapFactory.Options就可以按照一定的采样率来加载缩小后的图片,这样可以降低内存的使用率,避免OOM,提高了Bitmap加载时的性能。
BitmapFactory.Options只要是采用inSampleSize参数,即采样率(缩放比)。当inSampleSize为1时,采样后的图片为原始图片的大小,
当inSampleSize大于1时,比如2,那么采样后的图片大小为原图大小的1/2,而像素为原图的1/4,所占内存也是原图1/4。
inSampleSize应为是2的指数,1,2,4,8,16等等,
如果inSampleSize小于1,其作用为1.即无缩放效果。
如果inSampleSize是3,其作用为2,向下取整。
三.缩放加载图片的四个步骤
- /**
- * 图片按比例大小压缩方法
- *
- * @param srcPath (根据路径获取图片并压缩)
- * @return
- */
- public static Bitmap getimage(String srcPath) {
- BitmapFactory.Options newOpts = new BitmapFactory.Options();
- // 开始读入图片,此时把options.inJustDecodeBounds 设回true了
- newOpts.inJustDecodeBounds = true;
- Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);// 此时返回bm为空
- int w = newOpts.outWidth;
- int h = newOpts.outHeight;
- // 现在主流手机比较多是800*480分辨率,所以高和宽我们设置为
- float hh = 800f;// 这里设置高度为800f
- float ww = 480f;// 这里设置宽度为480f
- // 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
- int be = 1;// be=1表示不缩放
- if (w > h && w > ww) {// 如果宽度大的话根据宽度固定大小缩放
- be = (int) (newOpts.outWidth / ww);
- } else if (w < h && h > hh) {// 如果高度高的话根据宽度固定大小缩放
- be = (int) (newOpts.outHeight / hh);
- }
- if (be <= 0)
- be = 1;
- newOpts.inSampleSize = be;// 设置缩放比例
- newOpts.inJustDecodeBounds = false;
- // 重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
- bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
- return compressImage(bitmap);// 压缩好比例大小后再进行质量压缩
- }