DC+Bitmap Is it a bug?

12 views
Skip to first unread message

King

unread,
Dec 15, 2009, 6:59:28 AM12/15/09
to wxPython-users
"""
The idea is render a bitmap using memoryDC and keet it.
Later draw this bitmap on another memoryDC operation.
Problem is that bitmap is loosing it's transparency.
The code below will show you the problem
"""


# -*- coding: iso-8859-1 -*-#
#!/usr/bin/env python2.4

import wx

class DemoApp(wx.App):
def OnInit(self):
wx.InitAllImageHandlers() # called so a PNG can be saved

# Render a bitmap using MemoryDC.
# We are drawing an ellipse thus we need a bitmap with
# transparency. We are going to keep this bitmap for later...
width, height = 100, 50
size = width, height
colorBitmap = wx.EmptyBitmapRGBA(size[0], size[1], 0, 0, 0,
0)
mdc = wx.MemoryDC(colorBitmap)
mdc.SetPen(wx.Pen("white", 1))
mdc.SetBrush(wx.Brush("red"))
mdc.SetDeviceOrigin(0, 0)
mdc.DrawEllipse(0, 0, width, height)
# Select the Bitmap out of the memory DC
# by selecting a new uninitialized Bitmap
mdc.SelectObject(wx.NullBitmap)
del mdc

# Create another bitmap using memoryDC and
# draw the bitmap created above.
newBitmap = wx.EmptyBitmap(*size)
mdc = wx.MemoryDC()
mdc.SelectObject(newBitmap)
# Draw bitmap with a gray background
mdc.SetBackground(wx.Brush("gray"))
mdc.Clear() # make sure you clear the bitmap!
mdc.DrawBitmap(colorBitmap, 0, 0)
# Select the Bitmap out of the memory DC
# by selecting a new uninitialized Bitmap
mdc.SelectObject(wx.NullBitmap)
del mdc

# BUG:
# Save file and you can see that ellipse is saved
# with some level of transparency. It's not complete red.
img = newBitmap.ConvertToImage()
fileName = "memdc.png"
img.SaveFile(fileName, wx.BITMAP_TYPE_PNG)

return True

if __name__ == "__main__":
print "about to initialize the app"
app = DemoApp(0)
app.MainLoop()





Christopher Barker

unread,
Dec 15, 2009, 12:13:22 PM12/15/09
to wxpytho...@googlegroups.com
King wrote:
> Problem is that bitmap is loosing it's transparency.
> The code below will show you the problem

It seems to work fine on my OS-X box -- what OS and wx version number
are you using?

> import wx
>
> class DemoApp(wx.App):
> def OnInit(self):
> wx.InitAllImageHandlers() # called so a PNG can be saved
>
> # Render a bitmap using MemoryDC.
> # We are drawing an ellipse thus we need a bitmap with
> # transparency. We are going to keep this bitmap for later...
> width, height = 100, 50
> size = width, height
> colorBitmap = wx.EmptyBitmapRGBA(size[0], size[1], 0, 0, 0,
> 0)
> mdc = wx.MemoryDC(colorBitmap)
> mdc.SetPen(wx.Pen("white", 1))
> mdc.SetBrush(wx.Brush("red"))
> mdc.SetDeviceOrigin(0, 0)
> mdc.DrawEllipse(0, 0, width, height)
> # Select the Bitmap out of the memory DC
> # by selecting a new uninitialized Bitmap
> mdc.SelectObject(wx.NullBitmap)
> del mdc
>
> # Create another bitmap using memoryDC and
> # draw the bitmap created above.
> newBitmap = wx.EmptyBitmap(*size)

don't you want a wx.EmptyBitmapRGBA here, too?


-Chris



--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris....@noaa.gov

Christopher Barker

unread,
Dec 15, 2009, 12:14:36 PM12/15/09
to wxpytho...@googlegroups.com
King wrote:
> """
> The idea is render a bitmap using memoryDC and keet it.
> Later draw this bitmap on another memoryDC operation.
> Problem is that bitmap is loosing it's transparency.

Another thought -- you may want to use a GraphicsContext instead -- DCs
originally didn't support transparency at all, so maybe they don't work
as well for that.

King

unread,
Dec 15, 2009, 12:36:04 PM12/15/09
to wxPython-users

> Another thought -- you may want to use a GraphicsContext instead -- DCs
> originally didn't support transparency at all, so maybe they don't work
> as well for that.
>
I am on Win XP 32, Python 2.6.2, wxPython 2.8.10.1.
Yes, on GraphicsContext it's working fine.

The big question is that is it a bug on ms-win or it doesn't work with
DCs?
Even in my case the second bitmap is first filled with gray color and
ellipse is drawn later.
If DCs doesn't support transparency then I would have get an image
with black background & red
colour ellipse on top of it. Some thing is fishy and I have no idea :-
(


Chris, I would like to ask you few questions about DCs.

mdc = wx.MemoryDC(bmp)
gc = wx.GraphicContext.Create(mdc)

Drawing on gc is much slower then drawing on mdc. Is it the
transparency and anti-aliasing of gc or anything else?

How to render/draw anti-aliased fonts? Specially when your application
has an interactive scaling/zooming. Rendering
an offline bitmap using PIL or cairo and drawing it later is slower.

Prashant

Robin Dunn

unread,
Dec 15, 2009, 1:24:03 PM12/15/09
to wxpytho...@googlegroups.com
On 12/15/09 3:59 AM, King wrote:
> """
> The idea is render a bitmap using memoryDC and keet it.
> Later draw this bitmap on another memoryDC operation.
> Problem is that bitmap is loosing it's transparency.
> The code below will show you the problem
> """

On Windows the DCs are totally unaware of the alpha channel in the
target bitmap they are drawing upon, so they don't do anything to modify
it while drawing.


--
Robin Dunn
Software Craftsman
http://wxPython.org

Robin Dunn

unread,
Dec 15, 2009, 1:24:35 PM12/15/09
to wxpytho...@googlegroups.com
On 12/15/09 9:36 AM, King wrote:
>
> mdc = wx.MemoryDC(bmp)
> gc = wx.GraphicContext.Create(mdc)
>
> Drawing on gc is much slower then drawing on mdc. Is it the
> transparency and anti-aliasing of gc or anything else?

It's because on Windows it is using the MS GDI+ library for the backend,
which is quite slow compared to DCs.

>
> How to render/draw anti-aliased fonts? Specially when your application
> has an interactive scaling/zooming.

Very similar to doing it on a DC. Set the font and use DrawText.

King

unread,
Dec 17, 2009, 2:17:18 AM12/17/09
to wxPython-users
"""
Here is the new test. The code below generate a bitmap by rendering a
text using
GraphicsContext and later bitmap is used by another dc operation to
save it. Every
thing is working fine and no problem in transparency.
How ever if you change the line in generation part:
ctx = wx.GraphicsContext.Create(mdc)#Cairo.GraphicsContext.Create(mdc)
to
ctx = Cairo.GraphicsContext.Create(mdc)
the bit "text.png" is coming out with transparency but while reading
it back
using:
mdc.DrawBitmap(colorBitmap, 0, 0)
again the I am facing the some transparency problem.

May be cairo's DrawBimap function is not able to read properly or some
explanation
is required here.

"""
# -*- coding: iso-8859-1 -*-#
#!/usr/bin/env python2.4

import wx
import wx.lib.graphics as Cairo

class DemoApp(wx.App):
def OnInit(self):
wx.InitAllImageHandlers() # called so a PNG can be saved

font = wx.FFont(9, wx.SWISS, wx.FONTFLAG_BOLD, "Lucid
Console")


# Render a bitmap using MemoryDC.

width, height = 100, 100
size = width, height
colorBitmap = wx.EmptyBitmapRGBA(size[0]+1, size[1]+1, 0, 0,


0, 0)
mdc = wx.MemoryDC(colorBitmap)

ctx = wx.GraphicsContext.Create(mdc)
#Cairo.GraphicsContext.Create(mdc)
ctx.SetFont(font, "blue")
ctx.DrawText("wxPython Rocks!!!", 0, 45)
mdc.SelectObject(wx.NullBitmap)
del mdc
colorBitmap.SaveFile("text.png", wx.BITMAP_TYPE_PNG)

# Create another bitmap using memoryDC and
# draw the bitmap created above.

newBitmap = wx.EmptyBitmapRGBA(size[0]+1, size[1]+1, 0, 0, 0,
0)
mdc = wx.MemoryDC(newBitmap)


mdc.SetBackground(wx.Brush("gray"))
mdc.Clear() # make sure you clear the bitmap!
mdc.DrawBitmap(colorBitmap, 0, 0)

mdc.SelectObject(wx.NullBitmap)
del mdc
newBitmap.SaveFile("memdc.png", wx.BITMAP_TYPE_PNG)

Robin Dunn

unread,
Dec 17, 2009, 2:01:01 PM12/17/09
to wxpytho...@googlegroups.com
On 12/16/09 11:17 PM, King wrote:
> """
> Here is the new test. The code below generate a bitmap by rendering a
> text using
> GraphicsContext and later bitmap is used by another dc operation to
> save it. Every
> thing is working fine and no problem in transparency.
> How ever if you change the line in generation part:
> ctx = wx.GraphicsContext.Create(mdc)#Cairo.GraphicsContext.Create(mdc)
> to
> ctx = Cairo.GraphicsContext.Create(mdc)
> the bit "text.png" is coming out with transparency but while reading
> it back
> using:
> mdc.DrawBitmap(colorBitmap, 0, 0)
> again the I am facing the some transparency problem.
>
> May be cairo's DrawBimap function is not able to read properly or some
> explanation
> is required here.

