大多数下载流量由图像组成。因此,您可下载的图像越小,您的应用就能为用户提供越好的网络体验。本页面提供有关使图像文件更小、更适合网络传输的指南。
关于图像格式
Android 应用通常使用以下一种或多种文件格式的图像:AVIF、PNG、JPG 和 WebP。对于这些格式中的每一种,您都可以采取措施来减少图像大小。
AVIF
Android 12(API 级别 31)及更高版本支持使用 AV1 图像文件格式 (AVIF) 的图像。AVIF 是一种使用 AV1 编码的图像和图像序列的容器格式。AVIF 利用视频压缩中的帧内编码内容。与 JPEG 等较旧的图像格式相比,这在相同文件大小下显着提高了图像质量。要深入了解此格式的优势,请参阅 Jake Archibald 的博客文章。
PNG
减小 PNG 文件大小的一个关键是减少图像中每行像素使用的唯一颜色数量。通过使用更少的颜色,可以提高管道所有其他阶段的压缩潜力。
减少唯一颜色数量可以带来显著差异,因为 PNG 压缩效果部分取决于水平相邻像素颜色变化程度。因此,减少 PNG 图像中每行的唯一颜色数量有助于减小其文件大小。
在决定是否采用此策略时,应记住减少唯一颜色数量实际上相当于对图像应用了有损编码阶段。然而,编码工具可能无法很好地判断一个看似微小的错误在人眼看来有多糟糕。因此,您应该手动执行此工作,以帮助确保高效压缩和可接受的图像质量之间取得适当的平衡。
有两种特别有用的方法:努力采用索引格式和应用矢量量化。
努力采用索引格式
任何减少颜色的尝试都应从优化颜色开始,以便在将图像导出为 PNG 时可以使用 INDEXED 格式。INDEXED 颜色模式的工作原理是选择最佳的 256 种颜色,并将所有像素值替换为颜色调色板中的索引。结果是将(潜在的)1600 万种颜色减少到只有 256 种颜色:每像素从 3(不透明)或 4(透明)字节减少到 1 字节。这一变化是文件大小的第一个重要步骤减少。
图 1 显示了图像及其索引变体。

图 1. 转换为 INDEXED 格式前后的图像。
图 2 显示了图 1 图像的颜色调色板

图 2. 图 1 图像的颜色调色板。
将图像表示为调色板图像对于显着改进文件大小大有裨益,因此值得研究您的大多数图像是否可以转换。
当然,并非所有图像都可以仅用 256 种颜色准确表示。例如,有些图像可能需要 257、310、512 或 912 种颜色才能看起来正确。在这种情况下,矢量量化也可能有所帮助。
矢量量化
创建索引图像的过程最好描述为矢量量化 (VQ)。VQ 充当多维数的舍入过程。在此过程中,图像中的所有颜色根据其相似性进行分组。对于给定组,该组中的所有颜色都被一个单个的 中心点 值替换,该值最小化了该单元格(如果使用 Voronoi 术语,则为“站点”)中颜色的误差。在图 3 中,绿点代表输入颜色,红点是替换输入颜色的中心点。每个单元格由蓝线包围。

图 3. 对图像中的颜色应用矢量量化。
对图像应用 VQ 的结果是减少了唯一颜色数量,将每组颜色替换为单个颜色,该颜色在视觉质量上“非常接近”。
此技术还允许您定义图像中唯一颜色的最大数量。例如,图 4 显示了鹦鹉头部的 1670 万色(每像素 24 位,即 bpp)版本以及仅允许使用 16 种(3 bpp)唯一颜色的版本。

