1、资源压缩概述:为什么需要资源压缩?
各位做嵌入式 GUI 的同行,咱们开门见山。你辛辛苦苦把界面调好了,动画也顺了,结果一算 Flash 空间——超了。这种事我遇到过不下十次。资源压缩,说白了就是帮你的 GUI 在有限的存储空间里塞下更多内容。
嵌入式设备不像手机,Flash 和 RAM 都是按 MB 甚至 KB 来算的。一张 800×480 的 32 位真彩色图,不压缩直接存,要 1.5MB。你想想看,一颗主流 MCU 的 Flash 才多大?STM32F4 系列普遍 1MB 到 2MB,一张图就吃掉大半,剩下的代码、字体、布局文件往哪放?
核心结论:资源压缩不是可选项,而是嵌入式 GUI 工程的必选项。它直接决定了你的产品能不能在目标硬件上跑起来。
1.1 常见嵌入式 GUI 资源类型
我习惯把 GUI 资源分成四大类,每一类的压缩思路都不一样。咱们一个一个说。
| 资源类型 | 典型格式 | 存储占比 | 压缩难点 |
|---|---|---|---|
| 图片 | PNG、JPEG、BMP、RAW | 60%~80% | 色彩深度高,解码开销大 |
| 字体 | TTF、OTF、Bitmap Font | 10%~25% | 字符集大,点阵数据冗余 |
| 字符串 | UTF-8、UTF-16、ASCII | 5%~15% | 多语言支持导致体积膨胀 |
| 布局文件 | XML、JSON、二进制描述 | 1%~5% | 解析效率与压缩率需要平衡 |
1.2 图片资源——存储大头
图片是 GUI 资源里的「重量级选手」。我在一个智能家居面板项目里,光背景图就占了 800KB,整个界面资源包 1.2MB,MCU 的 Flash 才 1MB——根本烧不进去。
常见的图片压缩手段有几种:
- 调色板化: 把 32 位真彩色转成 8 位或 4 位索引色。比如 LVGL 的 L8 格式,一张图能从 1.5MB 降到 384KB。
- 有损压缩: JPEG 格式,适合照片类背景。但要注意,嵌入式 JPEG 解码库会占用额外 RAM。
- 无损压缩: PNG 格式,适合图标和文字界面。压缩率一般 2:1 到 5:1。
- 硬件压缩: 有些 MCU 内置 JPEG 编解码器,比如 NXP 的 i.MX RT 系列,解码几乎不占 CPU。
我的经验: 图标类资源优先用调色板 + RLE 游程编码。我曾经把一个 64×64 的 32 位图标从 16KB 压到 1.2KB,显示效果肉眼几乎看不出区别。
1.3 字体资源——被低估的体积
很多人觉得字体能有多大?一套完整的 16×16 点阵中文字库,GB2312 编码包含 6763 个汉字,每个字 32 字节,算下来 216KB。如果换成 24×24 点阵,直接飙到 486KB。要是再支持多语言——日文、韩文、西里尔文——轻松突破 1MB。
我做过一个出口欧洲的温控器,需要支持 8 种语言。一开始直接塞了 8 套 TTF 字体,Flash 直接爆了。后来改用子集化 + 位图缓存,只保留用到的字符,体积从 2.3MB 降到了 280KB。
字体压缩的常用策略:
- 字符子集化: 只包含界面用到的字符,别把整个 Unicode 字库都塞进去。
- 位图字体: 把 TTF 渲染成固定大小的点阵,省去渲染开销。
- 笔画压缩: 像 FreeType 的 SDF 字体,用距离场存储字形,体积小且缩放效果好。
注意: 字体压缩要兼顾显示质量。我曾经把字号压得太狠,结果在 2.8 寸屏上「横」和「黄」看起来一模一样——用户投诉说看不清温度数值。从那以后,我定了个规矩:字体压缩后必须做肉眼验收测试。
1.4 字符串资源——多语言的坑
字符串看起来不起眼,但多语言版本一上,体积就翻着倍涨。一个中文界面字符串表大概 5KB,加上英文、法文、德文、西班牙文,轻松到 30KB 以上。
我建议的做法是:
- 字符串 ID 化: 代码里用 ID 引用,运行时根据语言加载对应表。
- 字典压缩: 对重复出现的子串(比如「温度」「湿度」「设置」)建立字典索引。
- 二进制编码: 别用 XML 或 JSON 存字符串表,用紧凑的二进制格式,能省 30%~50% 空间。
1.5 布局文件——小体积也要精打细算
布局文件通常不大,但解析效率很关键。XML 布局虽然可读性好,但解析时要用 DOM 或 SAX 解析器,RAM 开销不小。我见过一个项目,布局 XML 解析时临时分配了 64KB 堆内存,直接把系统搞崩了。
我的建议:
- 编译期预处理: 把 XML 转成二进制描述,运行时直接内存映射。
- 模板化: 相似的布局复用模板,只传差异参数。
- 硬编码: 对于固定界面,直接用 C 结构体定义布局,零解析开销。
1.6 资源压缩的整体流程
下面这张图是我做项目时总结的资源压缩流程,你可以参考一下。
1.7 压缩的核心权衡
做资源压缩,本质上是在三个维度上找平衡:
- 压缩率: 能省多少空间?
- 解码速度: 解压需要多少 CPU 时间?
- 运行时 RAM: 解压过程需要多少临时内存?
我见过有人把图片压到极致,结果解码一张图要 500ms,界面切换卡得不行。也见过有人为了省 RAM 用流式解压,结果每帧都要重新解压,CPU 占用飙到 80%。
我的建议: 先定硬件边界——Flash 多大?RAM 多少?CPU 主频多少?然后在这个边界内找最优解。别盲目追求最高压缩率,也别为了省事完全不压缩。
1.8 本章小结
资源压缩是嵌入式 GUI 开发的必修课。图片、字体、字符串、布局文件,每一类都有各自的压缩套路。核心思路就一句话:在有限的硬件资源里,用最小的存储代价,换取可接受的显示质量和响应速度。
后面的章节,我会逐一拆解每种资源的压缩细节,包括具体的算法、工具链和代码实现。嗯,咱们一步步来。