How to create a transparent bitmap with wxWidgets ? Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
User avatar
alchemist
Experienced Solver
Experienced Solver
Posts: 80
Joined: Tue Sep 04, 2007 6:03 pm
Location: Lembeek - Belgium
Contact:

How to create a transparent bitmap with wxWidgets ?

Post by alchemist » Tue May 06, 2008 5:57 pm

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.
Kind Regards,
Xavier Miller.
http://xaviermiller.be

User avatar
doublemax
Moderator
Moderator
Posts: 15275
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax » Tue May 06, 2008 6:15 pm

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.
Use the source, Luke!

User avatar
alchemist
Experienced Solver
Experienced Solver
Posts: 80
Joined: Tue Sep 04, 2007 6:03 pm
Location: Lembeek - Belgium
Contact:

Post by alchemist » Tue May 06, 2008 6:33 pm

OK, I will give a try...
Kind Regards,
Xavier Miller.
http://xaviermiller.be

lester
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 211
Joined: Sat Sep 02, 2006 7:24 pm
Location: Ukraine

Post by lester » Wed May 07, 2008 12:23 am

You can use wxMask, fill background of bitmap with some unused colour, and then:

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

User avatar
alchemist
Experienced Solver
Experienced Solver
Posts: 80
Joined: Tue Sep 04, 2007 6:03 pm
Location: Lembeek - Belgium
Contact:

Post by alchemist » Wed May 07, 2008 7:36 am

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.
Kind Regards,
Xavier Miller.
http://xaviermiller.be

User avatar
alchemist
Experienced Solver
Experienced Solver
Posts: 80
Joined: Tue Sep 04, 2007 6:03 pm
Location: Lembeek - Belgium
Contact:

Post by alchemist » Wed May 07, 2008 11:08 am

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);
Attachments
transparent.png
Here is the transparent bitmap, represented by the "file_" variable
transparent.png (224 Bytes) Viewed 2759 times
result.png
and the result: nothing :'(
result.png (109 Bytes) Viewed 2759 times
Kind Regards,
Xavier Miller.
http://xaviermiller.be

upCASE
Site Admin
Site Admin
Posts: 3176
Joined: Mon Aug 30, 2004 6:55 am
Location: Germany, Cologne

Post by upCASE » Wed May 07, 2008 11:56 am

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.
OS: OpenSuSE, Ubuntu, Win XP Pro
wx: svn
Compiler: gcc 4.5.1, VC 2008, eVC 4

"If it was hard to write it should be hard to read..." - the unknown coder
"Try not! Do. Or do not. There is no try." - Yoda

User avatar
alchemist
Experienced Solver
Experienced Solver
Posts: 80
Joined: Tue Sep 04, 2007 6:03 pm
Location: Lembeek - Belgium
Contact:

Post by alchemist » Wed May 07, 2008 12:00 pm

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.
Kind Regards,
Xavier Miller.
http://xaviermiller.be

User avatar
doublemax
Moderator
Moderator
Posts: 15275
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax » Wed May 07, 2008 3:01 pm

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);
Use the source, Luke!

User avatar
alchemist
Experienced Solver
Experienced Solver
Posts: 80
Joined: Tue Sep 04, 2007 6:03 pm
Location: Lembeek - Belgium
Contact:

Post by alchemist » Wed May 07, 2008 3:26 pm

Thank you DoubleMax : it worked fine ! 8)
Kind Regards,
Xavier Miller.
http://xaviermiller.be

Post Reply