DrawBitmap loses the background of the image on win32

I’m experiencing a really weird issue on windows, I’ve attached some sample code which demonstrates the problem because I cant for the life of me work out why it’s doing this.

I’m just trying to draw a bitmap with a MemoryDC, and as part of creating the bitmap I want to draw a bitmap onto the image. On mac this works fine but for some reason on windows if I draw a bitmap on I lose everything else in the image. Does anyone know why?

I’m running windows 7 64bit, python 2.7.3 32bit, wx 2.8.12.1 (msw-unicode)

Many thanks!

windowsbitmap.py (1.84 KB)

I don't know why but forcing your banner_bmp to use a bit depth of 24 fixes the problem. It may be some kind of mismatch between that and the red square bmp's depth, or rather the type of native bitmap used under the covers (DDB vs DIB) or something. Regardless it is a bug and should be reported. Create a ticket for it and attach the source image for the red square bitmap, and try to provide enough info and descriptive text that somebody can reproduce the bug in C++ code.

···

On 6/14/12 4:18 AM, Paul wrote:

I'm experiencing a really weird issue on windows, I've attached some
sample code which demonstrates the problem because I cant for the life
of me work out why it's doing this.

I'm just trying to draw a bitmap with a MemoryDC, and as part of
creating the bitmap I want to draw a bitmap onto the image. On mac this
works fine but for some reason on windows if I draw a bitmap on I lose
everything else in the image. Does anyone know why?

I'm running windows 7 64bit, python 2.7.3 32bit, wx 2.8.12.1 (msw-unicode)

--
Robin Dunn
Software Craftsman

I’m experiencing a really weird issue on windows, I’ve attached some

sample code which demonstrates the problem because I cant for the life

of me work out why it’s doing this.

I’m just trying to draw a bitmap with a MemoryDC, and as part of

creating the bitmap I want to draw a bitmap onto the image. On mac this

works fine but for some reason on windows if I draw a bitmap on I lose

everything else in the image. Does anyone know why?

I’m running windows 7 64bit, python 2.7.3 32bit, wx 2.8.12.1 (msw-unicode)

I don’t know why but forcing your banner_bmp to use a bit depth of 24 fixes the problem. It may be some kind of mismatch between that and the red square bmp’s depth, or rather the type of native bitmap used under the covers (DDB vs DIB) or something. Regardless it is a bug and should be reported. Create a ticket for it and attach the source image for the red square bitmap, and try to provide enough info and descriptive text that somebody can reproduce the bug in C++ code.

Thanks Robin, setting the bit depth works great!

ticket is here: http://trac.wxwidgets.org/ticket/14403

···

On 14 June 2012 17:10, Robin Dunn robin@alldunn.com wrote:

On 6/14/12 4:18 AM, Paul wrote:

Robin Dunn

Software Craftsman

http://wxPython.org

To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com

or visit http://groups.google.com/group/wxPython-users?hl=en

I’m experiencing a really weird issue on windows, I’ve attached some

sample code which demonstrates the problem because I cant for the life

of me work out why it’s doing this.

I’m just trying to draw a bitmap with a MemoryDC, and as part of

creating the bitmap I want to draw a bitmap onto the image. On mac this

works fine but for some reason on windows if I draw a bitmap on I lose

everything else in the image. Does anyone know why?

I’m running windows 7 64bit, python 2.7.3 32bit, wx 2.8.12.1 (msw-unicode)

I don’t know why but forcing your banner_bmp to use a bit depth of 24 fixes the problem. It may be some kind of mismatch between that and the red square bmp’s depth, or rather the type of native bitmap used under the covers (DDB vs DIB) or something. Regardless it is a bug and should be reported. Create a ticket for it and attach the source image for the red square bitmap, and try to provide enough info and descriptive text that somebody can reproduce the bug in C++ code.

Thanks Robin, setting the bit depth works great!

ticket is here: http://trac.wxwidgets.org/ticket/14403

There’s one other issue I have with windows and making bitmaps. On mac the background of a new EmptyBitmap is transparent, but on windows its black and I can’t seem make it transparent either.

this seems to work on linux but not windows:

