2. TouchGFX基础架构

图像资源往往是TouchGFX项目里最占内存的大户。我见过不少团队,代码写得挺精简,结果一张全屏背景图就把RAM吃掉了大半。说白了,图像优化做得好不好,直接决定了你的MCU能不能跑得动这个界面。

这一章,我们专门聊图像资源的三个优化方向:压缩PNG、使用L8格式、减少色深。这三板斧砍下去,图像占用的内存通常能降50%以上。

核心观点:TouchGFX的图像内存占用 = 宽度 × 高度 × 每像素字节数。三个变量,每一个都有优化空间。

图像资源优化三大路径 图像内存占用 压缩PNG 使用L8格式 减少色深 无损压缩 有损压缩 调色板优化 256色调色板 1字节/像素 适合图标/小图 RGB565→RGB222 BW格式(1位) 灰度图优化 目标:内存占用降低50%以上

2.1 压缩PNG:从源头减负

很多人以为PNG放到TouchGFX项目里就是直接用的,其实不是。TouchGFX在编译时会把你丢进去的PNG转成二进制位图数据。但源文件越小,转换后的数据量也越小吗?嗯,这里要注意——PNG压缩只影响存储空间,不影响运行时内存。

那为什么还要压缩PNG?两个原因:

  • 减少固件体积:Flash空间有限,尤其是那些128KB、256KB的MCU。
  • 加快加载速度:从外部Flash读取时,数据量越小,读取越快。

我个人习惯用pngquant做有损压缩,配合optipng做无损后处理。举个例子:

# 有损压缩,将PNG颜色数降到256色
pngquant --quality=65-80 --speed=1 input.png

# 无损后处理,进一步减小文件体积
optipng -o7 input-fs8.png

我在项目中遇到过一张480×272的全屏背景图,原始PNG是380KB。用pngquant压到256色后,降到120KB,视觉上几乎看不出区别。再跑一遍optipng,又少了10KB。嗯,效果很明显。

小技巧:TouchGFX Designer里可以直接设置图像压缩级别。在Image属性面板找到"Compression",选"RLE"或"LZW4"。RLE适合大块单色区域,LZW4适合渐变丰富的图。

2.2 使用L8格式:1字节像素的魔法

L8格式是TouchGFX里我最喜欢的功能之一。说白了,就是给图像建一个256色的调色板,每个像素只存1个字节的索引值,而不是直接存RGB值。

对比一下内存占用:

格式 每像素字节数 320×240图像内存 适用场景
RGB565 2 153.6 KB 全彩照片、渐变背景
L8 1 76.8 KB 图标、按钮、简单插图
BW 0.125 9.6 KB 黑白文字、单色图标

看到没?L8比RGB565省了一半内存。而且调色板本身只占256×2=512字节(RGB565每个颜色2字节),几乎可以忽略不计。

怎么用L8?在TouchGFX Designer里:

  1. 选中你的图像资源
  2. 在属性面板找到"Format"
  3. 从下拉列表选择"L8"
  4. 点击"Generate"重新生成代码

我曾经在一个智能手表项目里,把所有图标都转成了L8格式。原本图标占用了80KB的RAM,转完之后只剩40KB。系统整体内存占用从180KB降到了140KB,刚好卡进那颗128KB RAM的MCU里——嗯,差点就要换芯片了。

注意:L8格式不适合照片级图像。256种颜色对于渐变丰富的图片来说,会出现明显的色阶断层。我建议只对图标、按钮、简单图形使用L8。

2.3 减少色深:能省则省

减少色深是最直接的优化手段。TouchGFX支持多种色深格式,从RGB565(16位)到L8(8位)再到BW(1位)。选哪种,取决于你的图像内容。

我一般这样选:

  • 全彩照片/背景图:RGB565,别省,省了会很难看
  • 图标/按钮:L8,256色足够
  • 纯文字/简单符号:BW,1位色深,内存占用只有RGB565的1/16
  • 灰度图:可以用L8的灰度调色板,或者直接用GRAY格式(如果TouchGFX版本支持)

举个例子,一个32×32的图标:

RGB565: 32 × 32 × 2 = 2048 字节
L8:     32 × 32 × 1 = 1024 字节
BW:     32 × 32 × 1/8 = 128 字节

从2KB降到128字节,差了16倍。你想想看,如果项目里有50个这样的图标,那差距就是100KB vs 6.25KB。

我曾经接手过一个项目,前任工程师把所有图像都用了RGB565,包括那些纯黑色的文字图标。我花了一个下午,把所有文字图标转成BW格式,内存占用直接降了40KB。嗯,有时候优化就是这么简单——选对格式就行。

经验之谈:不要盲目追求最低色深。在TouchGFX模拟器里先跑一遍,看看图像质量能不能接受。如果客户觉得图标有锯齿,那就升一档。平衡点在于:在可接受的质量下,选最低的色深。

2.4 实战:一张图的优化全过程

拿我最近做的一个温控器界面举例。有一张温度计的图标,原始PNG是24位色,尺寸64×64。

优化步骤:

  1. 压缩PNG源文件:用pngquant压到256色,文件从12KB降到4KB
  2. 导入TouchGFX:默认格式是RGB565,内存占用64×64×2=8KB
  3. 转L8格式:内存降到64×64×1=4KB
  4. 检查效果:温度计只有蓝红两色渐变,256色完全够用,没有色阶

最终,一张图标从8KB降到4KB,节省了50%。整个项目有30多个图标,总共省了120KB的RAM。嗯,这120KB刚好可以用来放一个动画序列。

工具推荐:用ImageMagick可以批量转换图像格式。比如把整个文件夹的PNG转成256色:mogrify -colors 256 *.png。但记得先备份原图。

2.5 避坑指南

最后,分享几个我踩过的坑:

  • 别对照片用L8:256色放照片,效果惨不忍睹。我试过,客户直接打回来重做。
  • 注意调色板对齐:L8的调色板在RAM里是连续存储的。如果调色板数据被意外修改,整个图像都会花掉。我曾经因为DMA传输地址没对齐,调色板读出来全是乱的,图像显示得像万花筒。
  • BW格式要慎用抗锯齿:1位色深没有灰度过渡,抗锯齿开了也没用,反而增加计算量。关掉它。
  • 测试要在真机上跑:模拟器里看着好好的L8图像,到真机上可能因为LCD驱动IC的色深支持问题,颜色完全不对。我遇到过一块只支持RGB565的屏幕,L8图像显示出来偏色严重,最后只能转回RGB565。