【ビットマップの概要】

ビットマッブは、Windows3.0以降DIB(device-independent bitmap)といわれるフォーマット形式が使われます。（それ以前はDDB(device-dependent bitmap)でした。）
以下ではスクリーン（デバイスコンテキスト）とファイルからのビットマップの基本情報の取り方をビットマップ関連の構造体を見ながら学習していきます。

【基本BITMAP情報の取得】

スクリーンに表示されたハンドル（HBITMAP）があるビットマップの基本的な情報を取る場合にはBITMAP構造体を使い、GetObject関数を次の様に使います。

typedef struct tagBITMAP {	//BITMAP構造体
	LONG bmType;		//0で無ければならない
	LONG bmWidth;		//ビットマップの幅(ピクセル単位で1以上)
	LONG bmHeight;		//ビットマップの高さ(ピクセル単位で1以上)
	LONG bmWidthBytes;	//スキャン時の列のバイト数（WORD単位・必ず偶数）
	WORD bmPlanes;		//カラープレーンの数（通常1）
	WORD bmBitsPixel;	//ピクセルの色を表すビット数
	LPVOID bmBits;		//ビット配列の位置を示す
} BITMAP;

この中で重要なのが「カラープレーンの数」と「ピクセルの色を表すビット数」です。というのはビットマップの基本的相違はカラーフォーマットですが、これは、

	【カラービット数】bmPlanes x bmBitsPixel

で決まるからです。カラービット数は1（2^1で白黒）、4（2^4で16色）、8（2^8で256色）、16（65536色）、24（トゥルーカラー又はフルカラー1677万色）、32（1677万色＋α）が定義されているの種類があり、フルカラー時にはRGBQUADがありません。

int GetObject(HGDIOBJ hgdiobj,		//グラフィックオブジェクトのハンドル
		int cbBuffer,		//情報を収納するメモリーバッファー
		LPVOID lpvObject	//そのバッファーのアドレス
);

ビットマップの場合は次のように書きます。（ビットマップのハンドルをhBitmapとして）

	BITMAP\tbm;
	GetObject((HGDIOBJ)hBitmap, sizeof(BITMAP), &bm);

尚、注意していただきたいのは、例えば16色のビットマップ（カラービット4）でも読みこまれるとそのデバイスコンテキストで他の型のビットマップになってしまうことです。（BMPViewerで確かめてください。）

【ビットマップファイルの構造】

次にビットマップファイルを見てみましょう。
DIB形式のビットマップはファイルの先頭から次のような構造になっています。

	BITMAPFILEHEADER構造体
	BITMAPINFO構造体
	ビット配列

2番目のBITMAPINFO構造体は、BITMAPINFOHEADER構造体とRGBQUAD構造体をまとめて管理するものです。

typedef struct tagBITMAPINFO {	// bmi
	BITMAPINFOHEADER	bmiHeader;
	RGBQUAD			bmiColors[1];
} BITMAPINFO;

bmiHeaderは、BITMAPINFOHEADER構造体を指定します。
bmiColors[1]は、RGBQUAD構造体または、DWORD型データの配列を指定します。1つになってますが、現実の処理では24ビットビットマップを除き下記のBITMAPINFOHEADER構造体のbiClrUsed分（長さは4バイト X biClrUsed）有ります。

このことからビットマップファイル構造は、

	BITMAPFILEHEADER構造体
	BITMAPINFOHEADER構造体
	RGBQUARD構造体
	ビット配列

になっていると言えます。

【BITMAPFILEHEADERの詳細】

ファイルの先頭に来るBITMAPFILEHEADER構造体は次のように定義されています。

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

bfTypeには、'BM'の２バイトが収められています。ファイルを読みこんだ時これを調べて'BM'を確認する必要があります。
bfSizeはファイルのサイズです。
bfOffBitsはファイルの先頭からビット配列までのオフセット値が入ります。

【BITMAPINFOHEADERの詳細】

次にBITMAPINFOHEADER構造体は次のように定義されています。

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

