[BMP]ビットマップの編集
編集と呼ぶには程遠いけど
前回 表示した赤塗りつぶしビットマップデータと、以下の画像を重ねてみる。
[作成環境]
・Visual Studi 2008 Standart Edition
・MFC-ダイアログベース
ダイアログクラスに以下のメンバを新に追加
private:
CBitmap m_bmp; // 背景
CBitmap m_img; // 画像(新規追加)
OnInitDialog()
// TODO: 初期化をここに追加します。
// ビットマップ背景データ部分を作成(高さ200px、幅300px)
BYTE *pData = new BYTE[200*300*4];
// 背景データ部分の初期化
for(int i = 0; i < 200*300*4; i += 4)
{
pdata[i] = 0x00; // 青成分
pdata[i+1] = 0x00; // 緑成分
pdata[i+2] = 0xFF; // 赤成分
pdata[i+3] = 0x00; // 未使用(予約領域)
}
// 画像ビットマップのロード
HBITMAP hbmp = (HBITMAP)LoadImage(0,
_T("C:\\sample.bmp"),
IMAGE_BITMAP,
0,
0,
LR_LOADFROMFILE);
// 取得したハンドルからビットマップオブジェクトを作成
m_img.Attach(hbmp);
// BITMAP構造体の取得
BITMAP bm;
m_img.GetBitmap(&bm);
// 高さと幅の取得
int iWidth = bm.bmWidth;
int iHeight = bm.bmHeight;
int size = iWidth * iHeight * 4;
// 画像データ領域バッファ確保
BYTE *pImg = new BYTE[ size ];
// 確保したバッファに画像データを格納
m_img.GetBitmapBits(size, pImg);
// 背景領域に画像データを上書き
int i,j;
for(i = 0; i < iHeight; i++)
{
for(j = 0; < iWidth * 4; j++)
{
pData[j + i * 300 * 4] = pImg[j + i * iWidth * 4];
}
}
// ビットマップの作成
m_bmp.CreateCompatibleBitmap(GetDC(), 300, 200);
// 作成したビットマップに、作成したデータ部分をセット
m_bmp.SetBitmapBits(200*300*4, pData);
delete [] pData;
delete [] pImg;
// Attachした画像はOnDestroy()内とか不要になった時点でDetach
OnPaint()
変更なし
結果
ちょっとした説明
pData[j + i * 300 * 4] = pImg[j + i * iWidth * 4];
前回も少し書いたが、ビットマップデータ部として1次元配列として確保している。
その中で特定の座標(x, y)を取り出すためには
先頭アドレスに (x + y * (幅))のオフセットを与えればよい。
(1ピクセルの表現にRGBQUADで4バイト要するので×4も行っている)
背景と画像では幅が違うので、折り返し位置を正しく表現したいために
今回の方法をとった。
多分もっとよいやり方はあると思う。
あくまで動作を知るためのコードということで。