许多情况下,我们的应用中需要的图片大小总是小于图片的原始大小如果我们不在载入之前做一些处理的话,那么我们会遇到比如图片资源占用大量内存的状况,所以通常在载入图片之前,我们做一些裁剪工作:
一、读取Bitmap的维度和类型
BitmapFactory类提供了一些数据解压方法,比如:decodeByteArray()、decodeFile()、decodeResource()等等。为了以各种来源的图片资源为基础创建位图(Bitmap),我们需要选择最有效的解压方法(具体详见Android官方文档),同时要注意的是,这些方法都会尝试为被构造的位图申请内存资源,因此比较容易出现OutOfMemory异常。每种解压方法都需要程序员自己声明一个BitmapFactory.Options(这其实是一个类),比如设定其中的inJustDecodeBounds属性为true,然后使用decode方法可以获取原图的size,同时会返回一个null的Bitmap对象,以及outWidth、outHeight、outMimeType属性,这个方法对于我们读取原图的大小、类型十分方便,下面是示例:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
为了避免上面提到的异常,需要在使用decode方法之前确定原图的大小,除非你十分确定原图的大小不小于你想剪裁的大小,但这一般是不可能的
二、载入一个裁剪的位图版本
现在图片的维度(大小)已经知道了,为了告诉decode方法给原图创建一个多大的子位图,我们需要设定inSampleSize参数,这个参数同样包含在BitmapFactory.Options对象之内,关于inSampleSize参数,做出如下说明:
1)参数为正,如果参数<=1,那么子图的最终裁剪大小即是原图的大小(相当于未裁剪)
2)参数大于1,一般是2的倍数,那么子图的长宽都会变为原来的:1/inSampleSize,这里要说明的是,即使我们为inSampleSize设定的参数大小不是2的倍数,它也会当成向下取正最接近的2的倍数,下面的实例就体现了这一点;
为什么我们要做裁剪?比如有一张1024*768像素的图像要被载入内存,然而最终你要用到的图片大小其实只有128*96,那么我们会浪费很大一部分内存,这显然是没有必要的,下面是一个实例:
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final