Home / Library / PIL / Handbook / The ImagePath module

The ImagePath module

ImagePath holds one thing, a Path: a sequence of coordinates stored compactly, which ImageDraw accepts anywhere it takes a list of points.

from PIL import Image, ImageDraw, ImagePath

points = [(10, 10), (100, 40), (180, 10), (180, 120), (10, 120)]
path = ImagePath.Path(points)

im = Image.new("RGB", (200, 140), "white")
draw = ImageDraw.Draw(im)
draw.polygon(path, fill="skyblue", outline="navy")

Why it exists

For a handful of points, a plain list is fine. Paths pay off when you have thousands, from a plot, a map outline or a traced contour, because the coordinates are held as a flat array of floats rather than a list of Python tuples. It is the same reason you would use array rather than list for numbers.

What a path can do

MethodWhat it does
getbbox()The bounding box of every point
tolist(flat=False)Back to a list of tuples, or a flat list
compact(distance=2)Drops points closer together than the distance, and returns how many went
map(function)Runs every point through a function, in place
transform(matrix)Applies an affine transform to every point

Moving and scaling a path

path.transform((2, 0, 10, 0, 2, 20))

The six numbers are the affine matrix (a, b, c, d, e, f), giving x = a*x + b*y + c and y = d*x + e*y + f. So that call scales by two and moves the result 10 across and 20 down.

Thinning a traced outline

path = ImagePath.Path(traced_points)
removed = path.compact(3)
print(removed, "points dropped,", len(path.tolist()), "left")

Contours traced from a bitmap tend to hold a point per pixel, most of which sit on the same straight lines. compact thins them out before drawing, which is faster and produces smaller output if you are exporting.

Related