找回密码
 会员注册
查看: 21|回复: 0

百度APPiOS端包体积50M优化实践(二)图片优化

[复制链接]

2

主题

0

回帖

7

积分

新手上路

积分
7
发表于 2024-10-8 19:04:05 | 显示全部楼层 |阅读模式
一. 前言在上一篇文章,我们介绍了包体积优化的必要性、安装包组成部分和生成过程、国内外大厂APP包体积分析、百度APP包体积优化技术方案及各项收益,本文重点讲述图片优化,解压IPA包后发现,百度APP中asset和bundle里面图片共有94M,这是我们重点优化的对象。本系列文章目录如下:? 《百度APP iOS端包体积50M优化实践(一)总览》:https://mp.weixin.qq.com/s/ANbFzg7X932o-iDpa8FcxQ ? ? 百度APP采用如下方式对不同的图片资源进行了优化:? ? 第一、无用图片优化,解决的是随着版本迭代,一些图片已经没有了引用关系,但还在IPA包中保留,挖掘这部分图片并删除,这个优化是所有包体积优化项目中ROI最高的,影响范围局限在单个组件内,质量可控,关键是提高查找无用图片的准确度; ? ? 第二、Asset Catalog优化:使用Asset Catalog管理的图片能被App Store工具App Thinning处理,处理后用户只会下载匹配其设备分辨率的图片资源,从而降低了用户下载的包体积; ? ? 第三、HEIC图片优化:跟PNG、JPEG、WebP相比,HEIC图片编码格式体积减少最小,从解码效率角度来说,跟WebP相比,HEIC硬解码效率高;二. 无用图片优化丨2.1?方案综述 ? ? ?首先获取所有图片资源,然后开发工具获取Objective-C、Swift、xib、storyboard、html、js、css、json、plist文件可能引用图片的静态字符串,接着前面两个集合做diff即可排查未引用的图片,最后针对字符串拼接的常见case做二次过滤,覆盖的case越多准确度越高,当然也要考虑ROI。丨2.2?获取所有图片开启每个库的源码,用脚本检测所有图片及图片所属关系,为后续分发及落地优化提供方便。如果不开源码使用二进制库或者ipa包会带来很多麻烦,如获取asset.car里面的图片资源比较困难,同时只能知道图片名称,不能直接获取图片属于哪一个库。开启每个库的源码后,用脚本递归遍历可获取所有图片,从图片路径可知道所属关系,参考代码如下所示:def findAllPictures(path): pathDir = os.listdir(path) for allDir in pathDir: child = os.path.join('%s%s' % (path, allDir)) if os.path.isfile(child): # 获取读到的文件的后缀 end = os.path.splitext(child)[-1] if end == ".png" or end == ".webp" or end == ".gif" or end == ".jpeg" or end == ".jpg": print("文件" + child + " 后缀 " + end) else: # 递归遍历子目录 child = child + "/" findAllPictures(child)丨2.3?获取可能引用图片静态字符串在这个环节,我们重点是要找到在代码中可能会引用图片的字符串集合,如在Objective-C的.m文件中,我们经常用如下代码去加载图片account_login来创建一个UIImageView对象, 针对Objective-C的.m文件内容,用正则过滤,匹配表达式为 @"(.*?)",即可获取所有可能加载图片的字符串集合。imgView.image = [UIImageimageNamed"account_login"];对于Swift文件我们通常通过如下代码去加载图片account_login,加载方式完全不一样,针对Swift这种文件,正则表达式应为"(.?)"。let imageView = UIImageView(frame: CGRectMake(100, 10, 200, 200))imageView.image = UIImage(named:"account_login.jpg")self.view.addSubview(imageView)对于html文件我们通常用如下代码去加载图片,正则表达式应为img\s+src="'["']。不同的文件加载图片的方式不同,如Objective-C、Swift、xib、storyboard、html、js、plist、json和css都不尽相同,在下面的表格,我整理出常用文件过滤图片使用的正则表达式。文件格式正则表达式Objective-C的.m文件?@"(.*?)"Objective-C的.mm文件@"(.*?)"Swift"(.?)"xibimage name="(.+?)"storyboardimage name="(.+?)"htmlimg\s+src="'["']js["']src["'],\s+"'["']? ??css([a-zA-Z0-9_-]*)\.(imageset|jpg|gif|png)plist>(.?)?./AssetsInfo.js通过AssetsInfo.json获取图片相关属性,但是无法获取里面的图片。如果想将car文件中的图片提取出来,推荐一个开源工具叫Asset Catalog Tinkerer,可以从github下载,这里给出github地址:https://github.com/insidegui/AssetCatalogTinkerer丨3.5?Asset Catalog的压缩算法使用3.4节介绍的XCode 自带工具assetutil可以知道每张图片的压缩算法,Compression字段值代表不同图片的采用的不同压缩算法,通过实践发现actool支持的压缩算法有 deepmap2、deepmap_lzfse、zip、lzfse、palette_img,具体采用哪种压缩算法跟很多因素有关,如图片自身特性、打包的XCode版本、Framework支持的iOS最低版本、编译配置(Asset Catalog Compiler - Options Optimization),从实际效果来看,XCode会根据综合上述因素选择一个压缩比最优的算法,另外这些压缩算法都是无损的。丨3.6?不要做无损压缩开发者在图片放入Asset Catalog之前千万不要做无损压缩,无损压缩算法是通过改变图片的压缩编码算法达到减少体积大小的目的,不会改变解码后的Bitmap 数据,从3.3节中我们知道Assets.car 文件的生成过程中,Asset Catalog 的工具 actool先做解码得到Bitmap数据,然后再编码压缩处理,针对无损压缩算法actool接收的Bitmap 数据并没有改变,所以无损压缩无法优化包体积,UI设计师给出的PNG图片如果采用Asset Catalog优化就千万不要做无损压缩。丨3.7?bundle多倍图片Asset优化 ? ?Asset Catalog是Apple在2013年发布的iOS7的系统开始引入的,从iOS 9 之后开始支持做资源管理,老代码(尤其是16年前的代码)都是用bundle的方式去管理图片,为此,我们开发脚本专门针对bundle多倍图片做检查,然后采用Asset优化,这种优化方式可以实现包体积立减一半,参考脚本如下所示:def find_all_bundle_pic(app_package_path, all_pic_list): """ 将所有bundle图片存入list中 """ pathDir = os.listdir(app_package_path) for child_file in pathDir: child_path = os.path.join('%s/%s' % (app_package_path, child_file)) # isfile:如果child是一个存在的文件则返回true,否则(bundle、文件夹会等)返回false if os.path.isfile(child_path): if child_path.endswith(".png") or child_path.endswith(".jpg") or child_path.endswith(".jpeg") or child_path.endswith(".gif") or child_path.endswith(".webp"): if child_path.find(".bundle") > 0: all_pic_list.append(child_path) else: find_all_bundle_pic(child_path, all_pic_list)def find_opt_pic(all_picture_list,final_opt_pic_list): """ 查找bundle中重复的多倍图片 """ for picture in all_picture_list: if picture.endswith("@2x.png"): prefix_2x = picture[0: len(picture) - 7] for picture1 in all_picture_list: # 前缀匹配 if picture1 != picture and picture1.startswith(prefix_2x): if (len(picture) == len(picture1) and picture1.endswith("@3x.png")) or len(picture) == len(picture1) + 3: final_opt_pic_list.append(picture) final_opt_pic_list.append(picture1)丨3.8 有损图片压缩可减少 Assets.car 大小从3.6节我们得知无损压缩对于Asset Catalog是没有体积优化效果的,但是有损压缩可减少Assets.car 大小,因为Asset Catalog自身也会对图片进行压缩优化,所以有损压缩图片的收益没有bundle转Asset Catalog收益明显,常用的有损压缩工具有TinyPng和pngquant。TinyPng是一个网页版的工具,通过合并图片中相似的颜色,将 24 位的 PNG 图片压缩成 8 位色值的图片,并且去掉了图片中不必要的元数据来实现压缩。对于单张图片压缩使用非常方便,链接地址如下:https://tinypng.com/,但是如果要处理批量图片压缩,上传过程中容易出现上传不成功等问题,这个工具不支持自定义压缩配置。pngquant是一个有损的PNG压缩开源库,提供了命令行和源码库两种形式。将24位或32位的RGBA PNG图转换成8位PNG图并保留透明度通道。通过这个库的转化可以显著减少png文件大小,pngquant采用的是本地脚本压缩,工具下载地址:https://pngquant.org,对批量压缩图片支持的比较友好,pngquant支持自定义压缩品质,配置压缩品质小于90后压缩率会高于TinyPng,并且pngquant是开源的,可以自定义,这是百度APP图片压缩的首选。四. HEIC图片编码优化丨4.1?HEIC图片编码优点HEIC(High Efficiency Image Coding)是一种图像编码标准,它可以极大提升压缩率,并有效减小储存占用,自iOS 11和macOS High Sierra(10.13)开始,苹果将HEIC设置为图片存储的默认格式,它由动态影像专家小组(MPEG)开发,并在MPEG-H Part 12(ISO/IEC 23008-12)中定义,以下是HEIC图片的特点:压缩率高:HEIC图片比JPEG图片压缩率高1.5倍,比PNG图片压缩率高3倍,也比GIF图片压缩率高3倍。节省内存:HEIC图片比JPEG图片节省20%的存储空间,比PNG图片节省50%的存储空间,比GIF图片节省80%的存储空间。解码效率高:在iOS系统中,HEIC采用硬解码,解码效率高,跟WebP(软编码)相比,是其100倍,但略慢于JPEG。保留原始图像质量:HEIC图片采用H.264和JEP格式压缩,可以保留原始图像质量。支持无损放大:HEIC图片支持无损放大,可以将图片放大两倍而不失真。色彩处理方面,HEIC图片可以根据像素点的亮度分布自动亮度、对比度和饱和度,从而更好地还原图像的真实色彩。系统兼容性好:我们知道iOS 11开始HEIC是图片存储的默认格式,也就是iOS 11以后的系统都支持HEIC图片,但我们百度APP目前还支持iOS10系统,对这部分用户如何处理?在实践中发现,在iOS10系统上,当把HEIC图片放xcasset文件里,最后图片也是可以正常显示的,我们做了一番原因排查,用Asset Catalog Tinkerer工具解压出Assets.car 文件,发现在xcasset里的HEIC图片,对于iOS10的系统,在打包时会被系统转化为png格式图片,Asset Catalog解决了HEIC图片的兼容性问题。丨4.2?如何生成HEIC图片利用Mac自带功能实现png转HEIC方法:右键图片,快速操作-》转换图像, 格式选HEIF,选择原图像。优化结果如下所示,左边是png原图(1.6M),右边是HEIC图片(106KB)。丨4.3?HEIC图片使用方法4.3.1?必须在Asset Catalog使用? ? ?HEIC图片必须放在Asset Catalog中才能使用,bundle方式不支持HEIC图片加载。? ? ?HEIC图片的加载使用方法和普通的asset图片一样,如下所示:imgView.image = [UIImage imageNamed"account_login"];4.3.2?对于大图HEIC格式明显体积小理论上来说,HEIC格式图片的体积是PNG格式图片的三分之一,但实际过程发现对于大图,这个优化效果很明显,但是对于小图尤其是小于10K的图片,HEIC图片还有可能超过PNG格式图片,所以我们在做HEIC图片编码优化时,对于小图不建议用这种方式。4.3.3?带有Alpha通道的PNG图片不要做有损压缩在实践过程中发现,一张PNG原图,尤其是带有Alpha通道,经过有损压缩(TinyPng或ImageOptim)后,再生成HEIC图片时,在iOS12,13,14系统上会显示绿幕,所以带有Alpha通道的PNG图片不要做有损压缩,存在兼容性问题。五. 总结图片优化是包体积优化的重头戏,百度APP经过两个Q的优化落地9.75M的收益解决了存量图片的问题,随后建立图片使用规范和无用图片检测流水线解决增量图片的问题。 ? ? ?本文详细介绍了无用图片检测方案、Asset Catalog图片优化和HEIC图片优化方案,后续我们会针对其他优化类型详细介绍其原理与实现,敬请期待。参考链接[1]、Asset使用方法:https://developer.apple.com/library/archive/documentation/Xcode/Reference/xcode_ref-Asset_Catalog_Format/index.html#//apple_ref/doc/uid/TP40015170-CH18-SW1[2]、Asset介绍:https://help.apple.com/xcode/mac/current/#/dev10510b1f7[3]、WWDC2018:Optimizing App Assets:https://developer.apple.com/videos/play/wwdc2018/227/[4]、TinyPng:https://tinypng.com/[5]、pngquant:https://pngquant.org[6]、HEIC图片介绍:https://mobiletrans.wondershare.com/heic-convert/what-is-heic-file.html
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2025-1-9 10:42 , Processed in 0.416789 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表