Windows のビットマップには、通常のGDIで使われるデバイス依存ビットマップ(DDB)の他にもDIB(デバイス独立ビットマップ)というものがあります。これは、ピクセルの色を単純な配列としてまとめたビットマップで、プログラムの中で直接配列を使うのと同じような感じで(あるいは配列としても)扱う事が可能です。
ただ、DIBに関する資料はなぜか非常に少ないのが現状なので、今回はいくつかの資料を基にとりあえずDIBを作って表示してみる事にしましょう。
まず、今回はフルカラー(24ビット)のDIBを作ります。この時のビットマップは、1ピクセルが3バイト(上位から順にBGR)の構成です。ビットマップの本体は、このピクセルの情報が下から上、左から右の順に並んでいますが、これは通常のビットマップの構造とは上下逆なので注意してください。
DIBを作る時は各ピクセルの色を格納したビットマップ本体の他に、ビットマップの大きさや色の形式などの情報を収めたBITMAPINFOHEADERとそのBITMAPINFOHEADER とパレットをまとめたBITMAPINFOという2つの構造体を作成する必要があります。最も、フルカラーではパレットは使いませんのでBITMAPINFOに入るのはBITMAPINFOHEADER だけですが。
実際にDIBを扱う時には、BITMAPINFO構造体と各ピクセルの色の情報を格納したビットマップ本体へのポインタが必要になります。
BITMAPINFOHEADER 構造体のメンバ biSize 構造体の大きさ(sizeof(BITMAPINFOHEADER)) biWidth ビットマップの横幅 biHeight ビットマップの高さ biPlanes ビットマップのプレーン biBitCount プレーンごとの色のビット数 biCompression 圧縮形式 biXPelsPerMeter Y方向の解像度(ピクセル/m) biYPelsPerMeter X方向の解像度(ピクセル/m) biClrUsed 使われている色数 biClrImporyant 重要な色 BITMAPINFO 構造体のメンバ bmiHeader BITMAPINFOHEADER 構造体 bmiColors カラーパレット情報
今回はフルカラーで圧縮したりもしませんのでBITMAPINFOHEADER構造体のbiCompression 以下は0(デフォルト)にしておきます。またプレーンは1にしてbiBitCountを24にすれば24ビットカラーが実現できますね。パレットは使用しないので、後はBITMAPINFO のbmiHeader にBITMAPINFOHEADER を設定するだけです。
構造体の方ができたら次はピクセルの情報を格納するビットマップ本体のメモリを確保します。GlobalAllocで必要なだけ確保しましょう。例えば、作成するビットマップの大きさを64*64とすれば、必要なサイズは64*64*3バイト(24ビットは3バイト)ですね。返されるアドレスをバイト型ポインタにキャストして、
lpBMP=(LPBYTE)GlobalAlloc(GPTR,64*64*3);
としておきます。ただしこのバッファは、横方向1列の大きさを4の倍数にそろえる必要があるので注意してください。今回の例では、横64ドット/1ドット3バイトで横1列が192バイトになり、4の倍数なのでそのままで問題ありません。
DIBの座標は、一番左下が原点(0、0)になっていますので、ビットマップの先頭アドレスをlpBMP、ビットマップの幅をdwWidthとすれば(x、y)のピクセルは以下のアドレスで参照出来ます。
青成分 lpBMP+x*3+y*3*dwWidth 緑成分 lpBMP+x*3+y*3*dwWidth+1 赤成分 lpBMP+x*3+y*3*dwWidth+2
例えば、64×64ピクセルのフルカラーDIBのビットマップ(lpBMP)をオレンジ色(RGB=255:128:0)で塗りつぶすなら以下のような感じです。
for (i=0;i<64*64;i++) { lpBMP[i*3]=0; lpBMP[i*3+1]=128; lpBMP[i*3+2]=255; }
作成したビットマップは、ウインドウのWM_PAINT メッセージを処理する時にStretchDIBitsでウインドウのデバイスコンテキストに描きます。
case WM_PAINT: hdc=BeginPaint(hwnd,&ps); StretchDIBits(hdc,0,0,64,64,0,0,64,64,lpBMP,&BmInfo, DIB_RGB_COLORS,SRCCOPY); EndPaint(hwnd,&ps);