BMP ファイル形式
Windows Bitmap。無圧縮(または軽度の圧縮)のラスター画像形式。
- MIME タイプ
- image/bmp
- 拡張子
- .bmp
- カテゴリ
- 画像
マジックナンバー(ファイル署名)
| 0x00000000 | 424D | BM | 'BM' header |
BMP 形式について
BMP はピクセルをほぼ生のまま保存するため、ファイルは大きくなりますが読み書きは非常に簡単で、Windows では今も中間形式として使われています。2 バイトのヘッダ BM に続いてファイルサイズとピクセル配列のオフセットが並び、その後ろに 2 つ目のヘッダ、DIB ヘッダが来ます。DIB ヘッダの最初のフィールドは自分自身の長さで、ひとつの形式が 30 年分・6 種類のヘッダ配置をさりげなく飲み込んでいるのはこの仕掛けのおかげです。行は高さが負でない限り下から上へ格納され、各行は 4 バイトの倍数までパディングされます。BMP リーダーを初めて書く人がぶつかる混乱は、だいたいこの 2 つの規則から来ています。
ヘッダーの構造(バイト単位)
| オフセット | 長さ | フィールド | 意味 |
|---|---|---|---|
| 0 | 2 | Signature | 42 4D、ASCII の BM。今の基準では 2 バイトのマジックナンバーは短すぎるので、ここで止まる検出器は BMP という単語や Bmw のような名前で始まるテキストファイルまで喜んでビットマップと判定します。直後のサイズフィールドが通例の妥当性チェックです。 |
| 2 | 4 | File size | ファイル全体のバイト数をリトルエンディアンで表したもので、両方のヘッダを含みます。他のたいていの形式のサイズフィールドと違ってこれは正確であることが期待されているので、ディスク上のサイズと突き合わせれば 4 バイト読むだけで整合性チェックになります。 |
| 6 | 4 | Reserved | 16 ビットのフィールドが 2 つ、どちらもゼロであることが要求されます。独自の用途のメモ帳代わりに使うエディタもあり、リーダー側は例外なく無視するので、ここが 0 でないことは破損というより、どのアプリが書いたかを示す手がかりになります。 |
| 10 | 4 | Offset to the pixel array | 実際の画素が始まるバイト位置をリトルエンディアンで、ファイル先頭から数えた値。古典的な 40 バイトの DIB ヘッダを持つ普通の 24 ビット画像なら 54 です。14 足す 40 で、間にパレットはありません。これより大きければ、隙間にパレット・カラーマスク・埋め込み ICC プロファイルのいずれかが入っています。 |
| 14 | 4 | DIB header size | 2 つ目のヘッダの長さであり、実質的には形式のバージョン番号です。12 は大昔の OS/2 BITMAPCOREHEADER、40 は BITMAPINFOHEADER でほぼどこでも目にするもの、52 と 56 はカラーマスクを追加したもの、108 は色空間フィールドを持つ BITMAPV4HEADER、124 は ICC プロファイルを持つ BITMAPV5HEADER です。 |
| 18 | 4 | Width | 符号付きリトルエンディアン 32 ビットの画素幅。符号付きですが負の幅は不正で、符号に意味があるのは高さだけです。12 バイトの OS/2 ヘッダは幅と高さを 16 ビットで格納するので、そこではこのオフセットは通用しません。 |
| 22 | 4 | Height | 符号付きリトルエンディアン 32 ビットの画素高さで、この形式でいちばん意外なフィールドです。正の値なら行は下から上、つまり画像の最終行が先に格納されていることを意味し、負の値なら上から下で、絶対値が実際の高さになります。Windows の画面キャプチャはここに負の数を書くことがよくあります。 |
| 26 | 2 | Colour planes | 必ず 1。プレーン方式のビデオメモリ時代の生き残りで、これ以外を受け付けるリーダーはありません。だからこそ BM 署名の直後に置く 2 つ目の妥当性チェックとして役に立ちます。 |
| 28 | 2 | Bits per pixel | パレット付きなら 1・4・8、カラーマスク付きなら 16 か 32、素の BGR 三つ組なら 24。0 になるのは、圧縮フィールドがペイロードは埋め込まれた JPEG または PNG だと宣言している特殊な場合だけです。チャンネル順に注意してください。BMP は青・緑・赤の順で、このサイトの他のどの形式とも逆です。 |
| 30 | 4 | Compression method | 0 は BI_RGB、つまり圧縮なしです。1 と 2 は 8 ビット画像と 4 ビット画像のランレングス符号、3 は明示的なチャンネルマスクを持つ BI_BITFIELDS、4 と 5 は画素配列が実は JPEG ファイルまたは PNG ファイルまるごとであることを宣言します。BMP をコンテナに変えてしまう、めったに使われない抜け道です。 |
| 34 | 4 | Image data size | 画素配列のバイト数。圧縮方式が BI_RGB のときはリーダー側で計算できるので 0 でも合法です。その計算でパディング規則が効いてきます。各行は幅 × ビット深度 ÷ 8 を 4 の倍数に切り上げた大きさを占めます。 |
| 38 | 8 | Horizontal and vertical resolution | 符号付き 32 ビットが 2 つ、単位はインチではなくメートルあたりの画素数なので、96 dpi は 3780 として格納されます。ほとんどのファイルでは両方 0 で、BMP が物理サイズを記録する唯一の場所です。 |
| 46 | 8 | Palette entry counts | パレットが実際に保持している色数と、そのうち表示に必要な色数。1 つ目が 0 なら 2 のビット深度乗の完全なパレットが存在することを意味します。ここが 0 の 256 色 BMP でも、ヘッダと画素の間に 1024 バイトのパレットが挟まっているのはそのためです。 |
似た形式との見分け方
| 紛らわしい形式 | 見分け方 |
|---|---|
| ICO | ICO のディレクトリエントリの中身は、14 バイトのファイルヘッダを剥がした BMP であることが非常に多く、その場合 DIB ヘッダから始まります。つまり前に BM の付かない裸の 28 00 00 00 です。さらに厄介なことに、画素配列の後ろに同じ寸法の 1 ビット AND マスクが続く関係で、高さフィールドには実際の 2 倍の値が入っています。このペイロードを ICO から取り出して .bmp として保存すると、縦に 2 倍伸びて下半分がゴミになった画像ができあがります。 |
| Clipboard DIB | Windows の 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 枚の画像しか持たず、ほぼ常に無圧縮だという点です。 |
| PNG | 89 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 と混同しやすい形式です。先頭バイトを見比べてください。