dc.SetBackground(wx.TRANSPARENT_BRUSH)

dc.Clear()

and I’ve tried a bunch of other methods and searching which don’t seem to work either.

Setting a mask colour to black

Converting to an image, setting a mask colour, calling InitAlpha and converting back

I tried loading a 1x1 transparent png and scaling it into my desired size, which works but I can’t seem to draw anything on it afterward- maybe what’s drawing is inheriting the alpha channel and everything that’s drawn is invisible.

···

On 15 June 2012 11:00, Paul Wiseman poalman@gmail.com wrote:

On 14 June 2012 17:10, Robin Dunn robin@alldunn.com wrote:

On 6/14/12 4:18 AM, Paul wrote:

Robin Dunn

Software Craftsman

http://wxPython.org

To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com

or visit http://groups.google.com/group/wxPython-users?hl=en

There's one other issue I have with windows and making bitmaps. On mac
the background of a new EmptyBitmap is transparent, but on windows its
black and I can't seem make it transparent either.

this seems to work on linux but not windows:

dc.SetBackground(wx.TRANSPARENT_BRUSH)
dc.Clear()

It may look like it is working, but probably not really ;-). Using a wx.TRANSPARENT_BRUSH is supposed to only tell the drawing operations to leave the pixels untouched that would normally be painted by the brush. It doesn't actually set them to be transparent. If Clear is doing something different than that then it should probably be considered a bug.

and I've tried a bunch of other methods and searching which don't seem
to work either.

Setting a mask colour to black

This should work, but you'll probably need to do it after you've drawn your other stuff on the bitmap and deselected it from the memory dc. You may have to deal with jaggy edges though since a mask doesn't understand blending. However if you initialize the bitmap to have a background color that is the same or nearly the same as where the bitmap will be used, and then set that to be your masked color, then the jaggy edges will probably not be noticeable.

Converting to an image, setting a mask colour, calling InitAlpha and
converting back
I tried loading a 1x1 transparent png and scaling it into my desired
size, which works but I can't seem to draw anything on it afterward-
maybe what's drawing is inheriting the alpha channel and everything
that's drawn is invisible.

On Windows, and somewhat on wxGTK, things drawn with a normal wxDC will pretty much ignore the target's existing transparency and alpha. The native APIs just are not designed to handle them. Instead you should look into using wx.GraphicsContext or the wx.GCDC (a graphics context that implements most of the wxDC API) as the native APIs they are built upon do support alpha blending, anti-aliasing, etc.

On the other hand, you may still run into some differences across platforms even with wx.GraphicsContext, although the differences have been diminishing. One way to be totally consistent on all platforms is to use something like Cairo instead. There are some helpers in wx.lib.wxcairo for interfacing between wx and pycairo, and the wx.lib.graphics provides a pure python implementation of a wx.GraphicsContext-like API using pycairo.

···

On 6/15/12 6:39 AM, Paul Wiseman wrote:

--
Robin Dunn
Software Craftsman

There’s one other issue I have with windows and making bitmaps. On mac

the background of a new EmptyBitmap is transparent, but on windows its

black and I can’t seem make it transparent either.

this seems to work on linux but not windows:

dc.SetBackground(wx.TRANSPARENT_BRUSH)

dc.Clear()

It may look like it is working, but probably not really ;-). Using a wx.TRANSPARENT_BRUSH is supposed to only tell the drawing operations to leave the pixels untouched that would normally be painted by the brush. It doesn’t actually set them to be transparent. If Clear is doing something different than that then it should probably be considered a bug.

and I’ve tried a bunch of other methods and searching which don’t seem

to work either.

Setting a mask colour to black

This should work, but you’ll probably need to do it after you’ve drawn your other stuff on the bitmap and deselected it from the memory dc. You may have to deal with jaggy edges though since a mask doesn’t understand blending. However if you initialize the bitmap to have a background color that is the same or nearly the same as where the bitmap will be used, and then set that to be your masked color, then the jaggy edges will probably not be noticeable.

Converting to an image, setting a mask colour, calling InitAlpha and

converting back

I tried loading a 1x1 transparent png and scaling it into my desired

size, which works but I can’t seem to draw anything on it afterward-

maybe what’s drawing is inheriting the alpha channel and everything

that’s drawn is invisible.

On Windows, and somewhat on wxGTK, things drawn with a normal wxDC will pretty much ignore the target’s existing transparency and alpha. The native APIs just are not designed to handle them. Instead you should look into using wx.GraphicsContext or the wx.GCDC (a graphics context that implements most of the wxDC API) as the native APIs they are built upon do support alpha blending, anti-aliasing, etc.

I tried wx.GCDC(wx.MemoryDC(wx.EmptyBitmap(w,h))) but I’m still getting the same result- How can I make the initial empty bitmap transparent?

On the other hand, you may still run into some differences across platforms even with wx.GraphicsContext, although the differences have been diminishing. One way to be totally consistent on all platforms is to use something like Cairo instead. There are some helpers in wx.lib.wxcairo for interfacing between wx and pycairo, and the wx.lib.graphics provides a pure python implementation of a wx.GraphicsContext-like API using pycairo.

I really like the idea of using cairo, it’s just I think I’ve pretty much written all the drawing functions now and I think it’d be too much work rewriting them all now as it’s only a few left now which don’t look quite right on windows. I wish I’d have used it when I started, it looks really good.

···

On 15 June 2012 19:38, Robin Dunn robin@alldunn.com wrote:

On 6/15/12 6:39 AM, Paul Wiseman wrote:

Robin Dunn

Software Craftsman

http://wxPython.org

To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com

or visit http://groups.google.com/group/wxPython-users?hl=en

Try wx.EmptyBitmapRGBA(w,h, r,g,b, 0)

···

On 6/21/12 10:12 AM, Paul Wiseman wrote:

I tried wx.GCDC(wx.MemoryDC(wx.EmptyBitmap(w,h))) but I'm still getting
the same result- How can I make the initial empty bitmap transparent?

--
Robin Dunn
Software Craftsman

I tried wx.GCDC(wx.MemoryDC(wx.EmptyBitmap(w,h))) but I’m still getting

the same result- How can I make the initial empty bitmap transparent?

Try wx.EmptyBitmapRGBA(w,h, r,g,b, 0)

Ah thanks, I didn’t know about that.

I decided to try the method of setting the background of the bitmap to be a similar colour to what I’m planning to draw the bitmap onto (the background isn’t a solid colour but it’s all similar shades so shouldn’t be noticeable like you said) and then set the mask of the bitmap. But I’ve hit another snag which I think could be a bug. I need to rotate the bitmap when I’m done, the only way I know to do this is to convert to wxImage and back but this is unexpectedly filling the image with noise. I attached some sample code to demo what I mean

bitmapnoise.py (1019 Bytes)

···

On 22 June 2012 06:48, Robin Dunn robin@alldunn.com wrote:

On 6/21/12 10:12 AM, Paul Wiseman wrote:

Robin Dunn

Software Craftsman

http://wxPython.org

To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com

or visit http://groups.google.com/group/wxPython-users?hl=en

I tried wx.GCDC(wx.MemoryDC(wx.EmptyBitmap(w,h))) but I’m still getting

the same result- How can I make the initial empty bitmap transparent?

Try wx.EmptyBitmapRGBA(w,h, r,g,b, 0)

Ah thanks, I didn’t know about that.

I decided to try the method of setting the background of the bitmap to be a similar colour to what I’m planning to draw the bitmap onto (the background isn’t a solid colour but it’s all similar shades so shouldn’t be noticeable like you said) and then set the mask of the bitmap. But I’ve hit another snag which I think could be a bug. I need to rotate the bitmap when I’m done, the only way I know to do this is to convert to wxImage and back but this is unexpectedly filling the image with noise. I attached some sample code to demo what I mean

I should have mentioned this is only happening when I set the mask.

I had a thought and tried setting the mask after doing the rotation, but doing that has an even weirder effect… you get the noise plus a black background. Really not sure what’s happening :S

···

On 22 June 2012 13:16, Paul Wiseman poalman@gmail.com wrote:

On 22 June 2012 06:48, Robin Dunn robin@alldunn.com wrote:

On 6/21/12 10:12 AM, Paul Wiseman wrote:

Robin Dunn

Software Craftsman

http://wxPython.org

To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com

or visit http://groups.google.com/group/wxPython-users?hl=en

On 22 June 2012 13:16, Paul Wiseman <poalman@gmail.com
    I decided to try the method of setting the background of the bitmap
    to be a similar colour to what I'm planning to draw the bitmap onto
    (the background isn't a solid colour but it's all similar shades so
    shouldn't be noticeable like you said) and then set the mask of the
    bitmap. But I've hit another snag which I think could be a bug. I
    need to rotate the bitmap when I'm done, the only way I know to do
    this is to convert to wxImage and back but this is unexpectedly
    filling the image with noise. I attached some sample code to demo
    what I mean

Sounds like it is time for another bug report.

I should have mentioned this is only happening when I set the mask.

I had a thought and tried setting the mask after doing the rotation, but
doing that has an even weirder effect.. you get the noise plus a black
background. Really not sure what's happening :S

That is apparently a feature. The docs say, "If the image has a mask, then the mask colour is used for the uncovered pixels in the rotated image background. Else, black (rgb 0, 0, 0) will be used."

···

On 6/22/12 5:24 AM, Paul Wiseman wrote:

--
Robin Dunn
Software Craftsman

On 22 June 2012 13:16, Paul Wiseman <poalman@gmail.com

I decided to try the method of setting the background of the bitmap

to be a similar colour to what I'm planning to draw the bitmap onto

(the background isn't a solid colour but it's all similar shades so

shouldn't be noticeable like you said) and then set the mask of the

bitmap. But I've hit another snag which I think could be a bug. I

need to rotate the bitmap when I'm done, the only way I know to do

this is to convert to wxImage and back but this is unexpectedly

filling the image with noise. I attached some sample code to demo

what I mean

Sounds like it is time for another bug report.

Just submitted it now: http://trac.wxwidgets.org/ticket/14436

I should have mentioned this is only happening when I set the mask.

I had a thought and tried setting the mask after doing the rotation, but

doing that has an even weirder effect… you get the noise plus a black

background. Really not sure what’s happening :S

That is apparently a feature. The docs say, “If the image has a mask, then the mask colour is used for the uncovered pixels in the rotated image background. Else, black (rgb 0, 0, 0) will be used.”

Doesn’t look like I’m ever going to get this bitmap function working :slight_smile: I’m going to try another way now.

By the way how do you select objects with the GCDC? It doesn’t have the method like the MemoryDC does. The only way I can find is by selecting it in the Memory DC first, then creating the gcdc, but if I want to switch bitmaps I have to Destroy the current one and do the same with a new memory dc.

···

On 22 June 2012 16:18, Robin Dunn robin@alldunn.com wrote:

On 6/22/12 5:24 AM, Paul Wiseman wrote:

Robin Dunn

Software Craftsman

http://wxPython.org

To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com

or visit http://groups.google.com/group/wxPython-users?hl=en

I was curious and wondered if the same thing happened if I set a mask on a bitmap created with EmptyBitmapRGBA with full alpha, but as far as I can tell the SetMaskColour doesn’t work on bitmaps created this way.

I tried drawing on a bitmap created with EmptyBitmapRGBA with 0 alpha but the text drawn on seems to get black noise around the edge from nowhere, kinda like if I drew on black and set black as the mask which doesn’t look great so I’ll keep trying different methods.

This has the be possible :slight_smile:

Ahh, finally got it by drawing the bitmap on with GraphicsContext after using GraphicsContext.Rotate rather than converting it to an image and back to rotate the bitmap. Phew!

···

On 25 June 2012 12:28, Paul Wiseman poalman@gmail.com wrote:

I was curious and wondered if the same thing happened if I set a mask on a bitmap created with EmptyBitmapRGBA with full alpha, but as far as I can tell the SetMaskColour doesn’t work on bitmaps created this way.

I tried drawing on a bitmap created with EmptyBitmapRGBA with 0 alpha but the text drawn on seems to get black noise around the edge from nowhere, kinda like if I drew on black and set black as the mask which doesn’t look great so I’ll keep trying different methods.

This has the be possible :slight_smile: