[cairo] pycairo and PIL

James Evans milamber at clark-evans.com
Tue Oct 4 16:22:55 PDT 2005


> 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

This patch wasn't intended to be a final solution. I know it only works
for cairo.ImageSurface(). I was looking for feedback on the solution
before I implemented all possible uses. create_from_png has the added
problem that you'd have to read the png in and create a buffer from it to
pass to cairo_image_surface_create_for_data, duplicating functionality in
pycairo that exists in cairo.

The feedback I've gotten from you is that you don't think this solution is
worth pursuing. Is that correct? (Also, please see comments below)


> 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.

I think it is becoming pretty clear that cairo really needs a get_data()
function to do what I want. I've got a couple of apps that I'd like to use
a cairo backend (creating animations for DVD menus), but need the data in
a format other than PNG and pipe it to another command. All this would be
simple if I could only get at the data in memory.

> 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 before.

The "extra" options to the frombuffer command can be useful in this
regard. I found the biggest problem was that PIL doesn't understand the
premultipled alpha. If you are willing to throw away the alpha data, then
using "XRGB" as the mode parameter to the raw decoder will read the data
in properly. If you want to keep the alpha channel, you need to
unpremultiply the alpha when bringing it into PIL.

> 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)

I agree this is wasteful. PIL also lacks an easy way to access the "raw"
in memory data for an image.

I guess what I was really trying to do was get the data from a
cairo.ImageSurface in a way that I could further manipulate the pixel data
for output. I'm mostly using PIL for its output capabilities without
leaving python or requiring lots of extra libraries. Writing a png
file,reading it in then piping it to a conversion program isn't exactly my
idea of efficiency.

Thanks,

james evans





More information about the cairo mailing list