在讲压缩的方法之前我们先来了解两个概念
1.图片的存在形式是三种:
1.文件的形式。(以二进制流存在于硬盘中)
2.流的形式。(以二进制流存在于内存中)
3.bitmap位图形式。
2.图片常用的压缩格式:
1.ALPHA_8 表示8位Alpha位图,即A=8,一个像素点占用1个字节,它没有颜色,只有透明度
2.ARGB_4444 表示16位ARGB位图,即A=4,R=4,G=4,B=4,一个像素点占4+4+4+4=16位,2个字节
3.ARGB_8888 表示32位ARGB位图,即A=8,R=8,G=8,B=8,一个像素点占8+8+8+8=32位,4个字节
4.RGB_565 表示16位RGB位图,即R=5,G=6,B=5,它没有透明度,一个像素点占5+6+5=16位,2个字节
我们在做压缩处理的时候,可以先通过改变Bitmap的图片编码格式,来达到压缩的效果,其实压缩最主要就是要么改变其宽高,要么就通过减少其单个像素占用的内存。
一张图片(BitMap)占用的内存=图片长度x图片宽度x单位像素占用的字节数
图片的四种压缩的方法
1.质量压缩法
质量压缩并不会改变图片在内存中的大小,仅仅会减小图片所占用的磁盘空间的大小,因为质量压缩不会改变图片的分辨率,而图片在内存中的大小是根据widthheight一个像素的所占用的字节数计算的,宽高没变,在内存中占用的大小自然不会变,质量压缩的原理是通过改变图片的位深和透明度来减小图片占用的磁盘空间大小,所以不适合作为缩略图,可以用于想保持图片质量的同时减小图片所占用的磁盘空间大小。另外,由于png是无损压缩,所以设置quality无效,以下是实现方式:
/**
* 质量压缩
*
* @param format 图片格式 jpeg,png,webp
* @param quality 图片的质量,0-100,数值越小质量越差
*/
public static void compress(Bitmap.CompressFormat format, int quality) {
File originFile = new File(Environment.getDataDirectory(), "originImg.jpg");
Bitmap originBitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
originBitmap.compress(format, quality, bos);//质量压缩
try {
FileOutputStream fos = new FileOutputStream(new File(sdFile, "resultImg.jpg"));
fos.write(bos.toByteArray());
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
2.采样率压缩
采样率压缩其原理是缩放bitamp的尺寸,通过调节其inSampleSize参数,比如调节为2,宽高会为原来的1/2,内存变回原来的1/4.
File originFile = new File(Environment.getDataDirectory(), "originImg.jpg");
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
Bitmap originBitmap= BitmapFactory.decodeFile(originFile.getAbsolutePath(), options);//采样率压缩
ByteArrayOutputStream bos = new ByteArrayOutputStream();
originBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
try {
FileOutputStream fos = new FileOutputStream(new File(sdFile, "resultImg.jpg"));
fos.write(bos.toByteArray());
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
3.RGB_565压缩
RGB_565压缩是通过改用内存占用更小的编码格式来达到压缩的效果。Android默认的颜色模式为ARGB_8888,这个颜色模式色彩最细腻,显示质量最高。一般不建议使用ARGB_4444,因为画质实在是辣鸡,如果对透明度没有要求,建议可以改成RGB_565,相比ARGB_8888将节省一半的内存开销。
File originFile = new File(Environment.getDataDirectory(), "originImg.jpg");
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap originBitmap= BitmapFactory.decodeFile(originFile.getAbsolutePath(), options);//RGB_565压缩
ByteArrayOutputStream bos = new ByteArrayOutputStream();
originBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
try {
FileOutputStream fos = new FileOutputStream(new File(sdFile, "resultImg.jpg"));
fos.write(bos.toByteArray());
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
4.缩放法压缩
放缩法压缩使用的是通过矩阵对图片进行裁剪,也是通过缩放图片尺寸,来达到压缩图片的效果,和采样率的原理一样。
public static void compress() {
File originFile = new File(Environment.getDataDirectory(), "originImg.jpg");
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap originBitmap= BitmapFactory.decodeFile(originFile.getAbsolutePath());
bm = Bitmap.createScaledBitmap(originBitmap, 150, 150, true);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bm .compress(Bitmap.CompressFormat.JPEG, 100, baos);
try {
FileOutputStream fos = new FileOutputStream(new File(sdFile, "resultImg.jpg"));
fos.write(bos.toByteArray());
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) {
Matrix m = new Matrix();
final int width = src.getWidth();
final int height = src.getHeight();
final float sx = dstWidth / (float)width;
final float sy = dstHeight / (float)height;
m.setScale(sx, sy);
Bitmap b = Bitmap.createBitmap(src, 0, 0, width, height, m, filter);
return b;
}