Math Figure

Hi Jeremy!

    > Hi John, I'm (slowly) getting around to doing all of the
    > things needed to bring backend_wx up to date (as far as
    > possible). backend_wxagg will arrive, but I'm trying to
    > get some other things into backend_wx first, specifically:

Good idea to port the stuff to backend_wx first ....

    > - Support for images (which is turning out to be trickier
    > than I thought) - Support for the object picker (which
    > should be easy) - Support Mathtext

    > The problem of Mathtext support is a superset of the image
    > support problem.

    > The approach which I'm looking at is to use wxImage, which
    > has a fast method for loading data (wxImage.SetData()) -
    > ths expects a C string of length width*height*3 (in format
    > RGBRGBRGB...).

    > Not sure what format im.as_str() returns as I can't find
    > any documentation (the im parameter to
    > RendererWx.draw_image() is an instance of
    > matplotlib.image, I assume), so I'm stuck (or was a couple
    > of nights ago).

Thanks for letting me know about the doc problem. I updated the doc
string with "The string is a numrows by numcols x 4 (RGBA) unsigned
char buffer". The best place to look in the code for guidance is

    rows, cols, s = im.as_str()
    X = fromstring(s, UInt8)
    X.shape = cols, rows, 4

You'll want to lose the alpha channel presumably, unless wx supports
it, something like

    RGB = X[:,:,:3]
    s = RGB.tostring() # to pass into the wx draw_rgb_from_buffer

I can also provide an as RGB method in the image module if you want -
see if the above works and if you are happy with the performance. If
not, let me know.

mathtext, while closely related, is a little more difficult. The
image returned by as_str is an MxN array of alpha values (no color
information). See backend_gtk again for guidance. In the example
from backend_gtk below, rgb is an rgb tuple and pbpix is an MxNx4 RGB


So each of the color elements in the RGBA array is constant and only
the alpha value is varied with the return value of font as_str. If wx
has no alpha channel, you'll have to do the blending yourself. If
there is get_image_rect, you can get the background image background
and manually blend the pixels. This is what I was doing in
backend_gtk before Trevor Blackwell showed me how to use the dark,
undocumented RGBA from numeric array support in pygtk. [If you just
ignore alpha, eg, and just set RGB anywhere alpha>0, it will look like
crap; I tried]. But if you can efficiently get the background image
into a Numeric array, you can do the blending yourself w/o too much
work. Easiest would be if wx supports rgba.

    > As you say, writing wxAgg is really pretty
    > straightforward, and it's on my (ever lengthening) ToDo
    > list... At the moment I don't have anything in a usable
    > state.

When you get the image_as_rgb thing working, we could do a wxagg dry
run by having backend agg provide image_as_rgb_str. My experience
with GTK and image support is that this is surprisingly fast, and has
acceptable interactive refresh rates while resizing etc. It shouldn't
be the final solution for efficiency sake, but should be trivial to
implement and wouldn't require any additional extension code.

Basically you just remove the renderer and the GC and forward all the
calls in the figure canvas to renderer agg, and then you could use the
currently nonexistent agg.image_to_rgb_str to render the image to the
wx canvas.

Down the road if you want to blit from extension code, you could do

class FigureCanvasWxAgg(FigureCanvasWX):

    def draw(self):
        Draw to the Agg backend and then copy the image to the
        wx canvas

        agg = self.switch_backends(FigureCanvasAgg)

        try: import _wxagg
        except ImportError:
            w, h, s = agg.renderer.image_as_rgb_str()
            _wxagg.blit(something, agg.something)

which would be nice because it would support users who couldn't
compile the additional extension code. I should look into doing
something similar in GTKAgg :slight_smile: