一、一句话理解
调色板是一张"颜色表"。图像里的每个像素不直接存颜色,只存一个编号(索引),真正的颜色要拿编号去调色板里查。
可以类比"按编号涂色"的填色画:画上只写着 1、2、3……,旁边有一张对照表写着"1 = 红,2 = 绿,3 = 蓝"。
这种图像叫索引色图像(Indexed Color),PNG 中对应颜色类型 3。
二、具体内容
1. 调色板本身
调色板是一个数组,每一项是一种颜色:
索引 R G B ──────────────────────── 0 255 0 0 红 1 0 255 0 绿 2 0 0 255 蓝 3 255 255 255 白 ... 255 ... ... ... 最多 256 项- 在 PNG 中,调色板存放在PLTE 块里,每项 3 字节(R、G、B),最多 256 项,所以块长度最大为 768 字节。
- 透明度单独存放在tRNS 块里,按顺序给每一项提供一个 Alpha 值。tRNS 可以比调色板短,没写到的项默认 Alpha = 255(不透明)。
2. 像素数据
像素数据里每个像素只是一个索引值:
像素数据(4×2 的小图): 0 0 1 1 2 2 3 3 查表后的实际颜色: 红 红 绿 绿 蓝 蓝 白 白索引的位数决定了调色板最多能用多少项:
| 位深 | 每像素占用 | 最多颜色数 |
|---|---|---|
| 1 位 | 1/8 字节 | 2 |
| 2 位 | 1/4 字节 | 4 |
| 4 位 | 1/2 字节 | 16 |
| 8 位 | 1 字节 | 256 |
这也是 PNG 规定调色板图不能是 16 位的原因:16 位索引意味着 65536 项调色板,已经失去意义。
三、作用
1. 节省空间(最主要的作用)
以一张 1000×1000 的图为例:
| 存储方式 | 像素数据大小 |
|---|---|
| RGB 真彩色,每像素 3 字节 | 约 3 MB |
| RGBA,每像素 4 字节 | 约 4 MB |
| 8 位调色板,每像素 1 字节 + 768 字节调色板 | 约 1 MB |
| 4 位调色板(16 色) | 约 0.5 MB |
数据量少了,再经过 Deflate 压缩后文件也更小。
2. 适合颜色少的图像
图标、Logo、像素画、简单的界面图、图表等,本来就只有几种到几十种颜色,用调色板几乎没有损失。
照片就不合适:照片可能有几十万种颜色,压缩到 256 色必然失真(出现色带、需要抖动)。
3. 历史原因:显卡硬件
早期显卡(如 VGA 的 256 色模式)显存很小,硬件本身就按"索引 + 调色板"工作。改调色板就能让整个画面变色,老游戏常用这个技巧做"调色板动画",比如水流、闪烁效果,不用改任何像素。GIF、BMP、PCX 等老格式都保留了调色板设计。
四、stb_image 怎么处理调色板
stb 的原则是:输出永远是直接的颜色值,不把调色板交给用户。
文件中: PLTE(颜色表) + tRNS(可选的 Alpha) + 像素索引 ↓ stbi__expand_png_palette 输出: 每个像素直接是 RGB 或 RGBA具体过程(对应上一篇 PNG 第四、八节):
- 读 PLTE:存进
palette[1024],即 256 项 × 4 字节(RGBA),Alpha 先填 255。 - 读 tRNS:把 Alpha 填进对应项,并把输出通道数从 3 改成 4。
- 反滤波:此时每像素只有 1 个通道,就是索引。低位深时不做 0~255 的放大,因为索引必须保持原值。
- 展开:逐像素查表:
for(i=0;i<pixel_count;++i){intn=orig[i]*4;// 索引 × 4 = 该颜色在表中的位置p[0]=palette[n];// Rp[1]=palette[n+1];// Gp[2]=palette[n+2];// Bif(pal_img_n==4)p[3]=palette[n+3];// Ap+=pal_img_n;}所以对使用者来说:
- 调色板 PNG 加载后,
comp报告的是3(无 tRNS)或4(有 tRNS),而不是 1; - 拿不到原始索引和调色板。如果确实需要索引(例如做像素画编辑器、要改调色板),stb_image 做不到,需要用 libpng 或 lodepng 等库。
五、其他格式里的调色板
| 格式 | 调色板情况 |
|---|---|
| PNG | PLTE 块,RGB;透明度放在 tRNS 块 |
| GIF | 必须使用调色板,最多 256 色;有全局调色板,每帧也可以有局部调色板;透明用一个"透明索引"表示 |
| BMP | 1/4/8 位图在文件头后跟调色板,每项 4 字节,顺序是B、G、R、保留 |
| TGA | 可选的颜色映射表(Color Map),项可以是 15/16/24/32 位 |
| PSD、JPEG | JPEG 不支持调色板;stb 的 PSD 解码只处理 RGB 等直接颜色模式 |
stb 对这些格式都是一样的做法:解码时查表展开,输出直接的颜色值。
六、总结
| 问题 | 答案 |
|---|---|
| 调色板是什么 | 一张颜色表,像素存索引,用索引查表得到颜色 |
| 内容是什么 | 最多 256 项 RGB 颜色(PNG 的 PLTE),可选配每项的 Alpha(tRNS) |
| 有什么作用 | 节省存储空间;适合颜色少的图;早期硬件的工作方式 |
| 缺点 | 最多 256 色,不适合照片 |
| stb 怎么处理 | 解码时展开成 RGB/RGBA,用户拿到的是直接颜色,拿不到索引 |