<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">用了很久图片压缩,之前人们一直使用google的官方图片压缩方法</span>
final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options);
public static int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; // Calculate the largest inSampleSize value that is a power of 2 and keeps both // height and width larger than the requested height and width. while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) { inSampleSize *= 2; } } return inSampleSize; }
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
仔细看calucelateInSamplesize方法,该算法返回的是一种压缩比例,仔细一看他的计算过程,你会发现,inSampleSize的变化过程是2-4-8,,而真正进入wile循环时,宽高就已经被看成是小了一半来计算的了,所以,上面那个网站说12M能压缩到0.75M,就是因为差距太大,如果安卓手机内部压缩自己的图片(大概是2M压缩到100K),所以此时,这个方法就适用于android编码压缩了。
所以鄙人针对于android编码时压缩,在此对它进行了优化,优化后代码如下:
运行: culculateInSampleSize(bm,200,300)效果:
<pre name="code" class="java"><span style="font-family: Arial, Helvetica, sans-serif;">/**</span>* 计算压缩比例值(改进版 by touch_ping)
文件大小从1.12M变成81.75k
最终附上完整压缩工具类:
package com.example.mqtest; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.util.Log; /** * 图片压缩工具类 * @author touch_ping * 2015-1-5 下午1:29:59 */ public class BitmapCompressor { /** * 质量压缩 * @author ping 2015-1-5 下午1:29:58 * @param image * @param maxkb * @return */ public static Bitmap compressBitmap(Bitmap image,int maxkb) { //L.showlog("压缩图片"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.JPEG, 50, baos);// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中 int options = 100; // Log.i("test","原始大小" + baos.toByteArray().length); while (baos.toByteArray().length / 1024 > maxkb) { // 循环判断如果压缩后图片是否大于(maxkb)50kb,大于继续压缩 // Log.i("test","压缩一次!"); baos.reset();// 重置baos即清空baos options -= 10;// 每次都减少10 image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%,把压缩后的数据存放到baos中 } // Log.i("test","压缩后大小" + baos.toByteArray().length); ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中 Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片 return bitmap; } /** * http://developer.android.com/training/displaying-bitmaps/load-bitmap.html * 官网:获取压缩后的图片 * * @param res * @param resId * @param reqWidth * 所需图片压缩尺寸最小宽度 * @param reqHeight * 所需图片压缩尺寸最小高度 * @return */ public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); } /** * 官网:获取压缩后的图片 * * @param res * @param resId * @param reqWidth * 所需图片压缩尺寸最小宽度 * @param reqHeight * 所需图片压缩尺寸最小高度 * @return */ public static Bitmap decodeSampledBitmapFromFile(String filepath, int reqWidth, int reqHeight) { final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(filepath, options); options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(filepath, options); } public static Bitmap decodeSampledBitmapFromBitmap(Bitmap bitmap, int reqWidth, int reqHeight) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 90, baos); byte[] data = baos.toByteArray(); final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeByteArray(data, 0, data.length, options); options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inJustDecodeBounds = false; return BitmapFactory.decodeByteArray(data, 0, data.length, options); } /** * 计算压缩比例值(改进版 by touch_ping) * * 原版2>4>8...倍压缩 * 当前2>3>4...倍压缩 * * @param options * 解析图片的配置信息 * @param reqWidth * 所需图片压缩尺寸最小宽度O * @param reqHeight * 所需图片压缩尺寸最小高度 * @return */ public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { final int picheight = options.outHeight; final int picwidth = options.outWidth; Log.i("test", "原尺寸:" + picwidth + "*" +picheight); int targetheight = picheight; int targetwidth = picwidth; int inSampleSize = 1; if (targetheight > reqHeight || targetwidth > reqWidth) { while (targetheight >= reqHeight && targetwidth>= reqWidth) { Log.i("test","压缩:" +inSampleSize + "倍"); inSampleSize += 1; targetheight = picheight/inSampleSize; targetwidth = picwidth/inSampleSize; } } Log.i("test","最终压缩比例:" +inSampleSize + "倍"); Log.i("test", "新尺寸:" + targetwidth + "*" +targetheight); return inSampleSize; } }
public static int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; // Calculate the largest inSampleSize value that is a power of 2 and keeps both // height and width larger than the requested height and width. while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) { inSampleSize *= 2; } } return inSampleSize; }