PNG ファイル形式
可逆圧縮のラスター画像形式、Portable Network Graphics。
- MIME タイプ
- image/png
- 拡張子
- .png
- カテゴリ
- 画像
マジックナンバー(ファイル署名)
| 0x00000000 | 89504E470D0A1A0A | ·PNG···· | PNG magic + CRLF guard |
PNG 形式について
PNG は画質をまったく劣化させずに保存でき、完全なアルファ透過に対応するため、スクリーンショット、ロゴ、アイコン、輪郭のはっきりした図版の定番になっています。すべての PNG は 8 バイトの署名で始まり、その中に改行コードの組が含まれています。テキストモードで転送されて壊れた場合に、目に見えて破損するようにするための仕掛けです。
ヘッダーの構造(バイト単位)
| オフセット | 長さ | フィールド | 意味 |
|---|---|---|---|
| 0 | 8 | PNG signature | 常に 89 50 4E 47 0D 0A 1A 0A。先頭バイトは最上位ビットを立ててあり、7 ビット転送を通すと目に見えて壊れます。続く 3 バイトが PNG の文字。CR LF の組、DOS の終端文字 1A、末尾の LF はいずれも、テキストモード転送で書き換えられたファイルが黙って通らずその場で失敗するためだけに置かれています。 |
| 8 | 4 | IHDR chunk length | IHDR のデータ長をビッグエンディアンで書いたもので、常に 00 00 00 0D、つまり 13 バイト。PNG のチャンクはすべて長さ・型・データ・CRC の順に並び、IHDR は必ず先頭のチャンクでなければなりません。 |
| 12 | 4 | IHDR chunk type | ASCII 4 文字の IHDR。チャンク型は大文字小文字に意味があり、1 文字目が大文字なら critical チャンクを表します。理解できないデコーダは読み飛ばさずにファイルごと拒否しなければなりません。 |
| 16 | 4 | Width | 画像の幅をピクセル単位で表すビッグエンディアンの符号なし 32 ビット。0 は不正で、仕様上の上限は 2^31 - 1 です。ありえない大きさを表示するツールは、まずこの 4 バイトをリトルエンディアンで読んでいます。 |
| 20 | 4 | Height | 画像の高さ。幅とまったく同じ形式です。オフセット 16 と合わせて、ここが PNG が自分のサイズを申告する唯一の場所で、照合できる複製はファイル内のどこにもありません。 |
| 24 | 1 | Bit depth | 1 サンプルあたりのビット数で、1・2・4・8・16 のいずれか。すべての深度がすべてのカラータイプで使えるわけではなく、インデックスカラーは 8 まで、アルファ付きの 2 種類は 8 以上に限られます。 |
| 25 | 1 | Colour type | 0 がグレースケール、2 がトゥルーカラー、3 がインデックスカラー(PLTE チャンクが必須)、4 がグレースケール+アルファ、6 がトゥルーカラー+アルファ。PNG が透過を失ったときに読むべきバイトはここで、6 だったものが 2 になっています。 |
| 26 | 1 | Compression method | 常に 0。ウィンドウサイズ 32768 バイト以下の deflate を意味します。2 つ目の方式は登録されたことがないので、それ以外の値ならヘッダが壊れています。 |
| 27 | 1 | Filter method | 常に 0。走査行ごとに適応的に選ぶ 5 種類のフィルタ集合を指します。各行が実際にどのフィルタを使ったかは圧縮ストリームの内側のバイトで、このヘッダには出てきません。 |
| 28 | 1 | Interlace method | 0 がインターレースなし、1 が Adam7。Adam7 を使うと数パーセントのサイズ増と引き換えに粗い画像を早い段階で表示できますが、今どきこれを出力するものはほとんどありません。 |
| 29 | 4 | IHDR CRC-32 | チャンク型とチャンクデータに対する CRC-32。長さフィールドは含みません。オフセット 12 から 28 のどこか 1 バイトでも書き換えると一致しなくなるので、手で編集したヘッダはこれで捕まります。 |
| 33 | variable | First chunk after IHDR | 次の長さと型の組。たいていは IDAT か、あるいは PLTE・tRNS・gAMA・sRGB・iCCP・pHYs・eXIf・acTL のいずれか。画素データより前に置く必要のある色情報とメタデータのチャンクです。 |
| -12 | 12 | IEND trailer | 壊れていない PNG は必ず同じ 12 バイト 00 00 00 00 49 45 4E 44 AE 42 60 82 で終わります。長さ 0 の IEND チャンクとその固定 CRC です。ここが末尾になければファイルは途中で切れています。 |
似た形式との見分け方
| 紛らわしい形式 | 見分け方 |
|---|---|
| APNG | アニメーション PNG は先頭 33 バイトがバイト単位で同一です。署名も IHDR も変わりません。違いは acTL アニメーション制御チャンクで、仕様上これは最初の IDAT より前に置く必要があるので、先頭数百バイトから 61 63 54 4C を探せば見つかります。acTL を無視するデコーダは静止した 1 フレーム目だけを描きますが、それがそもそも意図されたフォールバックです。 |
| ICO | 今どきの .ico は PNG 画像をまるごと内側に持てるので、hex ダンプには PNG 署名が現れます。ただしオフセット 0 ではありません。ICO は 00 00 01 00 で始まり、続くディレクトリの各エントリが画像の位置を指しています。PNG 署名はそのどれかのオフセットにあります。PNG だと結論づける前にオフセット 0 を確認してください。 |
| JPEG | FF D8 FF と 89 50 4E 47 で、紛らわしいところは何もありません。それでも確認する価値があるのは、たいていのエディタの PNG として保存が JPEG のすでに劣化した画素を変換ではなく再エンコードしてしまうからで、また .jpg に拡張子だけ変えたスクリーンショットは中身が PNG のままでもどこでも開けてしまうからです。 |
| WebP | どちらもアルファ付きの可逆データを扱え、スクリーンショットの出力先としてもよく使われます。WebP は RIFF ファイルで、オフセット 0 に 52 49 46 46、続いて 4 バイトのリトルエンディアン長、オフセット 8 に 57 45 42 50 が並びます。内部のどこにも PNG 署名はありません。 |
よくある壊れ方
- テキストモード転送。古い FTP クライアントや一部の CI アーティファクト処理は改行を変換するため、オフセット 4-5 の 0D 0A が 0A ひとつに潰れ、そこから先が 1 バイトずれて以降のチャンク CRC がすべて失敗します。署名はまさにこれを捕まえるために設計されました。
- ダウンロードの途中切れ。署名と IHDR は無事なので寸法は正しく読め、ビューアは画像の上のほうを描いたあと、IDAT ストリームが尽きたところから灰色や透明の行に落ちます。見分ける手がかりは末尾 12 バイトに IEND がないことです。
- チャンク内部の 1 バイト反転。libpng は CRC 不一致でファイルを拒否しますが、ブラウザはたいていそのまま描画するので、同じ PNG が Chrome では動くのにビルドスクリプトでは落ちます。チャンクごとに CRC を計算し直せばどれが動いたか分かります。
- 先頭にゴミが付いた場合。紛れ込んだ UTF-8 BOM、HTML のエラーページ、PHP の警告などが画像本体より前に出力されると、署名がオフセット 0 から押し出されます。画像のバイトはすべて残っているので、89 50 4E 47 より前を削れば直ります。
- カラータイプがひそかに書き換えられた場合。6 ではなく 2 で再エンコードするパイプラインを通すとアルファチャンネルが落ちます。できあがるのは透過のない完全に正しい PNG で、それを白状しているのはファイル中でバイト 25 だけです。
この形式の現在地
輪郭のはっきりしたもの、あるいは透過が要るものは今も PNG が既定の選択肢です。スクリーンショット、UI アセット、ロゴ、図解、アイコン、README に貼る画像はまず PNG でよいでしょう。写真については何十年も前に JPEG に負け、最近ではアルファを保ったままグラデーションの多い画像で圧倒的に小さくなる WebP や AVIF にも押されています。それでも PNG が第一候補であり続けるのは、あとから編集し直す可能性のある画像です。可逆なので、PNG で保存したスクリーンショットは切り抜きと注釈を十数回往復させても劣化しません。同じ画像を JPEG で保存すると、保存のたびに目に見えて汚れていきます。1997 年以降すべてのブラウザが対応しているので、新しい形式と違ってフォールバックを用意する必要もありません。
PNG ファイルをこのサイトで開く
どれもブラウザ内で動きます。ファイルが端末から出ることはありません。
関連する形式
PNG と混同しやすい形式です。先頭バイトを見比べてください。