■BMP形式(Windows DIB)

-- BMP形式入門 - BMPファイルの中身をちょっと覗いてみる --

間違い・誤字脱字を発見した場合はメールまたはBBSでお知らせください。

□ はじめに
□ BMP形式とは...
□ 全体の構造
□ ビットマップファイルヘッダ
□ ビットマップ情報ヘッダ
□ RGBQUAD構造体
□ ビット配列
□ 番外編 - ビットマップオブジェクト関連のWin32API関数

□ はじめに

デバイス独立ビットマップ(Device-Independent Bitmap)のフォーマットは情報ヘッダのちがいによってOS/2用とWindows用の2種類が 存在しますが、ここではWindows用のみ取り扱います。
また、16bit、32bitビットマップについては一般にあまり使われない形式なので省略しています。
圧縮形式(RLE形式:Run-Length Encoded)についても使う機会は少ないと思うので、これも省略します。

□ BMP形式とは...

Bitmapとは画像操作(移動、拡大縮小、回転、ペイントなど)を行なったり、 画像をディスクにファイルとして保存するためのグラフィックオブジェクトである。

Windows標準画像ファイル形式であるBMP形式は Windows Device-Independent Bitmap(略してDIBと呼ばれる)を、 ファイルに保存したものである。 拡張子は.BMPである(拡張子.DIBもある)。 ランレングス法で圧縮されたビットマップはRLE(Run-Length Encoded)形式と呼ばれるが、 無圧縮で使用されることのほうが圧倒的に多い。

ビットマップにはDIBの他にGDIで使用されるデバイス依存ビットマップ(Device-Dependent Bitmap)がある。 初期のWindowsではDDBが開発者の扱える唯一のビットマップであった。 その後、技術が向上し表示デバイスが多様化するのに伴って、 デバイスに依存しないかたちで画像を扱えるDIBが開発され、 Windowsは3.0から採用している。

DIBはもともとIBMとMicrosoftが共同でOS開発を行なっていた頃に作られた画像ファイル形式なので、 WindowsDIBの他に情報ヘッダの異なるOS/2用のDIBも存在する。


DIBには、以下の情報が含まれる。

1.BMPファイル作成時に使用された表示装置のカラーフォーマット
2.BMPファイル作成時に使用された表示装置の解像度
3.BMPファイル作成時に使用された表示装置用のパレット
4.ピクセルを定義するビット配列
5.ファイルサイズを小さくするための圧縮方法

□ 全体の構造

ファイルの構造 イメージ
ファイル全体の構造
オフセットサイズファイル構造
00 (0)(14)ファイルヘッダ( BITMAPFILEHEADER構造体 )
0E (14)biSize (40)情報ヘッダ( BITMAPINFOHEADER構造体 )
36 (54)(注 1)パレット(24bit、32bitBMPには存在しない)
bfOffBits(注 2)画像データ( ビット配列 )

BMPファイルの構造は基本的に4つのセクションにわかれている。 ファイルヘッダ部には「ファイルタイプ」や「ファイルサイズ」など、 ファイル自体に関する情報が納められてる。 情報ヘッダ部は画像として取り扱われるのに必要な情報が格納されてる。 パレット部はRGBQUAD構造体の配列としてインデックスカラーが格納される。

また、2バイト以上のデータは[ 最下位バイト → 最上位バイト ]の順 (リトルエンディアン)で格納される。
4バイトの例)  0x12345678 ⇒ 78 56 34 12


(注 1)… パレットのサイズ
biClrUsedが0以外の時は、(biClrUsed * 4)で計算し、
biClrUsedが0のときは、(1ピクセルの階調数 * 4)で計算する。
1ピクセルの階調数 = 2の(biBitCount)乗

/* マクロで取得する場合 */
#define getpalsize(clrused, bitcount) ( ( (clrused != 0) ? ( clrused ) : (1 << bitcount) )*4)


(注 2)
ビット配列部のサイズ = ( bfSize - bfOffBits )

□ ビットマップファイルヘッダ

BITMAPFILEHEADER structure
typedef struct tagBITMAPFILEHEADER {
        WORD    bfType; 
        DWORD   bfSize; 
        WORD    bfReserved1; 
        WORD    bfReserved2; 
        DWORD   bfOffBits; 
} BITMAPFILEHEADER; 

BITMAPFILEHEADER構造体
オフセット構造体メンバサイズ(byte)内容備考
00 (0)bfType2ファイルタイプ常に 0x42,0x4D ("BM")
02 (2)bfSize4ファイルサイズ(byte)
06 (6)bfReserved12予約領域使われていないので常に 0
08 (8)bfReserved12予約領域使われていないので常に 0
0A (10)bfOffBits4オフセットファイル先頭からビット配列先頭位置までのオフセット

bfType
    BMP形式として識別させるための識別子.

ここで扱う変数型について...
  typedef unsigned short  WORD
  typedef unsigned long  DWORD
  typedef unsigned char  BYTE
  typedef long  LONG

# その他の型については、Win32環境のC言語処理系ならwindef.hなどを参照

□ ビットマップ情報ヘッダ

BITMAPINFOHEADER structure
typedef struct tagBITMAPINFOHEADER{ 
   DWORD  biSize; 
   LONG   biWidth; 
   LONG   biHeight; 
   WORD   biPlanes; 
   WORD   biBitCount 
   DWORD  biCompression; 
   DWORD  biSizeImage; 
   LONG   biXPelsPerMeter; 
   LONG   biYPelsPerMeter; 
   DWORD  biClrUsed; 
   DWORD  biClrImportant; 
} BITMAPINFOHEADER; 

BITMAPINFOHEADER構造体
オフセット構造体メンバサイズ(byte)内容備考
0E (14)biSize4構造体のサイズ(byte)常に 0x28(40)  (注1)
12 (18)biWidth4画像の横幅(pixel)
16 (22)biHeight4画像の高さ(pixel)正の数ならビットマップの配列は下から上へ、負の数なら逆
1A (26)biPlanes2プレーン常に1
1C (28)biBitCount21ピクセルあたりの情報量(注2)
1E (30)biCompression4圧縮形式0: 無圧縮、1: 8bitRLE、2: 4bitRLE、3: ビットフィールド
22 (34)biSizeImage4ビット配列部のサイズbyte単位
26 (38)biXPixPerMeter4水平方向解像度メートルあたりの解像度 - 0 の場合がある
2A (42)biYPixPerMeter4垂直方向解像度メートルあたりの解像度 - 0 の場合がある
2E (46)biClrUsed4パレットの色数パレットが存在していても 0 になる事がある(注3)
32 (50)biClrImportant4重要なパレットのインデックス0 になる事がある

(注1)biSize … 構造体のサイズ
    このbiSizeはBMPファイルに保存されている情報ヘッダのサイズである。

(注2)biBitCount … 1ピクセルで何色表現できるかを表す。
    1 -- 2色(2階調ビットマップ)
	2階調(モノクロ)画像で、2個のRGBQUAD構造体が含まれる。
	ビット配列部分は0と1の配列で表され、それらが2つのRGBQUAD構造体にそれぞれ対応している。
    4 -- 16色(4bitビットマップ)
	16個のRGBQUAD構造体を含み、
	ビット配列部分は、パレットの何番目に登録されている色かを示すインデックスの配列になる。
    8 -- 256色(8bitビットマップ)
	256色まで表現できる。
	ビット配列部分は、インデックスの配列。
    24 -- 16,777,216色(フルカラービットマップ)
	RGBQUADを使わずにBGR順に並んだ3バイトで1ピクセルの色を表す。
	ビット配列部分はBGRの配列である。

(注3)biClrUsed … インデックスカラーの色数。
    biClrUsedが 0 の時はbiBitCountからパレットの色数を求める。

    if(biClrUsed == 0){
	colors = 1 << biBitCount;
    }else{
	colors = biClrUsed;
    }

□ RGBQUAD構造体

RGBQUAD structure
typedef struct tagRGBQUAD {
    BYTE    rgbBlue; 
    BYTE    rgbGreen; 
    BYTE    rgbRed; 
    BYTE    rgbReserved; 
} RGBQUAD;

RGBQUAD構造体
オフセット構造体メンバサイズ(byte)内容    備考    
-- rgbBlue1B 輝度
-- rgbGreen1G 輝度
-- rgbRed1R 輝度
-- rgbReserved1予約領域常に 0

RGBQUAD構造体はパレット部で個々のインデックスカラーの定義に使われる。

□ ビット配列

ビット配列部でのデータ格納方式はbiBitCountによって異なる。

24bit Bitmap
RGBの個々の階調(256階調) * チャンネル数(R,G,Bの3つ) = 8bits * 3 = 24bits = biBitCount

24bit(フルカラービットマップ)の場合は、 ピクセルのRGB輝度が青→緑→赤の順に3バイト(24bit)の配列として並んで格納されている (RGBQUADではない)。 biHeightが正の数値であれば、実際の画像の左下のピクセルを起点に画像上方に向かっていく配列(ボトムアップ方式)、 負の数値であれば左上のピクセルから始まって画像下方に向かう配列(トップダウン方式)になる。 BMPファイルを出力するアプリケーションはほとんどがボトムアップ方式(biHeightが正の数値)でピクセルの並びを記録している。 ピクセルRGB輝度は画像のピクセル総数(biWidth * abs( biHeight ) )と同じだけ繰り返される。

8bit Bitmap
最大256色のパレットを持つ、


パレットが存在する 8bit、4bit、1bitの場合、ビット配列部にはRGB輝度ではなく パレットのインデックス(パレットで何番目の色が使われているか)が格納されている。
24bit, 8bit, 4bit, 1bitのすべてにおいて、画像の水平方向1行分のピクセルのデータサイズ(バイト)は 4バイトで割り切れるように調整されていなければならない。 1行分のデータのサイズを4で割って余りが出る場合、 4の倍数バイトになるように余分な 0 を詰める


