0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Bitmap(*.bmp)ファイルフォーマット徹底解説!~基本から内部構造まで~

Last updated at Posted at 2025-04-12

はじめに

Bitmapファイル(*.bmp)は、画像データの先頭に画像の幅や高さ、ビット数などの情報を付加し、バイナリデータとしてファイルに保存されたファイルなので、画像データをプログラムから扱うのは、非常に便利なフォーマットです。

また、Bitmapファイルは、Jpegファイルのように画像ファイルに保存→読込をすることで、保存前の画像データとの誤差も生じないため、画像処理をする画像データを保存するには、Bitmapファイルフォーマットが良く用いられます。

最近では、C++ではOpenCV、C#では.NETのBitmapクラスなどがあるので、Bitmapファイルの中身を意識することなく、Bitmapファイルに保存/読込ができます。

工業用のカメラでは、1画素あたり10bit、12bitのグレースケールに対応したカメラがかなり普及してきていますが、OpenCVや.NETのライブラリでは、10bitや12bitの画像に対応していないことの方が多いのですが、ビットフィールと呼ばれる少々特殊な設定をすることで、Bitmapファイルでも対応することが可能となります。

そのため、Bitmapファイルの中身の構造を理解しておくことが重要となります。

Bitmapファイルの内部構造

Bitmapファイルは、決まった位置に特定の情報が配置されたメモリを、バイナリファイルとして保存することで、Bitmapファイル(*.bmp)となります。

この配置位置と、それぞれの意味について説明します。

Bitmapファイル全体の構造

まず、Bitmapファイルがどのようなブロックで構成されているか、全体像を把握しましょう。

BITMAPFILEHEADER ビットマップファイルヘッダー
ファイル全体の情報を格納
14バイト
BITMAPINFOHEADER ビットマップインフォヘッダー
幅、高さ、ビット数などの画像データに関する情報を格納
40バイト
カラーパレット(無い場合もあり) 画像データをどの色でモニタ上に表示するか?の設定 4 x index数
画像データ 画像データが、通常、画像の左下を原点として格納されている。
24bitカラー画像の場合は、B, G, R, B, G, R・・の順番

それでは、各ブロックの詳細を見ていきましょう。

1. ファイルヘッダー (BITMAPFILEHEADER): 14バイト固定

  • ファイルの先頭に必ず存在し、ファイルがBMPであることや、ピクセルデータまでのオフセットなどを示します。

    オフセット(byte) サイズ(byte) フィールド名 説明
    0 2 bfType ファイルタイプ。必ず "BM" (0x4D42)
    2 4 bfSize ファイル全体のサイズ (バイト)
    6 2 bfReserved1 予約領域 (通常 0)
    8 2 bfReserved2 予約領域 (通常 0)
    10 4 bfOffBits ファイル先頭からピクセルデータの開始位置までのオフセット (バイト)

2. 情報ヘッダー (BITMAPINFOHEADER): 40バイト固定

  • 画像の詳細情報(幅、高さ、色深度、圧縮形式など)を格納します。

    オフセット(byte) サイズ(byte) フィールド名 説明
    14 4 biSize この情報ヘッダーのサイズ (バイト)。通常 40 (0x28)。
    18 4 biWidth 画像の幅 (ピクセル)
    22 4 biHeight 画像の高さ (ピクセル)。
    正の値はボトムアップ形式 (左下原点)
    負の値はトップダウン形式 (左上原点)
    使用するプログラムによっては、負の値に対応していない場合もあります。
    26 2 biPlanes プレーン数 (常に 1)
    28 2 biBitCount 1ピクセルあたりのビット数 (色深度)。1, 4, 8, 16, 24, 32 など。
    30 4 biCompression 圧縮形式 (下記参照)
    34 4 biSizeImage ピクセルデータ部分のサイズ (バイト)。
    無圧縮(BI_RGB)の場合、0でも可 (パディング込みで計算可能)。
    38 4 biXPelsPerMeter 水平解像度 (ピクセル/メートル)。通常 0。
    42 4 biYPelsPerMeter 垂直解像度 (ピクセル/メートル)。通常 0。
    46 4 biClrUsed カラーパレット内の色数。
    0の場合、biBitCountに基づいて最大色数が使われる (例: 8bitなら256色)。
    50 4 biClrImportant 重要な色の数。0の場合、全ての色が重要。

