ByteScope

GIF ファイル形式

Graphics Interchange Format — インデックスカラーの画像と簡易アニメーション。

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

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

0x00000000474946383961GIF89a'GIF89a' (or 'GIF87a')

GIF 形式について

GIF は 1 フレームあたり 256 色のパレットに制限される一方、ループアニメーションと 1 ビットの透過に対応しており、それがミーム時代まで生き延びた理由です。ヘッダは仕様バージョンを示す ASCII 文字列 GIF87a か GIF89a で、その直後に 7 バイトの論理画面記述子が続き、キャンバスの大きさとグローバルカラーテーブルの構成を伝えます。そこから先はブロックの連なりで、それぞれ 1 バイトで始まります。2C なら画像、21 なら拡張ブロック、3B ならファイルの終わりです。画素はパレットのインデックスを LZW で圧縮し、画像ごとに可変長の符号ストリームを 1 本持ちます。写真の GIF が元の JPEG より大きくなりがちなのはそのためです。

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

オフセット長さフィールド意味
03Signature47 49 46、ASCII の GIF。どちらのバージョンでも固定で、仕様のどの版を受け入れるかを決めずに検出器が頼れるのはこの 3 バイトだけです。
33Version87a なら 38 37 61、89a なら 38 39 61。これは画像データではなく、この先どの種類のブロックが現れてよいかについての申告で、エンコーダは実際に使った機能を満たす最小のバージョンを書くことになっています。
62Logical screen widthキャンバス幅をピクセルで表すリトルエンディアンの 16 ビット。バイト順に注意してください。GIF は PNG より古く、数値を逆順に格納するので、40 00 は 16384 ではなく 64 です。キャンバスは個々のフレームの大きさとは限りません。
82Logical screen heightキャンバス高さのリトルエンディアン 16 ビット。個々のフレームはファイルの後ろで自分の位置と大きさを持ち、これよりずっと小さいこともあります。アニメーション GIF が変化していない部分を送り直さずに済むのは、まさにこの仕組みです。
101Packed screen descriptor fieldsビット 7 が立っていればグローバルカラーテーブルが続きます。ビット 6〜4 は元画像の色分解能、ビット 3 はソートフラグ。ビット 2〜0 が N を保持し、テーブルには 2 の (N+1) 乗個のエントリが入ります。よくある値 6 なら 128 色、7 なら 256 色すべてです。
111Background colour indexグローバルカラーテーブルへのインデックスで、どのフレームも塗っていないキャンバス領域に使われます。ほとんどのデコーダはこれを無視して未描画部分を透明として扱うので、あるビューアでは正しく見えて別のビューアでは色の縁が出る GIF は、このバイトをめぐって揉めています。
121Pixel aspect ratio0 は情報なしという意味で、事実上すべてのファイルがそう書いています。それ以外の値 V は画素アスペクト比が (V + 15) / 64 であることを表す、正方形でない画素を持つディスプレイ時代の名残です。
13variableGlobal colour tableパックドバイトのビット 7 が立っているときだけ存在し、その場合はちょうど 2 の (N+1) 乗 × 3 バイトの RGB 三つ組が並びます。128 エントリなら 384 バイトです。N を読み違えると以降のバイトオフセットが全部ずれるので、1 バイトの編集で GIF を壊す手段としては最も効果的です。
-11TrailerASCII のセミコロンにあたる 3B が 1 バイト、これでファイルが終わります。後ろに何があっても無視され、これが無いことがダウンロード途中切れの最速の判定材料です。

似た形式との見分け方

