58同城Android瘦身优化之webq实践

前言

我们知道,理想的网页应该在 1 秒内打开,而在页面的整体大小中,图片往往是所占比例最大的一部分(大约占到 60% 以上,更多了解请点击),也可以参照如下图所示。优化图片不仅可以加快页面显示,还能降低移动网络的流量费用。原图产生的 PNG、JPEG、GIF 和 SVG 图片一般都有很大的压缩余地。下文将重点介绍一款图片新格式:WebP,从而揭开它神秘的面纱。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p0E5JEcs-1655302609112)(http://static.zybuluo.com/wuxuejun/khbwakp82jzn3plwfyr88y5g/image_1bf3s90se1kr0refooi7j4di9.png)]

解决方案:使用 WebP 优化图像

什么是Webp?

WebP是一种同时提供了有损压缩无损压缩(可逆压缩)的图片文件格式,至于什么是有损压缩,什么是无损压缩,自己点进去看看

WebP的压缩的原理

第一步:宏块

与JPG相同的时,WebP也采用宏块进行压缩,典型的宏块由一个 16×16 的亮度像素(luma pixel)块和两个 8×8 的色度像素(chroma pixel)块组成。分块越小,预测越准,需要记录的信息也越多,一版来说,细节月丰富的地方,分块越细。相对不丰富的地方使用16x16分块。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tM3yGi21-1655302609115)(https:upload-images.jianshu.io/upload_images/11557323-f4ed0f04b88b5eb0.png?imageMogr2/auto-orient/strip|imageView2/2/w/625/format/webp)]

第二步:预测

WebP最大的不同之处在于每个4x4的宏块中都有一个预测模型。(又名:过滤),PNG过滤用的比较多,它对每一行做同样的事,WebP过滤是针对每一个块。

VP8帧内预测常用的三种宏块:

  • 4x4 亮度像素块
  • 16x16 亮度像素块
  • 8x8 色度像素块

编码器会将它们放在一个4x4的测试像素块填满,并确定哪一个生成了最接近原始块的值。这些用不同方法填满的块叫做”预测块”。

主要使用的预测方式有以下4种:

  • H_PRED(Horiz prediction-水平预测)——像素块中每一列使用左边一列(col L)的数据填充
  • V_PRED (vertical prediction-垂直预测)——像素块中每一行使用其上边一行(row A)的数据填充
  • DC_PRED (DC prediction - DC 预测)——像素块中每个单元使用 row A 和 col L 的所有像素的平均值填充。
  • True Motion (TrueMotion 预测)——一种超级先进的模式,我没找到原理,暂时还不懂。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fp1RF78b-1655302609117)(https:upload-images.jianshu.io/upload_images/11557323-07d7bd0078944974.png?imageMogr2/auto-orient/strip|imageView2/2/w/931/format/webp)]

image.png

对于4x4的亮度块,会有6种额外预测模式,类似于垂直预测与水平预测方式,他们可以从不同的方向去填充剩余色块。

第三步:DCT(离散余弦变换)

将预测部分的原图数据减去预测出来的数据,得到差值矩阵,最后对差值进行DCT。此步骤会生成一个频率系数矩阵,坐上的系数幅度最大,右下的最小,幅度值越小,频率越高。大部分图片信息都在左上区域,这一步的作用就是朱熬出图片的高频区域和低频区域。

第四步:量化

人眼对高频部分不敏感,这一步会将高频部分舍去。对上一步的频率系数表和量化表进行计算,将频率系数表和量化表按位相除,并四舍五入整数位,最终生成一个量化矩阵。

第五步:算法编码

WebP不同于JPEG,也可以说由于JPEG压缩的地方在于,WebP采用了算法编码压缩(Arithmetic encoding),JPEG采用的是霍夫曼编码(Huffman encoding),算法编码提供了优于霍夫曼编码5%-10%的压缩率。

WebP转换技术图片瘦身实践

一、Android系统版本对WebP的支持

