Home / Library / PIL / Handbook / The ImageDraw module

The ImageDraw module

ImageDraw draws onto an existing image, in place. You make a drawing object from the image, then call methods on it.

from PIL import Image, ImageDraw

im = Image.new("RGB", (400, 300), "white")
draw = ImageDraw.Draw(im)
draw.line((0, 0, 400, 300), fill="black", width=2)
im.save("out.png")

Shapes

MethodDraws
line(xy, fill, width)A line, or a path through several points
rectangle(xy, fill, outline, width)A box from two corners
rounded_rectangle(xy, radius, ...)The same with rounded corners
ellipse(xy, fill, outline, width)An ellipse inside a box
arc(xy, start, end, fill)Part of an ellipse outline
chord and piesliceAn arc closed with a line, or with two radii
polygon(xy, fill, outline)A closed shape through any number of points
point(xy, fill)Single pixels

Coordinates are either a flat sequence, (x0, y0, x1, y1), or a list of tuples. Colours can be names, hex strings or tuples matching the image mode.

Text

from PIL import ImageFont

font = ImageFont.truetype("DejaVuSans.ttf", 24)
draw.text((10, 10), "hello", font=font, fill="black")

Without a font argument you get a small built in bitmap font that cannot be resized, which is why nearly all real code loads a TrueType file.

This is where most handbook era code fails. draw.textsize() was removed in Pillow 10.
w, h = draw.textsize("hello", font=font)

left, top, right, bottom = draw.textbbox((0, 0), "hello", font=font)
w = right - left
h = bottom - top

For a single line where you only need the width, draw.textlength("hello", font=font) is simpler and returns a float. The converter flags all of this.

Centring text

The anchor argument removes most of the arithmetic:

draw.text((200, 150), "hello", font=font, fill="black", anchor="mm")

mm means middle horizontally and middle vertically, so the point you give is the centre of the text rather than its top left corner.

Transparency

To draw semi transparent shapes, draw onto a separate RGBA layer and composite it:

layer = Image.new("RGBA", im.size, (0, 0, 0, 0))
d = ImageDraw.Draw(layer)
d.rectangle((50, 50, 200, 150), fill=(255, 0, 0, 96))
im = Image.alpha_composite(im.convert("RGBA"), layer)

Related