
2026/10/15 3:53
PNG(2022)のデコード処理における各ステップ
RSS: https://news.ycombinator.com/rss
要約▶
日本語翻訳:
PNG ファイルは、4 バイトの長さフィールド、4 バイトの名前、データ内容、および誤り検出用の CRC から構成されるチャンクのシーケンスとしてデータを格納します。チャンク名の大小文字でその役割が決定され、大文字の場合には重要または公開済み(予約済み)なチャンクを示し、小文字の場合には補助的・私用・非安全なチャンクを示します。ファイルは 13 バイトのメタデータを含む IHDR チャンクで始まり、幅 (256)、高さ (256)、ビット深度 (8)、カラー空間 (Truecolor RGB)、圧縮方式 (0)、フィルタリング方式 (0)、インターレース(無効)、に続き、圧縮・フィルタリングされた画素データを保持する 1 つ以上の IDAT チャンクが続きます。例示の画像では、単一の IDAT チャンクが 62,801 バイトあります。ファイルは長さがゼロの IEND チャンクで終わり、CRC AE 42 60 82 で PNG の終了を示します。
画像を再構築するには、すべての IDAT チャンクをつなぎ合わせ、zlib で圧縮された生データとして扱い、標準的な zlib での展開を実行します。展開された各行は、zlib の圧縮性を高めるために画素値を補正するフィルタバイトで始まり、展開後は、5 つの方法(なし (0)、引き算 (23)、上方向 (77)、平均 (134)、Paeth (22))の一つを使用してこのフィルタを除去(デフィルタリング)する必要があります。例示では、最も頻繁に使用されたフィルタは Average (134) で、次に Paeth (22) でした。画像がインターレース形式の場合、Adam7 シーケンスに従って 7 パスに分けて読み込まれ、詳細が徐々に明らかになります。インターレース画像では水平方向の詳細が強調されており、これは人間の視覚知覚が長方形構造について水平方向の詳細を垂直方向よりも優先するためです。
本文
PNG ファイルのデコードプロセス解説
PNG ファイルはチャンクの系列として構成されています。各チャンクには以下の 4 つの要素が含まれます。
- 長さ情報: 4 バイト
- 名前: 4 バイト
- 実際のデータ: バイナリデータ
- CRC 値: チェックサム
チャンクの分類と重要性
チャンク名の文字ケース(大文字・小文字)によって、その役割が定義されます。
| カテゴリー | 大文字 (UPPERCASE) | 小文字 (lowercase) |
|---|---|---|
| Critical(必須) | 画像表示に必須 | プライベート、アプリケーション固有 |
| Public(公開) | 公的標準仕様 | リザーブ済み |
| Reserved(予約) | プログラムが理解する必要あり | セーフなコピーが可能 |
使用されているチャンク一覧
1. チャンク表示 (Signature & Metadata)
ファイルが PNG 形式であることを示すヘッダーです。改行文字を含む特定のバイト列(
89 50 4E 47 0D 0A 1A 0A)が含まれており、バイナリデータの破損を防止するための意図的な設計です。
以下のメタデータチャンクが存在します:
- 長さ:
(13 バイト)00 00 00 0D - タイプ:
(IHDR)49 44 48 52 - データ内容:
- 幅:256
- 高さ:256
- ビット深度:8
- 色空間:Truecolor RGB
- 圧縮方式:0 (Deflate)
- フィルター方式:0 (None)
- インタレース:無効
- CRC:
D3 10 3F 31
2. IDAT チャンク (Compressed Image Data)
圧縮された実際の画像データを保持します。今回のサンプルでは単一の IDAT チャンクのみが含まれていますが、一般的な PNG では複数のチャンクが連結されることもあります。
- 長さ:
(62,801 バイト)00 00 F5 51 - タイプ:
(IDAT)49 44 41 54 - データ内容: 圧縮およびフィルタリング済みの画像データ(ここでは省略)
- CRC:
BF EB 1B 15
3. IEND チャンク (End of File)
PNG ファイルの終了を示す空のチャンクです。
- 長さ:
(0 バイト)00 00 00 00 - タイプ:
(IEND)49 45 4E 44 - CRC:
AE 42 60 82
画像データの抽出
デコードプロセスの最初のステップです。
- 全 IDAT チャンクのデータを順次連結します。
- ※今回のサンプルは 1 つのみですが、複数の場合も存在します。
- ストリーミング対応: チャング先頭の長さ情報があるため、総データ長を事前に把握せずに処理できます。
- サイズ制限: 画像データが最大チャンクサイズ(65,535 バイト)を超える場合、自動的に複数の IDAT チャンクに分割されます。
圧縮データの特性確認 IDAT の生データを直接表示すると「ランダムノイズ」のように見えます。これは以下の理由によるものです:
- 高エントロピー: 圧縮アルゴリズムが正しく動作しており、元の低エントロピーデータからエンタープライジが高くなっているためです。
- 高効率な圧縮: データ量が画像の 3 分の 1 以下 にまで圧縮されているため、優れた圧縮効果が得られています。
非圧縮化(デコンプレッション)
IDAT チャンクのデータを zlib アルゴリズムを使用して解压処理します。
- アルゴリズム: 通常の zlib 圧縮のみ使用(画像固有の特殊メカニズムは関与しません)。
- フィルターの役割: フィルターは画像サイズを直接削減するものではなく、zlib においてより効率的な形式に変換するためのものです(詳細は PNG フィルタ関連記事 を参照)。
※圧縮解除後の状態 この段階では以下の異常現象が観察されます:
- 色調が全体的に不自然に見える。
- 画像全体が水平方向に歪んで見える。
- 原因: 各スキャンラインの先頭には、フィルタ値(1 バイト)が含まれているためです。
デフィルタリング
非圧縮化されたデータに対し、各行ごとのフィルタを逆処理して復元します。これにより元の画像が得られます。
フィルタータイプの使用頻度統計
- None (無効):
0 - Subtract (引き算):
23 - Up (上方向):
77 - Average (平均):
134 - Paeth:
22
インタレース処理(Adam7)
PNG はオプションでインタレース方式を採用し、画像を 7 つの部分画像に分割して表示します。これにより、低解像度の状態から徐々に詳細な情報が増えるように表示されます。
- 呼称: この部分画像の系列は 「Adam7」 と呼ばれます。
- データ格納: 各部分画像のデータはファイル内で連続して格納されます。
- パス構造: 抽出可能な 7 つの走査順(パス)は以下の順序です:
- パス 1
- パス 2
- パス 3
- パス 4
- パス 5
- パス 6
- パス 7
表示上の特性
- サブ画像の一部は長方形の形状をとりますが、最終的な画像は四角形になります。
- 水平方向の優先: 読み込み時に水平方向の詳細情報が垂直方向よりも多く認識されます。これは人間の視覚感知において水平方向の詳細の方が重要であるためです。
付録:バグについて
平均フィルタ(Average filter)の実装において、整数オーバーフローを不適切に処理する場合があります。
- 仕様: 整数オーバーフローの扱いは、他の計算ルールとは異なる仕様が適用されます。
- 挙動: オーバーフローが発生した場合、予期しない結果(バグ)が生じます。