3、图像资源优化:压缩格式选择、图片尺寸裁剪与纹理图集

图像资源,往往是 TouchGFX 项目里最吃内存、最拖帧率的元凶。我见过太多团队,动画卡顿的第一反应是去调刷新率、改 DMA 配置,结果查到最后,罪魁祸首就是一张 4MB 的启动图。

这一章,咱们就专门啃这块硬骨头。我会把压缩格式、尺寸裁剪、纹理图集这三个手段拆开揉碎了讲。说白了,就是让你手里的每一张图,都变成「刚刚好」的状态——不多占一个字节,不浪费一个像素时钟。

核心原则: 图像优化的本质,是用「视觉无损」换取「性能增益」。你不需要让每张图都完美,只需要让用户看不出瑕疵。

3.1 压缩格式选择:L8 vs RGB565 vs ARGB8888

TouchGFX 支持三种主流像素格式。选对了,内存占用能直接砍掉一半以上。选错了,嗯……我见过有人用 ARGB8888 存纯色图标,白白浪费 75% 的带宽。

格式 每像素位数 色深 Alpha 通道 典型场景
ARGB8888 32 bpp 16.7M 色 8 bit 全透明 照片、渐变背景、半透明叠加
RGB565 16 bpp 65K 色 无 图标、按钮、纯色块、非透明 UI 元素
L8 8 bpp 256 色 可选(占用额外调色板) 低色数图标、字体纹理、风格化界面

我的选择习惯:

  • 所有非透明的 UI 元素,一律用 RGB565。65K 色在 4.3 寸屏上根本看不出区别,但内存直接减半。
  • 需要半透明或渐变的地方,才上 ARGB8888。比如弹窗遮罩、滑动返回的残影效果。
  • L8 是个被低估的宝贝。我做过一个智能家居项目,所有图标只用 16 色,全部转成 L8 格式,整组图标从 800KB 缩到 80KB。你想想看,这差距有多大。
小技巧: 在 TouchGFX Designer 里,右键图片资源可以直接切换格式。切换后记得点「Run Simulator」预览一下——有些颜色在 RGB565 下会出现明显色带,这时候就得换回 ARGB8888。

3.2 图片尺寸裁剪:别让 MCU 做无用功

我曾经接手过一个项目,里面有一张 800×480 的全屏背景图,但实际内容只占了中间 400×300 的区域,四周全是纯白。你猜怎么着?TouchGFX 老老实实地把整张 800×480 的图加载到帧缓冲里,每次刷新都搬运 1.5MB 的数据——其中 70% 是没用的白色像素。

裁剪的核心逻辑:

  1. 物理裁剪: 在 Photoshop 或 GIMP 里,直接把图片裁到实际显示区域。别留多余边距。
  2. 逻辑裁剪: 如果一张图在运行时需要缩放或裁切,用 TouchGFX 的 Image 控件的 setScalingMode() 配合 setPosition() 来裁剪,而不是加载完整大图。
  3. 对齐到 4 字节: 图片宽度最好是 4 的倍数。因为 TouchGFX 的帧缓冲是按 4 字节对齐的,不对齐的话,DMA 传输效率会下降。
注意: 不要为了省内存而把图片裁得太小,然后靠 TouchGFX 的 Scale 模式放大。放大后的模糊效果,比 RGB565 的色带还难看。我的经验是:裁剪后的尺寸,至少是显示尺寸的 0.8 倍。

3.3 纹理图集(Texture Atlas):把零散碎片拼成整块

纹理图集,说白了就是把一堆小图拼成一张大图。为什么这么做?因为 TouchGFX 在渲染时,每切换一次纹理,都会产生一次状态切换开销。如果你有 50 个小图标,每帧切换 50 次纹理,帧率直接腰斩。

纹理图集的好处:

  • 减少纹理切换: 一次绑定,整组图标都能用。
  • 提高缓存命中率: 大图在内存中是连续存储的,CPU 和 DMA 的预取效率更高。
  • 降低碎片化: 小图分散加载容易造成内存碎片,拼成大图后一次性分配。

我建议的图集组织方式:

图集分组 包含内容 推荐格式 最大尺寸
Icon Atlas 所有导航图标、状态图标 L8 或 RGB565 512×512
Button Atlas 按钮的 normal/pressed/disabled 状态 RGB565 1024×512
Background Atlas 全屏背景、弹窗背景 RGB565 或 ARGB8888 1024×1024
工具推荐: 我习惯用 TexturePacker 来生成图集。它支持直接导出 TouchGFX 的 .png 和 .tga 格式,还能自动生成坐标 JSON。在 TouchGFX Designer 里,把图集当成一张普通图片导入,然后用 Image 控件的 setBitmap() 配合 setXY() 来截取子图。

3.4 知识体系总览

下面这张图,把咱们这一章的核心逻辑串起来了。你可以把它当成一个决策流程——拿到一张图,先走哪一步,再走哪一步。

图像资源优化决策流程 原始图像资源 是否需要透明/渐变? 是 ARGB8888 否 RGB565 / L8 尺寸裁剪(对齐4字节) 是否属于同一UI分组? 是 合并到纹理图集 否 单独加载 性能最优的加载方案 提示:纹理图集建议控制在 1024×1024 以内,避免超出 MCU 的 DMA 最大传输尺寸

3.5 避坑指南

最后,分享几个我踩过的坑,希望能帮你省点 debug 时间。

  • L8 的调色板陷阱: 我曾经把一张 256 色的 L8 图集用在 16 位屏上,结果颜色全乱了。后来才发现,L8 的调色板默认是 ARGB8888 格式的,如果你的屏只支持 RGB565,调色板里的颜色会被截断。解决办法:在 TouchGFX Designer 里手动指定调色板格式为 RGB565。
  • 纹理图集的 padding: 拼图集时,子图之间至少留 2 像素的 padding。否则相邻图标的边缘会出现「串色」——因为纹理过滤时会采样到隔壁像素。我习惯用 TexturePacker 的 padding: 2 选项。
  • 不要迷信 ARGB8888: 有一次客户坚持所有图都用 ARGB8888,说「画质好」。结果动画帧率从 60fps 掉到 35fps。后来我做了个盲测,让 10 个人分辨 RGB565 和 ARGB8888 的图标差异——没人能看出来。从那以后,我就把「RGB565 优先」写进了团队规范。
重要提醒: 每次修改图像格式或尺寸后,一定要在目标硬件上跑一遍性能测试。模拟器上的帧率不能代表真机表现——因为模拟器用的是 PC 的显存和带宽,而你的 MCU 只有可怜的几 MB SRAM。