8ビットDIBの色表現は32ビットや24ビット等のようにRGB成分そのものを指定するのではなく、
カラーテーブルのインデックスを指定する事で、間接的にRGB成分を指定します。
今回はその概念の違いをしっかりと理解して下さい。
8ビットDIBは消費メモリーが少なく、
任意の256色を使うことができるのでゲーム等によく使われます。
■カラーテーブル
32ビットや24ビットと異なるのはピクセル列に格納されている数値の意味です。
32ビットや24ビットの場合はRGB成分そのものでした。
しかし、8ビットの場合はカラーテーブルのインデックスです。
カラーテーブルにはRGB成分そのものが格納されています。
つまり、何番の色と指定すれば、
間接的にその番号に対応したRGB成分を指定した事になるのです。
カラーテーブルにはカラーパレットのインデックスが格納されている事もありますが、
今のところカラーパレットについて解説する予定はありません。
■カラーテーブルの作成
それではカラーテーブルはどこにあるのかというと、
BITMAPINFO 構造体の bmiColors メンバーがカラーテーブルの先頭を指しています。
ただし BITMAPINFO 構造体自体が1個のカラーテーブルを所有しています。
bmiColors[1] は先頭のカラーテーブルです。
従って、256個のカラーテーブルを作成したい場合は、
残り255個分のバッファを確保しなければなりません。
カラーテーブルのバッファは BITMAPINFO 構造体のバッファの
直ぐ後ろに確保すればいいでしょう。
bmiColors は BITMAPINFO 構造体の最後尾に位置しているので、
その直ぐ後ろにバッファを確保すれば、
予め用意されている1番目のカラーテーブルと2番目以降のカラーテーブルが
連続した領域にあることになり、アドレスの計算が楽です。
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO;
#define WIDTH 197 #define HEIGHT 100 #define BIT 8 #define COLOR ((DWORD)pow(2,BIT)) static LPBYTE lpPixel; static LPBITMAPINFO lpBmpInfo; static int length; //4の倍数に補正 if(WIDTH%4) length=WIDTH+(4-WIDTH%4); else length=WIDTH; lpPixel=(LPBYTE)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, length*HEIGHT+sizeof(BITMAPINFO)+sizeof(RGBQUAD)*(COLOR-1)); lpBmpInfo=(LPBITMAPINFO)(lpPixel+length*HEIGHT);
■RGBQUAD構造体
カラーテーブルはRGBQUAD構造体で表現されます。
typedef struct tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
rgbReserved は予約されているので 0 を指定して下さい。
int i; //カラーテーブルを設定する for(i=0;i<COLOR;i++){ lpBmpInfo->bmiColors[i].rgbBlue=i%128; lpBmpInfo->bmiColors[i].rgbGreen=128-i%128; lpBmpInfo->bmiColors[i].rgbRed=i%256; }
カラーテーブルは先頭ほどよく使う色を設定するのがマナーになっていますが、
絶対のルールではありません。
■DIBの情報を設定する
32ビットや24ビットと同じですが、
BITMAPINFOHEADER 構造体の biClrUsed メンバーに
実際に使うカラーテーブルの数を指定することができます。
0 を指定すれば最大数を意味します。
また BITMAPINFOHEADER 構造体の biBitCount メンバーに8(ビット)以下の値を指定することで
カラーテーブルが参照されるようになります。
//DIBの情報を設定する lpBmpInfo->bmiHeader.biSize=sizeof(BITMAPINFOHEADER); lpBmpInfo->bmiHeader.biWidth=WIDTH; lpBmpInfo->bmiHeader.biHeight=HEIGHT; lpBmpInfo->bmiHeader.biPlanes=1; lpBmpInfo->bmiHeader.biBitCount=BIT; lpBmpInfo->bmiHeader.biCompression=BI_RGB; //lpBmpInfo->bmiHeader.biClrUsed=COLOR;
■描画
ピクセル列に格納するのはカラーテーブルのインデックスです。
RGB成分そのものではありません。
また、0 に初期化されているピクセル列の初期色はカラーテーブルの 0 番に対応する色になります。
int x,y; //描画 for(i=0,y=25;y<=50;y++){ for(x=25;x<=50;x++){ lpPixel[x+y*length]=(++i)%COLOR; } }
■表示&解放
カラーテーブルを使用しているか、いないかは、
BITMAPINFOHEADER 構造体に設定されているビット数で判定されます。
case WM_PAINT: hdc=BeginPaint(hWnd,&ps); //表画面へ転送 StretchDIBits(hdc,0,0,WIDTH,HEIGHT, 0,0,WIDTH,HEIGHT,lpPixel,lpBmpInfo,DIB_RGB_COLORS,SRCCOPY); EndPaint(hWnd,&ps); return 0; case WM_DESTROY: HeapFree(GetProcessHeap(),0,lpPixel); PostQuitMessage(0); return 0;
★☆ ソースファイル表示 ☆★