关于 UI 界面使用的图片、JPG 和 alpha 等

我们的游戏在 UI 界面使用了过多的图片,以至于挤占了安装包的体积。

1. 其实可以不要用硬件支持的压缩格式

为了节省运行期的内存,这些图片都用了 ASTC_4x4 压缩格式。
但其实,这是不必要的。
因为大多数的界面都是打开之后短时间内关闭,不会一直挤占内存,
所以即便在内存中是非压缩的 RGBA,也不要紧。
常驻内存的少量图片仍然可以用 ASTC_4x4 来压缩。但这只是少数,不需要重点讨论了。

2. 各种图片格式的调查

之前的图片打包,不外乎是在硬件支持的各种压缩纹理格式之中,选择其一。
要么 ASTC,要么 ETC1、ETC2、PVRTC。
现在既然内存里可以直接用 RGBA,那选择就增加了一些。
各个格式的简单介绍如下:

名称 内存占用(字节/像素) 质量 优势 缺点
ASTC 0.11 ~ 1 有损(质量可调) 硬件支持,加载速度最快,占用内存很少。画质可调
ETC1 0.5 ~ 1 有损(质量中等) 硬件支持,加载速度最快,占用内存很少
ETC2 0.5 ~ 1 有损(质量中等) 硬件支持,加载速度最快,占用内存很少
PNG 4 无损 网络常见格式,对应软件多。画质无损
JPG 4 有损(质量可调) 网络常见格式,对应软件多。画质可调,同等画质情况下文件体积小
GIF 4 较差,颜色数量有限 网络常见格式,对应软件多。支持动画(游戏里不常用) 画质差
FLIF 4 无损 画质无损,且比 PNG 更小 解码速度很慢
WEBP 4 有损(质量可调)、或者无损 新一代格式(1),内部使用 VP8 编码。同等文件体积时,画质比 JPG 更高 VP8 诸多小毛病,实际上已经过时
BPG 4 有损(质量可调)、或者无损 新一代格式(2),内部使用 HEVC 编码。同等文件体积时,画质比 JPG 更高 HEVC 带来法务风险
HEIF 4 有损(质量可调)、或者无损 新一代格式(2),内部使用 HEVC 编码。同等文件体积时,画质比 JPG 更高 HEVC 带来法务风险
AVIF 4 有损(质量可调)、或者无损 新一代格式(3),内部使用 AV1 编码。同等文件体积时,画质比 JPG 更高

注释:

  1. 按编码格式的出现顺序,是 AV1 > HEVC > VP8,其中 AV1 是最新的。越新的格式,质量就更高,同时也意味着复杂、计算量大、速度慢。
  2. 图片加载的耗时,大致分为两部分。一是读取数据到内存,二是解码。如今的手机设备,读取数据很快,主要的耗时在解码。硬件支持的格式无需解码、所以极快。而硬件不支持的格式,解码速度往往就等同于加载速度。

诸多格式,各有特点。一些格式明显存在不能用的理由:

  • BPG, HEIF 由于 HEVC 编码的法务风险,还是不要用了
  • WEBP 由于画质问题被淘汰。虽然数据上胜过了 JPG,但我的主观感觉其实是不如 JPG 的,它压缩得到的 UI 图片往往很糊,损失了一些锐利的细节
  • GIF 由于画质问题被淘汰。因为只能支持 256 色,对于现代 UI 来说,往往不够
  • FLIF 由于解码速度太慢被淘汰(后面有数据、比 PNG 慢约 300 倍)

硬件支持的 ASTC, ETC1, 等等格式,虽然加载速度最高,内存也最省,但相同画质情况下,文件体积比 JPG 大。综合考虑的话,不一定合适。像我们之前,所有图片全都用 ASTC_4x4 其实不太可取。

于是剩下的只有:PNG, JPG, AVIF

AVIF 的画质是比 JPG 好很多的(相同文件体积时),具体可以参考这里:https://netflixtechblog.com/avif-for-next-generation-image-coding-b1d75675fe4
按这个文章的数据,在 0.4 bits/pixel 的情况下(一张 1024x1024 的图片只需 52.5k 字节):

名称 颜色格式 SSIM(从图表里肉眼观测、数值越高说明画质损失越小)
JPG YUV420 0.957
HEIF(HEVC) YUV420 0.981
AVIF-MSE YUV420 0.984
AVIF-SSIM YUV420 0.988
JPG YUV444 0.927
HEIF(HEVC) YUV444 0.977
AVIF-MSE YUV444 0.979
AVIF-SSIM YUV444 0.983

