PicScrub logoPicScrub
対応形式に戻る

PNG 形式

Portable Network Graphics

チャンクでできた構造

PNG は、数あるファイル形式のなかでもとくにきれいな設計をしています。 中身はすべて「チャンク」に整理されていて、それぞれが種類、データ、 チェックサムを持つ独立したブロックになっています。うまくできているのは、 デコーダが理解できないチャンクを読み飛ばせる点です。おかげで、古い ソフトを壊すことなくメタデータを載せられます。

賢いのはチャンク名の付け方です。頭文字が大文字なら「必須」(それがないと 画像を表示できません)。小文字なら「補助」、つまりあると便利だけれど 必須ではない、という意味になります。ここで問題になるメタデータのチャンクは すべて補助チャンクなので、安心して削除できるというわけです。

PNG のファイル構造

Signature
IHDR
Metadata
IDAT
IEND
Signature
8 バイト
89 50 4E 47 0D 0A 1A 0A
IHDR
25 バイト
画像ヘッダー(必須)
Metadata
100 バイト
tEXt、iTXt、eXIf チャンク
IDAT
可変長
圧縮された画像データ
IEND
12 バイト
画像の終了マーカー

PNG のシグネチャと IHDR

PNG のシグネチャ
IHDR の長さ(13)
IHDR の種類
幅(256)
高さ(256)
ビット深度、カラータイプなど
OffsetHexASCII
0000
89504E470D0A1A0A0000000D49484452
.PNG........IHDR
0010
00000100000001000802000000000000
.............

チャンクの構造

LengthTypeDataCRC32
4 バイト4 バイト可変4 バイト

チャンク名の命名ルール

  • • 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 などです。

Format: keyword + null + text

zTXt:圧縮されたテキスト

tEXt と同じですが zlib で圧縮されています。長いテキストに 使われます。

iTXt:国際化テキスト

UTF-8 のテキストで、圧縮は任意です。言語タグと翻訳された キーワードに対応しています。XMP メタデータの格納に使われます。

XMP keyword: XML:com.adobe.xmp\0

eXIf: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 を処理する流れ

1

シグネチャの確認

PNG のシグネチャ 89 50 4E 47 0D 0A 1A 0A を確かめます

2

チャンクの解析

各チャンクの長さと種類を読み、CRC を検証します

3

メタデータのチャンクを除外

tEXt、zTXt、iTXt、eXIf、tIME のチャンクを見つけて読み飛ばします

4

ファイルの再構築

シグネチャ + 選び抜いたチャンク + IEND の順に書き出します

残るチャンク

  • • IHDR、PLTE、IDAT、IEND(必須)
  • • sRGB、gAMA、cHRM(色)
  • • iCCP(カラープロファイル、任意)
  • • pHYs(画素の物理サイズ)
  • • tRNS(透明度)

削除されるチャンク

  • • tEXt(テキストのメタデータ)
  • • zTXt(圧縮されたテキスト)
  • • iTXt(国際化テキスト、XMP)
  • • eXIf(EXIF データ)
  • • tIME(更新日時)