BMP(ビットマップ)ファイル形式の完全ガイド:歴史・ヘッダ構造・色深度・圧縮と実装ポイント

BMP とは — 概要

BMP(Bitmap、ビットマップ)は、Windows 環境で広く使われてきたラスター画像ファイル形式の一つです。拡張子は一般に .bmp(または .dib)で表され、ピクセル単位で画像データをそのまま(または簡単な圧縮で)格納するため、実装が単純で扱いやすい一方、ファイルサイズが大きくなりがちという特徴があります。BMP は歴史的に Microsoft / Windows の標準的な画像形式として発展し、バージョン(DIB ヘッダーの種類)によって機能差があります。

歴史とバージョン

  • 起源:BMP は Windows の前身である Windows/Win32 環境に由来し、OS/2 用を含むいくつかの派生が存在します。
  • DIB ヘッダーの変遷
    • BITMAPCOREHEADER(12 バイト、主に OS/2 1.x 用)
    • BITMAPINFOHEADER(40 バイト、Windows における標準)
    • BITMAPV4HEADER(108 バイト、アルファマスクやカラースペース情報の追加)
    • BITMAPV5HEADER(124 バイト、より多くのカラー管理機能とメタ情報)
  • 互換性:古いソフトウェアは BITMAPINFOHEADER(v3)までしかサポートしないことがあるため、ファイルを作る際は対象環境の対応を確認する必要があります。

ファイル構造の基本

一般的な BMP ファイルは以下の順でデータが格納されます(BITMAPINFOHEADER 型を想定):

  • Bitmap File Header(14 バイト)
  • DIB Header(例:BITMAPINFOHEADER は 40 バイト)
  • カラーパレット(存在する場合、RGBQUAD の配列)
  • ピクセルデータ(ピクセル配列/ビットマップデータ)

主なヘッダーフィールド(BITMAPFILEHEADER / BITMAPINFOHEADER):

  • bfType:先頭 2 バイトは 'BM'(0x42 0x4D、リトルエンディアンで 0x4D42 を示す)
  • bfSize:ファイル全体のバイト数
  • bfOffBits:ピクセルデータ(ビットマップ配列)へのオフセット(ヘッダー+パレット分)
  • biSize:DIB ヘッダーのサイズ(例:40)
  • biWidth / biHeight:画像の幅・高さ(ピクセル)
  • biPlanes:常に 1(歴史的理由)
  • biBitCount:1, 4, 8, 16, 24, 32 などのビット深度
  • biCompression:圧縮方法(BI_RGB(非圧縮)、BI_RLE8、BI_RLE4、BI_BITFIELDS など)
  • biSizeImage:画像データのサイズ(バイト)。0 の場合もあり得る
  • biClrUsed / biClrImportant:カラーパレットの使用数や重要色数

ピクセル表現と色深度

BMP は複数のビット深度をサポートします。用途に応じてピクセルの表現方法が異なります。

  • 1-bit, 4-bit, 8-bit:各ピクセルはパレット(カラーテーブル)のインデックスとして格納される。パレットは RGBQUAD(青・緑・赤・予約 1 バイト)で表現される。8-bit の場合は典型的に 256 色パレットが使われます。
  • 16-bit:一般に 5-5-5(赤5・緑5・青5)または 5-6-5(赤5・緑6・青5)などのフォーマット。BITFIELDS(ビットマスク)を用いて個々の色ビット位置を指定することがある。
  • 24-bit:各ピクセルを 3 バイト(B, G, R の順)で格納。アルファは含まれないが、シンプルで互換性が高い。
  • 32-bit:通常 B, G, R, A(アルファ)順で 4 バイト。BITMAPV4/V5 でアルファや色空間情報をサポートするようになった。ただし、従来の GDI 処理ではアルファが無視される場合もある。

行のパディング(ストライド)と画素配置

BMP は各スキャンライン(行)のデータ長を 4 バイト境界に揃える(4 バイト単位でパディング)必要があります。これにより、行バイト数(stride)を計算する際は次式が用いられます。

rowSize(バイト) = ((bitsPerPixel * width + 31) / 32) * 4

例:24-bit、幅 101 ピクセルの場合、実データは 101 × 3 = 303 バイトだが、4 バイト境界に揃えるため 304 バイトとして格納される(1 バイトのパディング)。

