こんばんは。
昔、ゲームプログラムの書籍に、unsigned long型のバッファ同士を四角形に見立てて、コピーし合う様な手段が紹介されていました(最終的にはOSが持つ描写関数へ渡されます)。
動作確認はしていますが、アラも在りそうなので、以下参考程度で。
struct IMAGE
{
int width;
int height;
unsigned long* image;
};
static void Fill(IMAGE* p, int x, int y, int w, int h, unsigned long color)
{
x = std::min(std::max(0, x), p->width);
y = std::min(std::max(0, y), p->height);
w = std::min(std::max(0, w), p->width);
h = std::min(std::max(0, h), p->height);
for(int dy = y; dy < h; ++dy)
{
for(int dx = x; dx < w; ++dx)
{
p->image[dx + dy * p->width] = color;
}
}
}
static void Create(IMAGE* p, int width, int height, unsigned long color)
{
p->width = width;
p->height= height;
p->image = new unsigned long[p->width * p->height];
::Fill(p, 0, 0, width, height, color);
}
static void Delete(IMAGE* p)
{
const IMAGE zero = {0};
delete [] p->image;
*p = zero;
}
static void BitBlt(IMAGE* pdst, int xpos, int ypos, const IMAGE* psrc, unsigned long key)
{
const int x = std::max(0, xpos);
const int y = std::max(0, ypos);
const int x2 = xpos < 0 ? -xpos : 0;
const int y2 = ypos < 0 ? -ypos : 0;
for(int sy = y2, dy = y; (sy < psrc->height) && (dy < pdst->height); ++sy, ++dy)
{
for(int sx = x2, dx = x; (sx < psrc->width) && (dx < pdst->width); ++sx, ++dx)
{
const int dpos = dx + dy * pdst->width;
const int spos = sx + sy * psrc->width;
if(psrc->image[spos] == key)
continue;
pdst->image[dpos] = psrc->image[spos];
}
}
}
//ココは大きく環境依存する
static void SaveOSDepend(const IMAGE* p)
{
#pragma pack(push, 1)
struct
{
BITMAPINFOHEADER bih;
DWORD f[3];
} info = {0};
#pragma pack(pop)
info.bih.biSize = sizeof(info.bih);
info.bih.biBitCount = 32;
info.bih.biPlanes = 1;
info.bih.biCompression = BI_BITFIELDS;
info.bih.biWidth = p->width;
info.bih.biHeight = p->height;
info.bih.biSizeImage = info.bih.biWidth * info.bih.biHeight * (info.bih.biBitCount / 8);
info.f[0] = 0xff0000;
info.f[1] = 0x00ff00;
info.f[2] = 0x0000ff;
BITMAPFILEHEADER bfh = {0};
bfh.bfType = *((LPWORD)"BM");
bfh.bfOffBits = sizeof(bfh) + sizeof(info);
bfh.bfSize = bfh.bfOffBits + info.bih.biSizeImage;
FILE* fp = ::fopen("test.bmp", "wb");
::fwrite(&bfh, sizeof(bfh), 1, fp);
::fwrite(&info, sizeof(info), 1, fp);
for(int y = info.bih.biHeight - 1; y >= 0; --y)
{
const int pos = y * info.bih.biWidth;
::fwrite(&p->image[pos], info.bih.biWidth, info.bih.biBitCount / 8, fp);
}
::fclose(fp);
}
int main(int argc, _TCHAR* argv[])
{
IMAGE imgA;
IMAGE imgB;
//画像A 緑色で作成
::Create(&imgA, 128, 64, 0xff00);
//画像B 赤色で作成
::Create(&imgB, 256, 36, 0xff0000);
//画像B 5ピクセル余白を残して、白色で塗る(赤色の枠に白色の内部見たいな感じ)
::Fill(&imgB, 5, 5, 256 - 5, 36 - 5, 0xffffff);
//白色を透明色に指定して、画像Aに画像Bを転送する
::BitBlt(&imgA, 20, -2, &imgB, 0xffffff);
//32bit(windows bitmap)に変換セーブ
::SaveOSDepend(&imgA);
//画像A,Bの後始末
::Delete(&imgA);
::Delete(&imgB);
return 0;
}
お礼
回答ありがとうございます。 APIにLoadImage関数が存在していたので、透過処理も何かbmp専用の関数が存在するのかと思っていました。 >動作確認はしていますが、アラも在りそうなので、以下参考程度で。 補足をいただきたい点がございます。 #pragma pack(1)を使用する理由: 「BITMAPINFOHEADER構造体の仕様」と「パッキング」が関係しているらしいということはわかりました。 しかしそれ以上の情報を発見できなかったため、 #pragma pack(push, 1) struct{ BITMAPINFOHEADER bih; DWORD f[3]; } info = {0}; #pragma pack(pop) のコードを解析できません。 宜しければ何をしているのか教えていただけないでしょうか。