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

データ構造

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

基本的なデータ構造

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

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

PNGヘッダー

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

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

チャンクの構造

名称 サイズ 説明
Length 4byte データの長さ
Chunk Type 4byte チャンクの種類を表す
Chunk Data Length byte 実際のデータ
CRC 4byte 巡回単調検査

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) Length Dataの長さを表す,長さは常に13
0x0004(4) Chunk Type Chankの種類を表す,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) CRC Chank TypeとChunk Dataをもとに計算される
ビット深度とカラータイプの組み合わせ
カラータイプ 利用できるビット深度 解釈
0 1,2,4,8,16 グレースケール画像
それぞれのピクセルがグレースケールサンプルで構成されている
2 8,16 トゥルーカラー画像
それぞれのピクセルがR,G,B値により構成されている
3 1,2,4,8 インデックスカラー画像
それぞれのピクセルがパレットインデックスで構成されている
PLTEチャンクが必須
4 8,16 グレースケール+アルファ画像
それぞれのピクセルがグレースケールサンプルとアルファ値で構成されている
6 8,16 トゥルーカラー+アルファ画像
それぞれのピクセルがR,G,B,アルファ値で構成されている

IPLT

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

オフセット(サイズ) 名称 役割,補足
0x0000(4) Length Dataの長さを表す,長さは常3で割り切れる数
0x0004(4) Chunk Type Chankの種類を表す,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) CRC Chank TypeとChunk Dataをもとに計算される

IDAT

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

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

IEND

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

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

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

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

Memo
連続企画

Djangoクラスベースビューのすヽめ

Memo
連続企画

Djangoでブログを作ろう

GitHub
制作物

Django-Boost

Djangoでの開発を加速する拡張ライブラリ
GitHub
制作物

ktPyString

kotlinにpythonと同等の文字列操作を提供するライブラリ
GitHub
制作物

py_string

c++にpythonと同等の文字列操作を提供するライブラリ
GitHub
制作物

SwiftyPyString

Swiftにpythonと同等の文字列操作を提供するライブラリ