每个像素只分到 6 个时钟周期。在树莓派 Pico 2 搭载的 RP2350 芯片上,微控制器需要实时输出 DVI 信号。图像数据必须一边解压,一边送入扫描线缓冲。留给内核的解码时间,仅够执行一次读取、一次查表与一次写出。
这个极小预算直接淘汰了主流格式。标准 JPEG 解码即便手写汇编,单像素也需数百周期,且严重消耗内存。图形专家 Raph Levien 采取反向推演。他设计出 nibnib 格式,将解压过程固化为 4 行极简指令。
6 个周期压出 4 行内循环
微控制器直出数字视频信号。显示通道对时序要求极高,行扫描没有等待解压的停顿时间。每发射一个像素,数据总线就要在固定周期交付色彩数值。
设计者必须先写出解码汇编,再反推文件格式。nibnib 解码内循环精简至极:从输入流读 1 个字节,直接产出 2 个 16 位 RGB565 像素。整幅图像保持固定的 4bpp 存储密度。固定码率免去了偏移索引表,芯片能直接按步长寻址任意扫描行。
图:nibnib 的解码数据流——上一个像素被复制成 32 位,加上调色板里的差值,一次产出两个 RGB565 像素。来源:Raph Levien。
解码内循环仅包含 4 行 Rust 源码。核心逻辑直接映射到底层的单周期寄存器加法:
for x in 1..(width / 2) {
let inp = src[x + 3];
pix = ((pix >> 16) * 0x10001).wrapping_add(pal[inp as usize]);
out[x * 2] = pix & 0xffff;
out[x * 2 + 1] = pix >> 16;
}
代码展现了简洁的无分支流水线。前一像素被复制为两组 16 位数值,与调色板差值执行一次无符号加法。低 16 位直接作为左侧像素输出。高 16 位既作为右侧像素输出,又留给下一次迭代累加。
内循环去掉了所有动态条件跳转。它省去了色彩重采样,直接与内存写入机械咬合。这把解码开销压到了等同于内存拷贝的级别。
差值调色板抹平低色阶断层
4bpp 格式若用全局调色板,整图仅有 16 色。即使按行切分调色板,平缓渐变处仍会出现粗糙断层。低色深难以表现大面积的柔和阴影。
nibnib 的关键创新在于重构调色板的物理定义。调色板包含 256 项 32 位数据,存放相邻像素的增量差值。每个索引字节对应一对色彩变化量。前一个像素的色彩沿着扫描线不断累加前行。
图:测试原图 flowers7。来源:Raph Levien。
微分机制让调色板能以细腻步长贴合渐变。遇到剧烈边缘时,算法调用大差值表项快速跨越。有限的 256 个增量向量,在微控制器上重现了丰富的渐变轨迹。
这种增量思路源自复古图形架构。当年 Amiga 电脑的 HAM 模式曾用 6 比特索引改写色彩分量,呈现出 4096 色。nibnib 把这一策略注入现代微控制器总线。它用极低码率换来了生动的色彩过渡。
联合误差分配贴合人眼视觉感知
增量累加容易引起误差发散。如果编码时只贪婪匹配单点增量,微小舍入会在扫描线上逐步放大。整行色彩会向不可控方向偏色。
为了消除漂移,编码器引入了 Floyd-Steinberg 误差扩散算法。传统单点扩散无法处理一次产出双像素的结构。编码器转而同时评估相邻两点的联合误差。它在 256 个差值条目中展开穷举匹配。
图:纯随机调色板下的编码结果,边缘产生明显拖尾伪影。来源:Raph Levien。
图:引入 delta 颜色立方体后的效果,灰阶与平滑区域过渡恢复自然。来源:Raph Levien。
人眼视觉感知成为损失函数的约束核心。人眼对大面积低频亮度格外敏感,对微小高频噪点相对迟钝。编码器计算误差时,对两像素之和施加更高的惩罚权重,对两像素之差放宽公差。
调色板的构建兼顾了数值稳定性。它融合了高斯分布采样的随机离散值,并强制嵌入一个三维差值立方体。立方体确保极小变动与满量程差值随时可达。这杜绝了灰阶坏死与数值溢出。
非对称搜索换取极速解压
经典多媒体格式通常追求编解码对称性。JPEG 的离散余弦变换具备数学可逆性,压缩与解压耗时处于同一数量级。这种均衡在 PC 和服务器时代备受推崇。
nibnib 主动打破了对称平衡。解码端只保留 6 周期的极简指令,搜索负担全部转嫁给编码端。为了找出最优码字,编码器在三维空间中多维聚类,对全图扫描线展开暴力搜索。
编码耗时比解码过程慢了几个数量级。在开发机上编码一张中等尺寸测试图需要几秒钟,微控制器解压只需数毫秒。这种算力倾斜恰好满足了嵌入式场景的需求。
静态资源在固件编译期只压缩一次。部署后,它会在海量芯片上被反复实时读取。把计算开销前置到离线端,终端换取直接输出,这是受限环境下的解法。
单片机专用结构撞上现代桌面流水线
专用设计的优势难以平移到通用平台。nibnib 引起广泛讨论后,部分工程师探讨它在桌面 CPU 上替代标准格式的前景。
项目作者给出了明确的否定意见。nibnib 内循环存在强烈的像素串行依赖,前组像素直接作为后组的累加基数。这种串行链路打断了现代桌面 CPU 的超标量乱序执行与向量化并行通道。
桌面 CPU 拥有深流水线与宽执行单元,更青睐基于分块并行的 SIMD 指令。在 x86 或高端 ARM 上,向量化解码吞吐远高于标量加法。nibnib 本质上是一枚为低成本微控制器打造的专用齿轮。
文件规格处处体现着克制。文件头仅占用 2 字节宽度、2 字节高度与 256 个调色板项,行跨距补齐至 4 字节边界。它不存储扩展元数据,更不适合用于长期归档。它的使命仅是在闪存与显示屏之间搭建一条极短链路。
硬件预算压到 6 个周期时,格式设计原则发生倒置。微控制器总线时序直接雕刻数据排布,不再维持通用数学自洽。算法复杂度全部交由离线环境承担。微控制器借此在微秒内交付像素。
参考链接:
- Raph Levien 的 nibnib 开源仓库与技术说明。
- vic-2350 图像演示工程与 RP2350 DVI 驱动。
- Hacker News 社区关于微控制器超轻量图像格式的讨论。