[wxPython] scaling bitmaps

I've got a question:

The wxImage::Scale documentation indicates that the wxDC::blit function
can also be used to rescale bitmaps. However, I can't see how to do
this, since you can only specify the source-DC pixel range for copying.
Is this en error in the documentation or have I missed something about
the blit function?

can anyone help?
thanks,
Bryan

···

--

bryan cole wrote:

I've got a question:

The wxImage::Scale documentation indicates that the wxDC::blit function
can also be used to rescale bitmaps. However, I can't see how to do
this, since you can only specify the source-DC pixel range for copying.
Is this en error in the documentation or have I missed something about
the blit function?

can anyone help?
thanks,
Bryan

It looks like

wxDC.SetUserScale(xScale,yScale)

is what you want. Note, however, that in my experience image quality deteriorates notably when using this feature. You get better results when you use wxImage.Rescale(width, height), and convert to a bitmap afterwards.

Regards,

Oliver

···

--------------------------
F. Oliver Gathmann, Ph.D.
Cenix BioScience GmbH
Pfotenhauer Strasse 108
D-01307 Dresden, Germany
phone: +49 (351) 210-2735
fax: +49 (351) 210-1309
--------------------------

Let me throw in, that with

img = img.resize(size, Image.BICUBIC)

from PIL, I got the best results here, especially when scaling downwards.
At least for faxes. But it's also very expensive cpuwise. Therefor I'm
caching a bicubic 50% scaled b/w fax as 8 bit grayscale png, which are
slightly bigger as their b/w G3 tiff pendants. (Type L in PIL).

The problem arises here. Is there a way to display bw/grayscale bitmaps
directly in wxPython?

The depth argument in the constructor:

WxEmptyBitmap(width, height, depth = -1)

seem not to be supported in wxGTK 2.3.2-WxPython 2.3.2.1.

Robin? CVS?

Cheers,
  Hans-Peter

···

On Monday, 18. February 2002 13:48, F. Oliver Gathmann wrote:

bryan cole wrote:
>I've got a question:
>
>The wxImage::Scale documentation indicates that the wxDC::blit function
>can also be used to rescale bitmaps. However, I can't see how to do
>this, since you can only specify the source-DC pixel range for copying.
>Is this en error in the documentation or have I missed something about
>the blit function?
>
>can anyone help?
>thanks,
>Bryan

It looks like

wxDC.SetUserScale(xScale,yScale)

is what you want. Note, however, that in my experience image quality
deteriorates notably when using this feature. You get better results when
you use wxImage.Rescale(width, height), and convert to a bitmap afterwards.

Regards,

Oliver

Hans-Peter Jansen wrote:

The problem arises here. Is there a way to display bw/grayscale bitmaps
directly in wxPython?

The depth argument in the constructor:

WxEmptyBitmap(width, height, depth = -1)

seem not to be supported in wxGTK 2.3.2-WxPython 2.3.2.1.

Robin? CVS?

There is a slightly unusual way to do this: coax Pygame (pygame.org) into displaying its output in a wxPython window (last time I checked, this could be done by setting the environment variable SDL_WINDOWID to the handle of your wxWindows window as returned by window.GetHandle()) and load your grayscale image into a NumPy array that is directly mapped to your screen. Obviously, you are limited to one display window with this approach, but maybe that doesn't matter in the context of your application.

Oliver

···

--------------------------
F. Oliver Gathmann, Ph.D.
Cenix BioScience GmbH
Pfotenhauer Strasse 108
D-01307 Dresden, Germany
phone: +49 (351) 210-2735
fax: +49 (351) 210-1309
--------------------------

The depth argument in the constructor:

WxEmptyBitmap(width, height, depth = -1)

seem not to be supported in wxGTK 2.3.2-WxPython 2.3.2.1.

Robin?

The parameter is accepted but I think it is only there for historical
reasons and is currently ignored. The wxBitmap depth is supposed to always
match the display depth.

···

--
Robin Dunn
Software Craftsman
robin@AllDunn.com Java give you jitters?
http://wxPython.org Relax with wxPython!

Robin Dunn wrote:

> The depth argument in the constructor:
>
> WxEmptyBitmap(width, height, depth = -1)

The parameter is accepted but I think it is only there for historical
reasons and is currently ignored. The wxBitmap depth is supposed to always
match the display depth.

I wsa just playing with this last night, and it does seem to work. In my
case, I am using a wxBitmap that is selected into a wxMemoryDC, but not
blitted into anything, and never displayed. and as far as I could tell,
changing the depth parameter DID make a difference.

This brings up my question, which it looks like it not going to be easy
to answer. What I would like to be able to do is draw a bunch of objects
to a wxMemoryDC, each with a different color, and then use dc.GetPixel
to find out the color of a point, and therefor the object that is there.
The problem here is that wxColor assumes a 24 bit representation, so if
your wxBitmap is not 24 bits, the colors are translated when drawn, and
then back again when dc.GetPixel() is called. I thought I'd be OK if I
specified depth = 24 when I create the wxBitmap, but now it sounds like
that might not work. so far I have tested it on my Linux box, which is
running at 24bpp, and it works very nicely.

So, is there any way to know what each wxColor is translated to when
drawn to a wxBitMap of an arbitrary depth? Is there anyway to specify
the color in the "native" depth, rather than rgb values?

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                        
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

This brings up my question, which it looks like it not going to be easy
to answer. What I would like to be able to do is draw a bunch of objects
to a wxMemoryDC, each with a different color, and then use dc.GetPixel
to find out the color of a point, and therefor the object that is there.
The problem here is that wxColor assumes a 24 bit representation, so if
your wxBitmap is not 24 bits, the colors are translated when drawn, and
then back again when dc.GetPixel() is called. I thought I'd be OK if I
specified depth = 24 when I create the wxBitmap, but now it sounds like
that might not work. so far I have tested it on my Linux box, which is
running at 24bpp, and it works very nicely.

Sounds like a pretty expensive way to do this. Why not just give the
objects the ability to specify if they intersect a point (a HitTest method)
and then just travers your list and use object that last returned true for
HitTest? Then you don't have to make any (expensive!) API calls at all.

So, is there any way to know what each wxColor is translated to when
drawn to a wxBitMap of an arbitrary depth? Is there anyway to specify
the color in the "native" depth, rather than rgb values?

wxPallet will probably help for 8-bit depth, but I don't know if will be any
help for other depths...

···

--
Robin Dunn
Software Craftsman
robin@AllDunn.com Java give you jitters?
http://wxPython.org Relax with wxPython!

Robin Dunn wrote:

> This brings up my question, which it looks like it not going to be easy
> to answer. What I would like to be able to do is draw a bunch of objects
> to a wxMemoryDC, each with a different color, and then use dc.GetPixel
> to find out the color of a point, and therefor the object that is there.
> The problem here is that wxColor assumes a 24 bit representation, so if
> your wxBitmap is not 24 bits, the colors are translated when drawn, and
> then back again when dc.GetPixel() is called. I thought I'd be OK if I
> specified depth = 24 when I create the wxBitmap, but now it sounds like
> that might not work. so far I have tested it on my Linux box, which is
> running at 24bpp, and it works very nicely.

Sounds like a pretty expensive way to do this. Why not just give the
objects the ability to specify if they intersect a point (a HitTest method)
and then just travers your list and use object that last returned true for
HitTest? Then you don't have to make any (expensive!) API calls at all.

Well, that depends on what you mean by expensive. It's "common wisdom"
that sometimes you trade memory for speed, and this is all the more true
with interpretted languages. Anyway, when I'm dealing with up to
thousands of objects, that might be fairly complex polylines or
polygons, looping through and computing a hit-test on each object could
be pretty darn slow. A point-in-polygon test is a fair bit of
computation (not very fast in Python), and unless I can find a niftier
algorythm, a point-on-a-line can be even worse.

What API calls here do you think are expensive? It could take a while to
draw to the bitmap, but once I've done that, all I need is a single
GetPixel() call, and a dictionary lookup to find the object hit. With my
tests, it works very fast. I compared it to a simple hit-test with 1600
rectangles, and it is noticably faster (on a 1.2Ghz PIV) with the bitmap
approach. It is fast enough to work well on a MouseMove event, and I
don't think the hit-test approach would be.
Also, I think it's kind of a nifty solution, as I don't have to write a
bunch of hit-test code for every kind of object I want to draw. I got
the idea from PySketch, which takes a much more expensive approach: at
each mouse click, it creates a dc and re-draws each item to see if it is
hit! My approach will take some memory (very cheep these days), but is
pretty darn fast.

All that been said, I do feel like I am majorly re-inventing the wheel
here. It frustrates me to no end that this kind of thing isn't built
into the API. I havn't check out Klass' wxCanvas for a while, maybe it's
time to do that, he has written a lot of code to solve these kinds of
problems. Another option is OpenGL, but as I don't need 3-d it seemed
overkill. Maybe not.