3. カラーパレット (Color Palette) または ビットマスク: オプション、可変長

  • biBitCount が 1, 4, 8 の場合に存在します (インデックスカラー)。

    • biClrUsed で指定された数、または biBitCount から計算される最大色数分の RGBQUAD 構造体の配列です。
    • RGBQUAD 構造体 (4バイト): 青(B), 緑(G), 赤(R), 予約(通常0) の順で各1バイト。
  • カラーパレット: BMPファイル、特に色数が少ない画像(1bit, 4bit, 8bit)を効率的に格納するために「カラーパレット」という仕組みを利用します。これは「インデックスカラー」方式とも呼ばれます。

    カラーパレットが存在する条件:

    • 情報ヘッダーの biBitCount (1ピクセルあたりのビット数) が 1, 4, 8 のいずれかであり、かつ biCompressionBI_RGB または BI_RLE8, BI_RLE4 の場合に、カラーパレットが必須となります。
    • biBitCount が 16, 24, 32 の場合は、基本的にピクセルデータに直接色情報が含まれるため、カラーパレットは通常使用しません

    カラーパレットの構造:

    • カラーパレットは、情報ヘッダー (BITMAPINFOHEADER など) の直後、かつピクセルデータの前に配置されます。

    • パレットは、RGBQUAD という構造体の配列で構成されます。RGBQUAD は1つの色を定義するための4バイトのデータです。

      typedef struct tagRGBQUAD {
        BYTE rgbBlue;      // 青成分 (0-255)
        BYTE rgbGreen;     // 緑成分 (0-255)
        BYTE rgbRed;       // 赤成分 (0-255)
        BYTE rgbReserved;  // 予約領域 (通常は 0)
      } RGBQUAD;
      
      • rgbBlue, rgbGreen, rgbRed で色の三原色を各8ビット(0-255)で指定します。
      • rgbReserved は通常0ですが、ファイル形式やアプリケーションによってはアルファ値(不透明度)として解釈される可能性もゼロではありません(ただしBMPの標準的な仕様ではありません)。

    パレットのサイズ (色数):

    • パレットに格納される RGBQUAD 構造体の数(=パレットの色数)は、情報ヘッダーの biClrUsed フィールドによって決まります。
      • biClrUsed が 0 より大きい値の場合: その値がパレットの色数となります。例えば biClrUsed が 100 なら、100個の RGBQUAD (計 400バイト) がパレットとして存在します。ただし、biBitCount で表現可能な最大色数を超えることはできません (例: 4bit画像なら biClrUsed は16以下)。
      • biClrUsed が 0 の場合: biBitCount が示す最大の色数がパレットサイズとなります。
        • biBitCount = 1 : 2色 (2^1) のパレット (通常、白と黒)
        • biBitCount = 4 : 16色 (2^4) のパレット
        • biBitCount = 8 : 256色 (2^8) のパレット
          この場合、パレットの合計バイト数は (2^biBitCount) * sizeof(RGBQUAD) となります。

    ピクセルデータとの関係:

    • biBitCount が 1, 4, 8 の場合、ピクセルデータには実際のRGB値ではなく、**カラーパレットのインデックス(番号)**が格納されています。
    • 例えば、8bit画像 (biBitCount=8) の場合、ピクセルデータは1バイト単位で読み込まれ、そのバイト値 (0~255) がそのままカラーパレットのインデックスとなります。値が 10 であれば、カラーパレットの11番目 (0から数えるため) の RGBQUAD で定義された色が、そのピクセルの色となります。
    • 4bit画像 (biBitCount=4) の場合、1バイトに2ピクセル分の情報が含まれます。通常、上位4ビットが1ピクセル目のインデックス (0~15)、下位4ビットが2ピクセル目のインデックス (0~15) となります。
    • 1bit画像 (biBitCount=1) の場合、1バイトに8ピクセル分の情報が含まれます。各ビットがインデックス (0または1) に対応します。
  • ビットマスク (BI_BITFIELDS 指定時):

    • 情報ヘッダーの biCompression フィールドに BI_BITFIELDS (値: 3) が指定されている場合、これは通常 16bpp または 32bpp のダイレクトカラーモードで使用されます。
    • このモードでは、ピクセルデータ内のビットがどの色成分(赤、緑、青、場合によってはアルファ)に対応するかを定義するためのビットマスクが必要となります。
    • 重要: BI_BITFIELDS が指定された場合、カラーパレットは存在しません。カラーパレットが配置されるべき場所(情報ヘッダーの直後)には、代わりに RGB のビットマスクが配置されます。
    • 具体的には、情報ヘッダーの直後に、以下の3つの DWORD (符号なし4バイト整数、計12バイト) がこの順序で格納されます。
      1. Red Mask: ピクセルデータ内の赤成分に対応するビットを示すマスク (例: 16bit 5-6-5 なら 0xF800)。
      2. Green Mask: ピクセルデータ内の緑成分に対応するビットを示すマスク (例: 16bit 5-6-5 なら 0x07E0)。
      3. Blue Mask: ピクセルデータ内の青成分に対応するビットを示すマスク (例: 16bit 5-6-5 なら 0x001F)。
    • これらのマスクがあるため、ソフトウェアはピクセルデータ(16bit または 32bit の値)から正確な RGB 値を抽出できます。

4. ピクセルデータ (Pixel Data):

  • 実際の画像データが格納されます。
    この開始位置はファイルヘッダーの bfOffBits で示されます。
  • 格納順序:
    • biHeightの場合: ボトムアップ形式。画像の一番下の行から一番上の行へ、各行は左から右へ格納されます。基本的にこちらを使う
      ImageData.png

    • biHeightの場合: トップダウン形式。画像の一番上の行から一番下の行へ、各行は左から右へ格納されます。(比較的新しい形式で、biCompressionBI_RGB または BI_BITFIELDS の場合にのみ有効)

負の値に対応していないプログラムもあるので注意

  • パディング (Padding):

    • 各行のデータサイズ(バイト数)は、必ず4バイトの倍数になるように、末尾に0x00などのパディングデータが付加されます。これはメモリアクセス効率のためです。
    • 計算式: stride = floor((biBitCount * biWidth + 31) / 32) * 4
    • ピクセルデータ全体のサイズ (biSizeImage) は、無圧縮の場合 stride * abs(biHeight) で計算できます。
      (例) 8bitモノクロ 802 x 600画素の画像の場合
      メモリ上は 804 x 600画素分用意し、行の最後(右側)の2画素分の値は0にします。
  • 色深度ごとのデータ形式:

    • 1-bit: 1ピクセルを1ビットで表現。8ピクセルで1バイト。値はカラーパレットのインデックス0または1に対応。バイト内のビット順は通常、最上位ビット(MSB)が左端のピクセルに対応。
    • 4-bit: 1ピクセルを4ビットで表現。2ピクセルで1バイト。通常、1バイトの上位4ビットが左側のピクセル、下位4ビットが右側のピクセルのインデックス(0-15)に対応。
    • 8-bit: 1ピクセルを8ビット(1バイト)で表現。値はカラーパレットのインデックス(0-255)。
    • 16-bit: 1ピクセルを16ビット(2バイト)で表現。
      • biCompression = BI_RGB: 通常 RGB 5-5-5 形式 (最上位ビットは予約)。赤・緑・青 各5ビット。
      • biCompression = BI_BITFIELDS: ヘッダー直後のビットマスクに従って RGB 値を格納。一般的なのは RGB 5-6-5 形式(赤5, 緑6, 青5ビット)。
    • 24-bit: 1ピクセルを24ビット(3バイト)で表現。B, G, R の順で各8ビット。カラーパレットは使用しない (フルカラー)。
    • 32-bit: 1ピクセルを32ビット(4バイト)で表現。
      • biCompression = BI_RGB: 通常 B, G, R, 予約(未使用, A) の順で各8ビット。予約バイトはC言語では0を指定する場合が多かったか、.NETではアルファ値(透過率)として使われ、不透明の場合255を指定する。
      • biCompression = BI_BITFIELDS: ヘッダー直後のビットマスクに従って RGB(A) 値を格納。
  • 圧縮形式 (biCompression フィールドの値):

    • 0 (BI_RGB): 無圧縮 (最も一般的)
    • 1 (BI_RLE8): 8-bit Run-Length Encoding (8bppボトムアップ画像用)
    • 2 (BI_RLE4): 4-bit Run-Length Encoding (4bppボトムアップ画像用)
    • 3 (BI_BITFIELDS): ビットフィールド指定 (16bpp, 32bpp画像用)。
      カラーマスクが情報ヘッダ直後 (カラーパレットの代わり) に配置される。トップダウン形式も可能。
    • 4 (BI_JPEG): JPEG圧縮されたデータを含む (埋め込みJPEG、稀)
    • 5 (BI_PNG): PNG圧縮されたデータを含む (埋め込みPNG、稀)

