减少图像下载大小

大多数下载流量都来自图像。因此,您可以使可下载图像越小,您的应用就可以为用户提供越好的网络体验。此页面提供有关使图像文件更小且更适合网络的指南。

关于图像格式

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% 的字节即可。

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 压缩效率更高。

图 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 已安装图像调整大小功能。