I am open to suggestions, it looks like the color-depth problem may kill
this approach anyway. Does anyone know of a good source of algorythms
for hit-tests and this kind of thing?

wxPallet will probably help for 8-bit depth, but I don't know if will be any
help for other depths...

8 bit won't help, as I only think this is a good idea because I may have
to deal with thousands of objects. I did a little more checking, and I
was wrong: wxEmptyBitmap(x,y,depth) only works if depth is -1 or the
current depth of your display. Interestingly, the call doesn't create
any sort of error, it just creates a bitmap that reports a size of -1,
ans for every GetPixel() call, I get some wierd number.

At the moment, what I have works for a depth of 24, and should work for
higher depths, though I havn't tested that yet.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                        
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Geoff Gerrietts wrote:

If I understand what you're trying to do correctly (which maybe isn't
the case), might it not be easier for you to use a Numeric array, then
draw your shapes onto those arrays as if they were a bitmap?

It does sound like you do know what I'm trying to do, and it would work
great, except:
How do I draw to a Numeric Array??? I have done something similar in
other code, drawing to an bitmap with PIL, and then dumping the PIL
image to a Numeric array. I have thought about doing the same thing
here, except that I am imagining that the PIL drawing routines might be
slower, and there is no guarantee that they would create the same image
as the dc that is drawing to the screen, and the code to do the drawing
would be different than the DC drawing code, so it really would be a
much less nifty solution.

You could
have arbitrary depth then, and could in fact turn it into a "real"
bitmap after the fact if you were inclined to do so.

How would I do that, by the way? I may have a need to do this in the future.

I have the code in question at home, and I'm now at work, but perhaps
I'll post it here tomorrow. I'd like to get feedback.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                        
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Well, that depends on what you mean by expensive.

[... good points setting me straight :wink: ...]

I am open to suggestions,

It may be faster to convert your bitmap to a wxImage and use it's GetRed,
GetGreen, GetBlue methods. dc.GetPixel will have to do a system API call
but the wxImage methods just return values from an array of bytes.

That still won't help with the palette problem, but that may not be an
issue. Do you expect any of your users to be on an 8-bit display or can you
require at least 16-bit? 16-bit would give you 64k distinct colors that you
can map objects to...

···

--
Robin Dunn
Software Craftsman
robin@AllDunn.com Java give you jitters?
http://wxPython.org Relax with wxPython!

Chris Barker wrote:

Geoff Gerrietts wrote:

If I understand what you're trying to do correctly (which maybe isn't
the case), might it not be easier for you to use a Numeric array, then
draw your shapes onto those arrays as if they were a bitmap?

It does sound like you do know what I'm trying to do, and it would work
great, except:
How do I draw to a Numeric Array??? I have done something similar in
other code, drawing to an bitmap with PIL, and then dumping the PIL
image to a Numeric array. I have thought about doing the same thing
here, except that I am imagining that the PIL drawing routines might be
slower, and there is no guarantee that they would create the same image
as the dc that is drawing to the screen, and the code to do the drawing
would be different than the DC drawing code, so it really would be a
much less nifty solution.

You could
have arbitrary depth then, and could in fact turn it into a "real"
bitmap after the fact if you were inclined to do so.

How would I do that, by the way? I may have a need to do this in the future.

I have the code in question at home, and I'm now at work, but perhaps
I'll post it here tomorrow. I'd like to get feedback.

Try _renderPM from reportlab. I sucessfuly use it.

Niki Spahiev

Niki Spahiev wrote:

Try _renderPM from reportlab. I sucessfuly use it.

thanks, I havn't had a reason to check out ReportLab before, and it
looks like a very nice package. However, I con't see where _renderPM
would be any different than PIL in terms of the problems I forsee.

In fact, in the ReportLab docs it says that if you want to work with
bitmap images, you need PIL, so it may be using PIL underneith anyway.
Perhaps I'll look further into this.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                        
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Quoting Chris Barker (Chris.Barker@noaa.gov):

Geoff Gerrietts wrote:
> If I understand what you're trying to do correctly (which maybe isn't
> the case), might it not be easier for you to use a Numeric array, then
> draw your shapes onto those arrays as if they were a bitmap?

It does sound like you do know what I'm trying to do, and it would work
great, except:
How do I draw to a Numeric Array???

Well, you need Numeric, obviously. You create a matrix that's x by y
by depth elements, then you do the math to draw onto that surface.

