1. 课程导入

做嵌入式GUI开发,迟早会被图片卡住。我入行那会儿,第一个量产项目就是栽在图片上——界面切换像放幻灯片,用户按一下按钮,得等半秒才反应。后来一查,问题全出在图片这条链路上。

说白了,一张图片从文件变成屏幕上像素,要经过三道关卡:解码、传输、渲染。任何一环出问题,你的FPS就保不住。

1.1 图片加载的完整链路

先看看一张图片到底是怎么“走”到屏幕上的。我习惯把它分成三个阶段:

核心链路: 存储介质 → 解码器 → 内存缓冲区 → 显示驱动 → 屏幕

每个阶段都有各自的瓶颈。咱们一个一个拆。

图片加载性能瓶颈全景图 阶段1:解码 JPEG/PNG → 原始像素 阶段2:传输 内存 → 显存 / 缓冲区 阶段3:渲染 合成 → 刷新 → 显示 解码瓶颈 CPU占用高 内存临时开销大 传输瓶颈 总线带宽有限 DMA配置不当 渲染瓶颈 图层合成开销 刷新率不匹配 性能指标:FPS ↓ | 内存占用 ↑ | 加载时间 ↑ 任一环节出问题,整体体验都会崩

1.2 解码瓶颈:CPU的噩梦

解码是图片加载的第一关,也是最容易被低估的一关。你想想看,一张1920x1080的JPEG图片,压缩后可能只有200KB,但解码成RGB565原始数据,直接膨胀到 1920×1080×2 ≈ 4MB。如果是ARGB8888,那就是8MB。

我在一个STM32H7的项目上遇到过:用软件JPEG解码一张全屏背景图,耗时接近300ms。用户滑动页面时,每翻一页就要卡300ms,这谁受得了?

我的经验: 解码器选型很关键。硬件JPEG解码器(比如NXP i.MX系列、STM32MP1系列)能把解码时间从几百毫秒压到十几毫秒。如果芯片不带硬件解码器,那就得在图片尺寸和压缩格式上做取舍。

常见的解码问题:

  • 软件解码太慢——尤其是JPEG,DCT变换和霍夫曼解码都是CPU杀手
  • 解码缓冲区过大——临时内存不够,导致反复申请释放
  • 格式选错——PNG虽然无损,但解码比JPEG还慢,尤其是带alpha通道的

1.3 传输瓶颈:总线上的堵车

解码完的原始像素数据,得从内存搬到显示缓冲区。这一步看起来简单,但坑不少。

我记得有个项目用的是低端Cortex-M4,内部SRAM只有256KB。解码一张800x480的图片,RGB565格式,光原始数据就占800×480×2 ≈ 768KB。根本放不下!只能分块传输,每次传一小块到外部SDRAM,再刷到LCD。这一来一回,传输时间翻了好几倍。

传输方式 典型带宽 适用场景 注意事项
CPU逐像素拷贝 10~50 MB/s 小尺寸图片、低分辨率 CPU占用100%,卡顿明显
DMA传输 50~200 MB/s 中等尺寸、批量刷新 需要DMA通道,注意对齐
LTDC/DSI直接读取 200~500 MB/s 全屏刷新、视频播放 需要硬件支持,内存带宽要够

注意: 很多开发板标称的LCD接口速度是理论值。实际跑起来,总线仲裁、SDRAM刷新周期、DMA描述符开销都会吃掉带宽。我曾经测过一个方案,理论带宽400MB/s,实际传输大块数据时只有120MB/s——因为SDRAM的页命中率太低。

1.4 渲染瓶颈:最后一公里的坑

数据到了显示缓冲区,不等于就能流畅显示。渲染阶段的问题往往最隐蔽。

举个例子:你的GUI框架可能用了多层合成。背景一层、控件一层、弹窗一层。每次刷新都要把这三层叠在一起。如果每层都是全屏大小,那合成一次就要处理好几MB的数据。FPS能高才怪。

我见过最夸张的一个案例:某方案用软件做alpha混合,每帧要混合4层全屏ARGB8888图片。算下来,每帧要处理 800×480×4×4 ≈ 6MB 的数据。CPU主频才400MHz,FPS直接掉到15帧以下。

1.5 三个核心性能指标

衡量图片性能好不好,我一般只看三个数:

  • FPS(帧率)——低于30帧就能感觉到卡,低于20帧基本没法用
  • 内存占用——解码缓冲区、帧缓冲区、图层缓冲区,加起来不能超过系统可用内存的60%,否则GC或内存碎片会搞死你
  • 加载时间——从点击到图片显示,超过500ms用户就会觉得慢

我的经验阈值:

  • FPS ≥ 45:流畅
  • FPS 30~45:可接受
  • FPS < 30:必须优化
  • 加载时间 < 200ms:优秀
  • 加载时间 200~500ms:一般
  • 加载时间 > 500ms:不可接受

1.6 常见瓶颈速查表

做项目时,我习惯用这张表快速定位问题:

现象 可能瓶颈 快速验证方法
首次加载慢,后续快 解码瓶颈 测解码耗时,看CPU占用
滚动时卡顿 传输或渲染瓶颈 检查DMA配置,测帧合成时间
内存暴涨后卡死 内存泄漏或碎片 监控堆使用量,检查缓冲区释放
特定图片卡,其他不卡 图片格式或尺寸问题 对比不同格式、不同分辨率的解码时间

嗯,这一章先把全景搭起来。后面的章节,我会一个一个瓶颈拆开讲,包括怎么用硬件加速、怎么选图片格式、怎么优化内存布局。你先把这张图刻在脑子里——解码、传输、渲染,三个环节缺一不可。