PNG 形式
Portable Network Graphics
チャンクでできた構造
PNG は、数あるファイル形式のなかでもとくにきれいな設計をしています。 中身はすべて「チャンク」に整理されていて、それぞれが種類、データ、 チェックサムを持つ独立したブロックになっています。うまくできているのは、 デコーダが理解できないチャンクを読み飛ばせる点です。おかげで、古い ソフトを壊すことなくメタデータを載せられます。
賢いのはチャンク名の付け方です。頭文字が大文字なら「必須」(それがないと 画像を表示できません)。小文字なら「補助」、つまりあると便利だけれど 必須ではない、という意味になります。ここで問題になるメタデータのチャンクは すべて補助チャンクなので、安心して削除できるというわけです。
PNG のファイル構造
PNG のシグネチャと IHDR
| Offset | Hex | ASCII | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0000 | 89504E470D0A1A0A0000000D49484452 | .PNG........IHDR | |||||||||||||||
| 0010 | 00000100000001000802000000000000 | ............. | |||||||||||||||
チャンクの構造
チャンク名の命名ルール
- • 1 文字目が大文字 = 必須チャンク (理解できなければ扱えません)
- • 1 文字目が小文字 = 補助チャンク (任意。無視してもかまいません)
- • 2 文字目 = 公開(大文字)か プライベート(小文字)か
必須チャンク
画像として成立するために、必ず存在していて、かつ解釈できなければ ならないチャンクです。PicScrub は必須チャンクを常に残します。
IHDR:画像ヘッダー
シグネチャの直後に来る最初のチャンク。幅、高さ、ビット深度、 カラータイプ、圧縮方式、フィルタ方式、インターレース方式が 入っています。データはちょうど 13 バイトです。
IDAT:画像データ
zlib/deflate で圧縮された画像データが入ります。複数の IDAT チャンクに分かれることもあります。IDAT チャンクは連続して 並んでいなければなりません。
IEND:画像の終了
PNG データストリームの終わりを示します。必ず最後のチャンクで、 データ長はゼロです。
PLTE:パレット
インデックスカラーの画像(カラータイプ 3)では必須です。 1〜256 個の RGB パレットエントリを持ちます。
メタデータのチャンク
プライバシーに関わるメタデータが入りうる補助チャンクです。 PicScrub が削除するのはこれらです。
tEXt:非圧縮のテキスト
Latin-1 でエンコードされたキーと値の組。よく使われるキーは Author、Description、Copyright、Creation Time、Software などです。
zTXt:圧縮されたテキスト
tEXt と同じですが zlib で圧縮されています。長いテキストに 使われます。
iTXt:国際化テキスト
UTF-8 のテキストで、圧縮は任意です。言語タグと翻訳された キーワードに対応しています。XMP メタデータの格納に使われます。
XML:com.adobe.xmp\0eXIf:EXIF データ
2017 年に PNG の拡張として登録されました。TIFF 形式の生の EXIF データが入っており、構造は JPEG の EXIF と同じです。 GPS、日時、端末情報が入っていることがあります。
iCCP:ICC カラープロファイル
埋め込まれた ICC カラープロファイル。zlib で圧縮されています。 PicScrub は色を正確に保つため、初期設定では残します。
tIME:最終更新日時
7 バイト。年(2 バイト)、月、日、時、分、秒。画像が最後に 更新された日時が分かってしまいます。
色に関するチャンク
色の表示に影響しますが、ふつうは個人情報を含みません。 PicScrub は初期設定でこれらを残します。
sRGB
sRGB の色空間であることを示します。レンダリングインテントを表す 1 バイトです。
gAMA
ガンマ値。4 バイトの符号なし整数(100,000 倍した値)です。
cHRM
原色の色度と白色点の座標です。
sBIT
各チャンネルの元のサンプルビット深度です。
CRC32 による検証
PNG のどのチャンクにも、チャンクの種類とデータから計算した CRC32 の チェックサムが付いています。これでデータの整合性を保証します。
CRC の計算
CRC32 input = chunk_type (4 bytes) + chunk_data (N bytes) CRC32 output = 4 bytes appended after chunk data // PNG uses CRC-32 polynomial: 0xEDB88320
PicScrub が CRC を検証する理由
PNG ファイルを読むとき、PicScrub はデータの整合性を確かめるために 各チャンクの CRC を検証します。壊れたチャンクは安全に処理されます。
PicScrub が PNG を処理する流れ
シグネチャの確認
PNG のシグネチャ 89 50 4E 47 0D 0A 1A 0A を確かめます
チャンクの解析
各チャンクの長さと種類を読み、CRC を検証します
メタデータのチャンクを除外
tEXt、zTXt、iTXt、eXIf、tIME のチャンクを見つけて読み飛ばします
ファイルの再構築
シグネチャ + 選び抜いたチャンク + IEND の順に書き出します
残るチャンク
- • IHDR、PLTE、IDAT、IEND(必須)
- • sRGB、gAMA、cHRM(色)
- • iCCP(カラープロファイル、任意)
- • pHYs(画素の物理サイズ)
- • tRNS(透明度)
削除されるチャンク
- • tEXt(テキストのメタデータ)
- • zTXt(圧縮されたテキスト)
- • iTXt(国際化テキスト、XMP)
- • eXIf(EXIF データ)
- • tIME(更新日時)