Code Example

Here’s how celiagg can be used to render a red circle with the word “celiagg” inside:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import celiagg as agg
import numpy as np
from PIL import Image

state = agg.GraphicsState(drawing_mode=agg.DrawingMode.DrawStroke,
                          line_width=10.0)
transform = agg.Transform()
red_paint = agg.SolidPaint(1.0, 0.0, 0.0)
orange_paint = agg.SolidPaint(0.99, 0.66, 0.0)

canvas = agg.CanvasRGB24(np.zeros((400, 400, 3), dtype=np.uint8))

path = agg.Path()
path.ellipse(200, 200, 190, 190)
canvas.clear(1.0, 1.0, 1.0)
canvas.draw_shape(path, transform, state, stroke=red_paint)

font = agg.Font(agg.example_font(), 96.0)
transform.translate(30.0, 220.0)
canvas.draw_text("celiagg", font, transform, state, fill=orange_paint)

image = Image.fromarray(canvas.array, "RGB")
image.save("example.png")

Which gives the resulting image:

_images/example.png

Code Breakdown

Imports

First, we include some libraries. numpy is needed for the memory buffer which the canvas drawns into. PIL is used for simple image file I/O. Finally, celiagg is imported for obvious reasons:

1
2
3
import celiagg as agg
import numpy as np
from PIL import Image

State setup

Next, some state objects are created. Most important is the celiagg.GraphicsState object. Pay attention to the drawing_mode=agg.DrawingMode.DrawStroke keyword argument. This means that all drawing calls using this state will only draw the outline of the shapes being drawn.

The remaining state objects are transform which sets the affine transformation of the drawing and red_paint/orange_paint which determine the color of strokes (outlines) or fills when drawing.

5
6
7
8
9
state = agg.GraphicsState(drawing_mode=agg.DrawingMode.DrawStroke,
                          line_width=10.0)
transform = agg.Transform()
red_paint = agg.SolidPaint(1.0, 0.0, 0.0)
orange_paint = agg.SolidPaint(0.99, 0.66, 0.0)

Canvas creation

Then, also quite important, a canvas object is created. The canvas is a 400 x 400 pixel RGB bitmap with 8-bits per component.

11
canvas = agg.CanvasRGB24(np.zeros((400, 400, 3), dtype=np.uint8))

Draw a circle

We’re now ready to do some drawing. A path object is created to describe the shape that will be drawn. In this case, it’s an ellipse with an equal width and height of 190 pixels, ie: a circle. Because the canvas was instantiated with np.zeros, we call the canvas.clear method first to clear the background color to white. Finally, the circle is drawn with canvas.draw_shape.

13
14
15
16
path = agg.Path()
path.ellipse(200, 200, 190, 190)
canvas.clear(1.0, 1.0, 1.0)
canvas.draw_shape(path, transform, state, stroke=red_paint)

Draw some text

Next up, some text. We’ll use the Montserrat font which is included with celiagg, conveniently available via the example_font function. A font object is created with a point size of 96. The transform gets a translation of (30, 220) set. This corresponds to a point which is 30 pixels from the left side of the image and 220 pixels from the top of the image. (celiagg defaults to a top-left origin, but also supports bottom-left origin) The text will be drawn starting from that point.

18
19
20
font = agg.Font(agg.example_font(), 96.0)
transform.translate(30.0, 220.0)
canvas.draw_text("celiagg", font, transform, state, fill=orange_paint)

Note

Even though state specifies a drawing_mode of DrawStroke, the text will still be rendered as filled instead of drawing an outline. This is because text drawing mode is separate from the main [shape] drawing mode. text_drawing_mode in state defaults to agg.TextDrawingMode.TextDrawRaster. To draw text as vector data, state.text_drawing_mode can be set to something like agg.TextDrawingMode.TextDrawStroke. All modes except TextDrawRaster are drawn as vectors. Note that there is a performance penalty paid for this flexibility, but it allows things like patterned fills.

Save

Last but not least, the image is written to a PNG file for enjoyment in your favorite image viewer.

22
23
image = Image.fromarray(canvas.array, "RGB")
image.save("example.png")