图片的存在形式
1.文件形式(即以二进制形式存在于硬盘上)
2.流的形式(即以二进制形式存在于内存中)
3.Bitmap形式
这三种形式的区别:文件形式和流的形式对图片体积大小并没有影响,也就是说,如果你手机SD卡上的如果是100K,那么通过流的形式读到内存中,也一定是占100K的内存,注意是流的形式,不是Bitmap的形式,当图片以Bitmap的形式存在时,其占用的内存会瞬间变大, 我试过500K文件形式的图片加载到内存,以Bitmap形式存在时,占用内存将近5M,当然这个增大的倍数并不是固定的。
检测图片三种形式大小的方法:
文件形式: file.length()
流的形式: 讲图片文件读到内存输入流中,看它的byte数
Bitmap: bitmap.getByteCount()
图片在不同形式下大小原理
文件形式:图片的文件形式,文件大小与图片格式有很大关系,因为不同的格式对图片信息的格式和压缩算法不同,所以改变压缩算法和编码算法就可以减小文件的大小;
Bitmap形式:Bitmap在内存中是以像素单元的形式存在,当图片的长宽固定时,那么它的总像素点数量固定,而每一个像素点占用的空间将决定这个Bitmap占用的内存大小,比如平常的ARGB_8888就是每个像素占用4个字节,RGB_565是每个像素占用2个字节等。
图片的尺寸压缩
尺寸压缩的原理很简单,即减小图片的长宽,即减少了图片的像素量,当然图片的Bitmap形式大小会同比例减少,同时保存为文件形式占用的大小也会减少。
但是这里需要注意,图片的尺寸压缩,不是把大图片加载到内存中,在压缩为小图片,因为这样做对内存占用无意义,加载大图时已经导致占用大内存,正确的做法是使用图片解码时采样的方式,比如java的实现代码如下:
private Bitmap compressImageFromFile(String srcPath) {
BitmapFactory.Options newOpts = new BitmapFactory.Options();
newOpts.inJustDecodeBounds = true;//只读边,不读内容,很快不会加载图片内容
Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
int w = newOpts.outWidth; // 得到图片真实宽高,可以根据实际宽高计算采样率
int h = newOpts.outHeight;
newOpts.inJustDecodeBounds = false;
int sampleValue = 4; // 此处直接固定采样率,宽高采样为原来1/4,只能是2的指数次方,否则会向下取为2的指数次方;
newOpts.inSampleSize = sampleValue;//设置采样率
bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
return bitmap;
}
图片的质量压缩
图片质量压缩是指对图片保存到文件(或流)中的压缩编码方式进行调整,从而减小文件(或流)的大小,注意它不会减少图片的像素,比方说,,你的图片是300K的,1280700像素的, 经过该方法压缩后, File形式的图片是在100以下, 以方便上传服务器, 但是你BitmapFactory.decodeFile到内存中变成Bitmap时,它的像素仍然是1280700,当每个像素的ARGB值与原来Bitmap一样时,那么新的Bitmap占用内存大小和原来的未压缩Bitmap一样大。
Java的实现片段如下:
private void compressQuality() {
int maxSize = (int)(500 * 1024);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int options = 100;
if (baos.toByteArray().length > maxSize) {
while (baos.toByteArray().length > maxSize) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
baos.reset();// 重置baos即清空baos
options -= 10;// 每次都减少10
bm.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options,把压缩后的数据存放到baos中,注意要JPEG,PNG的格式无效
}
}
bm.compress(Bitmap.CompressFormat.JPEG, options, bos);
}
具体质量压缩原理算法参考:https://www.cnblogs.com/Arvin-JIN/p/9133745.html