Integration with other Libraries

NumPy & ImageSurface

Creating an ImageSurface from a NumPy array:
import numpy
import cairo

width, height = 255, 255
data = numpy.ndarray(shape=(height, width), dtype=numpy.uint32)
surface = cairo.ImageSurface.create_for_data(
    data, cairo.FORMAT_ARGB32, width, height)
Creating a NumPy array from an ImageSurface:
import numpy
import cairo

width, height = 255, 255
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
buf = surface.get_data()
data = numpy.ndarray(shape=(height, width),

Pygame & ImageSurface

Creating a pygame.image from an ImageSurface:
import pygame
import cairo

width, height = 255, 255
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
buf = surface.get_data()
image = pygame.image.frombuffer(buf, (width, height), "ARGB")

Pyglet & ImageSurface as Texture

Creating a pyglet.Texture from an ImageSurface:
import ctypes
import cairo

from pyglet import app, clock, gl, image, window

# create data shared by ImageSurface and Texture
width, height = 400, 400

surface_data = (ctypes.c_ubyte * (width * height * 4))()
surface = cairo.ImageSurface.create_for_data (surface_data, cairo.FORMAT_ARGB32,
width, height, width * 4);
texture = image.Texture.create_for_size(gl.GL_TEXTURE_2D, width, height, gl.GL_RGBA)
Draw pyglet.Texture bound to ImageSurface
window = window.Window(width=width, height=height)

def on_draw():

    # Draw texture backed by ImageSurface

    gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, width, height, 0, gl.GL_BGRA,

    gl.glTexCoord2f(0.0, 1.0)
    gl.glVertex2i(0, 0)
    gl.glTexCoord2f(1.0, 1.0)
    gl.glVertex2i(width, 0)
    gl.glTexCoord2f(1.0, 0.0)
    gl.glVertex2i(width, height)
    gl.glTexCoord2f(0.0, 0.0)
    gl.glVertex2i(0, height)

# call clock.schedule_update here to update the ImageSurface every frame

Pillow (PIL) & Cairo

Creating an ImageSurface from a PIL Image:
import PIL.Image as Image

def from_pil(im, alpha=1.0, format=cairo.FORMAT_ARGB32):
    :param im: Pillow Image
    :param alpha: 0..1 alpha to add to non-alpha images
    :param format: Pixel format for output surface
    assert format in (cairo.FORMAT_RGB24, cairo.FORMAT_ARGB32), "Unsupported pixel format: %s" % format
    if 'A' not in im.getbands():
        im.putalpha(int(alpha * 256.))
    arr = bytearray(im.tobytes('raw', 'BGRa'))
    surface = cairo.ImageSurface.create_for_data(arr, format, im.width, im.height)
    return surface

filename = 'test.jpeg'

# Open image to an ARGB32 ImageSurface
im =
surface1 = from_pil(im)

# Open image to an RGB24 ImageSurface
im =
surface2 = from_pil(im, format=cairo.FORMAT_RGB24)

# Open image to an ARGB32 ImageSurface, 50% opacity
im =
surface3 = from_pil(im, alpha=0.5, format=cairo.FORMAT_ARGB32)

Freetype-py & Cairo

See for examples. Most of the * examples illustrate conversion from FreeType bitmaps to Cairo surfaces; the two examples, and, illustrate conversion from FreeType glyph contours to Cairo paths.

ModernGL & ImageSurface as Texture

Creating a moderngl.Texture from an ImageSurface:
import moderngl
import cairo
ctx = moderngl.create_context(standalone=True)
width, height = 400, 400
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
texture = ctx.texture((width, height), 4, data=surface.get_data())

An example can also be found in the ModernGL project: