Android之图片压缩的方式和见解

图片的分辨率会比我们手机屏幕的分辨率高得多。大家应该知道,我们编写的应用程序都是有一定内存限制的,程序占用了过高的内存就容易出现OOM(Out Of Memory)异常。我们可以通过下面的代码看出每个应用程序最高可用内存是多少。
[java]  view plain  copy
  1. int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);  
  2. Log.d("TAG""Max memory is " + maxMemory + "KB");  

因此在展示高分辨率图片的时候,最好先将图片进行压缩。压缩后的图片大小应该和用来展示它的控件大小相近,在一个很小的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类型,从而根据情况对图片进行压缩。


一.如何加载一张图片

Android中的BitmapFactory类提供了四种方法:
1.decodeFile
2.decodeResource
3.decodeStream
4.decodeByteArray

二.加载图片的核心思想

采用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,取整。

三.缩放加载图片的四个步骤

1.BitmapFactory.Options的inJustDecodBounds(仅读取边界)参数设为true并加载图片
2.BitmapFactory.Options取出原图片原始宽高信息,它们对应outWidth和outHeight
3.根据采样率的规则并结合目标view的所需大小计算出采样率inSampleSize
4.将BitmapFactory.Options的inJustDecodBounds参数设为false,然后重新加载图片。
  1. /** 
  2.      * 图片按比例大小压缩方法 
  3.      * 
  4.      * @param srcPath (根据路径获取图片并压缩) 
  5.      * @return 
  6.      */  
  7.     public static Bitmap getimage(String srcPath) {  
  8.   
  9.         BitmapFactory.Options newOpts = new BitmapFactory.Options();  
  10.         // 开始读入图片,此时把options.inJustDecodeBounds 设回true了  
  11.         newOpts.inJustDecodeBounds = true;  
  12.         Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);// 此时返回bm为空  
  13.   
  14.         
  15.         int w = newOpts.outWidth;  
  16.         int h = newOpts.outHeight;  
  17.         // 现在主流手机比较多是800*480分辨率,所以高和宽我们设置为  
  18.         float hh = 800f;// 这里设置高度为800f  
  19.         float ww = 480f;// 这里设置宽度为480f  
  20.         // 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可  
  21.         int be = 1;// be=1表示不缩放  
  22.         if (w > h && w > ww) {// 如果宽度大的话根据宽度固定大小缩放  
  23.             be = (int) (newOpts.outWidth / ww);  
  24.         } else if (w < h && h > hh) {// 如果高度高的话根据宽度固定大小缩放  
  25.             be = (int) (newOpts.outHeight / hh);  
  26.         }  
  27.         if (be <= 0)  
  28.             be = 1;  
  29.         newOpts.inSampleSize = be;// 设置缩放比例  
  30. newOpts.inJustDecodeBounds = false;  
  31.         // 重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了  
  32.         bitmap = BitmapFactory.decodeFile(srcPath, newOpts);  
  33.         return compressImage(bitmap);// 压缩好比例大小后再进行质量压缩  
  34.     }  



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值