PNGイメージのデータ構造を知ってみる(1)

PNG(Portable Network Graphics)イメージのデータ構造がどうなっているのか調べてみた。

基本的なデータ構造

PNGイメージは最初の8バイトを除いてチャンクと呼ばれる構造で成り立っています。

名称サイズ説明
PNGヘッダー8bytePNGファイルであることを示す
IHDRチャンク25bytePNGイメージの基本情報
:::
IDATチャンクNbyte画像の実データ
:::
IENDチャンク12bytePNGファイルの終端を表す

PNGヘッダー

PNGヘッダーはこれがPNGファイルであることを示すための情報で、常に0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0Aで固定されています。
読み込んだファイルがPNGファイルかどうかはここを見ればわかります。
それぞれの値には以下のような意味があります。

16進数ASCII文字役割
0x89¥x89ASCII文字で表現できない値。
テキストファイルとして間違えてロードされてしまう可能性を減らす
0x50Pフォーマット名
0x4ENフォーマット名
0x47Gフォーマット名
0x0DCR(Ctrl-M)“改行文字"として解釈されてしまい、システムによって勝手に「\r」や「\n」に置き換えられたりしないかを検出するために利用される
0x0ALF(Ctrl-J)“改行文字"として解釈されてしまい、システムによって勝手に「\r」や「\n」に置き換えられたりしないかを検出するために利用される
0x1ACtrl-ZControl-z文字。ファイルの中身をテキストとして読み出し表示させようとしたDOSコマンドを停止させる
0x0ALF(Ctrl-J)“改行文字"として解釈されてしまい、システムによって勝手に「\r」や「\r\n」に置き換えられたりしないかを検出するために利用される

チャンクの構造

名称サイズ説明
Length4byteデータの長さ
Chunk Type4byteチャンクの種類を表す
Chunk DataLength byte実際のデータ
CRC4byte巡回単調検査

Portable Network Graphicsというだけあってバイトオーダーはネットワークオーダー(ビックエンディアン)です。
LengthはChunk Data部分の長さを表します。 最小で 0 最大で 2^31 - 1 までの値を収められます。

Chank Typeはチャンクの種類を表します。アルファベット4文字のデータがここに格納されます。詳しい種類については後述します。

Chunk DataはLength が 0 ではない場合、チャンクの種類に関連したデータが、格納されます。

CRCはChank TypeとDataの部分をcrc32チェックサムアルゴリズムを使って算出される値です。
データに破損がないかをチェックするのに利用します。

チャンクの種類

チャンクには必須のものと必須ではない補助的なものがあります。
今回は必須チャンクについて解説しようと思います。

必須チャンク

IHDR

IHDRチャンクはPNGヘッダーの直後に必要

オフセット(サイズ)名称役割,補足
0x0000(4)LengthDataの長さを表す,長さは常に13
0x0004(4)Chunk TypeChankの種類を表す,ASCII文字でIHDR
0x0008(4)Chunk Data(width)画像の幅
0x000C(4)〃(height)画像の高さ
0x0010(1)〃(bit depth)ビット深度
(有効な値は 1, 2, 4, 8, 16 だが、カラータイプにより使用できないものも出てくる)
※ 詳細は下の「ビット深度とカラータイプの組み合わせ」参照
0x0011(1)〃(color type)カラータイプ
(有効な値は0, 2, 3, 4, 6)※ 詳細は下の「ビット深度とカラータイプの組み合わせ」参照
0x0012(1)〃(compression method)圧縮手法
0x0013(1)〃(filter method)フィルター手法
0x0014(1)〃(interlace method)インターレース手法
0x0015(4)CRCChank TypeとChunk Dataをもとに計算される
ビット深度とカラータイプの組み合わせ
カラータイプ利用できるビット深度解釈
01,2,4,8,16グレースケール画像
それぞれのピクセルがグレースケールサンプルで構成されている
28,16トゥルーカラー画像
それぞれのピクセルがR,G,B値により構成されている
31,2,4,8インデックスカラー画像
それぞれのピクセルがパレットインデックスで構成されている
PLTEチャンクが必須
48,16グレースケール+アルファ画像
それぞれのピクセルがグレースケールサンプルとアルファ値で構成されている
68,16トゥルーカラー+アルファ画像
それぞれのピクセルがR,G,B,アルファ値で構成されている

IPLT

カラーパレット情報
カラータイプがIHDRのカラータイプが3の時のみ必須。複数の設置はできない。
後述のIDATよりも前に設置する必要がある。
Chunk Dataの長さが3で割り切れない時は、エラーになります。

オフセット(サイズ)名称役割,補足
0x0000(4)LengthDataの長さを表す,長さは常3で割り切れる数
0x0004(4)Chunk TypeChankの種類を表す,ASCII文字でPLTE
0x00(1)Chunk DataパレットNo.1 R 0-255
0x00(1)パレットNo.1 G 0-255
0x00(1)パレットNo.1 B 0-255
0x00(1)パレットNo.2 R
0x00(1)パレットNo.2 G
0x00(1)パレットNo.2 B
:::
0x—-(4)CRCChank TypeとChunk Dataをもとに計算される

IDAT

画像の実データ
最低でも1つは設置する必要がある。複数設置する場合は連続して設置する。
IHDRとIENDの間に設置する。

オフセット(サイズ)名称役割,補足
0x0000(4)LengthDataの長さを表す
0x0004(4)Chunk TypeChankの種類を表す,ASCII文字でPLTE
0x0008(N)Chunk Data実際のイメージデータ
0x—-(4)CRCChank TypeとChunk Dataをもとに計算される

IEND

PNGファイルの終端を表すチャンクです。
常に同じ値です。

オフセット(サイズ)名称役割,補足
0x0000(4)LengthDataの長さを表す,長さは常に0
0x0004(4)Chunk TypeChankの種類を表す,ASCII文字でIEND
0x0008(4)CRCChank Typeのcrc値0xAE 0x42 0x60 0x82で固定

このチャンクより先は読み込まれません。

今回はこの辺にして次回は補助チャンクについてまとめてみようと思います。