图片压缩基础:有损 vs 无损压缩,色深与调色板,PNG/JPEG/BMP在嵌入式中的取舍

做嵌入式GUI,图片压缩是绕不开的坎。我见过太多项目,UI设计得花里胡哨,结果一跑起来,Flash不够、刷屏卡顿,最后只能砍功能。说白了,图片压缩就是在「画质」和「资源」之间找平衡。

这一章,我们先把基础打牢。搞懂有损和无损的区别,弄明白色深和调色板是怎么回事,再看看PNG、JPEG、BMP这三种格式在嵌入式里到底该怎么选。

有损 vs 无损压缩

压缩的本质,就是去掉冗余信息。但怎么去,区别很大。

  • 无损压缩:压缩后解压出来,跟原图一模一样。一个像素都不差。常见的算法有LZW、Deflate(就是ZIP用的那个)。
  • 有损压缩:丢掉一些人眼不太敏感的信息,换来更高的压缩比。解压后跟原图有差异,但肉眼可能看不出来。

我刚开始做GUI时,总觉得无损才是王道,毕竟「数据不能丢」嘛。后来发现,在嵌入式设备上,Flash空间比那一点点画质损失值钱多了。

核心原则:图标、文字、界面元素用无损;照片、背景图、渐变图用有损。

为什么会这样?你想想看,图标里一条直线,如果压缩后边缘糊了,用户一眼就能看出来。但背景图稍微模糊一点,谁会在意?

色深与调色板

色深,就是每个像素用多少位来表示颜色。这个参数直接决定了图片占多大空间。

色深 颜色数 每像素大小 典型场景
1-bit 2 0.125 字节 黑白屏、单色图标
4-bit 16 0.5 字节 低端彩屏、简单界面
8-bit 256 1 字节 索引色图片、小图标
16-bit 65536 2 字节 中端彩屏、照片
24-bit 1677万 3 字节 高端显示、真彩图片
32-bit 1677万+Alpha 4 字节 带透明通道的真彩图

调色板,也叫索引色。说白了就是一张颜色表,图片里每个像素存的是「颜色在表中的编号」,而不是颜色本身。比如8-bit调色板,一张图最多256种颜色,每个像素只占1字节,但能显示的颜色是从1677万里挑出来的。

我的经验:在STM32这类MCU上,8-bit索引色是最实用的。一张320x240的图片,24-bit要230KB,8-bit只要77KB。画质损失?只要调色板选得好,肉眼几乎看不出区别。

我曾经在一个智能家居面板项目上,把所有图标都转成了4-bit索引色。16种颜色够用吗?够。因为图标本身颜色就少,而且我手动优化了调色板,把最常用的颜色放进去。最终Flash占用减少了60%,刷屏速度还快了一倍。

PNG/JPEG/BMP 在嵌入式中的取舍

这三种格式,各有各的脾气。选错了,后面全是坑。

BMP:简单粗暴,但别用

BMP是最原始的格式,不压缩,或者只做简单的RLE压缩。每个像素直接存颜色值,读取时不需要解码,直接往显存里怼就行。

优点:解码快,几乎零CPU开销。
缺点:文件巨大。一张320x240的24-bit BMP,整整225KB。

我建议:除非你的MCU性能极差,Flash又大得离谱,否则别用BMP。现在Cortex-M4以上的芯片,解码PNG也就几毫秒的事。

JPEG:照片专用,图标别碰

JPEG是有损压缩的典型代表。它利用人眼对亮度敏感、对色度不敏感的特性,把色度信息丢掉一大半。

优点:压缩比极高,照片可以压到原来的1/10甚至1/20。
缺点:有损,边缘会有振铃效应,文字和图标会糊。

我记得有一次,客户非要把一个带小字的界面存成JPEG,说「文件小」。结果上屏一看,字都糊成一团了。最后我给他改成PNG,文件大了30%,但字清晰了。

避坑指南:JPEG不适合包含文字、线条、图标的界面元素。只适合照片、渐变背景、纹理这类对细节要求不高的图片。

PNG:嵌入式GUI的万金油

PNG是无损压缩,支持索引色和真彩色,还带Alpha通道。它的压缩算法是Deflate,跟ZIP一样。

优点:无损,支持透明,压缩比适中。
缺点:解码比BMP慢,文件比JPEG大。

但说实话,在嵌入式GUI里,PNG是最常用的。为什么?因为GUI里的图片大多是图标、按钮、背景,这些都需要清晰边缘和透明效果。JPEG做不到,BMP太大,只有PNG最合适。

我个人习惯:所有UI元素都存成PNG,而且尽量用8-bit索引色。如果必须用真彩色,比如显示照片,才考虑JPEG。

格式对比一览

特性 BMP JPEG PNG
压缩方式 无/简单RLE 有损 无损
支持透明 否 否 是(Alpha通道)
索引色 支持 不支持 支持(1-8-bit)
解码复杂度 极低 中 中高
文件大小 极大 小 中
适用场景 极少用 照片、背景 图标、界面、透明图

知识体系图

下面这张图,把本章的核心逻辑串起来了。从原始图片开始,经过压缩方式、色深选择、格式取舍,最终落到嵌入式应用场景。

图片压缩基础知识体系 图片压缩基础 · 知识体系 原始图片 有损压缩 无损压缩 高色深(24/32-bit) 索引色(8-bit) 低色深(1/4-bit) JPEG PNG-24 PNG-8 BMP 照片 / 背景图 图标 / 按钮 / 界面 极少使用 核心取舍原则 图标/界面 → 无损 + 索引色 + PNG | 照片/背景 → 有损 + 高色深 + JPEG