Cairo is great for rendering stuff, but doesn’t give you many options to export your data. The Python Image Library has good options to save stuff. The problem I ran into is that I have a ARGB32 pycairo surface, and PIL doesn’t support ARGB32. It supports RGBA instead. After much experimentation, I came up with the following piece of code, using numpy to solve this problem:
def pilImageFromCairoSurface( surface ):
cairoFormat = surface.get_format()
if cairoFormat == cairo.FORMAT_ARGB32:
pilMode = 'RGB'
# Cairo has ARGB. Convert this to RGB for PIL which supports only RGB or
# RGBA.
argbArray = numpy.fromstring( surface.get_data(), 'c' ).reshape( -1, 4 )
rgbArray = argbArray[ :, 2::-1 ]
pilData = rgbArray.reshape( -1 ).tostring()
else:
raise ValueError( 'Unsupported cairo format: %d' % cairoFormat )
pilImage = PIL.Image.frombuffer( pilMode,
( surface.get_width(), surface.get_height() ), pilData, "raw",
pilMode, 0, 1 )
pilImage = pilImage.convert( 'RGB' )
return pilImage
This reportedly doesn’t work with python 3, which requires the “argbArray = ” line to read:
argbArray = numpy.fromstring( bytes(surface.get_data()), 'c' ).reshape( -1, 4 )
See the disqus comments below for more details.