1. 引言
在使用 TouchGFX 生成代码时,像图片、文本和字体这样的资源会被转换成 C++ 文件,然后与TouchGFX 应用程序代码、用户代码和 TouchGFX 库一起编译后存储在 Flash 中。 这意味着具有许多资源的大型或复杂项目会需要使用更多的 Flash 存储空间。
由于大多数应用中的存储器资源都是有限的,因此有几种方法可以减少应用对 Flash 存储器容量的需求。TouchGFX 提供四项内置功能,可以帮助显著减少应用程序的 Flash 存储器需求。 这四项功能分别是 L8 图片格式、图片压缩、可缩放矢量图形(SVG)和矢量字体。
本文只涉及图片压缩并会先介绍 TouchGFX 支持的图片压缩功能,然后结合客户使用 TouchGFX图形压缩功能出现图片显示丢失的问题进行分析。
2. TouchGFX 的图片压缩功能
2.1. TouchGFX 图片压缩功能简介
TouchGFX 从 4.22 版开始支持图片压缩。4.22 to 4.23 只支持 L8 格式的图片压缩。从 4.24 版本开始,支持 RGB565, RGB888, 以及 ARGB8888 压缩。
图片压缩通常有两种风格:无损或有损。 有损图片压缩通过去除图片的微小细节来实现。 这样通常会得到最大的缩减图片,但原始图片无法准确再现。 无损压缩总是无任何差异地再现原始图片,无损压缩的尺寸缩减通常较小。对于图形,通常要求 UI 元素完全按照其设计来绘制。 因此,TouchGFX 只支持无损压缩。
图片压缩的优点是存储空间需求减少,但也有缺点,因为图片在绘制到帧缓存时必须解压缩。 与绘制未压缩的图片相比,这种解压缩在许多情况下需要 CPU 做更多的工作。 结果可能是性能下降。这意味着必须将 Flash 减少带来的优势与 CPU 使用率增加带来的劣势进行权衡。STM32 中的图形加速器 DMA2D 和 GPU2D(ChromART and NeoChrom GPU)不能直接绘制压缩图片。压缩图片使用软件和硬件渲染的混合方式进行绘制,即压缩数据由软件分块解压缩,然后在适用的情况下将这些分块委托给 DMA2D 处理。许多应用中,不建议压缩所有图片,而是只压缩那些性能不受影响且与减少 Flash 相关的图片。
2.2. TouchGFX 支持的压缩方式
2.2.1 L8 压缩
L8 位图格式仅适用于高达 256 色的图片。 每个像素只是一个 8 位数字,表示与图片一起存储的颜色表中的一种颜色。L8 的压缩只是像素编号的压缩。颜色表保持不变。压缩的L8 图片像普通的未压缩位图一样使用。 关于 L8 像素格式可以参考:使用 L8 图片格式减少存储空间消耗 |TouchGFX Documentation
如果我们使用 L8 压缩 28,121 字节的一个图片,像素数据将减少到 5,735 字节。压缩图片数据(包括颜色表)的总大小小于原始图片的 20%。因此,压缩允许我们在同一个 Flash空间中拥有 5 个不同的背景或者将 Flash 需求减少 28,121 字节。压缩的 L8 图片可以像普通的未压缩位图一样使用。 例如,您可以使用图片控件显示图片,而无需在 TouchGFX Designer 或代码中对项目进行任何修改。
L8 图片转换器支持三种压缩算法(L4、RLE、LZW9)。
• L4,对每个像素进行 4 比特编码。 仅适用于最多 16 种颜色的图片。
• RLE,像素的游程编码。 仅适用于最多 64 种颜色的图片。
• LZW9,基于词典的编码。 适用于所有 L8 图片。
RLE 算法的解压缩速度比 LZW9 快得多,因此如果 LZW9 仅压缩图片,转换器将选择RLE 稍微好一点。
在 TouchGFX Designer 中,可以将压缩值设置为 “Auto(自动)” ,使图片转换器为你的图片选择合适的算法或者也可以强制使用特定的算法。比如在下图1是 TouchGFX designer 4.24 中 STM32U5A9DK 的 Demo6 中将其中一幅 background_texture_reverse.png 图片转换为 L8_RGB888 格式,然后压缩方式选择Auto。在 TouchGFX designer 上点击 Generate code 按钮后,可以在下图 2 的工程代码看到压缩情况,压缩率高达 81.5%。
图1. background_texture_reverse.png 图片转换为 L8_RGB888 格式
图2. 工程代码图片压缩情况
L8 图片压缩有一个默认设置,可在 TouchGFX Designer 的默认图片配置选项卡上进行配置,如下图 3。 在这里用户可以配置整个应用程序的默认设置。
图3. 默认图片设置
而且使用 L8 不同的算法对同一张图片进行压缩,它的压缩率和渲染时间也会有差异。具体可以参考:使用 L8 图片格式减少存储空间消耗 | TouchGFX Documentation
针对图片使用的颜色多于 256 种不能在 TouchGFX Designer 中直接转换为 L8 图片格式情况。可以让 UI 设计师转换图片或提供 256 色图片。使用图片操作工具可以执行转换颜色数量,同时不会过度损失图片质量,比如使用软件工具 Paint.NET。在软件打开原始图片,可以将图片“另存为”另一个文件,在“保存设置”对话框中,选择 8 位像素深度。
2.2.2 RGB 压缩 如前所述,TouchGFX 4.24 引入了对 RGB565、RGB888 和 ARGB8888 图片格式的图片压缩支持。对超过 256 种独特颜色的图片不能以 L8 图片格式存储和压缩必须以RGB565、RGB888 或 ARGB8888 格式进行存储压缩。使用 RGB 压缩方法跟 L8 压缩类似,如下图 4,压缩选项里只要选择 Yes,然后 Generate code 。
图4. RGB 压缩
图5. RGB888 压缩率情况
如上图 5 可以发现,对 background_texture_reverse.png 图片使用 RGB888 压缩,压缩率达到 93.1%。也可以看到,同样的图片使用 L8_RGB888 格式存储和使用 RGB888 格式存储,本身大小也有差异。 需要注意的是在某些情况下,将抖动算法应用于 RGB 图片会损害 RGB 压缩的有效性。 大多数情况下,绘制压缩图片的性能比绘制未压缩图片差。如前面所说,对于压缩图片STM32 MCU 的图形加速器比如 DMA2D 或 GPU2D 是不能直接绘制压缩的图片的。因此,压缩图片由软件和硬件混合绘制,从而导致性能较低且 CPU 负载较高。正所谓鱼与熊掌不可兼得,压缩图片虽然减小了 Flash 占用,但也导致了更高的 CPU 使用率,这个需要客户根据应用权衡取舍。 3. 问题产生 下面回到客户的问题,客户有两个问题一个是在使用图片压缩后,有些控件的图片不能被压缩。第二个是有时候图片可以被压缩,但显示的时候有的图片丢失了,显示不出来。我们知道有些控件是不支持压缩的图片的,这个很容易跟客户解释。如下图 6,像TextureMapper 控件不支持压缩的图片,选择这个控件使用的图片进行压缩会有警告,而如果继续强制压缩会产生 Error。
图6. TextureMapper 控件不支持压缩图片 而且对于不支持压缩图片的控件在图片压缩 | TouchGFX Documentation ST 网站也有说明,如下不支持压缩图像的控件有: • 纹理映射(TextureMapper) • 可缩放图像 • 指针和弧形仪表 • 用于填充图形下方区域的静态和动态图表 • 指针模拟时钟 • 圆、线和形状 • 圆形和线形进度条 我们可以看到 TextureMapper 控件就在限制使用压缩图片的名单里面,所以客户的第一个疑问也就解决了。 那客户遇到的图片在 TouchGFX designer 上可以被压缩,但却显示不出来是怎么回事呢?我们看下面复制客户问题的实验。我们继续以 STM32U5A9DK 的 Demo6 做实验。如下图 7,Watch 方块里面的时间,日历魔方是可以正常显示的。
图7. 未压缩图片前正常显示 下面我们将这几张日历,时间的图片进行 RGB888 压缩,看会发生什么。
图8. 对图片进行 RGB 压缩
图9. 编译过程日志 我们从上图 8 可以看到,对四张图片选择压缩,并没有显示警告标识,后续生成代码也没有报错,见图 9。 下面我们再来看看图片显示的效果。对比上面图七和下面图十,明显发现图 10 中有些图片丢失了,现象跟客户的一样。
图10. 压缩图片后显示异常 因为上面在使用 TouchGFX designer 选择图片压缩时并没有警告标识提醒。这不免让人怀疑,是否除了上面列出的限制不能使用压缩图片的控件外,还有其他的应用场景无法使用压缩图片。针对这个疑问,我们请教了 Division。 后面 Division 反馈,在这个 Demo6 里, Watch 的控件 TextureMapper 并没有在TouchGFX designer 界面直接使用压缩的图片,压缩图片如下图 11 显示,是在代码里被调用了,所以 TouchGFX designer 界面没有警告标识。并且强调,即使是在代码里,被限制使用压缩图片的控件如果使用了压缩图片也是不合规的。到这里,就能理解为什么图片压缩时会没有警告,却出现了图片显示丢失。所以对于客户应用中需要在代码里使用压缩图片时,就需要自己注意该控件是否支持使用压缩图片。
图11. 代码调用了 TextureMapper 控件
4. 问题解决 最后我们跟客户沟通发现,只要按照图像压缩 | TouchGFX Documentation 里的规范对压缩图片进行使用,后续没有再发现图片丢失的问题。
5. 小结 下面针对这次客户对于 TouchGFX 压缩图片使用,总结以下注意事项:
• 图片压缩可以帮助减少应用程序的 Flash 存储器需求。 • TouchGFX 只支持无损压缩。 • 许多应用中,不建议压缩所有图片,而是只压缩那些性能不受影响且与减少 Flash相关的图片。 • 大多数情况下,绘制压缩图片的性能比绘制未压缩图片差。对于压缩图片 STM32 MCU 的图形加速器比如 DMA2D 或 GPU2D 是不能直接绘制压缩的图片。因此,压缩图片由软件和硬件混合绘制,从而导致性能较低且 CPU 负载较高。 • 如果要在位图上使用 L8 图像格式,位图最多为 256 色。如果超过,请使用 RGB 格式或使用软件编辑图片为 256 色。 • 对于不支持压缩图片的控件,在 TouchGFX designer 或代码中都不宜使用压缩图片(具体参考图像压缩 | TouchGFX Documentation)。
以上供大家参考。
|