2. 图像资源优化:压缩PNG、使用L8格式、减少色深
图像资源往往是TouchGFX项目里最占内存的大户。我见过不少团队,代码写得挺精简,结果一张全屏背景图就把RAM吃掉了大半。说白了,图像优化做得好不好,直接决定了你的MCU能不能跑得动这个界面。
这一章,我们专门聊图像资源的三个优化方向:压缩PNG、使用L8格式、减少色深。这三板斧砍下去,图像占用的内存通常能降50%以上。
核心观点:TouchGFX的图像内存占用 = 宽度 × 高度 × 每像素字节数。三个变量,每一个都有优化空间。
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里:
- 选中你的图像资源
- 在属性面板找到"Format"
- 从下拉列表选择"L8"
- 点击"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。
优化步骤:
- 压缩PNG源文件:用pngquant压到256色,文件从12KB降到4KB
- 导入TouchGFX:默认格式是RGB565,内存占用64×64×2=8KB
- 转L8格式:内存降到64×64×1=4KB
- 检查效果:温度计只有蓝红两色渐变,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。