ByteScope

JPEG ファイル形式

非可逆圧縮のラスター画像形式。写真用として広く使われています。

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

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

0x00000000FFD8FF···Start-Of-Image marker

JPEG 形式について

JPEG は写真向けに調整された離散コサイン変換で圧縮し、ほとんど目に見えないわずかな画質と引き換えにファイルサイズを大幅に削減します。ファイルは Start-Of-Image マーカー FF D8 で始まり、FF D9 で終わります。その間はセグメントの連なりで、どのセグメントも FF とマーカーバイトで始まり、ほとんどはマーカーの直後に 2 バイトのビッグエンディアン長を持ちます。パーサがセグメントの中身をひとつも理解しないまま JPEG を歩けるのは、この長さのおかげです。画素データ自体は Start-Of-Scan マーカーより後ろのエントロピー符号化ストリームにあり、ここだけは長さフィールドをまったく持ちません。デコーダは次の本物のマーカーを探して終端を見つけます。

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

オフセット長さフィールド意味
02Start of Image markerFF D8。長さもペイロードも持たない数少ないマーカーのひとつです。カタログの署名が 2 バイトではなく 3 バイトを見ているのは、次のマーカーを開く FF がすぐ後ろに続くからで、これを要求しておくと、たまたま FF D8 で始まっただけのファイルを除外できます。
22First application markerFF E0 なら APP0 で、ファイルが JFIF に従うことを意味します。FF E1 なら APP1 で、たいていは Exif です。カメラやスマートフォンは APP1 を書き、画像エディタは APP0 を先に置いてその後ろに APP1 を置く傾向があります。両方あるファイルもまったく普通です。
42Segment lengthセグメントのバイト数をビッグエンディアンで表したもの。この 2 バイト自体は数えますが、手前にある 2 バイトのマーカーは数えません。サムネイルのない APP0 は 00 10、つまり 16 と読めるので、次のマーカーは 4 + 16 でオフセット 20 から始まります。
65JFIF identifier4A 46 49 46 00、ASCII の JFIF と NUL。APP1 が先に来る場合はオフセット 6 に 45 78 69 66 00 00 の 6 バイトが入り、そのセグメントは JFIF ではなく Exif になります。
112JFIF versionメジャーとマイナーを 1 バイトずつ。01 01 がバージョン 1.01、01 02 が 1.02 です。APP0 が最初のセグメントのときだけ存在し、Exif が先頭のファイルではこのバイトは TIFF 構造の一部になります。
131Density units0 なら密度の数値はアスペクト比しか表しません。1 なら dots per inch、2 なら dots per centimetre。ここに 0 を書いておきながら 72 と 72 を埋めるエンコーダも多く、JPEG から求めた印刷サイズがしばしば無意味なのはそのせいです。
144Horizontal and vertical densityビッグエンディアンの 16 ビットが 2 つ、X のあと Y。手前の単位バイトに従って解釈します。PNG が pHYs に入れているものの JFIF 版で、両者を同期させる仕組みはどこにもありません。
182Thumbnail width and heightそれぞれ 1 バイトで、ほぼ必ず 00 00 です。0 でない場合はオフセット 20 から幅 × 高さ × 3 バイトの無圧縮 RGB が続き、オフセット 4 のセグメント長もそれに合わせて増えます。手作業でも確かめやすい整合性チェックです。
-22End of Image markerFF D9。SOI と同じく長さを持ちません。この後ろに余分なバイトがあってもデコーダが無視する程度には合法で、画像ファイルに ZIP アーカイブやシェルスクリプトが忍び込めるのはこのためです。

似た形式との見分け方