biSizeには、構造体の大きさが入ります。
biWidthは、ビットマップの幅。
biHeightは、ビットマップの高さ。
biPlanesは、プレーンの数ですが1でなくてはいけません。
biBitCountは、ピクセルあたりの色数を示します。1, 4, 8, 16、24、32のいずれかです。
biCompressionは、圧縮方式を示します。BI_RGB（0）で圧縮なし。但し16、32ビット（biBitCount）ビットマップではBI_BITFIELDS（3）である必要があります。
biSizeImageは、ビットマップビットのサイズ。圧縮の時のみ必要。
biXPelsPerMeterは、水平解像度を示します。1メートルあたりのピクセル数。
biYPelsPerMeterは、垂直解像度を示します。
biClrUsedは、ビットマップイメージで使われている色数を示します。（上記参照）0はbiPlanesとbiBitCountによる最大色数を意味します。
biClrImportantは、イメージで使われている重要な色の数を示します。0は全て重要を意味します。

尚、上記で述べたBITMAP構造体のbmPlanes、bmBitsPixelはBITMAPINFOHEADER構造体のbiPlanes、biBitCountと夫々同一です。又構造体メンバーであるbiClrUsedは2~(biPlanes x biBitCount) = 色数となります。
又、Windows95ではBITMAPV4HEADER、Windows98ではBITMAPV5HEADERが定義されています。

【RGBQUADの詳細】

次にRGBQUAD構造体が来ます。
biClrUsedが0でなおかつ、biBitCountが1なら2つ、4なら16、8なら256個のRGBQUAD構造体が必要です。フルカラーの時はRGBQUAD構造体はありません。また、biClrUsedが0以外の時はその数だけRGBQUAD構造体が必要です。これをカラーテーブルなどと呼びます。具体的には、

BitCountが1の場合、モノクロフォーマットであり、2つの RGBQUAD 構造体が必要です。イメージはビットの ON/OFF で表現され、ビットが0の場合は最初に定義されている RGBQUAD の値で、1の場合は2番目の値で表示されます。従ってて RGBQUAD 値を変えれば様々な色による2値画像が作成可能です。 

BitCountが4の場合、16色フォーマットで16個の RGBQUAD が必要です。イメージは RGBQUAD の何番目の色になるかのインデックスで示され、1画素の表現には4bitが用いられます。 

BitCountが8の場合、256色フォーマットで256個の RGBQUAD が必要です。1画素の表現には 8bit(1Byte)が必要になる他は BitCount==4 の場合と変わりません。

BitCountが16の場合、65536色フォーマットでRGBQUAD は含まれません。イメージは16ビット(WORD)で表現され、WORD で展開されたとき最上位ビットは空でその後に5ビットずつ RGB と並んでいます。ただし、圧縮形式が BI_BITFIELDS の場合は RGBQUAD の位置にカラーマスクとなる3個の DWORD データが青、緑、赤の順番で並んでいるため、このマスクデータを元に各RGB値を決定します。

BitCountが24の場合、1677万色のフルカラー画像であり RGBQUAD は含まれません。BGR の順にそれぞれ1バイトで並んでおり、この3バイトで1画素を表します。

BitCountが32の場合、32ビット(DWORD)つまり4バイトで1画素を表し、RGBQUAD は含まれません。データの並びは DWORD に展開すると最初の1バイトが空でその後RGBの順番で各1バイトずつ並んでいます。ただしBYTEデータして参照すると RGBQUAD 構造体と同じ並びになります。このフォーマットも BitCountが16のときと同様に BI_BITFIELDS が指定されたときはカラーマスクが RGBQUAD の位置に指定されます。 

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


メンバは、それぞれ青、緑、赤の強さを表します。

【ビット配列】

RGBQUAD構造体のあとには、ビットマップデータが続きます。左下から右に、下から上にデータが入っています。（ボトムアップ・トップダウンにする時には高さを負の数にする必要があります。）
ビット配列を特定のデバイスコンテキスト、特定のビットマップ情報で取得するにはGetDIBits()関数を使ってください。
