トップ 戻る | ゲームプログラミング練習帳 ビットマップ作成からマップスクロール、イベント処理まで |
|
これまでに、Windowsのビットマップとしてメモリ上にピクセルデータを保持して自由に処理できるDIBとGDIの描画機能で簡単に図形や文字を描けるDDBを見てきました。ただ、これらのビットマップはどちらももう一方の機能は利用できず、DIBにGDIで文字を描くことはできないし、DDBの画像データを直接メモリ操作でアクセスすることもできない(あるいはすべきでない)んですよね。 DIBSectionCreateDIBSection()は、その名の通りDIBSectionと呼ばれる特殊なDIBを作成します。このDIBSectionは、DIB同様メモリ上にピクセル列(フレームバッファ)が取られプログラムからそのメモリ領域に自由にアクセスできるのですが、同時に返り値としてHBITMAPも取得できます。このHBITMAPを、メモリデバイスコンテキストに選択すれば、DDB同様そのデバイスコンテキストに対してGDIで描画できるのです。そしてその描画結果は、メモリ上のDIBのピクセル列にも反映されます。 DIBSectionを作成するには、まず作成するDIBSectionの形式をDIB同様BITMAPINFO構造体で定義します。そして、そのBITMAPINFOをCreateDIBSection()に渡すと指定形式のピクセル列がメモリ上に確保され、そのポインタを取得できます。ここで、ピクセル列は自分で確保するのではなく、システムが確保する点に注意してください。 今回は、256*256ピクセル、32ビットのDIBSectionを作ってみましょう。まず、BITMAPINFO構造体(内のBITMAPINFOHEADER)を設定します。BITMAPINFOHEADERのbiHeightは、GDIのデフォルト座標系にあわせるために、負の値にしてあります。
BITMAPINFOを定義したら、そのアドレスをCreateDIBSection()に渡し、ピクセル列のアドレス(引数で受け取り先を指定)とHBITMAP(返り値)を取得します。今回は、カラーテーブルは使わないので、引数のHDCはNULLを指定しています。 /* DIBSection作成 */ hbmpBMP = CreateDIBSection(NULL, &biBMP, DIB_RGB_COLORS, (void **)(&lpdwPixel), NULL, 0); これで、lpdwPixelに作成されたDIBのアドレスが格納されたので、DIBとしてピクセルを参照できるようになりました。次に、hbmpBMPを選択するメモリデバイスコンテキストを作成し、GDIでもピクセルにアクセスできるようにしましょう。このメモリデバイスコンテキストの作成は、DDBとほぼ同じです。
以上で、lpdwPixelを通した直接アクセス、hdcBMPを通したGDI描画と2種類の方法でDIBSectionに描画できるようになりました。さっそく、この2種類の方法でピクセルに描き込んでみましょう。今回は、赤、緑、青、白の256段階グラデーションをそれぞれの方法で描いてみました。
これで、DIBSectionの作成とピクセル処理は終了。後は、表示するだけですね。 /* DIBSectionを表示 */ BitBlt(hdc, 0, 0, 256, 256, hdcBMP, 0, 0, SRCCOPY); さて今回の注目点は、GDIで読み書きした場合の精度です。たとえば、画面モードをフルカラー以外の16ビットや8ビットにした場合、RGB各8ビット(24/32ビット)のフルカラーではじめて完全に再現できる256段階のグラデーションは、メモリ上のピクセル列にどのように反映され、またGDIでピクセルの色を取得した場合、どうなるのか。 そこで、そのあたりがどうなっているのか調べるために、ビットマップが表示されている部分にマウスを持ってくるとその下のピクセルの色をピクセル列への直接アクセスとGDI(GetPixel())で取得し、ウインドウのタイトルバーに表示するようにしてみました。
表示される数値は16進表記で、最上位2桁が0、下位24ビットが色情報です。ピクセル列の値(Buf)は、上位からRGB各2桁、GDIの方はBGR各2桁とRとBが入れ替わっているので注意してください。 私が試した環境では、8/16ビットで実行してもGDIの読み書きはフルカラーの精度で行われる(減色はなし)ようですね。DIBSectionを通すことで、GDIの描画結果をデバイスコンテキストの色深度によらずフルカラーでメモリ上に取得できる、ということなのでしょうか。もしそうだとしたら、なかなか便利かも。 実験を終えたら、DIBSectionを削除します。 /* DIBSectionをメモリデバイスコンテキストの選択から外す */ SelectObject(hdcBMP, hbmpOld); /* DIBSectionを削除 */ DeleteObject(hbmpBMP); /* メモリデバイスコンテキストを削除 */ DeleteDC(hdcBMP); プログラム実行すると、256×256ピクセルの32ビットDIBSectionを作成し、グラデーションを描画してからウインドウ上に描画します。 |
トップ 戻る | シーザム (防犯・護身用品専門店) |