If your question is "how do I get a wx API call that draws a line to
draw on the numeric array" that I can't answer. If your question is
"what are the transforms I need to draw shapes across a Numeric
matrix" that's a little easier -- there's stuff on the pygame site
that addresses that, as well as stuff in the Numeric documentation
itself.

My understanding of your problem is that the display of the bitmap is
really not particularly relevant, only the generation of a bitmap with
enough depth to it that you can identify an object by its colour
signature. As I said, I may be misunderstanding the problem domain.

I have done something similar in other code, drawing to an bitmap
with PIL, and then dumping the PIL image to a Numeric array. I have
thought about doing the same thing here, except that I am imagining
that the PIL drawing routines might be slower, and there is no
guarantee that they would create the same image as the dc that is
drawing to the screen, and the code to do the drawing would be
different than the DC drawing code, so it really would be a much
less nifty solution.

> You could
> have arbitrary depth then, and could in fact turn it into a "real"
> bitmap after the fact if you were inclined to do so.

How would I do that, by the way? I may have a need to do this in the future.

Turning it into a "real" bitmap may/would require interpolating your
depth into the display depth, but you can take a string of RGB data
and run it through PIL's "fromString" to generate an image you can
work with.

Further, if you draw everything using PIL, then blit the bitmap PIL
generates to the screen, you may lose speed but you have the bitmap.
Similarly, it seems to me (though I haven't gone looking for the API
calls to make it happen) that you can convert a rendered DC into a
bitmapped form, which you could then dump into numeric by way of PIL.

Another approach (with still more dependencies) is to hook pygame into
your app, and use the very nice surfarray module to manage your
Numeric to bitmap issues. This may give you more speed (and may not).

A lot of the strategy you choose in solving the problem will be a
question of how often your image is changing, your goals for the image
you're generating, etc. But:

It sounds like a lot of the suggestions I have to offer, are things
you've had some experience with, and I'm not opening any new doors for
you. It sounds to me like the problems you've set for yourself are
very hard, and while my angle of approach would be to look outside the
wxWindows API for my image handling, and maybe that's wrongheaded.

Thanks,
--G.

···

--
Geoff Gerrietts <ggerrietts@yahoo.com>
-rw-rw-rw-: permissions of the beast

I am getting a crash on wxPython-2.3.2.1.
Bizzarly devstudio would not recognize the debug info in wxmsw232h.dll so I
was forced
to download and compile wxwindows and wxpython myself. Now I do get debug
info.

From this I have found that a window is getting a size call on a null self

pointer:

wxWindowBase::SetSize(int 1, int 1, int 0, int 0, int 4) line 179 + 35 bytes
wxSizerItem::SetDimension(wxPoint {...}, wxSize {...}) line 232
_wrap_wxSizerItem_SetDimension(_object * 0x00000000, _object * 0x01a608cc,
_object * 0x06155b14) line 276
PYTHON21! 1e1131d6()

How can I find out where this happened on the python side?

Thanks,
Andrew

···

_____________________________________________________________________
This e-mail is confidential and may be privileged. It may be read, copied and used only by the intended recipient. No communication sent by e-mail to or from Eutechnyx is intended to give rise to contractual or other legal liability, apart from liability which cannot be excluded under English law.

This message has been checked for all known viruses by Star Internet delivered through the MessageLabs Virus Control Centre.

www.eutechnyx.com Eutechnyx Limited. Registered in England No: 2172322

I think I have found a bug in wxPython.

Take 2 MID child windows , A and B

A is maximized , B is not.
A contains gridsizers

Close A -> crash

wxWindowBase::SetSize(int 1, int 1, int 0, int 0, int 4) line 179
+ 35 bytes
wxSizerItem::SetDimension(wxPoint {...}, wxSize {...}) line 232
_wrap_wxSizerItem_SetDimension(_object * 0x00000000, _object * 0x01a608cc,
_object * 0x06155b14) line 276
PYTHON21! 1e1131d6()

If A was the only window then this does not happen.

I have found this bug is caused because wxwindows is

sending a size message to an item within a gridsizer after it has been
destroyed.

Removing the items from the sizer before closing the window cures the
problem.

Cheers,
Andrew

···

_____________________________________________________________________
This e-mail is confidential and may be privileged. It may be read, copied and used only by the intended recipient. No communication sent by e-mail to or from Eutechnyx is intended to give rise to contractual or other legal liability, apart from liability which cannot be excluded under English law.

This message has been checked for all known viruses by Star Internet delivered through the MessageLabs Virus Control Centre.

www.eutechnyx.com Eutechnyx Limited. Registered in England No: 2172322

Hi,

