■PNG形式(Portable Network Graphics)

-- GIFに変わる画像形式、PNG形式のファイル構造 --

このドキュメント(format_png.html)は、転載・再配布の際に制作者の許可を取る必要はありません。
間違い・誤字脱字を発見した場合はメールまたはBBSでお知らせください。


概要

  PNG(Portable Network Graphics)(注1)は、 圧縮アルゴリズム(LZW法)の使用に法外なライセンス料を課されたGIFに代わる、 新しい誰でも無料で自由に使えるフォーマットとして開発されました。 PNGはその名前のとおり(注2)、 初めからWEB上で使用される事を前提として設計されているので、 比較的高い圧縮率が期待できます。
  PNGはGIFの特徴である可逆圧縮、インデックスカラー、 プログレッシブ表示、透過など動画を除くほとんどの機能を継承し、 それに加えて、GIFでは利用できなかった新しい機能を備えた圧縮画像フォーマットです。 GIFと大きく違うのは、フルカラーやアルファチャンネルなども扱うことができる事と、 CRC検査方式によってデータ化けのような不正な値を検出できる仕組みになっていることです。 PNGの動画フォーマットとしてMNG(Multiple-image Network Graphics)というものもありますが、 現状ではあまり普及していません。

(注1)
PNGは【ping】(ピング)と発音する、と仕様書に書いてあります。
PNG Specification > 1.Introduction > Pronunciation 参照。

(注2)
一説によると、"PNG"には"PNG is Not GIF"(再帰的)という
意味も込められているとか。
"GNU is Not Unix"みたいですね。



チャンク構造

  PNGファイルは「チャンクChunk)」 と呼ばれる構造を成すデータの塊が複数集まって成り立っています。 先頭8バイトの「PNG識別子」以外、PNGファイル中に存在するデータはすべてチャンクを形成しています。 PNGファイルを理解するにはチャンクから始めなければなりません。 チャンク自体の構造は「データ部のサイズ」、「チャンク名」、「データ配列」、 「CRC検査数字」の4つの成分から成り立っています。

チャンクの構造
オフセット内容サイズ説明
00データサイズ4 bytesデータ配列のサイズを定義
04チャンク名4 bytesチャンクの名称(ASCII文字コード)
08データ配列可変長実際のデータ
08 + データサイズCRC検査数字4 bytesデータの正当性をチェック


以下は実際のPNG画像からチャンクを一つ抜き出したものです。
マルチバイトのバイトオーダーは上位→下位(ビッグエンディアン)です。
アドレス +0+1+2+3 +4+5+6+7 +8+9+A+B +C+D+E+F
[00000000] ---- ---- 0000000D 49484452
[00000010] 000000A0 00000078 08030000 00427C09
[00000020] 5D--- ---- ---- ----

上記のチャンクの内訳
アドレス08 〜 0B0C 〜 0F10 〜 1C1D 〜 20
内容データサイズチャンク名データ配列CRC検査数字

データサイズ = { 00, 00, 00, 0D } h 0x0D は10進数で13なので、データ配列のサイズは13バイトになる
チャンク名 = { 49, 48, 44, 52 } h ASCII文字コードで読むと、"IHDR"になり、IHDRチャンクとして認識される
データ配列 = { 00, ..(省略).. ,00 } h 実際のデータ配列(この例では13バイト)、詳細は後述のIHDR参照
CRC検査数字 = { 42, 7C, 09, 5D } h チャンク名とデータ配列を元にCRCアルゴリズム(注1)で算出される数値

# "-h"や"0x-"は16進数(hexadecimal)である事を表します。

(注1)
仕様書の巻末付録にサンプルコードが掲載されています。
PNG Specification > 15.Appendix:SampleCRCCode 参照

CRC(Cyclic Redundancy Check : 巡回冗長検査)とは、
予め定められた多項式から生成される定数でデータを割っ
た余りを検査数字(check digit)として使い、データ通信
の誤りを検出する検査方法。



  他の多くのフォーマットにみられる、ファイル先頭からのオフセットによって 特定のデータを格納する位置が厳格に定められているような構造(例えば、 先頭から何バイト目はこのデータという具合)であれば、 新しいデータを追加したい場合などは、 ファイルフォーマットの規格に変更を加えなければなりません。
  しかし、PNGのようにチャンク構造を持っている場合は、 あるチャンクのデータ長を変更しても他のチャンクには影響が及ばず、 新しいチャンクを登録しても他の既存のチャンクに影響が出ることはありません。 これはチャンク構造を持つPNGファイルがシーケンシャルな読み書きを前提としているためです。
  このような理由から、PNGは将来的な拡張に対して比較的柔軟に対応する事が可能です。


