近日在做一款饭否第三方客户端,饭否对于图片上传有着严格的大小限制(店小成本问题,┑( ̄Д  ̄)┍),GIF大小2M,静态图4M,即便如此,大部分拍照的图片都是超过4M大小的。
最开始使用的是Luban,但是经常出现该库读取Exif信息的时候出错崩溃,导致压根不压缩,所以想着自己写。
网上有一个压缩图片的片段比较好,思想是对JPEG图片的质量参数进行尝试,从100开始,做循环压缩,每次降低10,直到大小符合要求,代码如下:
public static void compressBmpToFile(Bitmap bmp,File file){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int options = 80;//个人喜欢从80开始,
bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
while (baos.toByteArray().length / 1024 > 100) {
baos.reset();
options -= 10;
bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
}
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write(baos.toByteArray());
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
但是在实践过程中,发现此段代码有较为严重的性能问题,核心在于baos.toByteArray().length
,查阅Android文档如下:
作为一个尝试获取压缩后大小的操作每次都重新分配大小是不合适的,需要获取压缩后占用空间,可以直接使用ByteArrayOutputStream.size()
即可,查阅其源代码,size()
返回流内部数组的大小,免去了重复分配且复制的操作。