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 资源压缩的整体流程

下面这张图是我做项目时总结的资源压缩流程,你可以参考一下。

嵌入式 GUI 资源压缩整体流程 原始资源 资源分类 图片压缩 字体压缩 字符串压缩 布局压缩 压缩后资源 压缩后资源 压缩后资源 压缩后资源 资源包打包 运行时解压加载 关键原则 压缩率 vs 解码速度 存储空间 vs 运行时 RAM

1.7 压缩的核心权衡

做资源压缩,本质上是在三个维度上找平衡:

  • 压缩率: 能省多少空间?
  • 解码速度: 解压需要多少 CPU 时间?
  • 运行时 RAM: 解压过程需要多少临时内存?

我见过有人把图片压到极致,结果解码一张图要 500ms,界面切换卡得不行。也见过有人为了省 RAM 用流式解压,结果每帧都要重新解压,CPU 占用飙到 80%。

我的建议: 先定硬件边界——Flash 多大?RAM 多少?CPU 主频多少?然后在这个边界内找最优解。别盲目追求最高压缩率,也别为了省事完全不压缩。

1.8 本章小结

资源压缩是嵌入式 GUI 开发的必修课。图片、字体、字符串、布局文件,每一类都有各自的压缩套路。核心思路就一句话:在有限的硬件资源里,用最小的存储代价,换取可接受的显示质量和响应速度。

后面的章节,我会逐一拆解每种资源的压缩细节,包括具体的算法、工具链和代码实现。嗯,咱们一步步来。