图 4. 应用矢量量化前后的图像。
立即,您可以看到质量有所损失;大多数渐变颜色已被替换,导致图像出现分带效应。此图像需要超过 16 种唯一颜色。
在您的管道中设置 VQ 步骤可以帮助您更好地了解图像使用的真实唯一颜色数量,并可以帮助您显著减少它们。有许多现成的工具可以帮助您实现此技术。
JPG
如果您正在使用 JPG 图像,可以进行一些小的更改,这可能会带来显著的文件大小节省。其中包括
- 通过不同的编码方法生成更小的文件大小(不影响质量)。
- 略微调整质量以获得更好的压缩效果。
采用这些策略通常可以使文件大小减少高达 25%。
选择工具时,请记住照片导出工具可能会在图像中插入不必要的元数据,例如 GPS 信息。至少,尝试利用现有工具帮助从文件中剥离此信息。
WebP
WebP 是从 Android 4.2.1(API 级别 17)开始支持的一种较新的图像格式。此格式为网络上的图像提供了出色的无损和有损压缩。使用 WebP,开发者可以创建更小、更丰富的图像。WebP 无损图像文件平均比 PNG 文件小 26%。这些图像文件还支持透明度(也称为 Alpha 通道),成本仅为增加 22% 的字节数。
在同等 SSIM 质量指数下,WebP 有损图像比同类 JPG 图像小 25-34%。在有损 RGB 压缩可接受的情况下,有损 WebP 也支持透明度,通常生成的文件大小比 PNG 小 3 倍。
有关 WebP 的更多信息,请访问 WebP 网站。
您可以使用 Android Studio 将现有的 BMP、JPG、PNG 或静态 GIF 图像转换为 WebP 格式。有关更多信息,请参阅使用 Android Studio 创建 WebP 图像。
选择格式
不同的图像格式适用于不同类型的图像。JPG 和 PNG 的压缩过程差异很大,它们产生的结果也截然不同。
选择 PNG 还是 JPG 通常取决于图像本身的复杂性。图 5 显示了根据开发者应用的压缩方案不同而呈现出截然不同的两张图像。左侧的图像细节较多,因此使用 JPG 压缩更有效。右侧的图像具有相同颜色的连续区域,因此使用 PNG 压缩更有效。

图 5. 适用于 JPG 与 PNG 的情况
WebP 作为一种格式可以支持有损和无损模式,使其成为 PNG 和 JPG 的理想替代品。唯一需要记住的是,它仅在运行 Android 4.2.1(API 级别 17)及更高版本的设备上具有原生支持。幸运的是,绝大多数设备都满足该要求。
图 6 提供了一个简单的可视化图表,帮助您决定使用哪种压缩方案。

图 6. 决定压缩方案
确定最佳质量值
有几种技术可以帮助您在压缩和图像质量之间实现适当的平衡。一种技术使用标量值,因此仅适用于 JPG 和 WebP。另一种技术利用 Butteraugli 库,适用于所有图像格式。
标量值(仅限 JPG 和 WebP)
JPG 和 WebP 的强大之处在于您可以使用标量值来平衡质量与文件大小。关键是找到适合您图像的正确质量值。质量水平过低会以牺牲图像质量为代价生成小文件。质量水平过高会增加文件大小,但不会为用户带来显着的好处。
最直接的解决方案是选择某个非最大值并使用该值。但是,请注意,质量值对每张图像的影响不同。例如,虽然 75% 的质量在大多数图像上看起来不错,但在某些情况下效果可能不佳。您应该确保针对具有代表性的图像样本测试您选择的最大值。此外,请务必对照原始图像进行所有测试,而不是在压缩版本上进行。
对于每天上传和重新发送数百万张 JPG 的大型媒体应用,手动调整每个素材是不切实际的。您可以通过根据图像类别指定几个不同的质量级别来解决这一挑战。例如,您可以将缩略图的质量设置为 35%,因为较小的图像可以隐藏更多压缩伪影。
Butteraugli
Butteraugli 项目是一个用于测试图像心理视觉误差阈值的库:观看者开始注意到图像退化的点。换句话说,该项目试图量化您的压缩图像的失真程度。
Butteraugli 允许您定义视觉质量目标,然后运行 PNG、JPG、有损 WebP 和无损 WebP 压缩。然后,您可以选择在文件大小和 Butteraugli 级别之间实现最佳平衡的图像。图 7 显示了 Butteraugli 如何用于查找视觉失真达到足以让用户感知到问题的最小 JPG 质量级别的示例;结果是文件大小大约减少了 65%。

图 7. 应用 Butteraugli 技术前后的图像。
Butteraugli 允许您基于输出或输入进行操作。也就是说,您可以在用户感知到结果图像中出现明显失真之前寻找最低质量设置,或者您可以迭代设置图像失真级别以了解其关联的质量级别。
服务尺寸
在服务器上仅保留图像的单一分辨率是很诱人的。当设备访问图像时,服务器以该分辨率提供图像,并将缩减交给设备处理。
此解决方案对开发者来说很方便,但对用户来说可能很痛苦,因为该解决方案迫使用户下载比他们需要的数据多得多的数据。您应该改为存储多种尺寸的图像,并提供最适合特定用例的尺寸。例如,对于缩略图,提供实际的缩略图图像而不是提供和缩减全尺寸版本会消耗少得多的网络带宽
这种方法有利于下载速度,并且对于可能使用有限或按流量计费数据计划的用户来说成本更低。这样做还会使图像在设备和主内存中占用更少的空间。对于 4K 等大型图像,这种方法还避免了设备在加载图像之前必须调整图像大小。
实施此方法需要您拥有一个后端图像服务,以提供具有适当缓存的各种分辨率的图像。有一些现有服务可以帮助完成此任务。例如,App Engine 已预装了图像大小调整功能。