制 作 中 ...



□ 番外編 - ビットマップオブジェクトを扱うWin32API関数

BitBlt
CreateBitmap
CreateBitmapIndirect
CreateCompatibleBitmap
CreateDIBitmap
CreateDIBSection
CreateDiscardableBitmap
ExtFloodFill
FloodFill
GetBitmapBits
GetBitmapDimensionEx
GetDIBColorTable
GetDIBits
GetPixel
GetStretchBltMode
LoadBitmap
MaskBlt
PatBlt
PlgBlt
SetBitmapBits
SetBitmapDimension
SetDIBColorTable
SetDIBits
SetDIBitsToDevice
SetPixel
SetPixelV
SetStretchBltMode
StretchBlt
StretchDIBits


BitBlt

BitBlt関数は、ピクセル矩形に相当するカラーデータをコピー先のデバイスコンテキストからコピー元のデバイスコンテキストにビットブロック転送する関数である(要するにコピーです)。

BOOL BitBlt(
    HDC hdcDest,  // コピー先のデバイスコンテキスト. 
    int nXDest,   // コピー先の矩形の左上頂点のX座標. 
    int nYDest,   // コピー先の矩形の左上頂点のY座標. 
    int nWidth,   // コピー元とコピー先の矩形共通の横幅. 
    int nHeight,  // コピー元とコピー先の矩形共通の高さ. 
    HDC hdcSrc,   // コピー元のデバイスコンテキスト. 
    int nXSrc,    // コピー元の矩形の左上頂点のX座標. 
    int nYSrc,    // コピー元の矩形の左上頂点のY座標. 
    DWORD dwRop   // ラスタオペレーションコード. 
);


ラスタオペレーションコード
  コピー元のカラーデータとコピー先矩形のカラーデータをどのように合成するかを
  定義するコードで、以下に列挙するコードを指定する.
  # ラスタオペレーションコードはStretchDIBits関数などでも使用します.
BLACKNESS 物理パレットのインデックス0に関連付けされている色でコピー先の矩形を
塗り潰す(この色はデフォルトの物理パレットでは黒).
DSTINVERT コピー先矩形の色を反転
MERGECOPY 指定された模様とコピー元の矩形の色を論理積演算子(AND)で合成.
MERGEPAINT 反転させたコピー元矩形の色とコピー先矩形の色を論理和演算子(OR)で合成.
NOTSRCCOPY 色を反転させたコピー元矩形をコピー先の座標にコピー.
NOTSRCERASE 論理和でコピー先とコピー元の矩形を結合してから、さらにその結果の色を反転.
PATCOPY 指定された模様をコピー先のビットマップにコピー.
PATINVERT 排他的論理和(XOR)で、指定された模様の色とコピー先矩形の色を結合.
PATPAINT 指定した模様の色と反転したコピー元の色を論理和で結合し、さらにその結果を
コピー先矩形の色と論理和で結合させる.
SRCAND コピー元とコピー先を論理積で結合.
SRCCOPY コピー元の矩形をそのままコピー先にコピー.
SRCERASE 反転させたコピー先の色とコピー元の色を論理積で結合.
SRCINVERT コピー元とコピー先を排他的論理和で結合.
SRCPAINT コピー元とコピー先を論理和で結合.
WHITENESS 物理パレットのインデックス1に関連付けられた色で、コピー先矩形を
塗り潰す(この色はデフォルトの物理パレットでは白).


戻り値

  関数が成功した場合には非ゼロを返す.
  失敗した場合はゼロを返す.拡張エラー情報を得るにはGetLastError関数を呼び出す事.

サンプルソースコード

  サンプル その1( html )
  いろいろな実行結果 - 画像
このカテゴリの目次へ


CreateBitmap

CreateBitmap関数は、指定された幅、高さ、カラーフォーマット(カラープレーンとピクセルあたりのビット数)からビットマップを作る.

HBITMAP CreateBitmap(
    int nWidth,          // ビットマップの横.
    int nHeight,         // ビットマップの高さ.
    UINT cPlanes,        // デバイスで使用されるカラープレーンの数.
    UINT cBitsPerPel,    // 1ピクセルの色を表すのに必要なビット数.
    CONST VOID *lpvBits  // ピクセル矩形に色をセットするために使うカラーデータ配列へのポインタ.
);


パラメータ
  lpvBits
    矩形中の1行ごとの配列はWORDアラインでなくてはならない(WORDアラインでない場合はゼロを詰める).

戻り値
  関数が成功した場合はビットマップのハンドルを返す.
  失敗した場合はNULLを返す.

備考
  ビットマップが作成された後、SelectObject関数でデバイスコンテキストに選択できる.

CreateBitmapはモノクロビットマップを作成するのに使い、カラーのビットマップを作成するにはCreateCompatibleBitmapを使うこと.

以 下 制 作 中 ...



このカテゴリの目次へ


[ 文書作成 ]
Kalashnikov <kalashnikov-lj@infoseek.jp >

[ 参考文献 ]
Win32 Developer's References / Microsoft