int psetIBMP(HIBMP hb,int x,int y,int c)
として、(x,y) にc で指定した色の点を打つようにします。
ただし、指定した点がDIBの範囲を超えていたら、エラーとして0を返しましょう。
色の指定は、
下位24ビットでRGBをそれぞれ8ビットで指定するおなじみの方式です
(上位8ビットは無視)。この数値からRGB各成分を取り出すには、
b=(c & 0x00ff0000)>>16; // B(青)成分 g=(c & 0x0000ff00)>>8; // G(緑)成分 r=c & 0x000000ff; // R(赤)成分
と各成分のビットのみを取り出してから、シフトして1バイトに収めます。
前回作ったDIB構造体には、ビットマップのバッファへのポインタlpBMP
とビットマップの横幅width、高さheight が格納されていますから、
ビットマップhbの点(x,y) にアクセスするには、
hb.lpBMP[(y*hb.width+x)*3] からの3バイトを参照すれば良いですね。
以上の事から、
「指定した点に指定した色の点を打つ」関数は以下のようになります。
int psetIBMP(HIBMP hb,int x,int y,int c) { BYTE r,g,b; if (x>hb.width-1 || y>hb.height-1) // 範囲外ならエラー return 0; b=(c & 0x00ff0000)>>16; // B(青)成分を分離 g=(c & 0x0000ff00)>>8; // G(緑)成分を分離 r=c & 0x000000ff; // R(赤)成分を分離 hb.lpBMP[(y*hb.width+x)*3]=b; hb.lpBMP[(y*hb.width+x)*3+1]=g; hb.lpBMP[(y*hb.width+x)*3+2]=r; return 1; }
・DIBにDIBを描く
次にDIBを他のDIBの上に描く(上書き)関数を作ってみましょう。
DIBのビットマップは単なる配列として扱えるので、
やる事は単純な配列のコピーだけです。
配列の大きさは、width、height を見ればわかるので、
描画するDIBの全範囲を描画対象のDIBの指定位置から、
横幅width 高さheight だけコピーする事になります。
コピーするには1ピクセル(3バイト)づつコピーしていっても良いのですが、
描画対象のDIBは単純な長方形ですからwidth
分をまとめてCopyMemory で転送してしまいましょう。
単純に考えて関数にすると、
void drawIBMPtoIBMP(HIBMP srcI,int x,int y,HIBMP desI) { int i; for (i=0;i<srcI.height;i++) // 一列づつコピー CopyMemory(desI.lpBMP+((i+y)*desI.width+x)*3, srcI.lpBMP+srcI.width*i*3,srcI.width*3); }という形になります。srcI が描画するDIB、desI が描画対象のDIBで(x,y) が描画座標です。
この問題に対処するには、 描画対象のDIBと描画するDIBの大きさや描画する座標を調べて、 描画するDIBがはみだすようならその部分を除いて描く「クリッピング」 を行う必要があります。 次回は、このクリッピング処理を考えてみましょう。
・プログラム
今回のプログラムはdrawIBMPtoIBMP を使って、 64*64ピクセルのDIBに32*32ピクセルのDIBを「上書き」する例です。 それぞれのビットマップは、まずpsetIBMP で青と緑に塗られてから、 64*64のビットマップの上に32*32のビットマップが描かれ、 画面に描画されます。