256色DIB

今回は、8ビット(256色)DIBを作ってみます。フルカラーの時は、色をRGBで直接指定していましたが、256色ではカラーテーブルに256色分の色を自分で作って、カラーテーブルの値で色を指定する事になります。
そのため、256色のカラーテーブルをどんな色で作るかが大問題で、うまく作らないと貧弱な「絵」しか描けません。ただ、1ピクセルに1バイトでアクセスできるので速度の面ではかなり有利です。

カラーパテーブルの問題はありますが、8ビットDIBを作る事自体は特に難しいことではありません。BITMAPINFOHEADER構造体の後に256色分のカラーテーブル配列を置いて、BITMAPINFO構造体のbmiColors に先頭のカラーテーブルを設定すれば、8ビットDIBの完成です。
なお、カラーテーブルの具体的な内容は以下の形のRGBQUAD型構造体です。

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

この構造体が256個続き、その先頭がBITMAPINFObmiColors になっているわけです。と言う事は、結局256色DIBの操作に必要なのは、BITMAPINFOとカラーテーブル、それに各ピクセルの色情報を格納するビットマップバッファ、の3つを保持するポインタ、という事になります。

  lpBuf=GlobalAlloc(GPTR,sizeof(BITMAPINFO)+255*sizeof(RGBQUAD)+128*128);

  lpInfo=(LPBITMAPINFO)lpBuf;
  lpRGB=(LPRGBQUAD)(lpBuf+sizeof(BITMAPINFOHEADER));
  lpBit=(LPBYTE)(lpBuf+sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD));

このように、3つの配列やバッファ用のメモリまとめて確保した後、それぞれにポインタを設定すれば管理が楽になるでしょう。ここでカラーテーブルRGBQUAD を256個でなく255個分確保しているのは、BITMAPINFO にすでに先頭の1個が含まれているからです。
BITMAPINFO の設定は、

  lpInfo->bmiHeader.biSize=sizeof(BITMAPINFOHEADER); // BITMAPINFO構造体
  lpInfo->bmiHeader.biWidth=128;                     
  lpInfo->bmiHeader.biHeight=128;                    
  lpInfo->bmiHeader.biPlanes=1;                     
  lpInfo->bmiHeader.biBitCount=8;                  
  lpInfo->bmiHeader.biCompression=BI_RGB;
  lpInfo->bmiHeader.biSizeImage=0;
  lpInfo->bmiHeader.biXPelsPerMeter=0;
  lpInfo->bmiHeader.biYPelsPerMeter=0;
  lpInfo->bmiHeader.biClrUsed=0;
  lpInfo->bmiHeader.biClrImportant=0;

  lpInfo->bmiColors[0]=lpRGB[0]; // カラーテーブルの先頭

という感じになります。

・カラーテーブルの設定

カラーテーブルに色を設定するには、RGBQUADrgbRed,rgbGreen,rgbBlue にRGBの数値を指定します。例えば、カラーテーブルの先頭に赤を設定するなら、

  lpRGB[0].rgbRed=255;
  lpRGB[0].rgbGreen=0;
  lpRGB[0].rgbBlue=0;

という感じになるわけです。プログラムでは、以下のようにして黒ー白のグレースケールを作っています。

  for (i=0;i<256;i++)
	  lpRGB[i].rgbRed=lpRGB[i].rgbGreen=lpRGB[i].rgbBlue=i;

・プログラム

今回のプログラムは、128*128の256色DIBに256段階のグレースケールを描画します。なるべくフルカラーでご覧ください。

プログラムソース表示


プログラミング資料庫 > Windowsプログラミング研究室