ByteScope

ICO ファイル形式

Windows のアイコンファイル。1 つ以上の小さなラスター画像を格納します。

MIME タイプ
image/x-icon
拡張子
.ico
カテゴリ
画像

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

0x0000000000000100····reserved + type 1 (icon)

ICO 形式について

ICO は同じアイコンを複数サイズまとめて格納するため、OS が適切なサイズを選べます。ブラウザは favicon にも使います。ヘッダは予約領域のゼロワード、画像タイプ 1、画像数と続き、そのあとに画像 1 つにつき 16 バイトのディレクトリエントリが並んで、それぞれの寸法・色深度・バイト長・ファイル内の位置を伝えます。ペイロード自体は独自の形式ではありません。ファイルヘッダを取り除いた Windows の DIB か、Windows Vista 以降なら PNG ファイルをまるごと埋め込んだもののどちらかです。つまり ICO は他の画像の山の前に置かれた小さな索引で、読むというのはまずディレクトリを読み、エントリごとに処理を振り分けることを意味します。

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

オフセット長さフィールド意味
02Reserved必ず 00 00。直後のタイプフィールドと合わせてこれがこの形式のマジックナンバーのすべてで、4 バイトのうち 2 バイトがゼロという異様に弱いものです。検出器は画像数が妥当か、最初のディレクトリエントリがファイル内を指しているかも併せて確認すべきです。
22Resource type01 00 ならアイコン、02 00 ならカーソル。.ico と .cur の違いはこの 1 バイトだけで、ヘッダもディレクトリもペイロードも他はまったく同じです。そして少し先の 2 つのフィールドが、この値によって意味を変えます。
42Image countファイル内の画像数をリトルエンディアンで表したもので、そのままこの直後に続く 16 バイトのディレクトリエントリの個数になります。favicon なら 2〜3 サイズが普通、Windows のアプリケーションアイコンなら 16 画素から 256 画素まで 6 個以上入っていることも珍しくありません。
61Width of the first image1 バイトなので表せる最大値は 255 です。Windows Vista が導入した 256 画素のアイコンは、0 を 256 と定義することで扱っています。バイトを額面どおり受け取るリーダーは幅 0 の画像を作り、たいていゼロ除算します。
71Height of the first image同じ符号化で、0 が 256 を意味する規則も同じです。DIB ヘッダと違ってこちらは本当の表示高さで、埋め込まれたビットマップが申告する 2 倍の値とは異なります。PNG 以外のエントリでは、この 2 つは設計上必ず食い違います。
81Palette entry count画像が使う色数。1 画素 8 ビット以上でパレットを持たない場合は 0 です。今どきの 32 ビットアイコンはここに必ず 0 を書きます。
91Reserved必ず 0。ファイル全体でも数少ない、解釈がまったく存在しないバイトです。だからこそ、弱い 4 バイトのマジックが本当にアイコンを意味しているか判断するときの追加チェックとして使えます。
102Colour planes, or cursor hotspot Xアイコンでは 0 か 1 であるべきで、リーダーは両方受け付けます。Pillow は 0 を、Windows のツール群は 1 を書きます。カーソルではこの同じ 2 バイトがホットスポットの X 座標、つまりポインタの先端とみなされる画素の位置になります。
122Bits per pixel, or cursor hotspot Yリトルエンディアンの色深度で、今どき誰もが書くアルファ合成アイコンなら 32、レガシーのパレットアイコンなら 8 か 4 です。カーソルではこの 2 バイトが縦方向のホットスポット座標になり、.cur を .ico にリネームすると色深度がありえない値になるのはそのためです。
144Size of the image dataこのエントリのペイロードのバイト長で、中身がヘッダなしの DIB でも PNG まるごとでも同じです。次のフィールドのオフセットに足せば後続画像の位置が出るので、何もデコードせずにディレクトリを歩いてファイルサイズと突き合わせられます。
184Offset of the image dataこのエントリのペイロードがファイル先頭から数えてどこから始まるか。画像 2 つのアイコンなら 1 つ目のエントリでは 38 です。6 バイトのヘッダに 16 バイトのエントリが 2 つ。ICO のレイアウトはすべて、決め打ちではなくこのポインタから発見します。
2216Second directory entryエントリは詰めて並んだ配列なので、2 つ目は 22、3 つ目は 38 から、同じ 12 フィールド構成で続きます。慣習的に大きいものから並べますが強制ではなく、Windows もブラウザも順序に依存していません。

似た形式との見分け方

紛らわしい形式見分け方
PNG今どきの ICO は PNG ファイルをまるごと抱えていることが多いので、hex ダンプには 89 50 4E 47 0D 0A 1A 0A が現れます。ただしオフセット 0 ではありません。画像 2 つの favicon なら、たいてい最初のディレクトリエントリのオフセットフィールドが指すとおり、オフセット 38 に出てきます。結論を出す前にオフセット 0 を読んでください。00 00 01 00 なら中身がたまたま PNG のアイコン、89 50 4E 47 なら誰かが .ico と名付けた PNG です。
CUR決め手はオフセット 2 のバイトだけです。タイプ 1 がアイコン、タイプ 2 がカーソルで、その結果オフセット 10 の 2 バイトとオフセット 12 の 2 バイトが、カラープレーンとビット深度ではなくホットスポット座標に変わります。カーソルをアイコンとして開くと 1 画素 12 ビットのような意味不明な色深度が報告されるのはそのためです。
BMPエントリのペイロードがビットマップの場合、それは正しい .bmp ファイルではありません。14 バイトの BITMAPFILEHEADER が剥がされているのでペイロードは DIB ヘッダのサイズ 28 00 00 00 から始まり、その中の高さフィールドは実際の 2 倍です。色データの後ろに同じ寸法の 1 ビット AND 透明マスクが続くためです。ペイロードを取り出して .bmp にリネームすると、縦 2 倍で絵の下にマスクがノイズとして見える画像になります。
PNG/SVG faviconバイトレベルの判定ではなく、実際に必要になる実務上の判断です。ブラウザは link rel=icon 要素経由ならどのパスに置かれた PNG や SVG でも何年も前から受け付けますし、拡張子に関係なく /favicon.ico で配られた PNG も受け付けます。今も本当に ICO コンテナを要求するのは Windows 自身、つまりエクスプローラ・タスクバー・.exe のリソースと、/favicon.ico を無条件に取りに来る非常に古いブラウザです。

よくある壊れ方

  • ディレクトリエントリがファイル末尾より先を指している場合。画像はそれぞれ独立して到達されるので、結果は部分的になります。16 画素のアイコンは描けて 256 画素は空白になったり、どのサイズを要求したかによってあるブラウザでは favicon が出て別のブラウザでは出なかったりします。チェックは算数です。すべてのエントリでオフセット足すサイズがファイル長を超えてはいけません。
  • PNG を favicon.ico にリネームしたもの。ファイル自体はどこも壊れていませんが、オフセット 0 が 00 00 01 00 ではなく 89 50 4E 47 と読めます。今のブラウザはどれも受け付けるのでウェブ上では動き、Windows やインストーラ、古いツールチェーンがアイコンリソースとして読もうとした瞬間に失敗します。
  • 画像数とエントリの数が食い違っている場合。サイズを 1 つ削ったのにオフセット 4 のカウンタを減らさないツールを通すと、リーダーは最初のペイロードの 16 バイトを 13 個目のディレクトリエントリとして解析し、ありえないオフセットを持つエントリができあがります。雑なソフトウェアではエラーではなくクラッシュになります。
  • 256 画素のサイズを 0 ではなく 256 と書いてしまう場合。幅も高さも 1 バイトなので、そもそも書けません。ここを間違える書き手は事故的に 0 に切り詰めてしまい、0 は 256 という規則を実装していないリーダーはサイズ 0 の画像だと報告します。同じファイルが Windows では大きなアイコンで、他の場所では不正なファイルになります。
  • DIB ペイロードの AND マスクが欠けているか、サイズが違う場合。色データは問題なくデコードでき、透明部分だけがゴミになるので、それ以外は正しいアイコンの周りに黒や白の四角が出ます。雑に変換されたアイコンセットでおなじみの症状です。

この形式の現在地

ICO が今も存在する理由は、実質ひとつです。ブラウザは HTML が求めていようといまいと、いまだにサイトのルートに /favicon.ico を取りに来るので、ひとつ置いておくのがログに余計な 404 を残さず、ブックマーク一覧に何かを表示させるいちばん安上がりな方法だからです。それ以外では Windows のリソース形式で、エクスプローラのアイコン、ショートカットのアイコン、タスクバーの項目、.exe や .dll にコンパイルされたアイコンリソースはすべて同じディレクトリ+ペイロード構造を使います。ウェブの実務はすでに先へ進んでいます。link rel=icon で宣言した SVG 1 つがブラウザの欲しがるあらゆるサイズに伸縮しますし、ベクターを受け付けないプラットフォームは PNG を数枚置けば足ります。多くのサイトが今、2 サイズだけの小さな .ico をレガシー用フォールバックとして置き、本気の作業は PNG と SVG のほうに注いでいるのはそのためです。ICO にしかできないことが 1 つだけ残っています。サイズごとに本当に別の絵を束ねられることです。16 画素のアイコンが縮小版ではなく簡略化した別の絵であるべきときには、これが効いてきます。

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

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

関連する形式

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

形式先頭バイト拡張子
PNG89 50 4E 47 0D 0A.png
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 でも悪意のあるペイロードを含んでいることがあります。特に拡張子とバイト列が食い違うときに真の形式を知るのは有用な第一段階ですが、マルウェアスキャンではありません。

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