紛らわしい形式見分け方
JFIF/Exifどちらも JPEG で、違いはオフセット 2 のマーカーだけで決まります。FF E0 でオフセット 6 が 4A 46 49 46 00 なら JFIF、そこから分かるのは密度の組だけです。FF E1 でオフセット 6 が 45 78 69 66 00 00 なら Exif で、オフセット 12 から完全な TIFF ヘッダが始まります。49 49 2A 00 か 4D 4D 00 2A、続いて最初のディレクトリへの 4 バイトオフセット。カメラの機種、露出、向き、GPS はそこにあります。両方のセグメントを持つファイルもあり、その場合に読む価値があるのは Exif のほうです。
HEICこの 2 つは同じスマートフォンの同じ役割を奪い合っていて、切り替えるスイッチはカメラアプリの設定の奥にあるトグル 1 つです。JPEG はオフセット 0 が FF D8 FF。HEIC はオフセット 0 にボックス長しかなく、オフセット 4 が 66 74 79 70 68 65 69 63 と読めます。iPhone から互換性優先モードで書き出した写真は JPEG、それ以外は HEIC です。
PNGFF D8 FF と 89 50 4E 47。拡張子を信じずに確認する価値があります。.png として保存した JPEG は JPEG のままでもブラウザは全部描いてしまいますし、スクリーンショットの文字がぼやける原因のいちばんは JPEG への再エンコードだからです。
JPEG 2000名前を共有しているだけの別のコーデックです。生の JPEG 2000 コードストリームは FF 4F FF 51 で始まり、ボックス形式の JP2 ファイルは 00 00 00 0C 6A 50 20 20 0D 0A 87 0A で始まります。どちらもブラウザではデコードできないので、学術系やアーカイブ系から落とした .jp2 は壊れているように見えます。

よくある壊れ方

  • 途中切れ。ヘッダは残っているのでビューアは寸法を把握して絵の上のほうを描き、そこでエントロピー符号化ストリームが尽きて残りは灰色のままか、最後のブロックが繰り返されます。手がかりは末尾 2 バイトで、無事な JPEG は FF D9 で終わります。
  • スキャンデータの内側でバイトが 1 つ増えたり減ったりした場合。ハフマン符号には再同期できるバイト境界がないので、破損より後ろのブロックはすべて誤った DC 予測でデコードされ、その行から下は色帯がずれた模様に溶けます。エンコーダがリスタートマーカーを書いていない限り、復帰する手立てはありません。
  • テキストモード転送。PNG を壊すのと同じ改行変換が、ここでは圧縮データの中の 0D 0A を書き換えます。JPEG にはセグメントごとのチェックサムがないので気づけません。ファイルは開き、ヘッダは完璧で、下 3 分の 2 が滲みます。
  • Exif ディレクトリの破損。APP1 のセグメント長は正しいのに、TIFF 構造の中のオフセットがセグメント終端より先を指しているようなケースです。写真は向きのタグを失い、アプリによって 90 度回って見えたり正しく見えたりします。セグメントごと削れば表示は直り、メタデータは消えます。
  • サーバのエラーページや紛れ込んだ BOM が先頭に付いた場合。FF D8 FF がオフセット 0 になくなるので、厳格なデコーダはファイルを門前払いし、寛容なものは前方を走査して開いてしまいます。ブラウザでは見えるのにビルドでは失敗する、あのおなじみの状況です。

この形式の現在地

JPEG は 30 年前の形式ですが、インターネット上の写真はいまだにほぼすべてこれで配信されています。これまで作られたあらゆるカメラ、スマートフォン、ブラウザ、プリンタ、スキャナ、デジタルフォトフレームが文字どおり全部デコードできる形式は他になく、その普遍性は WebP・AVIF・HEIC が節約してくれる 20〜50 パーセントより価値があります。本当に不利なのは輪郭のはっきりしたもの、つまりスクリーンショット、図解、文字、線画です。ブロック変換は、そうした画像を成り立たせている高周波成分をちょうど狙い撃ちで潰してしまいます。繰り返し編集して保存するものも同様で、保存のたびに非可逆エンコードがやり直され、傷が積み重なります。アルファチャンネルは一切ないので、透過が要るロゴを JPEG にすることはできません。後継として用意された JPEG XL は既存 JPEG の可逆再圧縮とバイトあたりの画質向上を提供しますが、ブラウザ対応が止まってしまい、今日の配信手段にはなっていません。現実的な答えは、picture 要素の中に JPEG をフォールバックとして残し、受け取れる相手には WebP か AVIF を配ることです。

JPEG ファイルをこのサイトで開く

どれもブラウザ内で動きます。ファイルが端末から出ることはありません。

関連する形式

JPEG と混同しやすい形式です。先頭バイトを見比べてください。

形式先頭バイト拡張子
PNG89 50 4E 47 0D 0A.png
WebP52 49 46 46.webp
HEIC66 74 79 70.heic
GIF47 49 46 38 39 61.gif

よくある質問

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

ファイル先頭の数バイトで、名前が何であろうとその形式を示すものです。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 でも悪意のあるペイロードを含んでいることがあります。特に拡張子とバイト列が食い違うときに真の形式を知るのは有用な第一段階ですが、マルウェアスキャンではありません。

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