I've found that the speed of the wxDC.DrawLines call (in wxPython)
depends **significantly** on the linewidth of the current wxPen.

I'm modifying the wxPlotCanvas from the wxPython library, for use as a
real-time data-plotting tool. Typically, I plot 2000-point datasets
(Numeric array) at rates up to 20 frames/sec. Using a wxPen of width
1-pixel, everything is fine: my PC (under MSWin98) cruises at 20% CPU
capacity. However, if I change the wxPen-width to 2, The plotting rate
is reduced to under 5 frames/sec and the CPU is working at 100%. I.e.
there is about an order-of-magnitude increase in CPU-overhead when I go
from PenWidth=1 to PenWidth=2.

Can anyone explain this? I doubt if it's a Python thing, as the wxPython
wrappers are simply calling the wxWindows functions. Why is a 2-pixel
linewidth so much harder to draw than a 1-pixel line? I don't know if
the same thing happens on Linux/wxGTK.

cheers,
Bryan

bryan cole wrote:

Hi,

I've found that the speed of the wxDC.DrawLines call (in wxPython)
depends **significantly** on the linewidth of the current wxPen.

I'm modifying the wxPlotCanvas from the wxPython library, for use as a
real-time data-plotting tool. Typically, I plot 2000-point datasets
(Numeric array) at rates up to 20 frames/sec. Using a wxPen of width
1-pixel, everything is fine: my PC (under MSWin98) cruises at 20% CPU
capacity. However, if I change the wxPen-width to 2, The plotting rate
is reduced to under 5 frames/sec and the CPU is working at 100%. I.e.
there is about an order-of-magnitude increase in CPU-overhead when I go
from PenWidth=1 to PenWidth=2.

Can anyone explain this? I doubt if it's a Python thing, as the wxPython
wrappers are simply calling the wxWindows functions. Why is a 2-pixel
linewidth so much harder to draw than a 1-pixel line? I don't know if
the same thing happens on Linux/wxGTK.

IMHO 1-pixel line is hardware accelerated while 2-pixel is not.

Niki Spahiev

bryan cole wrote:

I've found that the speed of the wxDC.DrawLines call (in wxPython)
depends **significantly** on the linewidth of the current wxPen.

there is about an order-of-magnitude increase in CPU-overhead when I go
from PenWidth=1 to PenWidth=2.

Can anyone explain this? I doubt if it's a Python thing, as the wxPython
wrappers are simply calling the wxWindows functions.

correct. You might want to post this on the wx-users mailing list.

I don't know if
the same thing happens on Linux/wxGTK.

well, I did a quick test on Linux/GTK, and didnt get the the same
effect. Wider pens were slower, but not all that much:

Drawing a 10,000 point polyline (from a Numeric array) took:
width time
  1 .03 s
  2 .04 s
  3 .04 s
  4 .05 s

However as someone suggested, it may have more to do with hardware
acceleration than OS/toolkit. Post a small test code, and let's try it
out on a number of different machines and OSs.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                        
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

"Chris Barker" <Chris.Barker@noaa.gov> writes:

well, I did a quick test on Linux/GTK, and didnt get the the same
effect. Wider pens were slower, but not all that much:

Drawing a 10,000 point polyline (from a Numeric array) took:
width time
  1 .03 s
  2 .04 s
  3 .04 s
  4 .05 s

How exactly did you measure this? With X you have to be a bit careful
when measuring such things, otherwise you only measure how fast Xlib can
queue the requests instead of how fast the Xserver actually executes
them. You either have to run in synchronous mode or perhaps execute a
request that requires a round-trip, such as querying the current mouse
pointer position.

Not having used wx much in recent months I don't know how do this
properly in wxPython.

   Bernhard

···

--
Intevation GmbH http://intevation.de/
Sketch http://sketch.sourceforge.net/
MapIt! http://mapit.de/

Bernhard Herzog wrote:

> Drawing a 10,000 point polyline (from a Numeric array) took:
> width time
> 1 .03 s
> 2 .04 s
> 3 .04 s
> 4 .05 s

How exactly did you measure this? With X you have to be a bit careful
when measuring such things, otherwise you only measure how fast Xlib can
queue the requests instead of how fast the Xserver actually executes
them. You either have to run in synchronous mode or perhaps execute a
request that requires a round-trip, such as querying the current mouse
pointer position.

Bingo! I just wrapped my timing around teh Drawlines() call, so I'm sure
I didn't measure the actual rendering speed. Qualitativly, from watching
it, there was NOT an order of magnitude difference, however.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                        
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov