DIB 情報ヘッダ


OS/2 の情報ヘッダ

前回の DIB ファイルヘッダ はバージョンに関係のない共通の仕様です
しかし、この次にくる情報ヘッダは、DIB のバージョンで異なります
ここが DIB をややこしくしてしまっているのですが、順番に理解していきましょう

まずは OS/2 スタイルの情報ヘッダです
この情報ヘッダは BITMAPCOREHEADER 構造体として表現されます
typedef struct tagBITMAPCOREHEADER { // bmch 
    DWORD   bcSize; 
    WORD    bcWidth; 
    WORD    bcHeight; 
    WORD    bcPlanes; 
    WORD    bcBitCount; 
} BITMAPCOREHEADER; 
bcSize にはこの構造体のサイズが格納されます
プログラムは、このメンバを調べることによって DIB 情報ヘッダのバージョンを知ることができます
bcWidth はイメージの幅、bcHeight はイメージの高さを表します
bcPlanes は常に 1 を指定しなければなりません
bcBitCount は、1ピクセルあたりのカラービット数を表します

このヘッダの bcBitCount は必ず 1、4、8、24 のいずれかになります
カラービット数は、1ピクセルの色を表現するのに使用するビット数です

ビット数色数
12色
416色
8256色
24フルカラー

ご存知の方も多いと思うが、2、16、256 色はインデックスカラーです
この場合は、情報ヘッダの次にカラーテーブルが付属します
さて、前回のバイナリデータを再び見てみましょう
typedef struct tagBITMAPCOREHEADER { // bmch 
    DWORD   bcSize; 
    WORD    bcWidth; 
    WORD    bcHeight; 
    WORD    bcPlanes; 
    WORD    bcBitCount; 
} BITMAPCOREHEADER; 
アドレス0123456789ABCDEF
00000000424D4800000000000000200000000C00
0000001000000A000A0001000100FFFFFF000000
0000002000000000000000000000000000000000
0000003000000000000000000000000000000000
000000400000000000000000

まず、このバイナリデータは OS/2 スタイル、つまり BITMAPCOREHEADER 型です
最初の構造体のサイズは 12、16進数の 0x0C になります
このビットマップは縦横ともに 10 ピクセルなので、その後の2ワードは 0A となっていますね
bcPlanes は常に 1 なので、この次のワードは 0x0100 となっています
さらに、このビットマップは簡単を守るためにカラービットを 1 にしてあります
#include <windows.h>

BITMAPFILEHEADER bmpFileHeader;
BITMAPCOREHEADER bmpCoreHeader;

LRESULT CALLBACK WndProc(HWND hWnd , UINT msg , WPARAM wp , LPARAM lp) {
	HDC hdc;
	PAINTSTRUCT ps;
	RECT rect;
	static TCHAR chStr[1024];

	switch (msg) {
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	case WM_CREATE:
		wsprintf(chStr , 
			TEXT("FILEHEADER\n")
			TEXT("bfType = %X\nbfSize = %d\nbfReserved1 = %d\n")
			TEXT("bfReserved2 = %d\nbfOffBits = %d\n\n")

			TEXT("COREHEADER\n")
			TEXT("bcSize = %d\nbcWidth = %d\nbcHeight = %d\n")
			TEXT("bcPlanes = %d\nbcBitCount = %d") ,

			bmpFileHeader.bfType , bmpFileHeader.bfSize ,
			bmpFileHeader.bfReserved1 , bmpFileHeader.bfReserved2 ,
			bmpFileHeader.bfOffBits ,

			bmpCoreHeader.bcSize , bmpCoreHeader.bcWidth ,
			bmpCoreHeader.bcHeight , bmpCoreHeader.bcPlanes ,
			bmpCoreHeader.bcBitCount
		);
		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hWnd , &ps);
		GetClientRect(hWnd , &rect);
		DrawText(hdc , chStr , -1 , &rect , DT_LEFT);
		EndPaint(hWnd , &ps);
		return 0;
	}
	return DefWindowProc(hWnd , msg , wp , lp);
}

int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,
			PSTR lpCmdLine , int nCmdShow) {
	HWND hWnd;
	MSG msg;
	WNDCLASS winc;
	HANDLE hFile;
	DWORD dwBytes;

	hFile = CreateFile(lpCmdLine , GENERIC_READ , 0 , NULL ,
		OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL , NULL);
	if (hFile == INVALID_HANDLE_VALUE) return 1;

	ReadFile(hFile , &bmpFileHeader , sizeof (BITMAPFILEHEADER) , &dwBytes , NULL);
	if (bmpFileHeader.bfType != 0x4D42) {
		MessageBox(NULL , TEXT("This is not a bitmap file") , NULL , MB_OK);
		return 1;
	}

	ReadFile(hFile , &bmpCoreHeader , sizeof (BITMAPCOREHEADER) , &dwBytes , NULL);
	CloseHandle(hFile);

	winc.style 		= CS_HREDRAW | CS_VREDRAW;
	winc.lpfnWndProc		= WndProc;
	winc.cbClsExtra		= winc.cbWndExtra	= 0;
	winc.hInstance		= hInstance;
	winc.hIcon		= LoadIcon(NULL , IDI_APPLICATION);
	winc.hCursor		= LoadCursor(NULL , IDC_ARROW);
	winc.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH);
	winc.lpszMenuName	= NULL;
	winc.lpszClassName	= TEXT("KITTY");

	if (!RegisterClass(&winc)) return 1;

	hWnd = CreateWindow(
			TEXT("KITTY") , TEXT("Kitty on your lap") ,
			WS_OVERLAPPEDWINDOW | WS_VISIBLE ,
			CW_USEDEFAULT , CW_USEDEFAULT ,
			CW_USEDEFAULT , CW_USEDEFAULT ,
			NULL , NULL , hInstance , NULL
	);

	if (hWnd == NULL) return 1;

	while (GetMessage(&msg , NULL , 0 , 0 )) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return msg.wParam;
}


前回のファイルヘッダを表示するプログラムを拡張したものです
このプログラムは、前回と異なり OS/2 スタイルの DIB のみを想定しています
それ以外、つまり Windows 版の DIB には対応していないので注意してください
また bfType 以外は、16 進数ではなく 10 進数でデータを表示するように改良しました
コマンドラインから OS/2 仕様の DIB ファイルを指定してください



前のページへ戻る次のページへ