
2026/10/30 13:17
Nibnib:解凍速度が極めて高速な画像圧縮
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
nibnib イメージ形式は、RP2350 マイクロコントローラ上で高速かつ決定論的なデコードを目的とした専用圧縮方式である。入力バイト 1 つあたり 2 ピクセルの並列デコードを行い、約 6 クロックサイクルで 1 ピクセル当りのデコードを完了し、4bpp の圧縮比を実現する。絶対値カラーを保持する標準的なパレット形式とは異なり、nibnib はパレットにカラーデルタを格納し、Floyd-Steinberg エラー拡散法を用いて人間の視覚感度特性をモデル化することで滑らかな領域での画質向上を図る。デコード処理は完全に決定論的であり、直前までにデコードされた最終ピクセルを 2 倍とし、ストリームからバイトを読み込みパレットでアップルックして加算し、入力バイト 1 つあたり 2 ピクセルの 16bpp(RGB 565)を生成する。一方、エンコーディングは非対称であり大幅に低速である。可能となるパレットとコードワードの組み合わせに対して探索を行い、立方体を小さなデルタ値および加重付きガウスランダムエントリで構成した初期化から始め、高品質な複製へデコード可能なエンコーディングを選択する。その貪欲的な左から右への探索手法のため、現時点ではシャープなエッジの右側に残留アーティファクトが生じるが、将来のバージョンでは右から左またはブーストロホン方式によるエンコーディングによりこの影響を低減することが可能である。イメージのレイアウトは、2 バイトで幅と高さを格納するヘッダー、256 エントリの 32 ビットパレット、そして各行が 2 ピクセルに続き ((width − 2)/2) バイトのパレットインデックスを持つ構成となっている。追加的なメタデータフィールドは存在せず、この形式はアーカイブストレージではなくリアルタイムレンダラーとの緊密な統合を意図している。元々 RP2350 での DVI 出力実験として開発された nibnib は、Apache License 2.0 または MIT ライセンスのいずれかを選択して vic-2350 リポジトリで入手可能である。
本文
Nibnib:極限デコード速度向け画像フォーマット
Nibnib は、RP2350 微制御装置における DVI 出力画質とパフォーマンスを最大化することを目的として開発された画像フォーマットです。低ビット深度のパレット方式を採用しつつも、パレットよりも優れる画質を実現する技術です。
概要と特徴
- 開発背景: RP2350 での DVI 出力において、約1 ピクセルあたり 6 サイクルの厳格な予算内での動作を実現するため考案されました。
- パレット方式の進化: 従来の「ピクセルごとのパレット Lookup」ではなく、デルタ値(差分)を格納することでソフトなグラデーション表現を劇的に改善します。
- 高速化機構: 入力データを 1 バイトで2 ピクセル分同時にデコードする仕組みにより、4bppの圧縮率を実現しています。
動作原理
デコードプロセスはシンプルかつ決定論的(非ランダム)です。エンコーディング側には多数の選択肢があるため、両者は非対称な関係にあります。
デコードアルゴリズム
- 処理単位: ピクセルペアごとに処理されます。
- 手順:
- 直前のデコード済みピクセルを複製。
- 入力ストリームから 1 バイトを読み出し、パレットで Lookup(色値取得)。
- 取得した 32 ビット分の値を、複製された前回のピクセルに足し合わせます。
- 低位の 16 ビットが左側のピクセル、上位の 16 ビットが右側のピクセルとなります(RGB565 フォーマット)。
実装例 (Rust)
RP2350 向けのオンザフライデコーダー実装は、
vic-2350 リポジトリに含まれています。以下は内側ループのロジックです。
// まず最初の 2 ピクセルを src[0..4] からコピーし、pix を初期化 for x in 1..(width / 2) { let inp = src[x + 3]; // 左シフトとパレット値の加算により RGB565 値を生成 pix = ((pix >> 16) * 0x10001).wrapping_add(pal[inp as usize]); // 低位 16 ビット(左ピクセル)と上位 16 ビット(右ピクセル)を抽出して出力 out[x * 2] = pix & 0xffff; // 左側 out[x * 2 + 1] = pix >> 16; // 右側 }
エンコーディングについて
エンコーディングは「可能なすべての画像空間を検索し、元の画像に最も近づくものを見つける」というアプローチをとります。これにより、JPEG の数学的逆変換とは異なり、エンコーディング速度がデコーディングの数桁遅いのが現状です。
検索の 2 つの次元
- パレットの選択
- 小規模なデルタ値の立方体と、重み付きガウス分布によるランダム値のブロックから構成されます。
- 構造はゼロ付近やフルスケール近傍でのオーバーフロー防止のために不可欠です。
- コードワード(パレットインデックス)の選定
エラー拡散の工夫
- 手法: Floyd-Steinberg エラー拡散法を採用しています。
- 特徴:
- 通常は 1 ピクセルずつ処理するが、Nibnib は同時に 2 ピクセル生成。
- パレットエントリ選択時には、両方のピクセルのエラー最小化を図りつつ、和に対して差よりも高い重みを付与しています(人間の視覚系が低い空間周波数に敏感であることのモデル化)。
将来の改善点
現在のバージョンは基本的ながら動作する技術ですが、さらに画質を向上させる余地があります。
- 検索アルゴリズムの高度化:
- 現在「貪欲法(グリードイアルゴリズム)」を採用していますが、これによりシャープなエッジの右側にアーティファクトが残ります。
- デコーディング方向は左から右ですが、エンコーディングを右から左へ(または行ごとに方向を交互に変えるブーストロホドン方式)に変更可能であり、足し算ステップ自体は実用上反転可能です。
- 探索の深化:
- 「大まかに同等のエラーを持つ選択」の中から、次のピクセルの探索を有利にするものを優先するなどのより深い探索が可能です。
- 速度向上:
- パレットエントリに対するブラストフォース(総当たり)探索を改善したり、パレット構造を工夫したりすることで、エンコーダー自体を高速化しつつ、デコーディング速度への影響を与えずに画質を向上させるアプローチが期待されます。
フォーマット仕様
極めて素朴な設計となっています。
- ヘッダ: 幅と高さはそれぞれ 2 バイト(計 4 バイト)。
- パレット: 次いで 256 個の 32 ビットパレットエントリが続きます。
- ピクセルデータ: 行順に配置されます。
- 各行は**2 ピクセル(RGB565 フォーマット)**から始まり。
- その後
バイト分のパレットへのインデックスが続きます。((width - 2) / 2)
- Stride: 行 stride は 4 バイトの倍数に丸め上げられています。
- 用途: メタデータは他になく、アーカイブ用途ではなく、デコーダーと密に連携することを想定しています。
ライセンス
本ソフトウェアは以下のいずれかのライセンスの下で提供されます(ご自由にお選びください)。
- Apache License 第 2.0 版
- ファイル:
または http://www.apache.org/licenses/LICENSE-2.0LICENSE-APACHE
- ファイル:
- MIT License
- ファイル:
または http://opensource.org/licenses/MITLICENSE-MIT
- ファイル: