Welcome, guest | Sign In | My Account | Store | Cart

We alias the memory from a cairo surface so that we can manipulate the bits as a numpy array, or display/manipulate the image in pygame.

Python, 57 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#!/usr/bin/env python

import cairo

w, h = 128, 128

# Setup Cairo
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
ctx = cairo.Context(surface)

# Set thickness of brush
ctx.set_line_width(15)

# Draw out the triangle using absolute coordinates
ctx.move_to(w/2, h/3)
ctx.line_to(2*w/3, 2*h/3)
ctx.rel_line_to(-1*w/3, 0)
ctx.close_path()

# Apply the ink
ctx.stroke()

# Output a PNG file
surface.write_to_png("triangle.png")

# Alias the image as a numpy array
import numpy

# This needs better than pycairo-1.2.2, eg. pycairo CVS:
# cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/cairo co pycairo
buf = surface.get_data()

a = numpy.frombuffer(buf, numpy.uint8)
a.shape = (w, h, 4)

a[:,:,2] = 255
surface.write_to_png("triangle1.png") # red triangle..

# Alias the image as a pygame surface
import pygame
from time import sleep

imsurf = pygame.image.frombuffer(buf, (w,h), "RGBA")
depth = 4*8

pygame.display.init()
surface = pygame.display.set_mode((w,h), pygame.DOUBLEBUF, depth)

done = False
while not done:
    surface.blit(imsurf, (0,0)) # blue triangle..
    sleep(0.1)
    events = pygame.event.get()
    for event in events:
        if event.type == pygame.QUIT:
            done = True
    pygame.display.flip()

Cairo provides scalar vector graphics routines (http://cairographics.org/) for slick looking alpha blended graphics.

In this recipe there is only one memory buffer involved. This means that changes to the image from cairo, numpy or pygame effect the same underlying image.

There is one odd bug, cairo and pygame disagree on which channel corresponds to which colour. So, after manipulating the image from numpy, cairo saves a red triangle, but then pygame displays a blue triangle.