2、PNG格式详解:压缩原理、索引色与Alpha通道

好,咱们进入第二个章节。上一章聊了图片格式选型的大框架,这一章我打算把PNG这个格式彻底讲透。为什么?因为在我做过的TouchGFX项目里,PNG几乎是最常用的图片格式,没有之一。但很多人用PNG只是因为它“支持透明”,至于它怎么压缩的、什么时候该用索引色、什么时候该用真彩色,其实没搞太清楚。

嗯,今天咱们就把这些掰开揉碎了讲。你理解透了PNG,后面选格式的时候心里就有底了。

2.1 PNG压缩原理:它到底是怎么把图片变小的?

PNG用的是无损压缩。说白了,就是压缩完的图片解压回来,跟原始数据一模一样,一个像素都不差。这一点跟JPEG那种“看着差不多就行”的思路完全不同。

PNG的压缩分两步走:

  1. 预过滤(Delta Filtering)——把像素数据转换成更容易压缩的形式
  2. Deflate压缩——用LZ77算法+Huffman编码做真正的压缩

我刚开始研究PNG的时候,觉得预过滤这步挺玄乎的。后来自己写了个小工具测试才明白——它其实就是把每个像素的值改成“跟左边/上面/左上角像素的差值”。你想啊,一张渐变图,相邻像素差别很小,差值就趋近于0,一堆0扔给Deflate压缩,效果自然好。

核心要点:PNG的无损压缩对“平坦区域”效果极佳,但对“高频细节”(比如照片、复杂纹理)压缩率有限。这也是为什么纯色UI图标用PNG很小,但照片级背景用PNG会很大。

PNG定义了5种过滤模式:None、Sub、Up、Average、Paeth。编码器会为每一行像素自动选择最优模式。我个人习惯在TouchGFK资源导出时,让工具自动选择——手动指定反而容易翻车。

2.2 索引色与真彩色:两种截然不同的色彩模式

这是PNG里最容易被忽视的一个知识点。很多人不知道,PNG其实有两种“玩法”。

2.2.1 索引色(Indexed Color,PNG-8)

索引色模式,说白了就是给图片建一个“调色板”。图片里最多只有256种颜色,每个像素存的是颜色在调色板里的编号,而不是颜色本身。

举个例子:一张图标只有红、白、灰三种颜色。用真彩色存,每个像素要3个字节(RGB)。用索引色存,每个像素只要1个字节(索引号),外加一个3×3字节的调色板。省了多少?你自己算算。

对比项 索引色(PNG-8) 真彩色(PNG-24/32)
颜色数量 最多256种 1600万+
每像素位数 1、2、4或8 bit 24 bit(RGB)或32 bit(RGBA)
文件大小 通常很小 较大
适用场景 图标、按钮、简单图形 照片、渐变、复杂图像

我在项目中遇到过一个坑:某次做智能家居面板,图标用了索引色PNG,在PC上看完全正常。烧到设备上一看,某些颜色出现了明显的色块和条纹。后来排查发现,是调色板排序跟TouchGFX的渲染引擎不兼容。从那以后,我养成了一个习惯——索引色图片导出后,一定在目标设备上预览一遍。

我的建议:如果你的UI图标颜色数不超过32种,果断用索引色。TouchGFX对索引色PNG的支持很成熟,能省下大量Flash空间。但记得把调色板优化模式设为“可感知”或“选择性”,别用“随性”。

2.2.2 真彩色(True Color,PNG-24/32)

真彩色就是每个像素直接用RGB或RGBA值表示。PNG-24是24位(RGB各8位),PNG-32是32位(RGBA各8位)。

什么时候必须用真彩色?

  • 图片包含连续渐变(比如按钮的阴影效果)
  • 图片是照片或渲染图
  • 颜色数超过256种

但要注意,真彩色PNG的文件体积通常比索引色大3-10倍。你想想看,一张480×272的全屏背景图,用PNG-32存,原始数据就有480×272×4≈522KB,压缩后一般也在200-400KB。如果你的Flash只有8MB,几张背景图就塞满了。

2.3 Alpha通道与透明度:PNG的杀手锏

PNG支持透明度,这是它能在UI领域称王的关键。但透明度也分两种:

  1. 二值透明度——要么全透明,要么全不透明。索引色PNG支持这种。
  2. 半透明度——每个像素有0-255的透明度级别。只有真彩色PNG-32支持。

为什么半透明这么重要?你想想看,一个按钮的圆角阴影、一个弹窗的毛玻璃背景、一个图标的抗锯齿边缘——这些都需要半透明才能实现平滑效果。

我曾经犯过一个低级错误:用PNG-24存了一个带阴影的图标,结果阴影边缘全是锯齿。折腾了半天才发现,PNG-24根本没有Alpha通道,阴影信息全丢了。换成PNG-32,问题立刻解决。

注意:TouchGFX对Alpha通道的处理方式跟PC浏览器不太一样。PC上PNG的Alpha是预乘的(Premultiplied Alpha),但TouchGFX默认使用非预乘(Straight Alpha)。如果你在Photoshop里导出时选了“预乘”,到TouchGFX里颜色可能会偏暗。我建议统一用“非预乘”导出。

2.4 PNG在TouchGFX中的优势与局限

做了这么多年嵌入式GUI,我对PNG的感情很复杂——它好用,但也不是万能的。

优势

  • 无损质量:UI元素边缘清晰,没有JPEG那种振铃效应
  • 完美透明:支持0-255级Alpha,实现平滑抗锯齿和阴影
  • 索引色优化:对图标类资源压缩率极高
  • 解码速度快:相比JPEG,PNG解码不需要浮点运算,在MCU上更友好
  • 工具链成熟:Photoshop、Figma、GIMP都能直接导出,不需要额外转换

局限

  • 文件体积大:照片级背景图用PNG,Flash很快就爆了
  • 不支持动画:动态图标得用GIF或Lottie,PNG搞不定
  • 解码内存开销:PNG解码需要额外的内存缓冲区,在RAM紧张的MCU上是个挑战
  • 索引色兼容性:某些编码器生成的索引色PNG,TouchGFX解析会出问题

我的经验法则:图标、按钮、小控件用PNG(优先索引色);全屏背景、照片用JPEG;需要动画的用Lottie或GIF。这个原则帮我省了至少30%的Flash空间。

2.5 PNG在TouchGFX中的知识体系

下面这张图是我整理的PNG知识结构,帮你快速建立全局认知:

PNG格式知识体系 PNG格式 压缩原理 预过滤(Delta Filtering) Deflate压缩(LZ77+Huffman) 色彩模式 索引色(PNG-8,≤256色) 真彩色(PNG-24/32) Alpha通道 二值透明度(索引色支持) 半透明度(PNG-32支持) TouchGFX中的应用策略 优势:无损、透明、解码快 局限:体积大、无动画 选型建议:图标用PNG

这张图把PNG的核心知识点串起来了。你从中心往外看:压缩原理是底层机制,色彩模式和Alpha通道是两种核心特性,最终都落到TouchGFX的应用策略上。搞懂这些,你选格式的时候就不会拍脑袋了。