大图片处理

图片的存在形式

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

你可能感兴趣的:(大图片处理)