图片的压缩分为质量压缩和尺寸压缩,下面就一一介绍这两种压缩
质量压缩
- 主要实现(一个小例子)
主要核心代码是 Bitmap.compress(args1,args2,args3);
参数1:Bitmap.CompressFormat.JPEG/PNG/WBPG; JPEG表示有损压缩,PNG表示无损压缩(也即是没有压缩),WBPG是Google推出的一种图片格式,相比较于JPEG可节约30%,但是从兼容性和整体的压缩大小来看,都是选择JPEG的。
参数2:int quality: 0~100 越大图片质量越高,可选的
参数3:OutputStream stream:表示压缩后的图片输出流。
示例代码:
/**
* 图片的质量压缩
*/
private void compressQuality() {
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "timo_compress.jpg");
try {
if (!file.exists()) {
file.createNewFile();
}
} catch (Exception e) {
e.printStackTrace();
}
//获取到bitmap
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.timo);
BufferedOutputStream ous = null;
try {
ous = new BufferedOutputStream(new FileOutputStream(file));
//参数1:压缩格式 PNG,JPEG,WEBP,正常情况下都是选用JPEG格式,JPEG是有损压缩,PNG的无损压缩(也就是没有压缩),WEBP是Google
//自己推出的图片格式,相比JPEG会节约30%,但是从兼容性和整体的压缩大小来看,都是选择JPEG格式的。
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, ous);
//释放内存中的bitmap
bitmap.recycle();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (ous != null) {
ous.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
尺寸压缩
1. 尺寸压缩实质上就是一个重新采样的过程,放大图像称为上采样,缩小图像称为下采样,Android提供了两种采样方法,分别称为临近采样和双线性采样。
- 临近采样:这种方式的压缩主要取决于inSampleSize参数的设置,越大,则压缩的比例就越大,inSampleSize = 4 那么宽和高就是原来的1/4,像素点数是原来的1/16。
/**
* 尺寸压缩
*/
private void compressSize() {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
//获取到Bitmap
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.timo, options);
//设置文件存储路径
String savePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath() + "/timo_option.jpg";
ImageUtils(savePath,bitmap);
}
/**
* 图片工具类
* @param filePath
* @param bitmap
*/
public void ImageUtils(String filePath, Bitmap bitmap) {
File file = new File(filePath);
try {
if (!file.exists()) {
file.createNewFile();
}
bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file));
boolean compress = bitmap.compress(Bitmap.CompressFormat.JPEG, 50, bufferedOutputStream);
bitmap.recycle();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if (bufferedOutputStream != null) {
bufferedOutputStream.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
双线性采样压缩
/**
* 双线性采样压缩:是通过一个像素点周围的2x2 个点的值,根据周围点值来计算取对应的权重,计算得到目标图像
*/
public void BilinearCompress(){
String filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath()+"/bili_tomo.jpg";
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.timo);
Matrix matrix = new Matrix();
matrix.setScale(0.5f,0.5f);
Bitmap mBitmap = Bitmap.createBitmap(bitmap,0,0,(bitmap.getWidth())/2,(bitmap.getHeight())/2,matrix,true);
ImageUtils(filePath,mBitmap);
}
- 关于Bitmap.recycle()方法的一点补充描述:此方法是用来释放内存中的bitmap占用的内存,建立bitmap引用是有两部分组成,一部分是Java层面的,一部分是C层面的,Java层面靠垃圾回收器进行垃圾回收的,C层面是是通过调用recycle()来调用JNI层面的代码来释放内存的。
- System.gc():方法的调用,是加快垃圾回收器的到来,不能保证立刻就来进行垃圾的回收。
- Bitmap.recycle()调用之后,此bitmap就不能再次使用了,再次使用就会抛出异常,所在在Activity中,在onStop或onDestroy中进行调用。
- 内存溢出的捕获:OutOfMemoryError 是个错误,在捕获的时候,写成Exception是不能捕获到的。