性能优化——Android图片压缩与优化的几种方式

图片优化压缩方式大概可以分为以下几类:更换图片格式,质量压缩,采样率压缩,缩放压缩,调用jpeg压缩

1、设置图片格式

Android目前常用的图片格式有png,jpeg和webp,

png:无损压缩图片格式,支持Alpha通道,Android切图素材多采用此格式

jpeg:有损压缩图片格式,不支持背景透明,适用于照片等色彩丰富的大图压缩,不适合logo

webp:是一种同时提供了有损压缩和无损压缩的图片格式,派生自视频编码格式VP8,从谷歌官网来看,无损webp平均比png小26%,有损的webp平均比jpeg小25%~34%,无损webp支持Alpha通道,有损webp在一定的条件下同样支持,有损webp在Android4.0(API 14)之后支持,无损和透明在Android4.3(API18)之后支持

采用webp能够在保持图片清晰度的情况下,可以有效减小图片所占有的磁盘空间大小

2、质量压缩

质量压缩并不会改变图片在内存中的大小,仅仅会减小图片所占用的磁盘空间的大小,因为质量压缩不会改变图片的分辨率,而图片在内存中的大小是根据width*height*一个像素的所占用的字节数计算的,宽高没变,在内存中占用的大小自然不会变,质量压缩的原理是通过改变图片的位深和透明度来减小图片占用的磁盘空间大小,所以不适合作为缩略图,可以用于想保持图片质量的同时减小图片所占用的磁盘空间大小。另外,由于png是无损压缩,所以设置quality无效,以下是实现方式:

/**

* 质量压缩

*

* @param format  图片格式 jpeg,png,webp

* @param quality 图片的质量,0-100,数值越小质量越差

*/

public static void compress(Bitmap.CompressFormat format, int quality) {

    File sdFile = Environment.getExternalStorageDirectory();

    File originFile = new File(sdFile, "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();

    }

}

3、采样率压缩

采样率压缩是通过设置BitmapFactory.Options.inSampleSize,来减小图片的分辨率,进而减小图片所占用的磁盘空间和内存大小。

设置的inSampleSize会导致压缩的图片的宽高都为1/inSampleSize,整体大小变为原始图片的inSampleSize平方分之一,当然,这些有些注意点:

1、inSampleSize小于等于1会按照1处理

2、inSampleSize只能设置为2的平方,不是2的平方则最终会减小到最近的2的平方数,如设置7会按4进行压缩,设置15会按8进行压缩。 

具体的代码实现方式如下:

/**

*

* @param inSampleSize  可以根据需求计算出合理的inSampleSize

*/

public static void compress(int inSampleSize) {

    File sdFile = Environment.getExternalStorageDirectory();

    File originFile = new File(sdFile, "originImg.jpg");

    BitmapFactory.Options options = new BitmapFactory.Options();

    //设置此参数是仅仅读取图片的宽高到options中,不会将整张图片读到内存中,防止oom

    options.inJustDecodeBounds = true;

    Bitmap emptyBitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath(), 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);

    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 void compress(View v) {

    File sdFile = Environment.getExternalStorageDirectory();

    File originFile = new File(sdFile, "originImg.jpg");

    Bitmap bitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath());

    //设置缩放比

    int radio = 8;

    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);

    try {

        FileOutputStream fos = new FileOutputStream(new File(sdFile, "sizeCompress.jpg"));

        fos.write(bos.toByteArray());

        fos.flush();

        fos.close();

    } catch (FileNotFoundException e) {

        e.printStackTrace();

    } catch (IOException e) {

        e.printStackTrace();

    }

}

5、JNI调用JPEG库

Android的图片引擎使用的是阉割版的skia引擎,去掉了图片压缩中的哈夫曼算法——一种耗CPU但是能在保持图片清晰度的情况下很大程度降低图片的磁盘空间大小的算法,这就是为什么ios拍出的1M的照片比Android5M的还要清晰的原因。

由于笔者能力有限,暂时没有对NDK这块做深入研究,后期将会将此方法补全

6、其他

还有一些技巧,比如在缩放压缩的时候,Bitmap.createBitmap(bitmap.getWidth() / radio, bitmap.getHeight() / radio, Bitmap.Config.ARGB_8888),如果不需要图片的透明度,可以将ARGB_8888改成RGB_565,这样之前每个像素占用4个字节,现在只需要2个字节,节省了一半的大小。

7、总结

1、使用webp格式的图片可以在保持清晰度的情况下减小图片的磁盘大小,是一种比较优秀的,google推荐的图片格式

2、质量压缩可以减小图片占用的磁盘空间,不会减小在内存中的大小

3、采样率压缩可以通过改变分辨率来减小图片所占用的磁盘空间和内存空间大小,但是采样率只能设置2的n次方,可能图片的最优比例在中间

4、尺寸压缩同样也是通过改变分辨率来减小图片所占用的磁盘空间和内存空间大小,缩放的尺寸没有什么限制

5、jni调用jpeg库来弥补安卓系统skia框架的不足,也是比较优秀的解决方式(方法会在后期补充)

既然尺寸压缩和采样率压缩都是通过改变图片的分辨率来降低大小,有什么区别吗?

其中一个原因已经说明了,采样率的压缩比例会受到限制,尺寸压缩不会,但是采样率压缩的清晰度会比尺寸压缩的清晰度要好一些,看图:

原图 大小:272kb,分辨率:1024*797

尺寸压缩 大小:64k  分辨率:256*200

采样率压缩 大小:52k 分辨率:256*200

可以看出,在缩小同样的倍数的情况下,采样率压缩看起来会比较柔和一些,尺寸压缩则锯齿比较多

————————————————

版权声明:本文为CSDN博主「孟凡勇」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/u013928412/article/details/80358597

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容

  • 为何要压缩 1、体积的原因如果你的图片是要准备上传的,那动辄几M的大小肯定不行的,况且图片分辨率大于设备分辨率的话...
    mahongyin阅读 794评论 0 1
  • 一直以来Bitmap都是开发中很棘手的问题,这个问题就是传说中的OOM(java.lang.OutofMemory...
    M悇芐冋忆阅读 4,689评论 0 11
  • 摘要:对android 上图片压缩,其实总结起来基本可以分为两类压缩:尺寸压缩和质量压缩, 尺寸压缩其实也可以理解...
    男爵是只猫丶阅读 8,761评论 2 14
  • 在介绍Android平台的压缩方案之前,先了解一下Bitmap的几个主要概念。 像素密度 像素密度指的是每英寸像素...
    niknowzcd阅读 855评论 1 3
  • 非原创,只是整理,如果里面发现引用的内容没有标识出来,欢迎指出。 一、基本知识 (1)两种图片: 1)矢量图: 矢...
    风再起时ME阅读 2,435评论 0 19