|
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を作成し、表示します。 |