上一篇说道位图的压缩技巧,解决读取图片占用大量内存的情况,今天说一下把图像压缩成文件控制文件的大小,主要用在图片上传的情况下,先介绍一个方法:
bitmap.compress(CompressFormat format, int quality, OutputStream stream)
第一个参数指导了压缩的类型,一般指导JPEG格式:
CompressFormat.JPEG
第二个参数是压缩率:1~100的整数,越小压缩出的图片越小质量越差,100则不压缩。
第三个参数是输出文件流。
我们在使用这个方法进行压缩的时候进程通过循环来连续压缩,保证尽可能地减小图片到指定大小(下面是100kb),代码如下:
private static Bitmap compress(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int options = 100;
while (baos.toByteArray().length / 1024 > 100) {
// 循环判断如果压缩后图片是否大于100kb,大于继续压缩
baos.reset();// 重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, options, baos);
// 这里压缩options%,把压缩后的数据存放到baos中
options -= 10;// 每次都减少10
if (options <= 0) {
break;
}
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
// 把压缩后的数据baos存放到ByteArrayInputStream中
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);
// 把ByteArrayInputStream数据生成图片
return bitmap;
}
这个方法被称之为质量压缩,它并不会改变图片的像素数量,而是对像素的位深度透明度进行压缩,从而达到压缩的目的,因为像素数量没有变化,所以这个方法并不能无限压缩,到达一个极限之后就不会再减小了。
我们依然可以通过减小采样率的方式进行图片大小的压缩,就是减少图片的像素来减小所占的空间:
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inSampleSize = 2;
ByteArrayInputStream isBm = new ByteArrayInputStream(out.toByteArray());
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null , null );
这里设置采样率为2,及长宽各减小至原来的1/2。最好根据原图的大小和压缩后需要达到的大小来动态计算采样率,可以参见我的上一篇博客:
http://blog.csdn.net/liaoinstan/article/details/48781511
这种压缩方法可以把图片压缩到足够小,但是也有一点不好的地方,就是压缩率只能是整数,如果需要的大小可能正好介于2个采样率之间就不好办了,采样率差1可能导致图片大小差很多。
这里推荐一个用于生产缩略图的方法来进行压缩,指定期望的宽高来进行缩略图的生成:
public static Bitmap zoomImage(Bitmap bgimage, double newWidth,double newHeight) {
// 获取这个图片的宽和高
float width = bgimage.getWidth();
float height = bgimage.getHeight();
// 创建操作图片用的matrix对象
Matrix matrix = new Matrix();
// 计算宽高缩放率
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// 缩放图片动作
matrix.postScale(scaleWidth, scaleHeight);
Bitmap bitmap = Bitmap.createBitmap(bgimage, 0, 0, (int) width,(int) height, matrix, true);
return bitmap;
}
这个方法可以很好的将图片压缩的指定的大小,我们在进行图片的压缩的时候最好先进行质量压缩,如果质量压缩达不到预期的大小再进行图像的缩放,这样可以尽可能高的保存压缩后图片的清晰度。
这里图片的压缩完成了,接下来就是上传,我们一般都是使用第三方服务来管理图片,而不在本地服务器保存图片,这样的结构轻量,为后台的开发人员省去了很多精力来处理图片。目前的云存储服务也比较多,下一篇,我就介绍下目前比较流行也比较稳定的七牛云存储服务来管理我们上传的图片。