问题:大图片上传前(1m左右),该怎么处理?
图片大小不变,无损质量压缩
参考代码如下:
/**
* Compress by quality, and generate image to the path specified
*
* @param image
* @param outPath
* @param maxSize target will be compressed to be smaller than this size.(kb)
* @throws IOException
*/
public static void compressAndGenImage(Bitmap image, String outPath, int maxSize) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
// scale
int quality = 0;
// Store the bitmap into output stream(no compress)
image.compress(Bitmap.CompressFormat.JPEG, quality, os);
// Compress by loop
while ( os.toByteArray().length / 1024 > maxSize) {
// Clean up os
os.reset();
// interval 10
quality -= 10;
image.compress(Bitmap.CompressFormat.JPEG, quality, os);
}
Log.i("COMPRESS", "quality:" + quality);
// Generate compressed image file
FileOutputStream fos = new FileOutputStream(outPath);
fos.write(os.toByteArray());
fos.flush();
fos.close();
}
下面贴一组测试数据
I/COMPRESS: oriWidth = 3264
I/COMPRESS: oriHeight = 1840
I/COMPRESS: oriSize = 1047535 = 1023Kb
I/COMPRESS: quality:0
I/COMPRESS: resultWidth = 3264
I/COMPRESS: resultHeight = 1840
I/COMPRESS: resultSize = 97045
参数说明:quality=0时,压缩生成的图片大小最小。上面的数据看到 97045(95Kb)/ 1047535 = 0.09 大概压到了原图的1/10,不过效果也大大折扣,损失了图片质量。
原图
1023Kb
quality0
压缩到1/10后的图片
第二组测试数据
I/COMPRESS: oriWidth = 3264
I/COMPRESS: oriHeight = 1840
I/COMPRESS: oriSize = 1047535
I/COMPRESS: quality:50
I/COMPRESS: resultWidth = 3264
I/COMPRESS: resultHeight = 1840
I/COMPRESS: resultSize = 334230
结果占原图 0.32,差不多1/3,效果如下。
quality50
326Kb
第三组测试数据
I/COMPRESS: oriWidth = 3264
I/COMPRESS: oriHeight = 1840
I/COMPRESS: oriSize = 1047535
I/COMPRESS: quality:100
I/COMPRESS: resultWidth = 3264
I/COMPRESS: resultHeight = 1840
I/COMPRESS: resultSize = 3018902
quality==100时,压出的图片大小是原图的2.88倍大小……由此看出quality并不是越大越好。
探究 合适的quality的值
08-21 23:17:15.832 14351-14351/com.jinll.mylife I/COMPRESS: oriWidth = 3264
08-21 23:17:15.832 14351-14351/com.jinll.mylife I/COMPRESS: oriHeight = 1840
08-21 23:17:15.832 14351-14351/com.jinll.mylife I/COMPRESS: oriSize = 1047535
08-21 23:17:15.942 14351-14351/com.jinll.mylife I/COMPRESS: quality:10
08-21 23:17:16.002 14351-14351/com.jinll.mylife I/COMPRESS: resultWidth = 3264
08-21 23:17:16.002 14351-14351/com.jinll.mylife I/COMPRESS: resultHeight = 1840
08-21 23:17:16.002 14351-14351/com.jinll.mylife I/COMPRESS: resultSize = 108006
08-21 23:21:49.409 18668-18668/com.jinll.mylife I/COMPRESS: oriWidth = 3264
08-21 23:21:49.409 18668-18668/com.jinll.mylife I/COMPRESS: oriHeight = 1840
08-21 23:21:49.409 18668-18668/com.jinll.mylife I/COMPRESS: oriSize = 1047535
08-21 23:21:49.519 18668-18668/com.jinll.mylife I/COMPRESS: quality:20
08-21 23:21:49.589 18668-18668/com.jinll.mylife I/COMPRESS: resultWidth = 3264
08-21 23:21:49.589 18668-18668/com.jinll.mylife I/COMPRESS: resultHeight = 1840
08-21 23:21:49.589 18668-18668/com.jinll.mylife I/COMPRESS: resultSize = 147664
08-21 23:20:17.040 17130-17130/com.jinll.mylife I/COMPRESS: oriWidth = 3264
08-21 23:20:17.040 17130-17130/com.jinll.mylife I/COMPRESS: oriHeight = 1840
08-21 23:20:17.040 17130-17130/com.jinll.mylife I/COMPRESS: oriSize = 1047535
08-21 23:20:17.160 17130-17130/com.jinll.mylife I/COMPRESS: quality:30
08-21 23:20:17.230 17130-17130/com.jinll.mylife I/COMPRESS: resultWidth = 3264
08-21 23:20:17.230 17130-17130/com.jinll.mylife I/COMPRESS: resultHeight = 1840
08-21 23:20:17.230 17130-17130/com.jinll.mylife I/COMPRESS: resultSize = 212542
quality10
105Kb
quality20
144Kb
quality30
207Kb
结论:
quality==30的时候,如果对于最后压缩生成的照片的要求不是那么高时,已经满足需求了。
下面是简版代码,生成的图片大概为原图的1/5。
参考数据:2.56M 的jpg 压缩完 422Kb
/**
* Compress pic and generate image to the path specified
*
* @param image
* @param outPath
* @throws IOException
*/
public static void compressAndGenImage(Bitmap image, String outPath) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
// scale
int quality = 30;
// Store the bitmap into output stream(no compress)
image.compress(Bitmap.CompressFormat.JPEG, quality, os);
// Generate compressed image file
FileOutputStream fos = new FileOutputStream(outPath);
fos.write(os.toByteArray());
fos.flush();
fos.close();
}