大部分下载流量由图像构成。因此,下载图像越小,您的应用就能为用户提供更好的网络体验。此页面提供有关减小图像文件大小和使其更适合网络环境的指导。
关于图像格式
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 显示了一张图像及其索引变体。
图 2 显示了图 1 中图像的颜色调色板
将图像表示为调色板图像对于显著改善文件大小非常有帮助,因此,如果您的大部分图像可以转换,则值得进行调查。
当然,并非每张图像都可以仅用 256 种颜色准确地表示。例如,某些图像可能需要 257、310、512 或 912 种颜色才能看起来正确。在这种情况下,矢量量化也可能有所帮助。
矢量量化
创建索引图像的过程可以更好地描述为矢量量化 (VQ)。VQ 用作多维数字的舍入过程。在此过程中,图像中的所有颜色都根据其相似性进行分组。对于给定的组,该组中的所有颜色都将替换为单个中心点值,这将最大限度地减少该单元格(如果使用 Voronoi 术语,则为“位置”)中颜色的误差。在图 3 中,绿点表示输入颜色,红点表示替换输入颜色的中心点。每个单元格都由蓝线包围。
将 VQ 应用于图像的结果减少了唯一颜色的数量,用视觉质量“非常接近”的单一颜色替换每组颜色。
此技术还允许您定义图像中唯一颜色的最大数量。例如,图 4 显示了 1670 万种颜色(每像素 24 位或 bpp)的鹦鹉头部以及仅允许使用 16 种(3 bpp)唯一颜色的版本。
您可以立即看到质量有所下降;大部分渐变色已被替换,图像上出现了条带效果。此图像需要的唯一颜色超过 16 种。
在您的管道中设置 VQ 步骤可以帮助您更好地了解图像使用的唯一颜色的真实数量,并可以帮助您大幅减少它们。您可以使用许多现成的工具来帮助您实现此技术。
JPG
如果您使用的是 JPG 图像,您可以进行一些小的更改,从而可能节省大量文件大小。这些包括
- 通过不同的编码方法生成较小的文件大小(不会影响质量)。
- 稍微调整质量以获得更好的压缩。
追求这些策略通常可以使您减少多达 25% 的文件大小。
选择工具时,请记住,照片导出工具可能会将不必要的元数据(例如 GPS 信息)插入到图像中。至少,尝试利用现有工具帮助从文件中去除此信息。
WebP
WebP 是一种从 Android 4.2.1(API 级别 17)开始支持的较新的图像格式。此格式为网络上的图像提供了卓越的有损和无损压缩。使用 WebP,开发人员可以创建更小、更丰富的图像。WebP 无损图像文件平均比 PNG 小 26%。这些图像文件还支持透明度(也称为 alpha 通道),其成本仅为多 22% 字节。
WebP 有损图像比在等效SSIM 质量指数下同等的 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 压缩效率更高。
WebP 作为一种格式,可以支持有损和无损模式,使其成为 PNG 和 JPG 的理想替代品。唯一需要注意的是,它仅在运行 Android 4.2.1(API 级别 17)及更高版本的设备上具有原生支持。幸运的是,大部分设备都满足此要求。
图 6 提供了一个简单的可视化图表来帮助您决定使用哪种压缩方案。
确定最佳质量值
您可以使用多种技术来在压缩和图像质量之间取得平衡。一种技术使用标量值,因此仅适用于 JPG 和 WebP。另一种技术利用 Butteraugli 库,适用于所有图像格式。
标量值(仅限 JPG 和 WebP)
JPG 和 WebP 的强大之处在于您可以使用标量值来平衡质量和文件大小。诀窍在于找出适合您图像的正确质量值。质量等级过低会产生较小的文件,但会以牺牲图像质量为代价。质量等级过高会增加文件大小,而不会为用户带来明显的益处。
最直接的解决方案是选择某个非最大值并使用该值。但是,请注意,质量值会对每张图像产生不同的影响。例如,75% 的质量在大多数图像上看起来都很好,但在某些情况下可能效果不佳。您应该确保针对具有代表性的图像样本测试您选择的最大值。此外,请确保所有测试都针对原始图像进行,而不是针对压缩后的版本。
对于每天上传和重新发送数百万张 JPG 的大型媒体应用程序,对每个资源进行手动调整是不切实际的。您可以根据图像类别指定几个不同的质量级别来应对这一挑战。例如,您可以将 35% 设置为缩略图的质量设置,因为较小的图像隐藏了更多压缩伪影。
Butteraugli
Butteraugli 项目是一个用于测试图像心理视觉误差阈值的库:观察者开始注意到图像降质的点。换句话说,该项目试图量化压缩图像的失真程度。
Butteraugli 允许您定义视觉质量目标,然后运行 PNG、JPG、WebP 有损和 WebP 无损压缩。然后,您可以选择文件大小和 Butteraugli 水平最均衡的图像。图 7 显示了如何使用 Butteraugli 找到视觉失真足够高以至于用户可以感知到问题的最小 JPG 质量级别的一个示例;结果是文件大小减少了大约 65%。
Butteraugli 允许您基于输出或输入进行操作。也就是说,您可以查找在用户感知到结果图像中明显的失真之前的最低质量设置,或者您可以迭代地设置图像失真级别来了解其相关的质量级别。
服务尺寸
只在服务器上保留图像的单一分辨率很诱人。当设备访问图像时,服务器以该单一分辨率提供图像,并将缩小比例的工作留给设备。
此解决方案对开发者来说很方便,但对用户来说可能很痛苦,因为此解决方案迫使用户下载比他们需要的更多的数据。您应该改为存储多种尺寸的图像,并为特定用例提供最合适的尺寸。例如,对于缩略图,提供实际的缩略图图像而不是提供并缩小全尺寸版本可以节省更多的网络带宽。
这种方法有利于下载速度,并且对于可能使用有限或计量数据计划的用户来说成本更低。这样操作还可以减少图像在设备和主内存中占用的空间。对于大型图像(例如 4K 图像),这种方法还可以避免设备在加载图像之前需要调整图像大小。
实施这种方法需要您拥有一个后端图像服务来提供各种分辨率的图像并进行适当的缓存。现有的服务可以帮助完成此任务。例如,App Engine 已安装图像调整大小功能。