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で質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
準・究極の選択
「年収1000万円で一生カレーライス」か 「年収180万円で毎日何でも食べ放題」 あなたはどちらを選びますか?
-
フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
あなたが普段思っている「これまだ誰も言ってなかったけど共感されるだろうな」というあるあるを教えてください
-
映画のエンドロール観る派?観ない派?
映画が終わった後、すぐに席を立って帰る方もちらほら見かけます。皆さんはエンドロールの最後まで観ていきますか?
-
海外旅行から帰ってきたら、まず何を食べる?
帰国して1番食べたくなるもの、食べたくなるだろうなと思うもの、皆さんはありますか?
-
天使と悪魔選手権
悪魔がこんなささやきをしていたら、天使のあなたはなんと言って止めますか?
-
ビットマップ(bmp)形式で背景を透過にできる?
画像編集・動画編集・音楽編集
-
画面を強制的に再描画させる方法
C言語・C++・C#
-
MFCで画像を表示させているのですが、透過表示する方法がわかりません。
C言語・C++・C#
-
-
4
Visual Studioでのbmpファイルの背景透明化
C言語・C++・C#
-
5
透過背景画像のビットマップ形式保存について
その他(ソフトウェア)
-
6
MFCでbitmapを背景にしてstaticテキストを透過させる方法
C言語・C++・C#
-
7
ダイアログの一部を半透明化する C++(MFC)
C言語・C++・C#
-
8
JPEGやPNGが読めるLoadImage関数
C言語・C++・C#
-
9
GDI+で高速な描画
C言語・C++・C#
-
10
画面リサイズ時のちらつきをなくす方法
C言語・C++・C#
-
11
Windowsプログラミング:BitBltで半透明な透かしを作りたい
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【お題】絵本のタイトル
- ・【大喜利】世界最古のコンビニについて知ってる事を教えてください【投稿~10/10(木)】
- ・メモのコツを教えてください!
- ・CDの保有枚数を教えてください
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・ハマっている「お菓子」を教えて!
- ・最近、いつ泣きましたか?
- ・夏が終わったと感じる瞬間って、どんな時?
- ・10秒目をつむったら…
- ・人生のプチ美学を教えてください!!
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・都道府県穴埋めゲーム
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
2の補数を計算するプログラム
-
OpenCVによる4値化について
-
C言語で%を使わない余りの出し方
-
C言語 サイコロ 2つの値を返せない
-
Cプログラムによる画像の高速フ...
-
C言語でテーブル引きしたら速度...
-
ある商品のロス率を5%見込み、...
-
2÷3などの余りについて
-
信頼区間の1.96や1.65ってどこ...
-
Aの値からBの値を除するとは??
-
O(n log n)について2
-
マイナスからプラスへ転じた時...
-
新型コロナ感染状況について
-
数学 確率変数Xは、X=2またはX...
-
整数問題6 三角形とtan
-
#define _CRT_SECURE_NO_WARNIN...
-
Enterキーを押されたら次の処理...
-
C言語での引数の省略方法
-
プログラムでの数字につく”f”の...
-
関数f(x)= x³‐3ax²+3ax+2 が極...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
intとlongは同じ?
-
2の補数を計算するプログラム
-
再起呼び出しの回数をカウント...
-
C++ bmp 透過処理
-
OpenCVによる4値化について
-
カードシャッフルのブログラム...
-
C言語で%を使わない余りの出し方
-
argvのNULLチェック
-
コマンドプロンプトのウィンド...
-
分数の足し算をさせるプログラ...
-
関数とビット列
-
ヌメロンのプログラム
-
whileとifを使い偶数を出すには
-
迷路を脱出する経路探索プログ...
-
プログラミングに関して
-
C++で表を作成したいのです ...
-
C言語で簡単なパックマンゲーム...
-
| (or) を使った関数の引数の作...
-
条件が多い場合
-
複数の共有メモリの作成
おすすめ情報