No.3ベストアンサー
- 回答日時:
こんばんは。
昔、ゲームプログラムの書籍に、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)
のコードを解析できません。
宜しければ何をしているのか教えていただけないでしょうか。
No.4
- 回答日時:
こんにちは。
御礼いただきました。32bit,16bitでbmpファイルを作成する際、BITMAPINFOHEADER構造体の後ろに、DWORD x 3の配列を付加させないといけません。
本来は、
::malloc(sizeof(BITMAPINFOHEADER) + sizeof(DWORD) * 3);
の様にして52バイト割り当てますが、メモリーリークの種を増やしたくなかったので、
#pragma pack(push, 1)//パディングが入ってサイズが崩れるとマズイいので念のため
struct{
BITMAPINFOHEADER bih;
DWORD f[3];
} info = {0};
#pragma pack(pop)
上記の様な52バイトの構造体を作成しました。
大体ビットマップのフォーマットは、以下の様になっています。
http://homepage2.nifty.com/tsugu/sotuken/ronbun/ …
http://dencha.ojaru.jp/programs_07/pg_graphic_04 …
24bit
BITMAPFILEHEADER
BITMAPINFOHEADER
イメージ
32, 16bit
BITMAPFILEHEADER
BITMAPINFOHEADER
DWORD[3]
イメージ
モノクロ、16色、256色
BITMAPFILEHEADER
BITMAPINFOHEADER
RGBQUAD[2 又は 16 又は 256]
イメージ
※(1)sizeof(DWORD) と sizeof(RGBQUAD)は等しい
※(2)その他、RLE4bit と RLE8bitが存在する
※(3)DWORD[3]の中身
32bitの場合
[0] = 0xff0000
[1] = 0xff00
[2] = 0xff
16bitの場合
[0] = 0xf800
[1] = 0x7e0
[2] = 0x1f
又は、
[0] = 0x7c00
[1] = 0x3e0
[2] = 0x1f
を選択。
因みに当方が書いたコードは32bitですが、windows APIでビットマップハンドルを使用して構わないならば、このコードは回りくど過ぎるかもしれません。
補足ありがとうございます。
#pragma pack(push, 1)以下の処理に関してある程度は理解できました。
確認させていただきたいのですが、
http://ja.wikipedia.org/wiki/Windows_bitmap
このプログラムでは32bit、16bitのみ対応で、24bitなどDWORD[3]が含まれない形式の場合は正常に動作しない、ということでよろしいでしょうか。(全ビット数に対応する場合は「1ピクセルあたりのビット数」を参照してIMAGE構造体の内容を変える?)
また、BITMAPINFOHEADER構造体以外にも
BITMAPINFOHEADER2:64byteだから新しい形式?
BITMAPV5HEADER:今はこれが主流?
などの構造体も存在するらしいですが、これらにも対応はしていないということですよね。
>因みに当方が書いたコードは32bitですが、windows APIでビットマップハンドルを使用して構わないならば、このコードは回りくど過ぎるかもしれません。
WindowsAPIの使用に関しては一向に構いません。(寧ろ BITMAPINFOHEADER bin; はAPIの構造体だと思っておりました)
//画像表示
HDC hDC = GetDC( hWnd );
HDC hCompatDC = CreateCompatibleDC( hDC );
HBITMAP hPrevBitmap = (HBITMAP)SelectObject( hCompatDC, hBitmap );
BitBlt( hDC, 0, 0, 640, 480, hCompatDC, 0, 0, SRCCOPY );
当初このような処理から透過処理を実現できないものかと考えておりました。
最も提供していただいたソースの方が他のフォーマットに対応する時(jpeg等)色々とやりやすそうですが。
No.2
- 回答日時:
ビットマップにも色々とフォーマットがありますが、
画像の透過処理の一般的な理屈は
1.転送先の画像ビットデータに対して
2.転送元の画像ビットデータが透過色でなければ
それをを上書きする
だけです。
実際の関数は対象OS、ビットマップの種類、使用する
ライブラリによって異なります。
ビットマップはピクセルあたり24ビットのものを想定しています。
(bmpの種類とはこのことですよね?)
OSはWindowsです。
使用するライブラリは標準C++ライブラリです。
これだけでは説明不足でしょうか。
>2.転送元の画像ビットデータが透過色でなければそれをを上書きする
実際に透明にしているわけではないんですね。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) EXCELのグラフを画像(JPG形式)で保存、通常実行がうまく行かない。ステップインはうまく行く 3 2022/08/30 12:06
- その他(ソフトウェア) ペイントで切り抜いた画像の背景を透明に 2 2022/09/15 10:20
- HTML・CSS 角丸画像の背景色を透明にしたいです 1 2023/06/23 23:15
- Photoshop(フォトショップ) 【至急】 ウェブサイトやアプリとかでよく見かける、添付画像のように背景にあるものをぼかしつつ透過する 2 2023/07/17 10:57
- Photoshop(フォトショップ) 塗りつぶした画像を透過させない方法について。上からレイヤーで塗った場合は透過できると聞きましたが、レ 1 2022/10/22 13:41
- Excel(エクセル) エクセルVBA 特殊フォルダのパスを取得の方法を教えてください 3 2022/09/02 13:14
- Excel(エクセル) エクセル VBA For Next 繰り返しの書き方を教えてください 6 2022/09/01 14:11
- HTML・CSS 画像が分割されて切り替わる、ループアニメーションが作りたい 7 2023/05/27 17:12
- Android(アンドロイド) スマホ(Android、iosどちらも可)で、2枚の類似画像(写真)の変化前後を比較したい。 添付画 1 2023/08/20 15:15
- Excel(エクセル) エクセル、画像ファイル名の書かれたセル(複数個所)に画像を一括で表示させる方法 1 2023/04/19 00:19
このQ&Aを見た人はこんなQ&Aも見ています
-
「どうして捨てられないの?」前妻の物を捨てられない男性の心理って?
前妻の物を捨てられない理由に加え、捨てるための手段はあるのかを専門家に聞いてみた!
-
ビットマップ(bmp)形式で背景を透過にできる?
画像編集・動画編集・音楽編集
-
画面を強制的に再描画させる方法
C言語・C++・C#
-
Visual Studioでのbmpファイルの背景透明化
C言語・C++・C#
-
-
4
MFCで画像を表示させているのですが、透過表示する方法がわかりません。
C言語・C++・C#
-
5
MFCでbitmapを背景にしてstaticテキストを透過させる方法
C言語・C++・C#
-
6
imgctl.dllを使って読み込んだ画像ファイルをTransparentBltで画く方法
C言語・C++・C#
-
7
CStringのFindで文字列検索を行いたいのですが
C言語・C++・C#
-
8
GDI+で高速な描画
C言語・C++・C#
-
9
Windowsプログラミング:BitBltで半透明な透かしを作りたい
C言語・C++・C#
-
10
ダイアログの一部を半透明化する C++(MFC)
C言語・C++・C#
-
11
MFCでOnPaintのタイミング
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
おすすめ情報