読み込んだBITMAPをミラーしてから背景透過で転送

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
nasunasi
記事: 5
登録日時: 7年前

読み込んだBITMAPをミラーしてから背景透過で転送

#1

投稿記事 by nasunasi » 7年前

初めての質問故、ご迷惑等お掛けするかも知れませんが、よろしくお願いいたします。

今回、私が直面している問題は、

void Draw_Char( HDC hdc, int char_num, int pos, int dir )
@param
[tab=30]hdc[tab=30]表示したいデバイスコンテキストのHDC
[tab=30]char_num[tab=30]読み込む画像の変更用変数
[tab=30]pos[tab=30]画像を表示する位置の変更用変数
[tab=30]dir[tab=30]画像を表示する際の非ミラー・ミラー変更用の変数

のような、画像を表示する関数の中身として

① LoadImage()で外部ファイルからBITMAPイメージ読み込む。

② dir の値がミラーを求める場合、仮のメモリデバイスコンテキスト hdc_mem2 を作成して、まずはここに SelectObject()で読み込んだイメージを割り当てる。

③ StretchBlt()で仮のメモリデバイスコンテキスト hdc_mem2 に割り当てられたイメージを、ミラーして本命のメモリデバイスコンテキスト hdc_mem に転送。

④この時点で、不要になったと思われる仮のメモリデバイスコンテキストは DeleteDC() で破棄。

⑤ TransparentBlt() で hdc_mem に転送されているはずのイメージを、背景透過色を指定して、表示用のデバイスコンテキスト hdc に転送。

このような流れを想定してDraw_Char()を組み立ててみたところ、非ミラー時には正常に画像が表示されるのですが、ミラー時には画像が表示されません。
おそらくミラー時に挟んでいる StretchBlt() を使ったイメージの転送が正しくないのだと思いますが、現状この代替となるイメージのミラー方法を私は知りません。

今回はDxLib等を使用せずに、生のWindowsAPIの組み合わせで解決することに興味があること。
また、透過用のマスクイメージを用意、または自動作成して、論理的に透過するといった仕組み以外での解決を希望しています。

現在の進展・・・YuO様からご指摘いただいた、ミラー時にビットマップが明示的に割り当てられていないという点について検討した結果、問題を解決することが出来ました。本当にありがとうございました!

以下、現在の問題の関数部分です。

コード:

/*
画像の表示関数
@param	hdc			画像を表示するHDC
		char_num	画像の識別番号
		pos			画像の表示位置
		dir			画像の表示方向
*/
void Draw_Char( HDC hdc, int char_num, int pos, int dir )
{
	static int bmpw, bmph, pos_x, pos_y;
	static HDC hdc_mem;
	static HBITMAP hBmp;
	BITMAP bmp_info;

	switch( char_num )
	{
	case 1:
		hBmp = ( HBITMAP )LoadImage( hInst,	// インスタンスハンドル
			TEXT("otama1.bmp"),				// イメージの名前
			IMAGE_BITMAP,					// イメージタイプ
			0,								// 幅
			0,								// 高さ
			LR_LOADFROMFILE );				// 読み込みオプション
		break;
	case 2:
		hBmp = ( HBITMAP )LoadImage( hInst,	// インスタンスハンドル
			TEXT("otama2.bmp"),				// イメージの名前
			IMAGE_BITMAP,					// イメージタイプ
			0,								// 幅
			0,								// 高さ
			LR_LOADFROMFILE );				// 読み込みオプション
		break;
	default:
		break;
	}
	
	GetObject( hBmp, ( int )sizeof( bmp_info ), &bmp_info );
	bmpw = bmp_info.bmWidth;
	bmph = bmp_info.bmHeight;
	hdc_mem = CreateCompatibleDC( NULL );
	if( dir == 1 )
	{
		SelectObject( hdc_mem, hBmp );
	}
/*
質問解決に関わる修正部分。(修正後を後述します)
ここから~
*/
	else if( dir == 2 )
	{
		static HDC hdc_mem2;
		hdc_mem2 = CreateCompatibleDC( NULL );

		SelectObject( hdc_mem2, hBmp );

                // 仮のメモリDC(hdc_mem2)に割り当てたイメージを
                // 本命のメモリDC(hdc_mem)に転送 (しているつもりです。おそらくこれが正しくない)
		StretchBlt( hdc_mem,	// 転送先
		bmpw,						// 転送先x座標
		0,						// 転送先y座標
		(-bmpw),				// 転送先長方形の幅
		bmph,					// 転送先長方形の高さ
		hdc_mem2,				// 転送元
		0,						// 転送元x座標
		0,						// 転送元y座標
		bmpw,
		bmph,
		SRCCOPY );				// ラスタオペレーションコード

		DeleteDC( hdc_mem2 );
	}
/*
~ここまで、修正部分
*/

	switch( pos )
	{
	case 1:
		pos_x = 0;
		pos_y = 0;
		break;
	case 2:
		pos_x = 150;
		pos_y = 0;
		break;
	case 3:
		pos_x = 300;
		pos_y = 0;
		break;
	default:
		break;
	}

	TransparentBlt( hdc,	// 転送先
	pos_x,					// 転送先x座標
	pos_y,					// 転送先y座標
	bmpw,					// 転送先長方形の幅
	bmph,					// 転送先長方形の高さ
	hdc_mem,				// 転送元
	0,						// 転送元x座標
	0,						// 転送元y座標
	bmpw,
	bmph,
	RGB( 200, 10, 10 ) );	// ラスタオペレーションコード

	DeleteDC( hdc_mem );
	DeleteObject( hBmp );
}
以下、質問解決に関わる修正部分

コード:

	else if( dir == 2 )
	{
		HBITMAP hBmp2; // hdc_mem2と互換性のあるビットマップ用

		HDC hdc_mem2;
		hdc_mem2 = CreateCompatibleDC( NULL );
		SelectObject( hdc_mem2, hBmp );

		hBmp2 = CreateCompatibleBitmap( hdc_mem2, bmpw, bmph ); // hdc_mem2と互換性のあるビットマップの作成
		SelectObject( hdc_mem, hBmp2 ); // hdc_memにhBmp2を割り当て

		StretchBlt( hdc_mem,	// 転送先
		(bmpw - 1),					// 転送先x座標 
		0,						// 転送先y座標
		(- bmpw),					// 転送先長方形の幅
		bmph,					// 転送先長方形の高さ
		hdc_mem2,				// 転送元
		0,						// 転送元x座標
		0,						// 転送元y座標
		bmpw,
		bmph,
		SRCCOPY );				// ラスタオペレーションコード

		DeleteDC( hdc_mem2 );
		DeleteObject( hBmp2 ); // hBmp2の破棄
	}


softya様
マルチポストとなってしまった件、配慮と確認に欠けてしまい、本当に申し訳ありません。
現状、あちらは追記ができない状態で相互リンクが不可能であるため、大変身勝手な行いとなってしまいますが、あちらの質問を削除させていただきます。
最後に編集したユーザー nasunasi on 2013年3月21日(木) 19:49 [ 編集 10 回目 ]

YuO
記事: 941
登録日時: 9年前
住所: 東京都世田谷区

Re: 読み込んだBITMAPをミラーしてから背景透過で転送

#2

投稿記事 by YuO » 7年前

dir == 2の時に,hdc_memに対して明示的にビットマップが割り当てられていません。
この状態では,白黒の1bit x 1bitのビットマップが割り当てられるだけになります。
これは,MSDNにも記述があります。
CreateCompatibleDC function (Windows)
Remarks
A memory DC exists only in memory. When the memory DC is created, its display surface is exactly one monochrome pixel wide and one monochrome pixel high. Before an application can use a memory DC for drawing operations, it must select a bitmap of the correct width and height into the DC. To select a bitmap into a DC, use the CreateCompatibleBitmap function, specifying the height, width, and color organization required.
ちゃんとビットマップを割り当てましょう。

ところで,各種変数がstaticなのは何故ですか。
コードを読む上で非常に邪魔だったのですが。
# staticということは関数の状態であり,前回の呼び出しの状態を保持することに意味があると読み取れるが,今回は状態を保持していなかった。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 読み込んだBITMAPをミラーしてから背景透過で転送

#3

投稿記事 by softya(ソフト屋) » 7年前

マルチポストだと思われます。
「Windows言語を使用した画像の表示-画像をミラーした上で、背景を透過して表示- ... - Yahoo!知恵袋」
http://detail.chiebukuro.yahoo.co.jp/qa ... 1104181281
フォーラムルールですので、相互リンクをお願いします。
http://dixq.net/board/board.html
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 読み込んだBITMAPをミラーしてから背景透過で転送

#4

投稿記事 by softya(ソフト屋) » 7年前

softya様
マルチポストとなってしまった件、配慮と確認に欠けてしまい、本当に申し訳ありません。
現状、あちらは追記ができない状態で相互リンクが不可能であるため、大変身勝手な行いとなってしまいますが、あちらの質問を削除させていただきます。
削除は回答者に失礼ですので、お礼を書いて終了させて欲しかったです(お礼で相互リンクできたはずです)。
あと返答の形で書いてもらわないと話がつながらない(更新に気づかない)のでお願いします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

nasunasi
記事: 5
登録日時: 7年前

Re: 読み込んだBITMAPをミラーしてから背景透過で転送

#5

投稿記事 by nasunasi » 7年前

重ね重ね、申し訳ありません・・・。

私の質問内容にも至らなさや誤解を招く問題があったのでしょうが、頂いた1件の回答内容に不適切な表現があったため、解決にして残すのもいかがなモノかという思いから、短絡的に削除してしまいました。

公共の場で皆様にご迷惑をおかけすることを避けたいとは思っているのですが、自身の至らなさ故、なかなかうまくいきません。
少しでもそのような事態を避けられるよう、慎重に行動させて頂きたいと思います。

nasunasi
記事: 5
登録日時: 7年前

Re: 読み込んだBITMAPをミラーしてから背景透過で転送

#6

投稿記事 by nasunasi » 7年前

YuO様
ご回答、ありがとうございます。
明示的なビットマップイメージの割り当てについて考え直してみます!
# static についてですが、参考にしている書籍のサンプルプログラムを元に、作り替えていた過程で、必要の有無を気にせずに残してしまったようです。今後の変更や使用する状況を見て、調整させて頂きます。
最後に編集したユーザー nasunasi on 2013年3月22日(金) 06:46 [ 編集 1 回目 ]

nasunasi
記事: 5
登録日時: 7年前

Re: 読み込んだBITMAPをミラーしてから背景透過で転送

#7

投稿記事 by nasunasi » 7年前

YuO様よりご指摘頂いた、ミラー時(dir == 2)、本命のメモリDCにビットマップイメージが明示的に割り当てられていないという点を修正した結果、ミラー時にビットマップイメージが表示されないという問題を解決することが出来ました。

ご指摘下さったYuO様、ありがとうございました。

ご迷惑をお掛けしてしまったsoftya(ソフト屋)様、申し訳ありませんでした。

閉鎖

“C言語何でも質問掲示板” へ戻る