bitmapの透過

解決


origi  2004-12-31 01:05:43  No: 55863

タイトルそのまんまで質問です。
今、自分はビットマップをメモリデバイスコンテキスト(HDC)を使っていたのを
DIBに変えてみました。
HDCを使っていたときは、もう一つメモリを作っておき、マスクを描画しといて、
それを表に描画するときに透過処理をしていました。
けれど、DIBのほうはそんな方法使えないので、どうしたらいいのか困っています。
なにか良い方法は無いでしょうか?よろしくお願いします。

ついでに、HDCを使っていたときは以下のようにしていたのですが、

HDC hDC01, hDC01_mask;
HBITMAP hBmp01, hBmp01_mask;

WinAPI.....
{
   WM_CREATE:
      hBmp01 = LoadImage();
      hdc = GetDC(hWnd);
      hDC01 = CreateCOmpatibleDC(hdc);
      SelectObject(hDC01, hBmp01);
      DeleteDC() // Release?
      CreateMask(hDC01, hDC01_mask, hBmp01, &hBmp01_mask);//マスクを作る関数
                                    //hDC01_mask と hBmp01_mask にマスクが作られる

   WM_PAINT:
     BitBlt(hdc, ..... , hDC01_mask, SRCAND);
     BitBlt(hdc, ......, hDC01, SRCPAINT);
   WM_CLOSE:
    DeleteDC(hDC01);
    DeleteObject(hBmp01);
    DeleteDC(hDC01_mask);
    Deleteobject(hBmp01_mask);
}

色々なプログラムを見ていると、メモリデバイスを取得したらすぐ破棄しているのですが、
このように長期(プログラムの最初から最後まで)にわたって使っても大丈夫なのでしょうか?


origi  2004-12-31 01:14:08  No: 55864

環境いい忘れました。
VC++.NET の WindowsXP です。


シャノン  2004-12-31 02:50:13  No: 55865

メモリDC を DIB にした、とはどういうことでしょうか?
そこがいまいち掴めていません。

> 色々なプログラムを見ていると、メモリデバイスを取得したらすぐ破棄しているのですが、
> このように長期(プログラムの最初から最後まで)にわたって使っても大丈夫なのでしょうか?

そのプログラムを見る限りでは、WM_CREATE で CreateCompatibleDC し、WM_CLOSE で DeleteDC しているようですので、この Create / Delete の対応が一対一であれば問題はありません。

システム内に存在できる DC の数は決まっていて、そんなに多くないので、アプリは可能な限り早く削除しないと、他のアプリが DC を取得できなくなる、という解説も見たことがありますが、デマ、あるいは昔の仕様かと思われます。

GetDC の説明には

> デバイスコンテキストの数は、利用可能なメモリの量によってのみ制限されます。

と書かれていますので。


シャノン  2004-12-31 03:05:25  No: 55866

>       hdc = GetDC(hWnd);
>       hDC01 = CreateCOmpatibleDC(hdc);
>       SelectObject(hDC01, hBmp01);
>       DeleteDC() // Release?

この DeleteDC は何を消去しているのでしょうか?
GetDC で取得したものならば、ReleaseDC で解放すべきです。
Get / Release、Create / Delete が対になります。

> メモリDC を DIB にした、とはどういうことでしょうか?
> そこがいまいち掴めていません。

今まではビットマップをメモリ DC に選択したものを保持していたところ、これからは DIB のビットマップハンドルを持っておくようにした、ということでしょうか?
DIB の直接描画といえば、SetDIBits、SetDIBitsToDevice、StretchDIBits などがあります。このうち、StretchDIBits だけがラスタオペレーションコードを渡せるようですが…


origi  2004-12-31 03:38:02  No: 55867

説明不足ですみません・・・。
DCをDIBにしたというのは、今まではメモリDCにHBITMAPを描画して、
それを表に描画としていました。でも今作っているプログラムでは
WM_PAINT  時に何回もそれで描画してるので、別の質問のときに処理が重いと指摘されました。
なので、そこでもらったアドバイスにDIBを使うと良い、といわれたので、
HBITMAP→DC→クライアント  ではなく、
グローバルな変数  HBITMAPINFO * bmpInfo ,BYTE * bPix のように宣言して、
それをStretchDIBitsでクライアントに描画しています。
その際、描画に透過処理をしたいのですが、方法が分りません。
なにか、方法は無いでしょうが?


てつや  2005-01-01 05:22:44  No: 55868

>なので、そこでもらったアドバイスにDIBを使うと良い、といわれたので、
そんな事はありません。StretchDIBtisを使う度にDIB-DDB変換が行われるので、
かえって重くなります。

WM_PAINTのたびにメモリDCをCreateCompatibleDCすると重いので、
グローバルにして使いまわすだけで正解だと思います。

どうしてもDIBで行いたい場合は、CreateMaskのDIB版を作成する必要があります。

ソースがちょっとおかしいです。
 WM_CREATE:
      hBmp01 = LoadImage();
      hdc = GetDC(hWnd);
      hDC01 = CreateCOmpatibleDC(hdc);
      // SelectObject(hDC01, hBmp01);
      // hDC01がもともと持っているHBITMAPが行方不明になっています。
      HBITMAP preBmp = SelectObject(hDC01, hBmp01);
      // preBmpは2度と使わないのならDeleteする。
      DeleteObject(preBmp) ;
      //DeleteDC() // Release?
      ReleaseDC(hdc) ;//シャノンさんの指摘の通り

      CreateMask(hDC01, hDC01_mask, hBmp01, &hBmp01_mask);//マスクを作る関数
                                    //hDC01_mask と hBmp01_mask にマスクが作られる

   WM_PAINT:
     BitBlt(hdc, ..... , hDC01_mask, SRCAND);
     BitBlt(hdc, ......, hDC01, SRCPAINT);
   WM_CLOSE:
    DeleteDC(hDC01);
    //DeleteObject(hBmp01);
    // hDC01がDeleteされる時に選択されているHBITMAPは同時に破棄されるので
    // hBmp01の破棄は不要。
    DeleteDC(hDC01_mask);
    Deleteobject(hBmp01_mask);


origi  2005-01-01 06:09:29  No: 55869

てつやさん、アドバイスありがとうございます。
てつやさんの言うとおり、グローバルのメモリDCにしようと思います。


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

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






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