ByteScope

BMP ファイル形式

Windows Bitmap。無圧縮(または軽度の圧縮)のラスター画像形式。

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

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

0x00000000424DBM'BM' header

BMP 形式について

BMP はピクセルをほぼ生のまま保存するため、ファイルは大きくなりますが読み書きは非常に簡単で、Windows では今も中間形式として使われています。2 バイトのヘッダ BM に続いてファイルサイズとピクセル配列のオフセットが並び、その後ろに 2 つ目のヘッダ、DIB ヘッダが来ます。DIB ヘッダの最初のフィールドは自分自身の長さで、ひとつの形式が 30 年分・6 種類のヘッダ配置をさりげなく飲み込んでいるのはこの仕掛けのおかげです。行は高さが負でない限り下から上へ格納され、各行は 4 バイトの倍数までパディングされます。BMP リーダーを初めて書く人がぶつかる混乱は、だいたいこの 2 つの規則から来ています。

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

オフセット長さフィールド意味
02Signature42 4D、ASCII の BM。今の基準では 2 バイトのマジックナンバーは短すぎるので、ここで止まる検出器は BMP という単語や Bmw のような名前で始まるテキストファイルまで喜んでビットマップと判定します。直後のサイズフィールドが通例の妥当性チェックです。
24File sizeファイル全体のバイト数をリトルエンディアンで表したもので、両方のヘッダを含みます。他のたいていの形式のサイズフィールドと違ってこれは正確であることが期待されているので、ディスク上のサイズと突き合わせれば 4 バイト読むだけで整合性チェックになります。
64Reserved16 ビットのフィールドが 2 つ、どちらもゼロであることが要求されます。独自の用途のメモ帳代わりに使うエディタもあり、リーダー側は例外なく無視するので、ここが 0 でないことは破損というより、どのアプリが書いたかを示す手がかりになります。
104Offset to the pixel array実際の画素が始まるバイト位置をリトルエンディアンで、ファイル先頭から数えた値。古典的な 40 バイトの DIB ヘッダを持つ普通の 24 ビット画像なら 54 です。14 足す 40 で、間にパレットはありません。これより大きければ、隙間にパレット・カラーマスク・埋め込み ICC プロファイルのいずれかが入っています。
144DIB header size2 つ目のヘッダの長さであり、実質的には形式のバージョン番号です。12 は大昔の OS/2 BITMAPCOREHEADER、40 は BITMAPINFOHEADER でほぼどこでも目にするもの、52 と 56 はカラーマスクを追加したもの、108 は色空間フィールドを持つ BITMAPV4HEADER、124 は ICC プロファイルを持つ BITMAPV5HEADER です。
184Width符号付きリトルエンディアン 32 ビットの画素幅。符号付きですが負の幅は不正で、符号に意味があるのは高さだけです。12 バイトの OS/2 ヘッダは幅と高さを 16 ビットで格納するので、そこではこのオフセットは通用しません。
224Height符号付きリトルエンディアン 32 ビットの画素高さで、この形式でいちばん意外なフィールドです。正の値なら行は下から上、つまり画像の最終行が先に格納されていることを意味し、負の値なら上から下で、絶対値が実際の高さになります。Windows の画面キャプチャはここに負の数を書くことがよくあります。
262Colour planes必ず 1。プレーン方式のビデオメモリ時代の生き残りで、これ以外を受け付けるリーダーはありません。だからこそ BM 署名の直後に置く 2 つ目の妥当性チェックとして役に立ちます。
282Bits per pixelパレット付きなら 1・4・8、カラーマスク付きなら 16 か 32、素の BGR 三つ組なら 24。0 になるのは、圧縮フィールドがペイロードは埋め込まれた JPEG または PNG だと宣言している特殊な場合だけです。チャンネル順に注意してください。BMP は青・緑・赤の順で、このサイトの他のどの形式とも逆です。
304Compression method0 は BI_RGB、つまり圧縮なしです。1 と 2 は 8 ビット画像と 4 ビット画像のランレングス符号、3 は明示的なチャンネルマスクを持つ BI_BITFIELDS、4 と 5 は画素配列が実は JPEG ファイルまたは PNG ファイルまるごとであることを宣言します。BMP をコンテナに変えてしまう、めったに使われない抜け道です。
344Image data size画素配列のバイト数。圧縮方式が BI_RGB のときはリーダー側で計算できるので 0 でも合法です。その計算でパディング規則が効いてきます。各行は幅 × ビット深度 ÷ 8 を 4 の倍数に切り上げた大きさを占めます。
388Horizontal and vertical resolution符号付き 32 ビットが 2 つ、単位はインチではなくメートルあたりの画素数なので、96 dpi は 3780 として格納されます。ほとんどのファイルでは両方 0 で、BMP が物理サイズを記録する唯一の場所です。
468Palette entry countsパレットが実際に保持している色数と、そのうち表示に必要な色数。1 つ目が 0 なら 2 のビット深度乗の完全なパレットが存在することを意味します。ここが 0 の 256 色 BMP でも、ヘッダと画素の間に 1024 バイトのパレットが挟まっているのはそのためです。

