画像を重ねあわせするには?

解決


ぜろ  2006-02-04 06:51:34  No: 60655

みなさま、はじめまして。
私の環境は、Windows XP SP1
            Visual C++ SDK
です。
子ウィンドウが4つあり、3つは子ウィンドウでペイントし、残り1つで子ウィンドウ3つの描画を重ねて表示させたいのですが(レイヤーのように)
今、3つの描画する子ウィンドウでTransparentBltを使用し白(RGB(255,255,255))を透過色とするように設定し、なんとか重ねて表示させています。
しかし白をぬれないという欠点があり、困っています。
どのようにすれば解決できますでしょうか?
ちなみに
子ウィンドウ1〜3には仮想メモリをそれぞれ設けて、その仮想メモリを
PatBltでWHITENESSに塗り、その上からBitBltでペイントさせています。
子ウィンドウ4には仮想メモリ4を設けて、子ウィンドウ1〜3の仮想メモリに描画されている画像をTransparentBltでそれぞれ白を透過色として仮想メモリ4に転送し、そのあとでBitBltにSRCCOPYを使用し、表示させるといった方法で作成しています。

この方法でなくてもできるのでしたらご教授お願い致します。


Ban  2006-02-04 22:40:01  No: 60656

透過色は、もっと使わない緑とかにすればよいのではないかと。
もしくは、レイヤ毎に内部で使用していない色を透過色にするとか。


ぜろ  2006-02-05 03:42:47  No: 60657

Ban様お返事ありがとうございます。
先に述べておけばよかったのですが、
3つの子ウィンドウはそれぞれコモンダイアログによりカラーを選べる選択になっております。
  上記の仕様において、レイヤ毎に内部で使用していない色というのを透過色に指定するというのは可能でしょうか?


Toshi  2006-02-05 04:44:33  No: 60658

SetROP2()は試しましたか?

ラスタオペレーション関連は他にも有った様な気もしますが、自宅なのでVC6.0のMSDNしか有りません。でもこれで行けそうな気がするんですが。


Ban  2006-02-05 08:08:30  No: 60659

> 3つの子ウィンドウはそれぞれコモンダイアログによりカラーを選べる
> 選択になっております。

ソフトの制約で「固定で白は塗れない」のならそれはどうかと思いますが、
「ユーザが白をレイヤの透過色に指定」して、そのレイヤで白が塗れないと
言うことであれば、おそらくそれで仕様通りの正しい挙動なのでは?

透明色を意識させたくないならユーザに選択などさせないでしょうし、
選択する以上「白を塗る=そこを透過したい」という意思だと思いますが。

使い勝手が問題なら、仕様レベルで再検討された方がいいような気も。
デフォルトの選択色をもっと影響の少ない色にするとか、
そうやって選定した、影響の少ない色を予約してしまうとか...。

> 上記の仕様において、レイヤ毎に内部で使用していない色というのを
> 透過色に指定するというのは可能でしょうか?

力技なら、DIBSection あたりでビットを走査すれば、使ってない色がわかるかと。
# 256色以下ならパレットを舐める。
可能なら予めバックグランドで走査しておくとか。
# もしくは前述のように、害の少ない色を先に予約してしまうか、
# ユーザに「使ってない色」を選ばせるか....。

ところで、試してなくてなんですが、AlphaBlend では透過できませんでしたか。

もしくは ID3DXSplite 使ってみるとか...(こちらは用途次第でしょうが。


ぜろ  2006-02-06 01:38:04  No: 60660

Toshi様、Ban様お返事ありがとうございます。
Toshi様
  SetROP2()の使用方法を探してみたのですが、どのように使用すればよいのか
今ひとつわかりません(泣)私が間違っていたら申し訳ないのですが、
調べてみたところ、同じウィンドウ内での論理演算だと感じました。
もし違っていれば、少し詳しく教えてはくれないでしょうか?
ちなみに、私もVC++ 6.0です。

Ban様
  AlphaBlendの使用ですが、指定した画像すべてが透過処理されてしまい
  上手く自分の思う処理ができませんでした。私の力不足なのか、そのような仕様
なのかは定かではありませんが。

あとID3DXSpliteというものはどのようなものなのでしょうか?
google検索でもヒットしなかったので(汗)

↓にプログラムの一部を書いておきますのでお気づきになられましたら
ご教授いただけますでしょうか?

case WM_CREATE:
//子ウィンドウ1
hMenu = GetMenu ( hWnd );
GetWinRect( hWnd, &wx, &wy );
hInstance = ((LPCREATESTRUCT ) lParam ) ->hInstance;
InitApp( hInstance , ChdProc1 , "child1" );
hChdWnd1 = CreateWindow (
      "child1" ,
      ""       ,
      WS_CHILD | WS_BORDER | WS_VISIBLE |
      ES_MULTILINE | ES_WANTRETURN |
      ES_AUTOHSCROLL | ES_AUTOVSCROLL ,
      0 ,
      0 ,
      wx/2 ,  
      wy/2 ,
      hWnd ,
      (HMENU)ID_CHILD1 ,
      hInstance ,
      NULL 
      );
hdc = GetDC(hChdWnd1);
hBitmap1 = CreateCompatibleBitmap( hdc , wx , wy );
hBuffer1 = CreateCompatibleDC( hdc );
SelectObject( hBuffer1 , hBitmap1 );
SelectObject( hBuffer1 , GetStockObject(NULL_PEN) );
PatBlt ( hBuffer1 , 0 , 0 , wx , wy , WHITENESS );
ReleaseDC( hChdWnd1 , hdc );

この子ウィンドウ設定が1〜4ございます。
//子ウィンドウ4 -> プロシージャ
LRESULT CALLBACK ChdProc4 ( HWND hChdWnd4, UINT msg, WPARAM wParam, LPARAM lParam )
{
int id;
HDC hdc;
PAINTSTRUCT ps;

switch ( msg ) {
case WM_PAINT:
hdc = BeginPaint ( hChdWnd4 , &ps );
TransparentBlt( hBuffer4 , 0 , 0 , wx , wy , hBuffer1 , 0 , 0 , wx , wy , RGB(255,255,255) );
TransparentBlt( hBuffer4 , 0 , 0 , wx , wy , hBuffer2 , 0 , 0 , wx , wy , RGB(255,255,255) );
TransparentBlt( hBuffer4 , 0 , 0 , wx , wy , hBuffer3 , 0 , 0 , wx , wy , RGB(255,255,255) );
BitBlt( hdc , 0 , 0 , wx , wy , hBuffer4 , 0 , 0 , SRCCOPY );
EndPaint ( hChdWnd4 , &ps );
break;

これが重ねあわせる子ウィンドウの設定でございます。
部分的ですので理解できない部分があると思いますが
よろしくお願いします。
長文失礼致しました。


Ban  2006-02-06 11:44:34  No: 60661

> AlphaBlendの使用ですが、指定した画像すべてが透過処理されてしまい
> 上手く自分の思う処理ができませんでした。私の力不足なのか、
> そのような仕様なのかは定かではありませんが。

それは、画像全体に一様のα値を適用されたからでは。(そういう機能もある
ピクセル毎に透過するには、ピクセル毎にα値を持つ必要があるはずですが、
元画像を 32bpp で保持してα値の設定を....とかされてますか。

> あとID3DXSpliteというものはどのようなものなのでしょうか?
> google検索でもヒットしなかったので(汗)

え?と思ったら、ID3DXSprite でした...orz(かっこわるっ
ようは、重ねあわせは DirectX 任せでどうだろうということです。
# スプライト自体、DirectGraphicsの中では微妙かも。


Toshi  2006-02-06 20:10:22  No: 60662

あら私仕様を把握してないのかな?
ウィンドウ4にウィンドウ1〜3の画像をラスタで重ねてやればいいんじゃないかと思ったのですが。
当然、ウィンドウ4=同一ウィンドウ内での話になります。
昔、家庭用ゲーム機やMSX等で流行った「スプライト機能」なんかはラスターオペレーションの代表みたいなもんです。
とは言っても、Windowでは私も使った事無いので詳細は説明し兼ねますが、そんな難しい話では無いと思いますので簡単なサンプルかなんかで試してみたらいかがでしょう?

もし私が仕様を理解してなくて見当違いな事を書いてたら流して下さい。


porin  2006-02-07 06:22:06  No: 60663

いまいちイメージがつかめないのですが
ようは全ての色+透明が使えればいいわけですよね?

子ウインドウそれぞれにモノクロ2階調のマスク用デバイスコンテキストを
用意すればいいだけじゃないでしょうか?

# 子ウインドウに何かしらの描画を行うたびにマスクも更新
# で、子ウインドウ4にマスク付きで転送(ラスタ)
# ……言ってることは Toshi さんと何ら変わりませんが^^;


ぜろ  2006-02-08 00:34:15  No: 60664

Ban様、Toshi様、porin様お返事ありがとうございます。
Ban様
AlphaBlendにその様な使用方法があることをしりませんでした(汗
ID3DXSpriteはDirectXを使用するのですか。
全く知りませんでした!

Toshi様
私はまだまだ全然勉強不足なので、Toshi様のほうがあってるかと思われます。

porin様
通常のペイントソフトではないので、理解しがたいものかと思います。
かといって、複雑かといえば複雑ではないのですが、
私がまだまだ勉強不足なので^^;

マスクを使用する方法も一度考えたのですが、描画した画像を
マスク用画像に変換する方法がわからずに、今の方式になってしまいました。

私が難しく考えすぎなのかもしれませんが、一度色々な方法で試したいと思います。


Toshi  2006-02-08 21:56:38  No: 60665

あ、失礼しました。
MSDNを良く見てみたら、SetRop2()はペン描画に対するラスターオペレーションしか出来ないみたいです。
これじゃダメですね。

ちなみに、アホな事言っちゃうかも知れませんが
単純に BitBlt()で SRCPAINTを指定して重ねちゃダメですか?


porin  2006-02-09 02:22:32  No: 60666

難しく考えすぎかなーと

ちなみに描画した画像をマスク用画像に変換しても白と透明の区別がつかないので
描画する前にマスクを用意する必要があります。

イメージだとこんな感じ
(画像の中央に白を塗ったとする)

画像            白黒マスク      転送先
(白1色)      
[[[[[[          [[[[[[          
[[[[[[    →    [[  [[    →      [[
[[[[[[          [[[[[[


ぜろ  2006-02-16 05:40:00  No: 60667

おかげさまでなんとか表示することができました。
いろいろ助言くださった方、本当にありがとうございました。
またなにかあれば、書き込みしますのでよろしくお願いします。


Toshi  2006-02-16 07:28:04  No: 60668

出来ればどうやって解決したか書いて欲しい所ですが・・・
(技術板のマナーとして)


ぜろ  2006-02-17 04:18:17  No: 60669

すみませんでした。描くべきですね^^;

えと、半ば強制的ですが・・・。
最初に、仮想メモリにRGB(254 , 254 , 254 )をブラシで塗る設定して
表示させることにし、透過色指定転送(TransparentBlt)を使用し
RGB(254 , 254 , 254 )を指定して転送させています。

マスク画像を使用する方法もかなりがんばって作ったのですが、
どうしても転送過程で失敗してしまいました。転送するときにたまに
フリーズしてしまう現象がおきてしまい、どうしてもわからず上記の
方法で再検討させていただきました。
勉強しなおしてできるようにという考えも含みまして
解決を押させていただきました。

色々助言ありがとうございました。諦めたわけじゃないので
また、ここにきて書き込みをしたいと思います。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加