看来从数值上,AVIF 的画质是明显好于 JPG 的。
但是解码速度也明显的慢了。因为 AVIF 是基于 AV1 编码,这个编码目前还不成熟,编码解码的速度并不理想。我看了另一篇帖子:https://github.com/joedrago/avif/issues/11,用的是一张 512x512 的图片,

<Decode> [PNG]: Time: 1.43 ms
<Decode> [JPEG]: Time: 0.39 ms
<Decode> [HEIC]: Time: 1.47 ms
<Decode> [HEIF]: Time: 102.06 ms
<Decode> [WebP]: Time: 24.00 ms
<Decode> [BPG]: Time: 39.60 ms
<Decode> [FLIF]: Time: 364.84 ms
<Decode> [AVIF]: Time: 154.54 ms
<Encode> [PNG]: Time: 39.63 ms
<Encode> [JPEG]: Time: 2.46 ms
<Encode> [HEIC]: Time: 65.51 ms
<Encode> [HEIF]: Time: 1799.63 ms
<Encode> [WebP]: Time: 168.42 ms
<Encode> [BPG]: Time: 2761.79 ms
<Encode> [FLIF]: Time: 6160.68 ms
<Encode> [AVIF]: Time: 346592.24 ms

"HEIC" means using Apple's built-in HEVC codec, "HEIF" means using libheif

可以看到 AVIF 的解码速度比 JPG 慢 100 倍,而编码速度更是骇人听闻的慢了 10 万倍,于是也只能说一句“告辞”。等它慢慢去优化吧。

逛了一圈回来,发现还是 JPG 和 PNG 最为靠谱。其中 PNG 体积略大,但好在画质无损。在 UI 实际只有极少图片需要真正的无损画质。而大多数图片都用 JPG 更为合适。

3. 关于 JPG

3.1 JPG 的 alpha

JPG 有一个问题是“不支持 alpha”,这可以通过两种办法来解决。
一是在引擎层面,用两张 jpg 图片,一张保存 RGB,另一张保存 alpha,到运行之时把它们合并为 RGBA。这又细分为两种:(1) 加载时,在内存中合并为 RGBA;(2) 渲染时,采样两张图片然后在 shader 里合并为 RGBA。两种做法各有优劣。前者性能略高一点,后者可以支持更多用途(例如把 RGB 和 alpha 各用一张 ETC1,因为 ETC1 是无法在内存中合并为 RGBA 的,但在 shader 就可以)。
二是从 JPG 格式层面。注意到 JPG 格式本来支持三种颜色格式,分别是 Gray, RGB, CMYK,对应了 1 通道、3 通道、4 通道。暴雪公司的著名游戏《魔兽争霸3》中,有一种用法。把 RGBA 四个通道的数据当作 CMYK 数据(注意是“当作”CMYK,不是“转换颜色空间到”CMYK),然后保存为 CMYK 格式的 JPG(他们换了文件头部、然后重新起了个名字叫做 BLP)。这个做法看起来是可行的。正常的 JPG 编码会把 RGB 转为 YCbCr,于是还有了 YUV420 和 YUV444 等等的区别(前者通常肉眼感觉更好,而后者的数值损失更小)。而 CMYK 是否也会转为 YCbCr?我没有再去调查。

3.2 JPG 的解码速度

一般而言,JPG 的解码应该是极快的,比 PNG 更快。(前文引用的数据中指出,一张 512x512 的图片耗时为 0.39 毫秒)
如果测试发现 JPG 解码比 PNG 慢,可能是用错了库。一般老的游戏引擎可能搭载了 libjpeg,而后来有了 libjpeg-turbo 是使用 SIMD 的加速版本,它宣称是提速了 2~6 倍。有文章说“Most web browsers use the open source libjpeg-turbo for decoding JPEG files”,意味着今天的 libjpeg-turbo 已经开始取代原来的 libjpeg 了。
另外,JPG 压缩时,画质是可调的。越高的画质,不仅意味着文件体积的增大,而且也意味着解码速度变慢。最高画质、较差画质,解码速度可能会有成倍的差距。

还有一个方案是使用 GPU(而非 CPU)来做解码。但这都只是一些尝试,没看到太多人这样用。

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

推荐阅读更多精彩内容