[cairo] pycairo and PIL

Steve Chaplin stevech1097 at yahoo.com.au
Wed Sep 28 07:27:51 PDT 2005

On Wed, 2005-09-21 at 16:10 -0500, James Evans wrote:
> I've been using pycairo to do some simple graphics for a project that I
> need to access the image in PIL. Rather than using surface.write_to_png()
> and then reading the image file into PIL I added a get_data() method to
> the surface object that returns the data in Image.frombuffer() compatible
> format.
> I think this is an important piece of functionality to make cairo useful
> to other python toolkits. I think this could be used as the basis for a
> wxCairoDC to provide the power of cairo to wxPython based apps.
> With this patch you can create a PIL image from a cairo surface with:
> import Image
> newimage = Image.frombuffer("RGBA", (surface.get_width(),
> surface.get_height()), surface.get_data(), "raw", "RGBA", 0,1)

I tried the patch, and it works for surfaces created with 
   surface = cairo.ImageSurface (format, width, height)
which calls the patched ImageSurface.__new__(), but does not work for
surfaces created with other methods, for example
    surface = cairo.ImageSurface.create_from_png (filename)
    surface = cairo.ImageSurface.create_for_data (data, format, w, h, s)
which call
    PycairoSurface_FromSurface() instead of ImageSurface.__new__()
For these surfaces I got
>>> data = surface.get_data()
SystemError: null argument to internal routine
since there is no Python buffer associated with the PycairoImageSurface

Its a two step process getting pycairo pixel data into/out of PIL
1) Accessing the pixel data. 
cairo does not make this easy since cairo_surface_t is an opaque type
that hides the data. Maybe there's a reason for this, if not then a
function like
    char* data = cairo_image_surface_get_data()
would make things much easier.

2) Giving PIL the pixel data in a format it can understand.
It would be simpler if PIL had an encoder/decoder for ARGB32.
PIL supports many image file formats and pixel data formats, but I
didn't see any support for mode="ARGB32". I don't know if they have
decided not to support it or whether it has never been requested

Image.frombuffer() (as in your example) is useful for getting a pycairo
image into PIL.
Going in the other direction - transferring a PIL image into pycairo,
the corresponding method "Image.tobuffer()" or "Image.asbuffer()" would
be useful. (You could use Image.tostring() but it wastes memory copying
the image, when you could be reading the actual buffer instead)


Send instant messages to your online friends http://au.messenger.yahoo.com 

More information about the cairo mailing list