My guess is that Cairo is having some of the same problems with the
alpha-ignorant Windows DC that wx has had to deal with. If you avoid
using the wx.MemoryDC and do a little Cairo specfic things then it does
what I think it is you are wanting:

import wx.lib.wxcairo as wxcairo

colorBitmap = wx.EmptyBitmapRGBA(size[0]+1, size[1]+1, 0, 0, 0, 0)

surface = wxcairo.ImageSurfaceFromBitmap(colorBitmap)
ctx = Cairo.GraphicsContext.CreateFromSurface(surface)

ctx.SetFont(font, "blue")
ctx.DrawText("wxPython Rocks!!!", 0, 45)

del ctx
colorBitmap = wxcairo.BitmapFromImageSurface(surface)
colorBitmap.SaveFile("text.png", wx.BITMAP_TYPE_PNG)

# Create another bitmap using memoryDC and
# draw the bitmap created above.

newBitmap = wx.EmptyBitmap(size[0]+1, size[1]+1)
mdc = wx.MemoryDC(newBitmap)
mdc.SetBackground(wx.Brush("light grey"))


mdc.Clear() # make sure you clear the bitmap!

mdc.DrawBitmap(colorBitmap, 0, 0, True)


mdc.SelectObject(wx.NullBitmap)
del mdc
newBitmap.SaveFile("memdc.png", wx.BITMAP_TYPE_PNG)

King

unread,
Feb 10, 2010, 1:11:54 PM2/10/10
to wxPython-users
After all those discussions regarding DCs in various posts my
application is running fine on MS-Win.
As I said I have written is custom object oriented scene graph where
you two options for rendering.
wx.GraphicsContext and Cairo. Both are working fine on Ms-Win.

Now I started to test my app on Linux and none of the rendering method
is working properly. Cairo is badly crashing the
application. See here:
http://groups.google.com/group/wxpython-users/browse_thread/thread/89d0b0054eb8d1e4/6730a4f916b5c5cf#6730a4f916b5c5cf

and again bitmap transparency issue has risen. I am rendering off-line
bitmaps and then drawing them later. The alpha(transparency) is
replaced by pure black color in the bitmap. Here is code that I using
to draw a bitmap

import wx

class DemoApp(wx.App):
def OnInit(self):
wx.InitAllImageHandlers() # called so a PNG can be saved

font = wx.FFont(9, wx.SWISS, wx.FONTFLAG_BOLD, "LucidConsole")


# Render a bitmap using MemoryDC.
width, height = 100, 100
size = width, height

colorBitmap = wx.EmptyBitmapRGBA(size[0]+1, size[1]+1, 0, 0,
0, 0)

mdc = wx.MemoryDC(colorBitmap)
ctx = wx.GraphicsContext.Create(mdc)

ctx.SetFont(font, "blue")
ctx.DrawText("wxPython Rocks!!!", 0, 45)

ctx.SetBrush(wx.Brush("red"))
ctx.DrawRectangle(10,10,25,25)
# Select the Bitmap out of the memory DC by selecting a new
# uninitialized Bitmap
mdc.SelectObject(wx.NullBitmap)
del mdc
# Save file
colorBitmap.SaveFile("text.png", wx.BITMAP_TYPE_PNG)
return True

if __name__ == "__main__":
print "about to initialize the app"
app = DemoApp(0)
app.MainLoop()

The bitmap is coming empty and instead of wx.EmptyBitmapRGBA if you
use wx.EmptyBitmap, bitmap is coming out with
a text and a red colour rectangle in it but also some garbage is
pixels is coming out.

I must find a solution for either wx.GraphicsContext or Cairo on Linux
or I am f|<ed.....


Thanks

Prashant

#####################################
Operating System: Linux 2.6.31-14-generic i686
Python Version: 2.6.4rc2 (r264rc2:75497, Oct 20 2009, 02:55:11)
[GCC 4.4.1]
wxPython Version: 2.8.10.1 (gtk2-unicode)
wxPython Info: (__WXGTK__, wxGTK, unicode, gtk2, wx-assertions-off,
SWIG-1.3.29)
Python Encoding: Default=UTF-8 File=UTF-8
wxPython Encoding: utf-8
System Architecture: 32bit i686
Byte order: little
Frozen: False
#####################################

Reply all
Reply to author
Forward
0 new messages