モノクロ10~16bit画像の場合

ビットフィールドの設定を用います。

BITMAPFILEHEADERbfOffBitsを66 (= 14 + 40 + 4 x 3)
BITMAPINFOHEADERbiBitCountを16
BITMAPINFOHEADERbiCompressionBI_BITFIELDS
に設定します。
さらに、カラーパレットとしてRGBQUADを3つ分使用します。
ここでは、カラーパレットというよりも、1画素のデータのビット数(16bit)に対して、どのビットが有効なのか?を示すビットマスクとして用います。

RGBQUADの3つのうち、
bmiColors[0]がR(赤)
bmiColors[1]がG(緑)
bmiColors[2]がB(青)
の画像表示色のビットマスクとなります。

例えば、モノクロ10bitの場合、16bit中下位10bitが有効データとなります。
ビットで表現すると 0000001111111111 となります。
16進数で32bitの値として表現すると 0x0003FF となります。

これをRGBQUADで表すと、RGBQUAD全体32bit中の上位ビットから順に

rgbReserved, rgbRed, rgbGreen, rgbBlue

の順番で並んでいるので、最終的にカラーパレットは

// Rのビットマスク
bmiColors[0].rgbReserved = 0x00
bmiColors[0].rgbRed = 0x00
bmiColors[0].rgbGreen = 0x03
bmiColors[0].rgbBlue = 0xFF
// Gのビットマスク
bmiColors[1].rgbReserved = 0x00
bmiColors[1].rgbRed = 0x00
bmiColors[1].rgbGreen = 0x03
bmiColors[1].rgbBlue = 0xFF
// Bのビットマスク
bmiColors[2].rgbReserved = 0x00
bmiColors[2].rgbRed = 0x00
bmiColors[2].rgbGreen = 0x03
bmiColors[2].rgbBlue = 0xFF

となります。

ビットフィールドの設定は、あまり一般的に用いられてません。
そのためビットフィールドに対応していないプログラム、ライブラリが多くありますが、Windowsのフォトアプリでは、ビットフィールドの値が反映され、画像が表示されます。

モノクロの10~16bitで保存したBitmap画像ファイルはWindowsのエクスプローラでは32bitと表示されます。

2025-04-12_18h24_42.png

おまけ。便利ツールの紹介

Bitmapファイルは、画像データにヘッダ情報が付いたただのバイナリファイルなので、Bitmapファイルの構造を確認するには、バイナリエディタがあると便利です。

私が良くお世話になっているのは、 TSXBIN というソフト
これ、かなりおススメです。
https://www.vector.co.jp/soft/dl/winnt/util/se513258.html

下記の画像は、モノクロ10bitのBitmapファイルを、TSXBINで表示した時の画面です。
2025-04-12_18h17_41.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?