ByteScope

PNG ファイル形式

可逆圧縮のラスター画像形式、Portable Network Graphics。

MIME タイプ
image/png
拡張子
.png
カテゴリ
画像

マジックナンバー(ファイル署名)

0x0000000089504E470D0A1A0A·PNG····PNG magic + CRLF guard

PNG 形式について

PNG は画質をまったく劣化させずに保存でき、完全なアルファ透過に対応するため、スクリーンショット、ロゴ、アイコン、輪郭のはっきりした図版の定番になっています。すべての PNG は 8 バイトの署名で始まり、その中に改行コードの組が含まれています。テキストモードで転送されて壊れた場合に、目に見えて破損するようにするための仕掛けです。

ヘッダーの構造(バイト単位)

オフセット長さフィールド意味
08PNG signature常に 89 50 4E 47 0D 0A 1A 0A。先頭バイトは最上位ビットを立ててあり、7 ビット転送を通すと目に見えて壊れます。続く 3 バイトが PNG の文字。CR LF の組、DOS の終端文字 1A、末尾の LF はいずれも、テキストモード転送で書き換えられたファイルが黙って通らずその場で失敗するためだけに置かれています。
84IHDR chunk lengthIHDR のデータ長をビッグエンディアンで書いたもので、常に 00 00 00 0D、つまり 13 バイト。PNG のチャンクはすべて長さ・型・データ・CRC の順に並び、IHDR は必ず先頭のチャンクでなければなりません。
124IHDR chunk typeASCII 4 文字の IHDR。チャンク型は大文字小文字に意味があり、1 文字目が大文字なら critical チャンクを表します。理解できないデコーダは読み飛ばさずにファイルごと拒否しなければなりません。
164Width画像の幅をピクセル単位で表すビッグエンディアンの符号なし 32 ビット。0 は不正で、仕様上の上限は 2^31 - 1 です。ありえない大きさを表示するツールは、まずこの 4 バイトをリトルエンディアンで読んでいます。
204Height画像の高さ。幅とまったく同じ形式です。オフセット 16 と合わせて、ここが PNG が自分のサイズを申告する唯一の場所で、照合できる複製はファイル内のどこにもありません。
241Bit depth1 サンプルあたりのビット数で、1・2・4・8・16 のいずれか。すべての深度がすべてのカラータイプで使えるわけではなく、インデックスカラーは 8 まで、アルファ付きの 2 種類は 8 以上に限られます。
251Colour type0 がグレースケール、2 がトゥルーカラー、3 がインデックスカラー(PLTE チャンクが必須)、4 がグレースケール+アルファ、6 がトゥルーカラー+アルファ。PNG が透過を失ったときに読むべきバイトはここで、6 だったものが 2 になっています。
261Compression method常に 0。ウィンドウサイズ 32768 バイト以下の deflate を意味します。2 つ目の方式は登録されたことがないので、それ以外の値ならヘッダが壊れています。
271Filter method常に 0。走査行ごとに適応的に選ぶ 5 種類のフィルタ集合を指します。各行が実際にどのフィルタを使ったかは圧縮ストリームの内側のバイトで、このヘッダには出てきません。
281Interlace method0 がインターレースなし、1 が Adam7。Adam7 を使うと数パーセントのサイズ増と引き換えに粗い画像を早い段階で表示できますが、今どきこれを出力するものはほとんどありません。
294IHDR CRC-32チャンク型とチャンクデータに対する CRC-32。長さフィールドは含みません。オフセット 12 から 28 のどこか 1 バイトでも書き換えると一致しなくなるので、手で編集したヘッダはこれで捕まります。
33variableFirst chunk after IHDR次の長さと型の組。たいていは IDAT か、あるいは PLTE・tRNS・gAMA・sRGB・iCCP・pHYs・eXIf・acTL のいずれか。画素データより前に置く必要のある色情報とメタデータのチャンクです。
-1212IEND 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 を確認してください。
JPEGFF 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 と混同しやすい形式です。先頭バイトを見比べてください。

形式先頭バイト拡張子
JPEGFF D8 FF.jpg
GIF47 49 46 38 39 61.gif
WebP52 49 46 46.webp
BMP42 4D.bmp

よくある質問

ファイルのマジックナンバーとは何ですか?

ファイル先頭の数バイトで、名前が何であろうとその形式を示すものです。PNG は必ず 89 50 4E 47 で始まり、ZIP は 50 4B 03 04 で始まります。OS もブラウザも file コマンドも、拡張子を信用せずこのバイト列を読みます。だからファイル名を変えても中身の正体は変わりません。

マジックナンバーを自分で確認する方法は?

macOS や Linux なら xxd -l 16 ファイル名 で先頭 16 バイトが表示されます。Windows なら PowerShell で Format-Hex -Path ファイル名 -Count 16 です。あるいはこのサイトのファイル形式判別ツールにドロップすれば、ローカルでバイト列を読んで形式を教えてくれます。アップロードはありません。

2 つの形式が同じマジックナンバーを持つのはなぜ?

一方が他方の上に作られているからです。docx、xlsx、pptx、apk、jar、epub はすべて中身が ZIP アーカイブなので ZIP の署名で始まり、区別するには内部のエントリを見る必要があります。Java の class ファイルと macOS のユニバーサルバイナリはどちらも CA FE BA BE で始まり、直後のフィールドで見分けます。

マジックナンバーがまったくないファイルもある?

あります。XML、HTML、JSON、SVG、CSV といったテキストベースの形式には固定のバイト署名がないため、構造から判別します。先頭の <?xml 宣言、<svg 要素、あるいは { に続く引用符付きのキーなどです。これは確定ではなく推測なので、このリファレンスではそうした形式をプローブ判別として示しています。

マジックナンバーが一致すればそのファイルは安全?

いいえ。わかるのは形式であって、中身が無害かどうかではありません。正規の PDF や docx でも悪意のあるペイロードを含んでいることがあります。特に拡張子とバイト列が食い違うときに真の形式を知るのは有用な第一段階ですが、マルウェアスキャンではありません。

PNG かもしれないファイルをお持ちですか?ファイル形式判別ツールで調べる — マジックナンバーをローカルで読み取ります。アップロードは一切ありません。またはすべての形式を見る。