在做微信分享的时候,由于分享的缩略图要求不得大于32K,否则不能调起微信,所以总结了一下Android图片的压缩问题,大部分资料都是来自网上各位的分享,自己只是完善或修改了一下,本着继续分享的精神,也方便自己记忆,于是总结如下。

Android图片压缩主要有两种方式:1.压缩图片分辨率 2.压缩图片质量

一、先看压缩图片分辨率,很好理解,如本来1280*768的图片压缩为640*384大小。废话不说,直接上代码:

/**
	 * 按比例压缩图片分辨率
	 * @param inBitmap
	 * @param outHeight 输出图片高度,可据此保持比例计算输出宽度
	 * @param needRecycled 是否回收inBitmap
	 * @return
	 */
	public static Bitmap createScaledBitmapByOutHeight(Bitmap inBitmap, int outHeight, boolean needRecycled) {  		
		int bitmapHeight = inBitmap.getHeight();
		int bitmapWidth = inBitmap.getWidth();
		int outWidth = bitmapWidth * outHeight / bitmapHeight;
		
		return createScaledBitmap(inBitmap, outWidth, outHeight, needRecycled);
	} 
	
	/**
	 * 按比例压缩图片分辨率
	 * @param inBitmap
	 * @param outHeight 输出图片宽度,可据此保持比例计算输出高度
	 * @param needRecycled 是否回收inBitmap
	 * @return
	 */
	public static Bitmap createScaledBitmapByOutWidth(Bitmap inBitmap, int outWidth, boolean needRecycled) {  		
		int bitmapHeight = inBitmap.getHeight();
		int bitmapWidth = inBitmap.getWidth();
		int outHeight = bitmapHeight * outWidth / bitmapWidth;
		
		return createScaledBitmap(inBitmap, outWidth, outHeight, needRecycled);
	}
	
	/**
	 * 指定输出的宽高缩放图片
	 * @param inBitmap
	 * @param outWidth
	 * @param outHeight
	 * @param needRecycled
	 * @return
	 */
	public static Bitmap createScaledBitmap(Bitmap inBitmap, int outWidth, int outHeight, boolean needRecycled) {  				
		
		Bitmap thumbBmp = Bitmap.createScaledBitmap(inBitmap, outWidth, outHeight, true);
		if (needRecycled) {
        	inBitmap.recycle();
        }
		
		return thumbBmp;
	}



前两个方法可以指定期望的宽度或高度,并按比例缩放图片的分辨率,第3个方法可以随意指定期望的宽高,缩放图片。

上面代码是对输入的bitmap进行缩放,还可以从资源或文件中加载图片并缩放,具体如下:

/**
	 * 从资源加载并压缩图片
	 * @param res
	 * @param resId
	 * @param outWidth 目标宽度
	 * @param outHeight 目标高度
	 * @return
	 */
	public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,  
	        int outWidth, int outHeight) { 
	    final BitmapFactory.Options options = new BitmapFactory.Options();  
	    options.inJustDecodeBounds = true; // 假解,来获取图片大小  
	    BitmapFactory.decodeResource(res, resId, options);  
	    options.inSampleSize = calculateInSampleSize(options, outWidth, outHeight);  
	    // 使用获取到的inSampleSize值再次解析图片  
	    options.inJustDecodeBounds = false;
	    //options.inPreferredConfig = Config.RGB_565;
	    return BitmapFactory.decodeResource(res, resId, options);  
	} 
	
	/**
	 * 从文件中加载并压缩图片
	 * @param res
	 * @param resId
	 * @param outWidth 目标宽度
	 * @param outHeight 目标高度
	 * @return
	 */
	public static Bitmap decodeSampledBitmapFromFile(String pathName, int outWidth, int outHeight) {
	    final BitmapFactory.Options options = new BitmapFactory.Options();  
	    options.inJustDecodeBounds = true; // 假解,来获取图片大小  
	    BitmapFactory.decodeFile(pathName, options);
	    options.inSampleSize = calculateInSampleSize(options, outWidth, outHeight);  
	    // 使用获取到的inSampleSize值再次解析图片  
	    options.inJustDecodeBounds = false;
	    //options.inPreferredConfig = Config.RGB_565;
	    return BitmapFactory.decodeFile(pathName, options);
	} 
	
	/**
	 * 计算options.inSampleSize
	 * @param options
	 * @param reqWidth
	 * @param reqHeight
	 * @return
	 */
	public static int calculateInSampleSize(BitmapFactory.Options options,  
	        int reqWidth, int reqHeight) {  
	    // 源图片的高度和宽度  
	    final int height = options.outHeight;  
	    final int width = options.outWidth;  
	    int inSampleSize = 1;  
	    if (height > reqHeight || width > reqWidth) {  
	        // 计算出实际宽高和目标宽高的比率  
	        final int heightRatio = Math.round((float) height / (float) reqHeight);  
	        final int widthRatio = Math.round((float) width / (float) reqWidth);  
	        // 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高  
	        // 一定都会大于等于目标的宽和高。  
	        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;  
	    }  
	    return inSampleSize;  
	}

二、压缩图片的质量

/**
	 * 压缩图片质量,把图片压缩到outSize以内
	 * @param inBitmap 原始bitmap
	 * @param outSize 压缩到的大小
	 * @param needRecycled 是否回收bitmap
	 * @return
	 */
	public static Bitmap compressImage(Bitmap inBitmap, int outSize, boolean needRecycled) {  
		  
        ByteArrayOutputStream baos = new ByteArrayOutputStream();  
        inBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        int quality = 100;  
        while (baos.toByteArray().length / 1024 > outSize) {
        	if (quality <= 0) {
        		ByteArrayInputStream outBais = new ByteArrayInputStream(baos.toByteArray());
        		return BitmapFactory.decodeStream(outBais, null, null);// 如果quaLity为0时还未达到32k以内,返回得到的最小值;如需要可结合分辨率压缩
        	}
            baos.reset();
            //PNG格式下,这种压缩不起作用(quality:0-100,如果目标大小太小,有时候质量压缩不一定能达到效果,需结合分辨率压缩)
            inBitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
            Log.e("AN", "bitmap size:"+ baos.toByteArray().length / 1024 + "k");
            quality -= 10;
        }
        if (needRecycled) {
        	inBitmap.recycle();
        }
        
        
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        Bitmap outBitmap= BitmapFactory.decodeStream(bais, null, null);//ByteArrayInputStream转成bitmap
        
        return outBitmap;  
    }



需要注意的是compress方法,该压缩方法只对JPEG格式有效,对于PNG格式,则会忽略第二个参数quality,即压缩不起作用。这种压缩只是对图片质量有影响,并不会改变图片大小。

当然,如有需要,以上两种压缩方法可以结合使用。