また biHeight が正の値だとピクセルデータは「下から上」順(ボトムアップ)で保存され、負の値だと「上から下」順(トップダウン)で保存されます。

圧縮方式と特殊形式

  • BI_RGB(値 0):非圧縮(実務上「無圧縮」)。BMP の基本。
  • BI_RLE8 / BI_RLE4:ランレングス圧縮(8-bit / 4-bit 用)。簡単な圧縮だが汎用性は限定的。
  • BI_BITFIELDS(値 3):16-bit や 32-bit で色マスクを指定する方式。各色のビット位置・幅を明示できる。
  • BI_JPEG / BI_PNG(値 4 / 5):内部に JPEG / PNG データを格納する非標準的な拡張。すべてのビューアでサポートされるとは限らない。
  • BI_ALPHABITFIELDS(値 6 などの拡張):アルファ情報用マスクを扱うための指定(Windows の拡張)。

BGR 順序とエンディアン

BMP のピクセルは一般に B, G, R(下位バイトが青)順で並びます(24-bit:B G R、32-bit:B G R A)。ファイルはリトルエンディアンで数値を格納するため、マルチバイトの整数フィールドはリトルエンディアンで読み書きする必要があります。

拡張機能:アルファ、カラーマネジメント、ICC プロファイル

BITMAPV4HEADER / V5HEADER では色マスクやアルファ、さらにはカラースペース情報(サイフォマトや色空間の識別子、ICC プロファイルの埋め込み)を扱えます。これにより、BMP でも高度な色管理や透過をサポート可能になりましたが、古いビューアやライブラリではこれらを解釈できないことがあるため注意が必要です。

利点と欠点(用途)

  • 利点
    • 実装が簡単でパースが容易(ヘッダー構造が明確)
    • 非圧縮のため画像劣化がない(可逆)
    • Windows 系アプリケーションとの互換性が高い
  • 欠点
    • ファイルサイズが大きく、Web 配信・記憶効率が悪い(PNG/JPEG/WebP に比べ不利)
    • 古い仕様ではアルファや色空間対応が弱い
    • 複数の派生(OS/2 版など)とヘッダーの違いにより、互換性問題が起きることがある

セキュリティと実装上の注意点

単純な形式である一方、実装ミス(不十分な境界チェック、整数オーバーフロー、巨大な biSizeImage 値の扱いなど)は脆弱性を生むことがあります。外部から受け取った BMP を扱う場合は、ヘッダーの整合性チェック(bfOffBits がファイル長を超えないか、biSize / biHeight / biWidth の妥当範囲など)を厳格に行うべきです。

実用的な読み書きのポイント(チェックリスト)

  • bfType が 'BM' であることを確認する
  • bfOffBits(ピクセルデータ開始位置)がヘッダ長+パレットを含んだ適切な位置であることを確認する
  • biSize(DIB ヘッダーのサイズ)に応じて読み取るヘッダー構造を切り替える(12/40/108/124 バイトなど)
  • ビット深度に応じたパレットの読取り、またはビットマスク(BITFIELDS)の適用を行う
  • 行のパディング(4 バイト境界)を正しく扱う
  • biHeight の正負で行の並び(ボトムアップ/トップダウン)を判定する
  • ファイルサイズや画像データサイズが矛盾していないかを確認する(オーバーフロー対策)

BMP を使うべき場面と代替形式

BMP は編集や一時保存、Windows ネイティブな処理パイプライン向けの中間形式として便利ですが、配信用(特に Web)では PNG(可逆圧縮、アルファ対応)や JPEG(写真向けの非可逆圧縮)に置き換えることが一般的です。近年は WebP や AVIF といった新しいフォーマットも登場しており、圧縮効率や機能で BMP を凌駕します。

まとめ

BMP は歴史が深く理解しやすいファイル形式で、ピクセルデータを直接的に格納するため学習や低レベル実装、Windows 系アプリとの連携に適しています。一方で、ファイルサイズや古い仕様による制約を理解したうえで、用途に応じて PNG や JPEG などの形式を選択するのが現代的な運用と言えます。実装時にはヘッダの多様性、パディング、エンディアン、圧縮方式、色マスク、そして入力検証に注意してください。

参考文献