紛らわしい形式見分け方
GIF87a/GIF89a違いはオフセット 3 の 3 バイトだけで、ヘッダの他の部分は同じです。89a で追加されたのはグラフィック制御拡張、つまりフレーム遅延・廃棄方法・透過色インデックスを運ぶ 21 F9 ブロックと、アプリケーション拡張です。したがってアニメーションするファイルや透過を少しでも持つファイルは 89a を名乗らなければなりません。不透明な静止画なら 87a を名乗っても嘘ではなく、macOS の sips などは今もそう書きます。
Netscape looping extensionGIF 仕様にはアニメーションをループさせる規定がありません。あの挙動は 21 FF 0B に続けて ASCII 11 バイトの NETSCAPE2.0 を書いたアプリケーション拡張ブロックから来ていて、その後ろのサブブロックの 2 バイト目と 3 バイト目がリトルエンディアンのループ回数、0 なら無限です。先頭数百バイトから 4E 45 54 53 43 41 50 45 を探してください。無ければ、エディタの画面で何度回っていようと再生は 1 回きりです。
PNG89 50 4E 47 と 47 49 46。透過付きの可逆なインデックス画像という点で用途が重なりますが、その用途では PNG の完勝です。透過は 1 インデックスではなく完全なアルファ、色は 256 色パレットではなくチャンネルあたり最大 16 ビット、圧縮率も上。GIF に残された唯一の強みは、video 要素なしでアニメーションすることだけです。
WebPアニメーション WebP は同じ仕事をはるかに少ないバイト数でこなす RIFF ファイルで、オフセット 0 に 52 49 46 46、オフセット 8 に 57 45 42 50、オフセット 12 にアニメーションフラグを立てた VP8X チャンクが並びます。今どきのチャットや SNS の多くは、アップロードされた GIF を WebP や MP4 に変換したうえで、同じ .gif の URL で配信し続けています。

よくある壊れ方

  • 途中切れ。ヘッダとパレットは無事なのでビューアはキャンバスの大きさを把握し、届いた分のフレームだけ描いて止まります。末尾に 3B のトレーラが無いことが決め手で、最後のフレームが途中までしか届いていない場合は LZW ストリームが尽きたところが単色の帯になります。
  • グローバルカラーテーブルのサイズが誤っている場合。オフセット 10 のバイトの下位 3 ビットが後続するパレットのバイト数を決めるので、ニブルが 1 つ狂っただけで最初のブロックの開始位置が数百バイトずれ、他のバイトがすべて正しくてもファイルは読めなくなります。
  • LZW ストリームの同期ずれ。符号は可変長でバイト境界をまたいで詰め込まれ、位置合わせの仕組みがないので、1 ビット反転するとそのフレームの残りが斜めのノイズになります。フレームごとにストリームが独立しているため、被害は次の画像ブロックで止まり、アニメーションの最後まで伝播することはありません。
  • Netscape アプリケーション拡張の消失。未知の拡張ブロックを保持しないツールを通して再エンコードするとループ回数が黙って落ち、無限に回っていたアニメーションが 1 回で止まるようになります。ファイルとして不正なところは何もないので、どのツールも問題を報告しません。
  • 廃棄方法の書き換え。各グラフィック制御拡張にある 3 ビットの廃棄フィールドが、次のフレームを描く前に今のフレームを消すかどうかを決めます。変換ツールが誤った値を書くと、フレームが前のフレームの上に積み重なっていく、あの尾を引く描画になります。ファイル自体は正しく、ただアニメーションの仕方が間違っているだけです。

この形式の現在地

GIF は 10 年前に引退していてもおかしくない形式ですが、消える気配はありません。理由はひとつ、video 要素もコーデックのライセンスも再生ボタンも要らずに、あらゆるレンダラ、メールクライアント、チャット、Wiki の中でそのまま動く唯一のアニメーション画像形式だからです。短いループクリップなら、アニメーション WebP やミュートした MP4 のほうが数分の一のサイズでしかも高画質だとしても、いちばん摩擦の少ない選択肢であり続けています。大手プラットフォームの多くが .gif のアップロードを受け付けたうえで裏で WebP や H.264 に変換し、URL の拡張子だけ据え置いているのはそのためです。静止画としての出番はもう完全にありません。1 フレーム 256 色と完全透過 1 色というパレットではあらゆる面で PNG に負けますし、かつて敬遠された LZW 特許も 2004 年に切れました。今も本当に価値があるのは、小さな UI アニメーションやスピナー、そして地味ですが、ファイル本体より周りの HTTP ヘッダのほうが大きいマーケティングメールの 1 ピクセル計測画像です。

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

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

関連する形式

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

形式先頭バイト拡張子
PNG89 50 4E 47 0D 0A.png
WebP52 49 46 46.webp
JPEGFF D8 FF.jpg

よくある質問

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

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

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