分享到微信

当前解读页的微信分享二维码

用微信扫一扫打开,点击右上角「···」分享给朋友或朋友圈。

手机上可截屏后,在微信扫一扫中从相册识别二维码。

raphlinus/nibnib

多媒体与设计

面向微控制器实时显示的 4bpp 图像格式,解码器极小且确定,适合在像素预算紧张时按行输出。

121
5
Rust
Apache-2.0
创建于 3 天前

项目介绍

nibnib 是一个把解码速度放在首位的图像格式,而非追求压缩率。它源于 RP2350 微控制器上的实验:每像素大约 6 个周期的预算,刚够取像素、查调色板并写入行缓冲。格式仍以调色板为核心,但每个表项存的是增量而不是绝对颜色,因此在柔和区域比普通调色板图像质量更好。

解码是确定性的:把上一个已解码像素复制成 32 位值,读入一个字节,加上对应的 32 位调色板项,就得到两个 16bpp RGB 565 像素。一个输入字节出两个像素,也就是 4bpp。编码则是慢的一侧:它要在调色板和码字空间里搜索,并用 Floyd-Steinberg 误差扩散把量化误差分摊给后续像素。

它面向的是在小型 MCU 或固定功能显示路径上做紧凑图像管线的人,而不是需要通用照片格式的用户。

快速使用

仓库目前没有现成的命令行工具,也没有完整的编码/解码操作说明。使用格式可从仓库中的 Rust 源码和 README 描述的解码内层循环入手:

// first two pixels copied from src[0..4], initializing pix
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;
}

输入流布局是固定的:2 字节宽、2 字节高、256 个 32 位调色板项,然后按行排列。每行先有两个 RGB 565 像素,再接 (width - 2) / 2 个调色板索引,行跨度向上补齐到 4 字节的倍数。想在硬件上跑,RP2350 的实时解码器在 vic-2350 项目的 image 示例里;作者提到在 Adafruit Fruit Jam 板上可以从 SD 卡以 60fps 串流 640x480 视频,或从 flash 显示静态图。

使用约束

  • 格式只有尺寸和调色板,没有其他元数据,明确不用于归档存储。
  • 当前编码器比解码慢几个数量级,而且不是自适应的:调色板由固定的小增量立方体加随机高斯值组成,并不根据输入图像生成。
  • 编码搜索是贪心的,锐利边缘右侧会留下伪影;README 把从右到左或逐行交替方向编码列为后续改进方向。
  • 解码器与 16bpp RGB 565 输出绑得很紧,集成位置通常在显示路径附近。
  • 许可证可选 Apache-2.0 或 MIT。

HotRepo 点评

这个格式一出现就有明确的目标场景和公开讨论,而不是一个打磨完成的发布版。2026-11-02,仓库进入 Rust 新项目榜记录,在约三小时的窗口内新增 14 个 Star,总计 114 Star、5 个 Fork。2026-10-30 的 Hacker News 讨论获得 149 分和 24 条评论。

讨论有助于判断定位:有人质疑强调解码速度却没有和 JPEG 对比;也有人认为目标是那些无法实时解码 JPEG 的平台,并给出每像素约 6 条指令的说法。同一讨论中,作者指向 Fruit Jam 演示,并说明 RP2350 解码器用 symbolasm 写成。因此实际评估应看解码器是否适合固定显示管线,因为编码速度和画面质量都还处在早期阶段。

项目源码与说明

本文由 AI 根据项目 README 生成,更新于 ,以项目官方文档为准。

Hacker News 讨论

Nibnib: Image compression with extreme decompression speed
▲ 149 · 24 条评论 · 2026年10月30日