Android:图片压缩的几种方式

1、前言

  • Android中,图片的压缩对于内存的优化很重要
  • 通过这篇文章对Android中的几种图片压缩方式进行对比

2、作用

通过图片压缩,实现内存优化,避免OOM异常

3、内存

图片占用内存计算公式:图片所占内存 = 图片的分辨率w * 图片的分辨率h * 一个像素占用的字节数

获取图片内存大小的代码如下:

public void getBitmapSize(View view) {
        File file = Environment.getExternalStorageDirectory();
        File originFile = new File(file,"dog.jpg");
        Bitmap originBitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath());
        int bitmapSize = getBitmapSize(originBitmap);
        Log.i("测试","图片所占内存大小->" + bitmapSize);
}

4、分类

  • 设置图片格式
  • 质量压缩
  • 采样率压缩
  • 尺寸压缩

4.1、设置图片格式

Android目前常用的图片格式有pngjpegwebp等。

  • png:无损压缩图片格式,支持背景透明,体积相对较大
  • jpeg:有损压缩图片格式,不支持背景透明,体积相对较小
  • webp:是一种同时提供有损压缩和无损压缩的图片格式,无损webp平均比png小26%,有损的webp平均比jpeg小30%左右,采用webp能够在保持图片清晰度的情况下,可以有效减小图片所占的磁盘空间大小。

实验可得:同分辨下的一张图,jpeg格式下大小为124kb,而png格式下大小为2M

4.2、质量压缩

质量压缩并不会改变图片在内存中的大小,只会改变图片占用磁盘的大小,因为质量压缩改变的是图片的位深透明度来减少图片占用的磁盘空间大小;
根据内存计算公式知道,宽高都没变,所以内存并不会改变,所以想保持图片的质量同时减少图片所占用的磁盘空间大小,可以选用质量压缩,质量压缩的示例代码如下:

public void qualityCompress(Bitmap.CompressFormat format,int quality){
        File file = Environment.getExternalStorageDirectory();
        File originFile = new File(file,"dog.jpg");
        Bitmap originBitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath());
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        originBitmap.compress(format,quality,bos);//quality:10=22.57,50=98.12kb,70=122.97kb
        int bitmapSize = getBitmapSize(originBitmap);
        Log.i("测试","质量压缩后图片所占内存大小->" + bitmapSize);//结果:5760000
        try {
            FileOutputStream fos = new FileOutputStream(new File(file,"resultQualityImg.jpg"));
            fos.write(bos.toByteArray());
            fos.flush();
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

}

注:质量压缩关键是quality的值,quality值与图片体积大小成反比,并且由于png是无损压缩,所以设置quality无效

4.3、采样率压缩

采样率压缩不仅能压缩图片内存大小,还可以减少图片体积大小,代码如下:

public void sampleRateCompress(int inSampleSize) {
        File file = Environment.getExternalStorageDirectory();
        File originFile = new File(file, "dog.jpg");
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = false;
        options.inSampleSize = inSampleSize;
        Bitmap resultBitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath(), options);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        resultBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);//quality:100=215.38kb,80=50.41kb
        int bitmapSize = getBitmapSize(resultBitmap);
        Log.i("测试","采样率压缩后图片所占内存大小->" + bitmapSize);//结果:1440000
        try {
            FileOutputStream fos = new FileOutputStream(new File(file, "resultSampleRateImg.jpg"));
            fos.write(bos.toByteArray());
            fos.flush();
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

采样率压缩的关键是inSampleSize参数,假如inSampleSize设置为2,那么会导致图片的宽高都为1/2,而内存大小为1/4

注:采样率压缩图片也和quality参数有关,quality和图片体积大小成正比,和内存无关

4.4、尺寸压缩

尺寸压缩就是对图片进行一定的缩放,导致宽高的变化,达到压缩图片的目的;和采样率压缩一样,尺寸压缩也是能压缩图片内存大小,还可以减少图片体积大小,代码如下:

public void sizeCompress(int radio) {//radio:5=47.85kb,2=221.39kb
        File sdFile = Environment.getExternalStorageDirectory();
        File originFile = new File(sdFile, "dog.jpg");
        Bitmap bitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath());
        //设置缩放比
        Bitmap result = Bitmap.createBitmap(bitmap.getWidth() / radio, bitmap.getHeight() / radio, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(result);
        RectF rectF = new RectF(0, 0, bitmap.getWidth() / radio, bitmap.getHeight() / radio);
        //将原图画在缩放之后的矩形上
        canvas.drawBitmap(bitmap, null, rectF, null);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        result.compress(Bitmap.CompressFormat.JPEG, 100, bos);//
        int bitmapSize = getBitmapSize(result);
        Log.i("测试","尺寸压缩后图片所占内存大小->" + bitmapSize);//结果:230400
        try {
            FileOutputStream fos = new FileOutputStream(new File(sdFile, "resultSizeRateImg.jpg"));
            fos.write(bos.toByteArray());
            fos.flush();
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

尺寸压缩的关键是ratio参数,假如ratio设置为2,那么会导致图片的宽高都为1/2,而内存大小为1/4

注:尺寸压缩图片也和quality参数有关,quality和图片体积大小成正比,和内存无关
尺寸

5、采样率压缩和尺寸压缩的区别

从上面的实验结果看出,采样率压缩和尺寸压缩原理似乎的一样的,那么我们从压缩效果展示这两者的区别


原图 分辨率:1200*1200 大小:124kb
采样率压缩 分辨率:600*600 大小:78.2kb
尺寸压缩 分辨率:600*600 大小:74.4kb
  • 在分辨率相同的情况下,采样率压缩和尺寸压缩的图片大小相近
  • 从采样率压缩和尺寸压缩对比图看出,采样率压缩会让图片更加柔和,而尺寸压缩会更清晰些

6、总结

通过以上的压缩方法分类描述,相信你已经对图片压缩有了更深的了解,那么就可以根据不同的使用场景对相应的图片压缩方式进行选择了

7、案例下载

点我下载

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容