前段时间,项目的一个需求涉及图片压缩之后上传。要求是压缩之后的图片要和原图尺寸一致,压缩后的大小控制在< 600KB,并且重新加载的时候不能卡顿更不能OOM,在此做一下记录。
质量压缩
使用方式:
public String compressAndImage(Bitmap image) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
//压缩比重,图片存储在磁盘上的大小会根据这个值变化。值越小存储在磁盘的图片文件越小,取值
//区间为0-100,小于0时会抛异常
int options = 100;
image.compress(Bitmap.CompressFormat.JPEG, options, os);
// Compress by loop
while (os.toByteArray().length / 1024 > 500) {
os.reset();
if (options > 10) {
options -= 10;
image.compress(Bitmap.CompressFormat.JPEG, options, os);
} else {
options = 1;
image.compress(Bitmap.CompressFormat.JPEG, options, os);
break;
}
}
File file = new File("图片路径");
// Generate compressed image file
FileOutputStream fos = new FileOutputStream(file);
fos.write(os.toByteArray());
fos.flush();
fos.close();
return file.getAbsolutePath();
}
Bitmap.CompressFormat.PNG无效。
采样率压缩
使用方式:
public Bitmap handleImageToBitmap() {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
//此时只是为了获取当inJustDecodeBounds设置为true的时候,
// BitmapFactory通过decodeResource或者decodeFile解码图片时,
// 返回的Bitmap对象为null,这样可以避免Bitmap的内存分配,
// 但是它可以获取Bitmap的宽度、高度
BitmapFactory.decodeFile("文件路径", options);
options.inJustDecodeBounds = false;
//采样率,这个值决定了压缩后的图片大小
options.inSampleSize = 2;
return BitmapFactory.decodeFile("文件路径", options);
}
采样率压缩改变了图片的尺寸大小,减少了图片的像素点数,使得加载进内存的对象也变小了,当然对应图片保存到磁盘上所占空间也会变小。这些都取决于采样率的设定。一般这种压缩方式在做缩略图时用的较多。另附上做缩略图时,采样率(options.inSampleSize)的值设置方式:
public static int handleSampleSize(BitmapFactory.Options options, int aimsWidth, int aimsHeight) {
int height = options.outHeight;//获取原始图片的高度
int width = options.outWidth;//获取原始图片的宽度
//inSampleSize小于等于1会按照1处理
//inSampleSize只能设置为2的平方,不是2的平方则最终会减小到最近的2的平方数,如设置7会按4进行压缩。
int inSampleSize = 1;//设置初始采样率
if (height > aimsHeight || width > aimsWidth) {
final int heightRatio = Math.round((float) height / (float) aimsHeight);
final int widthRatio = Math.round((float) width / (float) aimsWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
尺寸压缩
即通过压缩图片尺寸而改变图片的大小。
public static Bitmap zoomCompress(Bitmap bitmap) {
Matrix matrix = new Matrix();
matrix.setScale(0.5f, 0.5f);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, true);
}
RGB_565压缩
在Android中,图片在内存是以Bitmap对象存在的,Bitmap所占内存计算方式:图片长度 x 图片宽度 x 一个像素点占用的字节数
图片的压缩格式共有以下四种:
ALPHA_8:表示8位Alpha位图,即A=8,一个像素点占用1个字节,它没有颜色,只有透明度
ARGB_4444:表示16位ARGB位图,即A=4,R=4,G=4,B=4,一个像素点占4+4+4+4=16位,2个字节
ARGB_8888:表示32位ARGB位图,即A=8,R=8,G=8,B=8,一个像素点占8+8+8+8=32位,4个字节
RGB_565:表示16位RGB位图,即R=5,G=6,B=5,它没有透明度,一个像素点占5+6+5=16位,2个字节
ARGB_4444压缩出来的画质很差,所以对透明度没有要求的话可以采用RGB_565的方式进行压缩:
public static Bitmap rgbCompress(String imgPath) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
return BitmapFactory.decodeFile(imgPath, options);
}
也可以采用ARGB_8888,只不过压缩出来大小变化可能会很小。
第三方
鲁班压缩------接近微信朋友圈的压缩方法
放一张作者提供的效果对比图:
具体使用方法上面链接里有,就不多做叙述。这种方案适合那种,要求图片压缩后尺寸不变、体积要变小加载进内存的对象也要变小的需求,亲测效果还不错,而且压缩出来的图片也不会模糊,压缩出来的格式是JPEG。
总结
使用每种压缩方式都要根据自己的需要来选择,有时候可能需要其中两种方式组合使用。对于第三方的选择上要慎重,毕竟使用第三方会增大apk的体积,能用系统提供的方法解决就尽量不用第三方。
最后如果文章有错误,请大家评论指正。希望我的分享能帮到大家!