8ビットDIB/BMPはフルカラーの中から(最大)256色のカラーテーブル(パレット)を作成し、このカラーテーブルの中の色を使って画像を表現しています。ピクセル列はカラーテーブルのインデックスを表す1ピクセル8ビットで表され、カラーテーブルさえうまく設計すれば実用上十分な表現力を持つので、ゲームやアニメ調の絵でよく使われる(今となっては使われていた、かな)形式ですね。今回は8ビットBMPを読み込んで、その画像を32ビットフルカラーDIBに描いてみましょう。 カラーテーブルの作成8ビットBMPのカラーテーブルは、BITMAPINFOHEADERの後(BITMAPINFOのbmiColors)にRGBQUADの配列として格納されています。ピクセル列の各ピクセルの値はこのカラーテーブルのインデックスになっており、例えば(1、 1)が0なら、それは(1、 1)のピクセルがカラーテーブル0番の色である事を表します。実際に使用されている色数が256未満の場合は、カラーテーブルを実際の色数分だけ用意しその数をBITMAPINFOHEADERのbiClrUsedで指定できますが、biClrUsedを0にすると使用色数が256色とみなされます。 実際のカラーテーブルの作成は簡単で、まずファイルを読み込みlpbiHeadにBITMAPINFOのポインタを設定したらlpbiHead->bmiColorsをLPDWORD型変数に入れるだけです。 fh=CreateFile(lpszFn,GENERIC_READ,0,NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,NULL); /* ファイルオープン */ /* BMP読み込みバッファ確保 */ lpBuf=(LPBYTE)GlobalAlloc(GPTR,GetFileSize(fh,NULL)); ReadFile(fh,lpBuf,GetFileSize(fh,NULL),&dummy,NULL); lpbiHead=(LPBITMAPINFO)(lpBuf+sizeof(BITMAPFILEHEADER)); offset=*(LPDWORD)(lpBuf+10); lpBMP=lpBuf+offset; /* ビットマップバッファの先頭アドレス */ /* カラーテーブルdwColors設定 */ dwColors=(LPDWORD)lpbiHead->bmiColors; これで、dwColorsに32ビットDIBのRGB値としてそのまま使える形でカラーテーブルが格納されたので、後はBMP内の各ピクセルの番号に対応するRGBを32ビットDIBのピクセルに設定していくだけ。 /* ビットマップの大きさ保存 */ iWidth=lpbiHead->bmiHeader.biWidth; iHeight=lpbiHead->bmiHeader.biHeight; /* 32ビットDIB用バッファ確保 */ lpDIB=(LPBYTE)GlobalAlloc(GPTR,(sizeof(BITMAPINFO)+iWidth*iHeight*4)); /* 32ビットDIBのヘッダ・ピクセル列ポインタ設定 */ lpbiInfo=(LPBITMAPINFO)lpDIB; lpPixel=(LPDWORD)(lpDIB+sizeof(BITMAPINFO)); /* BITMAPINFO構造体設定 */ lpbiInfo->bmiHeader.biSize=sizeof(BITMAPINFOHEADER); lpbiInfo->bmiHeader.biWidth=iWidth; lpbiInfo->bmiHeader.biHeight=iHeight; lpbiInfo->bmiHeader.biPlanes=1; lpbiInfo->bmiHeader.biBitCount=32; /* カラーテーブルdwColors設定 */ dwColors=(LPDWORD)lpbiHead->bmiColors; if ((iWidth) % 4==0) /* バッファの1ラインの長さを計算 */ iLength=iWidth; else iLength=iWidth+(4-(iWidth) % 4); /* カラーテーブルを参照して各ピクセルのRGBを設定 */ for (i=0;i<iHeight;i++) for (j=0;j<iWidth;j++) lpPixel[j+i*iWidth]=dwColors[lpBMP[j+i*iLength]]; 上の例では、lpPixel[j+i*iWidth]が32ビットDIBのピクセルでlpBMP[j+i*iLength]が8ビットBMPのピクセルですね。8ビットビットマップの各ピクセルはカラーテーブルのインデックスなので、その値でカラーテーブルの配列を参照すれば(dwColors[lpBMP[j+i*iLength]])RGB値を取得できます。 プログラムドロップされた8ビットBMPから32ビットDIBを作成し、表示します。 |