ファイルの構成

ファイル構造 "image_png.PNG"
ファイル全体の構造
データ構造役割説明
PNG識別子PNGの識別子PNG画像を識別するための8バイトの配列
IHDRチャンクイメージヘッダ画像サイズやビット深度など、画像全般の重要なデータ
補助チャンク--ガンマ値や色度など色の表示に関する複数のチャンク
PLTEチャンクパレットインデックスカラーモードでは必須
補助チャンク--透過色などの表示に関する複数のチャンク
追加チャンク--複数の公開チャンク, 無理に書き込む必要なし
IDATチャンクイメージデータ圧縮された画像データの配列, 複数存在しても良い
IENDチャンク画像の終端PNGファイルの終端, データ長はゼロ



標準必須チャンク(Standard Critical Chunks)
IHDR    PLTE    IDAT    IEND

  IHDR、PLTE、IDAT、IENDの4つを必須チャンクと呼びます。 これらは、あらゆるアプリケーションによって解釈される事が保証されているチャンクです。 有効なPNG画像は、1つのIHDR、1つ以上のIDAT、1つのIENDを必ず含まなければなりません。 PLTEが存在するかどうかはカラータイプに依存します。

標準補助チャンク(Standard Ancillary Chunks)
cHRM    gAMA    iCCP    sBIT     sRGB    bKGD    hIST    tRNS
pHYs    sPLT    tIME    iTXt     tEXt    zTXt

  補助チャンクは、エンコーダが書き込まなくても構わず、デコーダが無視することも出来るという意味で、任意のチャンクです。 しかしながら、補助チャンクの情報が利用可能な場合は書き込み/読み込みが規格により推奨されています。
  現時点で登録されている14個の補助チャンクのすべてを書き込む必要はありません。cHRM、gAMA、tRNSあたりは比較的よく見かけると思います。

追加公開チャンク(Additional Public Chunks)
oFFs    pCAL    sCAL
gIFg    gIFt    gIFx    fRAc

  追加公開チャンクは(作成中…)


チャンクの分類
標準チャンク
( Standard Chunks )
必須チャンク
( Critical Chunks )
チャンク名位置備考
IHDR PNG識別子の直後 - -
PLTE IDAT以前 - -
IDAT 複数の場合は連続 複数可
IEND ファイル終端 - -
補助チャンク
( Ancillary Chunks )
チャンク名位置備考
cHRM PLTE、IDAT以前 - -
gAMA 同上 - -
iCCP 同上 - -
sBIT 同上 - -
sRGB 同上 - -
bKGD PLTE以後かつIDAT以前 - -
hIST 同上 - -
tRNS 同上 - -
pHYs IDAT以前 - -
sPLT IDAT以前 複数可
tIME 規定無し - -
iTXt 規定無し 複数可
tEXt 規定無し 複数可
zTXt 規定無し 複数可
追加チャンク
( Additional Chunks )
公開チャンク
( Public Chunks )
チャンク名位置備考
oFFs - - - -
pCAL - - - -
sCAL - - - -
gIFg - - - -
gIFt - - - -
gIFx - - - -
fRAc - - - -
私用チャンク
( Private Chunks )
私用チャンクは後述



PNG識別子(PNG File Signature)

  PNG識別子はファイル先頭に必ず置かれる8バイトの定数です。
  内容は常に以下の用になり、ここでファイルがPNG形式である事を認識します。

16進表記  89  50   4E  47   0D  0A   1A  0A 
C言語での表記 \211P NG \r\n \032\n

  ASCII文字コードを知っている人なら「あれ、最初の0x89って何だ?」と思うでしょう。 これは、一般のテキストファイルが偶然にPNGファイルとして誤認されないための非ASCII文字の値です。 そして、2〜4バイト目には"PNG"の文字が埋め込まれます。
  また、PNG識別子は一般的なファイル伝送のトラブルも即座に発見出来るようになっています。
CR-LF(0x0D, 0x0A)の部分は改行文字を変更してしまう不正なファイル伝送を検出し、 次の^Z文字(0x1A)はMS-DOS上でファイルの表示を停止します。 最後のLF文字(0x0A)はCR-LFの逆伝送をチェックします。

GIFと違って、PNGはファイル識別子はもちろん、ファイル中のどこにもバージョンナンバーが現れません。 柔軟な拡張性を重視したためです。


IHDRチャンク



制 作 中 ...




PLTEチャンク



以 下 制 作 中 ...



[ 文書作成 ]
Kalashnikov <kalashnikov-lj@infoseek.jp>

[ 参考文献 ]
PNG Specification, Version 1.2