第一步:读取图片的尺寸和和类型
根据图片数据源的不同选择BitmapFactory的相应的静态方法,通过下面的方法就能够常见图片解码生成Bitmap对象。
如果是图片数据源是二进制流,选择BitmapFactory.decodeByteArray()方法,
如果图片在某个文件路径下面,选择BitmapFactory.decodeFile()方法,
如果图片是在APP的内部的res文件夹下面BitmapFactory.decodeResource()方法,
注意:通常调用上面三种方法签名中带有BitmapFactory.Options类型参数的方法,通过设置BitmapFactory.Options对象的inJustDecodeBounds 属性为true,这样就不会为解码图片分配内存,也就返回了一个空的Bitmap对象。但可以通过该方法获取到图片的宽和高以及图片的格式,通过这种方式我们就能在分配内存创建bitmap之前获取该图片的格式和尺寸(宽与高)这样就避免了出现java.lang.OutOfMemory异常。除非你百分之百确定此图片恰好在内存范围之内,否则一定要在解码图片之前获取其尺寸与类型,代码示例:
1 BitmapFactory.Options options = new BitmapFactory.Options(); 2 options.inJustDecodeBounds = true; 3 BitmapFactory.decodeResource(getResources(), R.id.myimage, options); 4 int imageHeight = options.outHeight; 5 int imageWidth = options.outWidth; 6 String imageType = options.outMimeType;
第二步:将压缩版的图片加载到内存。
在第一步中我们已经得到了图片的尺寸,然后我们实际图片预计所使用内存,应用本身其他也需要占用内存,屏幕的大小,当前设备的像素,显示该图片的UI组件的宽与高等因素来决定是否要压缩图片如果要压缩图片,需要计算图片的压缩比例。然后将该压缩比例赋值给 BitmapFactory.Options对象的inSampleSize属性,注意在此之前BitmapFactory.Options对象的inJustDecodeBounds需要为true。同时计算的压缩比例应该是2的n(n为非负整数)次方,因为如果不为2的n次方,会采用四舍的方式转换到最接近该比例2的n次方那个数,示例代码如下:
1 public static int calculateInSampleSize( 2 BitmapFactory.Options options, int reqWidth, int reqHeight) { 3 // 图片实际的高于宽 4 final int height = options.outHeight; 5 final int width = options.outWidth; 6 int inSampleSize = 1; 7 8 if (height > reqHeight || width > reqWidth) { 9 10 final int halfHeight = height / 2; 11 final int halfWidth = width / 2; 12 13 //计算最大的压缩比例,比例是2的幂并保证实际图片宽与高要大于最终展示图片的宽与高 14 while ((halfHeight / inSampleSize) > reqHeight 15 && (halfWidth / inSampleSize) > reqWidth) { 16 inSampleSize *= 2; 17 } 18 } 19 return inSampleSize; 20 }
第三步:生成压缩后的图片
不要忘记此时需要将BitmapFactory.Options之前对象属性的inJustDecodeBounds设置为false,否则得到的Bitmap是null 。代码如下:
1 public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, 2 int reqWidth, int reqHeight) { 3 4 // First decode with inJustDecodeBounds=true to check dimensions 5 final BitmapFactory.Options options = new BitmapFactory.Options(); 6 options.inJustDecodeBounds = true; 7 BitmapFactory.decodeResource(res, resId, options); 8 9 // Calculate inSampleSize 10 options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 11 12 // Decode bitmap with inSampleSize set 13 options.inJustDecodeBounds = false; 14 return BitmapFactory.decodeResource(res, resId, options); 15 }
第四步:展示压缩的图片
1 mImageView.setImageBitmap( 2 decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));