似た形式との見分け方

紛らわしい形式見分け方
ICOICO のディレクトリエントリの中身は、14 バイトのファイルヘッダを剥がした BMP であることが非常に多く、その場合 DIB ヘッダから始まります。つまり前に BM の付かない裸の 28 00 00 00 です。さらに厄介なことに、画素配列の後ろに同じ寸法の 1 ビット AND マスクが続く関係で、高さフィールドには実際の 2 倍の値が入っています。このペイロードを ICO から取り出して .bmp として保存すると、縦に 2 倍伸びて下半分がゴミになった画像ができあがります。
Clipboard DIBWindows の CF_DIB クリップボードデータも同じくオフセット 14 から始まる BMP で、BM 署名もファイルサイズもありません。クリップボードのバイト列をそのままディスクに書くツールは、先頭 4 バイトが 28 00 00 00 のファイルを作ります。正しい画素オフセットを入れた 14 バイトの BITMAPFILEHEADER を前に付ければ、普通の .bmp に戻ります。
TIFFどちらも無圧縮の保管用途やスキャナ出力に使われ、どちらも多バイト数値をリトルエンディアンで格納しますが、ヘッダの 2 バイトで決着します。BMP は 42 4D、TIFF は 49 49 か 4D 4D。実務上の違いは、TIFF が複数ページ・任意のメタデータ・複数の圧縮方式を扱えるのに対し、BMP はちょうど 1 枚の画像しか持たず、ほぼ常に無圧縮だという点です。
PNG89 50 4E 47 と 42 4D。アルファチャンネルを使える可逆ラスターという同じ用途を狙っていて、サイズでは PNG がおよそ 1 桁勝ちます。BMP 側の言い分は、依存ライブラリなしで午後 1 回あれば正しいデコーダが書けるということで、ファームウェアのスプラッシュ画面や組み込み UI が使い続けているのはそのためです。

よくある壊れ方

  • 行パディングの忘れ。各行は 4 バイトの倍数までパディングしなければならないので、幅 63 画素の 24 ビット画像は 1 行あたり 1 バイト余分に必要です。これを省いて書き出すと行が 1 バイトずつ横にずれていき、画像は斜めにせん断されます。BMP のバグとしてはいちばん見覚えのある症状です。
  • 画素配列のオフセットの誤り。オフセット 10 の 4 バイトだけが画像データを指しているので、ツールがパレットや ICC プロファイルを挿入しながらここを更新しないと、デコーダはヘッダの一部を画素として読み始めます。結果は画像の下端に色ノイズの帯が出て、その上のすべてがずれます。
  • 高さの符号の取り違え。符号付きの高さを符号なしとして扱うリーダーは、上から下のキャプチャを 40 億超の高さと解釈してファイルを拒否します。符号を完全に無視するリーダーは絵を上下逆に描きます。どちらの失敗も、オフセット 22 にあるまったく正しい 4 バイトから生まれます。
  • 途中切れ。行は通常下から上に格納されるので、途中で切れた BMP が失うのは絵の下ではなく上です。このサイトの他のどの形式とも逆の挙動になります。オフセット 2 のサイズがディスク上のファイルと合わないので、確認はそれがいちばん速い方法です。
  • チャンネル順の入れ替わり。BMP は青・緑・赤の順で格納するので、赤・緑・青だと思い込んだ変換ツールを通すと空がオレンジ、肌が青の画像ができます。ファイルとして不正な箇所はどこにもないので、どのバリデータも報告しません。

この形式の現在地

BMP は Windows 生まれの形式で、外に出ていく理由がなく、実際に出ていきませんでした。ウェブでの居場所はありません。同じ絵を PNG にすれば画質はそのままで 10 分の 1 になるのが普通です。カメラもスマートフォンもこれを吐きません。それでも生き残っているのは、圧縮しないことがむしろ利点になる 2 つの場面があるからです。ひとつは Windows 自身で、クリップボードの画像形式は DIB ですし、画面キャプチャやスキャナのドライバは今もビットマップを渡してきます。エクスプローラのサムネイルや .exe のリソースも同じ構造の上に成り立っています。もうひとつは、デコーダを持つこと自体が高くつく場所です。ブートローダのスプラッシュ画面、マイコンのディスプレイ、プリンタのファームウェア、試験装置が BMP を読むのは、画素配列が既知のオフセットに既知の順序でそのまま置いてあり、エントロピー符号を実装しなくて済むからです。画像処理パイプラインの中間形式としても十分理にかなっています。書き出しは一瞬で、しかも完全に可逆です。やってはいけないのは、これを配信形式に使うことだけです。

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

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

関連する形式

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

形式先頭バイト拡張子
PNG89 50 4E 47 0D 0A.png
TIFF49 49 2A 00.tif
ICO00 00 01 00.ico

よくある質問

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

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

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