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.