Page 1 of 1

How to create a transparent bitmap with wxWidgets ?

Posted: Tue May 06, 2008 5:57 pm
by alchemist
Hello,

I wish to create wxBitmaps with transparency, based on transparent bitmaps (PNG's with alpha channel) and drawings (using wxDC functions).

The idea is to pre-bufferize some long drawings into a bitmap that I will Blit() or DrawBitmap() in wxEVT_PAINT events.

I tried it on MacOS with success:

Code: Select all

        wxBitmap buf(100, 50);
        buf.UseAlpha();
       
        wxMemoryDC *memDC = new wxMemoryDC(buf);
        memDC->SetBackground(*wxTRANSPARENT_BRUSH);
        memDC->Clear();
        delete memDC;

        memDC = new wxMemoryDC(buf);
        // draw a red rectangle
        memDC->SetBrush(*wxRED_BRUSH);
        memDC->SetPen(*wxTRANSPARENT_PEN);
        memDC->DrawRectangle(10, 10, 30, 30);

        // draw the same rectangle from a file
        memDC->DrawBitmap(file_, 50, 00, true);
        delete memDC;
       
        buf.SaveFile(_("result.png"), wxBITMAP_TYPE_PNG);
In MacOS, I have as result a PNG with transparency with a transparent bitmap and a transparent red box drawn with wxMemoryDC.

But with wxGTK and wxMSW, the result is not correct :
- in wxGTK, the background is black
- in wxMSW, all the bitmap is transparent.

What can I do ?

I tried to ask this question some days ago, but I reformulate it to be more clear.

Posted: Tue May 06, 2008 6:15 pm
by doublemax
First you should try creating your bitmap explicitly with 32bit depth:

Code: Select all

wxBitmap buf(100, 50, 32);
If that still doesn't work, try using wxGraphicsContext (or wxGCDC which provides a wxDC compatible interface). It's not properly documented, check the "drawing" sample.

Posted: Tue May 06, 2008 6:33 pm
by alchemist
OK, I will give a try...

Posted: Wed May 07, 2008 12:23 am
by lester
You can use wxMask, fill background of bitmap with some unused colour, and then:

bitmap.SetMask( new wxMask( bitmap, unused_colour ) );

Posted: Wed May 07, 2008 7:36 am
by alchemist
lester wrote:You can use wxMask, fill background of bitmap with some unused colour, and then:

bitmap.SetMask( new wxMask( bitmap, unused_colour ) );
Can that mask be "progressive" (values between 0 and 255)? I don't think so.

I prefer the solutions of using transparent pen and brushes through wxGCDC. I am on Mac today, and since wxGCDC *IS* a wxDC, I have to wait to be on Windows to test the difference.

Posted: Wed May 07, 2008 11:08 am
by alchemist
Hello,

It doesn't work, because I don't start from a real DC but a wxMemoryDC. The result is the same as before.

Here is my code:

Code: Select all

	wxBitmap buf(100, 50, 32);
	buf.UseAlpha();
	
	wxMemoryDC *memDC = new wxMemoryDC(buf);
	wxDC *tempDC = memDC;
	wxGCDC *gcDC = new wxGCDC(tempDC);

	// draw a red rectangle 
	gcDC->SetBrush(*wxRED_BRUSH);
	gcDC->SetPen(*wxTRANSPARENT_PEN);
	gcDC->DrawRectangle(10, 10, 30, 30);

	// draw the same rectangle from a file
	dc->DrawBitmap(file_, 50, 00, true);

	delete gcDC;
	tempDC = 0;
	delete memDC;
	
	buf.SaveFile(_("result.png"), wxBITMAP_TYPE_PNG);

Posted: Wed May 07, 2008 11:56 am
by upCASE
Hi!
Just a small hint: Graphics Context needs to be enabled at compile time.

Check the setup.h file in wx/msw at about line 579. The default is having wxUSE_GRAPHICS_CONTEXT disabled.

Posted: Wed May 07, 2008 12:00 pm
by alchemist
yes, I did it (otherwise, the code didn't compile) ;)

But what I do is different from the sample : I draw into a wxMemoryDC and not a real Window's DC.

Posted: Wed May 07, 2008 3:01 pm
by doublemax

Code: Select all

wxMemoryDC *memDC = new wxMemoryDC(buf);
wxDC *tempDC = memDC;
wxGCDC *gcDC = new wxGCDC(tempDC); 
this should be wxGCDC(*tempDC). Strange that it compiled...

Is there a special reason why you created all the DCs on the heap?

I tested with the following code and it seems to work fine on XP (i left out blitting of the bitmap)

Code: Select all

wxBitmap buf(100, 50, 32);
buf.UseAlpha();

wxMemoryDC memDC(buf);
wxGCDC dc(memDC);

dc.SetBackground(*wxTRANSPARENT_BRUSH);
dc.Clear(); 

// draw a red rectangle
dc.SetBrush(*wxRED_BRUSH);
dc.SetPen(*wxTRANSPARENT_PEN);
dc.DrawRectangle(10, 10, 30, 30);

memDC.SelectObject(wxNullBitmap);
buf.SaveFile(wxT("c:\\result.png"), wxBITMAP_TYPE_PNG);

Posted: Wed May 07, 2008 3:26 pm
by alchemist
Thank you DoubleMax : it worked fine ! 8)