android图片压缩解决办法

来源:互联网 发布:集装箱在线计算软件 编辑:程序博客网 时间:2024/06/06 17:58

对图片的尺寸大小进行缩放来达到压缩的目的

只是大家需要注意的是,这里需要按照原始图片的宽高比(srcRatio)来计算最终输出图片的宽高(actualOutWidth,actualOutHeight),最后通过actualOutWidth,actualOutHeight来计算采样值sampleSize。

核心代码如下:

BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeFile(srcImagePath, options);//根据原始图片的宽高比和期望的输出图片的宽高比计算最终输出的图片的宽和高float srcWidth = options.outWidth;float srcHeight = options.outHeight;float maxWidth = outWidth;//期望输出的图片宽度float maxHeight = outHeight;//期望输出的图片高度float srcRatio = srcWidth / srcHeight;float outRatio = maxWidth / maxHeight;float actualOutWidth = srcWidth;//最终输出的图片宽度float actualOutHeight = srcHeight;//最终输出的图片高度if (srcWidth > maxWidth || srcHeight > maxHeight) {    if (srcRatio < outRatio) {        actualOutHeight = maxHeight;        actualOutWidth = actualOutHeight * srcRatio;    } else if (srcRatio > outRatio) {        actualOutWidth = maxWidth;        actualOutHeight = actualOutWidth / srcRatio;    } else {        actualOutWidth = maxWidth;        actualOutHeight = maxHeight;    }}//计算sampleSizeoptions.inSampleSize = computSampleSize(options, actualOutWidth, actualOutHeight);
举个极端例子:
假如原始图片宽为srcWidth=40,高为srcHeight=20。期望输出的宽为maxWidth=300,高为maxHeight=10。 那么srcRatio=40:20=2,outRatio=300:10=30. 显然srcRatio<outRatio,那么我们的实际最终输出图片的尺寸应该以maxHeight(10)为准即actualOutHeight = maxHeight,最后根据原图的比率来计算actualOutWidth=actualOutHeight*srcRatio = 10*40/20=20,最后得到的actualOutWidth=20. 最终输出图片的宽高比为20:10=2,和原始图片宽高比相同。其它情况类似,这里不做详解了。

对图片进行质量压缩

针对这种情况,android的Bitmap类中API接口有compress方法
public boolean compress(CompressFormat format, int quality, OutputStream stream)
三个参数的理解应该不难,大家可以查看官方doc文档。compress方法主要通过quality来控制输入到stream中的像素质量。
这针对希望输出的图片占用的空间不大于一定的值这种场景会比较合适,因为我们可以通过循环判断压缩后的大小是否大于定值,如果满足则减少quality继续执行compress操作。核心代码如下

//进行有损压缩ByteArrayOutputStream baos = new ByteArrayOutputStream();int options_ = 100;actualOutBitmap.compress(Bitmap.CompressFormat.JPEG, options_, baos);//质量压缩方法,把压缩后的数据存放到baos中 (100表示不压缩,0表示压缩到最小)int baosLength = baos.toByteArray().length;while (baosLength / 1024 > maxFileSize) {//循环判断如果压缩后图片是否大于maxMemmorrySize,大于继续压缩    baos.reset();//重置baos即让下一次的写入覆盖之前的内容    options_ = Math.max(0, options_ - 10);//图片质量每次减少10    actualOutBitmap.compress(Bitmap.CompressFormat.JPEG, options_, baos);//将压缩后的图片保存到baos中    baosLength = baos.toByteArray().length;    if (options_ == 0)//如果图片的质量已降到最低则,不再进行压缩        break;}

压缩一个超大图是要费时间的,所以大家应该考虑将压缩放到后台线程中执行,如果没有高并发的需求使用AsyncTask就能解决问题。
核心代码:

private class CompressTask extends AsyncTask<String, Void, String> {    @Override    protected String doInBackground(String... params) {        return compressImage();//执行压缩操作    }    @Override    protected void onPreExecute() {        if (compressListener != null) {            compressListener.onCompressStart();//监听回调(开始压缩)        }    }    @Override    protected void onPostExecute(String imageOutPath) {        if (compressListener != null) {            compressListener.onCompressEnd(imageOutPath);//监听回调(压缩结束)        }    }}

经过适当的封装代码可以通过在Activity中的执行
LGImgCompressor.getInstance(this).withListener(this). starCompress(Uri.fromFile(imageFile).toString(),outWidth,outHeight,maxFileSize);
来启动压缩任务

具体参考demo开源github地址如下:
LGImageCompressor


0 0
原创粉丝点击