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ピクセルの色を表現するのに使用するビット数です
ビット数 | 色数
|
---|
1 | 2色
|
---|
4 | 16色
|
---|
8 | 256色
|
---|
24 | フルカラー
|
---|
ご存知の方も多いと思うが、2、16、256 色はインデックスカラーです
この場合は、情報ヘッダの次にカラーテーブルが付属します
さて、前回のバイナリデータを再び見てみましょう
typedef struct tagBITMAPCOREHEADER { // bmch
DWORD bcSize;
WORD bcWidth;
WORD bcHeight;
WORD bcPlanes;
WORD bcBitCount;
} BITMAPCOREHEADER;
アドレス | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
|
---|
00000000 | 42 | 4D | 48 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 20 | 00 | 00 | 00 | 0C | 00
|
---|
00000010 | 00 | 00 | 0A | 00 | 0A | 00 | 01 | 00 | 01 | 00 | FF | FF | FF | 00 | 00 | 00
|
---|
00000020 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00
|
---|
00000030 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00
|
---|
00000040 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00
|
---|
まず、このバイナリデータは 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 ファイルを指定してください