Android 系统在 4.0 版本中添加入了 WebP 的支持,并在 4.2.1 版本中加强了它:

  • 4.0+ (Ice Cream Sandwich): 基础的 WebP 支持
  • 4.2.1+ (Jelly Beam MR1): 支持带透明度与无损的 WebP

Fresco 默认使用系统的 WebP 方案来加载它。

但同时,Fresco 能够让你在更老的版本中使用 WebP,所以如果你想要在 Android 2.3 版本的设备上使用 WebP, 你需要做的就是在工程中添加一个 webpsupport的依赖:

dependencies { // your app's other dependencies compile 'com.facebook.fresco:webpsupport:1.0.1'}
  1. 无损压缩的WebP比PNG至少压缩26%的体积,在相同的SSIM下有损压缩的WebP比JPEG压缩至少25-34%的体积;
  2. 无损WebP的支持的透明通道只占大约22%的字节,有损压缩支持RGB和透明度的压缩,通常可以压缩PNG的1/3文件大小

二、实践转换图片

实践出真知,为了得出准确的结论,将WebP技术应用到我们的58Android项目中,以下内容都为实践结论:

将PNG转换WebP的效果

将三种图片同时在手机上显示查看效果,图片类型如下:

  1. 原图
  2. 原图无损压缩(58%)
  3. 原图转WebP(有损压缩75%)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6EgofAzW-1655302731400)(http://5b0988e595225.cdn.sohucs.com/images/20180713/e65a19832cc946cdba8f14da31c6f1e6.jpeg)]

从上图可以看出三种图片从肉眼看是无差别的

PNG转WebP是可以控制有损压缩比例的,上图有损压缩75%,肉眼查看无差别,那其他的压缩比例呢?

接下来我们继续做实验查看:

三张图片进行对比

第一张为原图、第二张为使用tinypng在线压缩过的图片、第三张为WebP不同压缩比例的图片

  • 无损压缩转换

  • 有损压缩(75%)转换

  • 无损压缩(50%)转换

  • 无损压缩(0%)转换

三、数据分析

在这里插入图片描述

通过图片效果对比和上表数据分析,WebP的有损压缩75%是图片肉眼看是无差别的,文件体积减少也是较大的,是官方推荐方案

以上对比我们初步有了方案,再思考一个问题:

PNG经(tinypng)压缩是可以叠加压缩,同时图片体积也叠加减少的,那叠加压缩的图片在进行WebP转换是不是效果会更好呢?

带着问题我们做一个实验

1.先将PNG经过tinypng叠加压缩,查看效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T08NlRyP-1655302609126)(http://5b0988e595225.cdn.sohucs.com/images/20180713/4b47a35d1a8e45869ed13e8292e7890c.jpeg)]

2.将每次叠加压缩后的图片转换WebP(有损压缩75%),查看效果

原图转换WebP

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FLFtaWED-1655302609132)(http://5b0988e595225.cdn.sohucs.com/images/20180713/55fd52d173a940deb6b77ffc74eeebff.jpeg)]

第一次压缩(叠加)后转换WebP

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y4WmAVsy-1655302609133)(http://5b0988e595225.cdn.sohucs.com/images/20180713/91d860b6541d45c9915b2f1e6dc05648.jpeg)]

第二次压缩(叠加)后转换WebP

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l2Vrio4f-1655302609134)(http://5b0988e595225.cdn.sohucs.com/images/20180713/0b75ea0d25d2488e971c7b1ef4502bde.jpeg)]

第三次压缩(叠加)后转换WebP

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1NIAnU7Q-1655302609135)(http://5b0988e595225.cdn.sohucs.com/images/20180713/36ba294100954503af7af6a4be9c9651.jpeg)]

第四次压缩(叠加)后转换WebP

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HHDY9WTV-1655302609137)(http://5b0988e595225.cdn.sohucs.com/images/20180713/845cc3a862d649efafab4c11f80d6cf6.jpeg)]

可以看出图片肉眼看是无差别的

我们在分析一下体积变化

在这里插入图片描述

结论:webp文体大小与图片压缩次数成正比,WebP的转换最好是用原图转换

GIF转换WebP效果对比

1、原GIF图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-45r3dkap-1655302609138)(http://5b0988e595225.cdn.sohucs.com/images/20180713/3842d01204ed4cdcb6bc94da02819049.gif)]

2、将原gif转换AnimationWebP

在这里插入图片描述

PNG(images with transparency/alpha)转换WebP效果对比

带有透明通道的图片转换效果对比

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sNdZPUhN-1655302609140)(http://5b0988e595225.cdn.sohucs.com/images/20180713/260ab0ad807d4a358aae766b6f28e304.jpeg)]

查看效果后产出结论

1、项目中的原图体积是39.6KB(之前是经过压缩了的图片),转换(75%)后的体积是43.0KB,反而增大了;2、不是所有的图片在推荐的有损转换75%的情况下体积会变小,尤其是有透明度通道的图片; 四、讲解一下Android studio 自带 WebP Tool

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RIxWmZfF-1655302609141)(http://5b0988e595225.cdn.sohucs.com/images/20180713/f77bbc4ffad74e11baedf3cf9f299ea1.jpeg)]

  • 支持有损转换,默认推荐75%,同时支持无损转换;
  • 可以跳过那些转换后比原是大小大的文件;
  • 点9图是默认跳过,不支持转换的;
  • 可以跳过有透明度通道的图片;

四、将项目中hybrid module 的drawable资源压缩

以上试验可以看到WebP转换技术可以使图片体积减小,如果我们将项目中的资源图片都替换成WebP是不是APK的体积会明显减小呢?

就以我们58主工程的hybrid module的drawable资源做实验

  1. 使用WebP tool 将所有资源转换,跳过含有透明度通道的图片
  2. 查看APK大小

在这里插入图片描述

效果分析:1、仅hybird库就可以减少将近1MB的大小,全部替换更客观; 2、但因为WebP格式存在机型适配问题,不能将全部图片替换.

WebP对图片的体积减少真的是个利器,那么内存方面的影响呢,我们项目中图片框架是Fresco,同时Fresco对WebP也做了很好的支持,接下来使用Fresco加载WebP查看内存的占用。

五、Fresco加载WebP在项目实践中的内存占用

项目中往往引导图都是较大的图片资源,使用引导图作为试验对象,查看内存情况,同时可以得出是否有优化空间。

1、项目中找一个引导图做实践

先来看PNG和WebP图片引导图的显示效果

PNG图片,原生控件ImageView加载显示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nR8BwZ9A-1655302609143)(http://5b0988e595225.cdn.sohucs.com/images/20180713/97934b6227614b158c41db1f2305bb2e.jpeg)]

WebP图片,Fresco控件加载WebP显示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XACdUuGV-1655302609147)(http://5b0988e595225.cdn.sohucs.com/images/20180713/07784b0a60c54d2cb80ebc9a2a99e595.jpeg)]

显示效果一致,肉眼看无差别 #引导图PNG转换为WebP操作数据对比

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t6gU4Ys1-1655302609148)(http://5b0988e595225.cdn.sohucs.com/images/20180713/52dbe89f3c79453aab12e223601708dd.jpeg)]

图片体积减少40% 2、引导图PNG和WebP内存占用对比

为了更好的显示对比效果,我做了一个显示数量扩大的试验,具体操作步骤如下:

先使用PNG图片为引导图

  • 使用一个引导框(Dialog)为例,有一个引导图,如上图显示;
  • 将引导图的PNG图片资源用原生ImageView加载,在未弹起引导框时记录初始状态内存量(A);
  • 弹起引导框->关闭引导框->再弹起引导框->关闭引导框,每个引导框对象都是new 出来的,如此重复1000次后,记录执行1000次引导操作后内存量(B);
  • 强制执行GC操作,执行多次,在内存平稳时记录执行GC后内存量©;
  • 计算执行GC后比初始状态增加内存量(C-A)。

将PNG图片转换为WebP后使用Fresco加载,重复PNG图片引导图的操作步骤,然后进行数据对比

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0OKg8VpP-1655302609149)(http://5b0988e595225.cdn.sohucs.com/images/20180713/176525a941dc46b792bbc5dec81e6bd2.jpeg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CthcOTCE-1655302609150)(http://5b0988e595225.cdn.sohucs.com/images/20180713/b257b49529f04789b93838d6940a482b.jpeg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hElIfdwQ-1655302609151)(http://5b0988e595225.cdn.sohucs.com/images/20180713/8523a0e9ef6a497083fe4ece5ae0d95a.jpeg)]

3、将结果纪录并对比

在这里插入图片描述

结论:1、5.0以上系统,由于内存管理的优化,所以对于5.0以上的系统 Fresco将Bitmap缓存直接放到了Java Heap中,5.0以下系统,图片不存储在Java heap,而是存储在ashmem;2、Android 原生ImageView的PNG显示引导图增大了native heap内存;3、使用原生ImageView 加载图片内存增大要比使用Fresco大;4、强制执行GC只会释放Java Heap,对Native Heap 无影响; 七、Android Profier的使用简介

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n7n46YA3-1655302609151)(http://5b0988e595225.cdn.sohucs.com/images/20180713/6e3c4d1834864ce1b4b21009f2c7600e.jpeg)]

如上图所示,内存分析器的默认视图包括以下内容:

  • ① 强制执行垃圾收集事件的按钮。

  • ② 捕获堆转储的按钮。

  • ③ 记录内存分配的按钮。

  • ④ 放大时间线的按钮。

  • ⑤ 跳转到实时内存数据的按钮。

  • ⑥ 内存使用时间表,其中包括以下内容:

    • 每个内存类别使用多少内存的堆栈图,如左边的y轴和顶部的颜色键所示。
    • 虚线表示已分配对象的数量,如右侧y轴所示。
    • 每个垃圾收集事件的图标。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hR43MsFR-1655302609152)(http://5b0988e595225.cdn.sohucs.com/images/20180713/0bf6b2bc6fa247cc9f452555141aa167.jpeg)]

在classes列表中,您可以看到以下信息:

  • Heap Count: 堆中的实例数。
  • Shallow Size: 此堆中所有实例的总大小(以字节为单位)。
  • Retained Size: 这个类的所有实例(以字节为单位)保留的内存总大小。

在类列表的顶部,可以使用左下拉列表在以下堆转储之间切换

  • Default heap: 当系统没有指定堆时。
  • App heap: 应用程序分配内存的主堆。
  • Image heap: 系统引导映像,包含在引导期间预加载的类。这里的分配保证永远不会移动或离开。
  • Zygote heap: Android系统中分发应用程序进程的写时复制堆

六、项目使用WebP格式文件的规范

  1. 使用推荐转换方案,75%有损压缩;
  2. Fresco对WebP的使用做了支持,相当于扩展了一种图片类型,API的使用和PNG、JPEG、GIF无差别;
  3. 对于大图显示建议使用Fresco加载,使用WebP格式降低文件体积

总结

WebP的压缩优于其他图片,主要得益于起继承自VP8的帧内预测技术,相比于JPEG对图像原值进行编码来说,WebP编码的是预测值和原值的差值,这也是WebP体积更小的主要原因,最后,WebP使用了更优秀的算法编码。有关Android性能优化的更多学习~获

这个WebP的压缩过程用,一张图可以囊括表述:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nnEEvO0j-1655302609153)(https:upload-images.jianshu.io/upload_images/11557323-8aa39167b695e06d.png?imageMogr2/auto-orient/strip|imageView2/2/w/710/format/webp)]

当然以上主要是针对WebP的有损压缩(lossy WebP)来进行的原理讲解,无损压缩的逻辑与其完全不同,不过我们提高性能,主要也是采用的有损WebP。

希望以上内容,对大家了解WebP的原理有一定的帮助,能让大家更好的去使用WebP。

猜你喜欢

转载自blog.csdn.net/Androidxiaofei/article/details/125305806