ImageDraw Module
The ImageDraw module provides simple 2D graphics for Image objects. You can use this module to create new images, annotate or retouch existing images, and to generate graphics on the fly for web use.
Import
from PIL import Image, ImageDraw
ImageDraw.Draw()
Creates a drawing object that can be used to draw on the given image.
| Parameter | Type | Description |
|---|---|---|
im | Image | The image to draw in. Note: image is modified in place. |
mode | str | Mode to use for drawing. Defaults to the image mode. |
Basic Usage
img = Image.new("RGB", (400, 300), "white")
draw = ImageDraw.Draw(img)
draw.rectangle([50, 50, 350, 250], outline="black", width=2)
img.save("output.png")
Drawing Methods
All methods accept fill (interior colour) and/or outline (border colour). Colours can be strings like "red", hex "#ff0000", or RGBA tuples (255, 0, 0, 128).
| Method | Signature | Description |
|---|---|---|
arc() | arc(xy, start, end, fill=None, width=1) | Draw an arc between start and end angles (degrees, clockwise from 3 o'clock). |
bitmap() | bitmap(xy, bitmap, fill=None) | Draw given bitmap over image at given offset, with fill for set pixels. |
chord() | chord(xy, start, end, fill=None, outline=None, width=1) | Same as arc but connects endpoints with a straight line. |
ellipse() | ellipse(xy, fill=None, outline=None, width=1) | Draw an ellipse inside a bounding box. Pass a 4-tuple [x0,y0,x1,y1]. |
circle() | circle(xy, radius, fill=None, outline=None, width=1) | Draw a circle. xy is the center point. |
line() | line(xy, fill=None, width=1, joint=None) | Draw a line between all points in xy. joint can be "curve" for round joins. |
pieslice() | pieslice(xy, start, end, fill=None, outline=None, width=1) | Same as arc but draws a pie slice from center to endpoints. |
point() | point(xy, fill=None) | Draw individual pixels. |
polygon() | polygon(xy, fill=None, outline=None, width=1) | Draw a polygon from a list of points [(x0,y0), (x1,y1), ...]. |
regular_polygon() | regular_polygon(bounding_circle, n_sides, rotation=0, fill=None, outline=None, width=1) | Draw a regular polygon with n_sides sides inscribed within a circle. |
rectangle() | rectangle(xy, fill=None, outline=None, width=1) | Draw a rectangle. xy is [x0,y0,x1,y1] or [(x0,y0),(x1,y1)]. |
rounded_rectangle() | rounded_rectangle(xy, radius=0, fill=None, outline=None, width=1) | Draw a rectangle with rounded corners. |
Text Methods
| Method | Signature | Description |
|---|---|---|
text() | text(xy, text, fill=None, font=None, anchor=None, spacing=4, align="left", direction=None, features=None, language=None, stroke_width=0, stroke_fill=None, embedded_color=False) | Draw text at position xy. |
multiline_text() | multiline_text(xy, text, fill=None, font=None, anchor=None, spacing=4, align="left", direction=None, features=None, language=None, stroke_width=0, stroke_fill=None, embedded_color=False) | Draw multi-line text, splitting on \n. |
textlength() | textlength(text, font=None, direction=None, features=None, language=None, embedded_color=False) | Returns the length of a string given the current font, in pixels. |
textbbox() | textbbox(xy, text, font=None, anchor=None, spacing=4, align="left", direction=None, features=None, language=None, stroke_width=0, embedded_color=False) | Returns bounding box (left, top, right, bottom) of the given text. Useful for centering. |
Centered Text
from PIL import Image, ImageDraw, ImageFont
img = Image.new("RGB", (400, 200), "#1a1a2e")
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("DejaVuSans.ttf", size=36)
text = "Pillow Python"
# Get bounding box for centering
bbox = draw.textbbox((0, 0), text, font=font)
x = (img.width - (bbox[2] - bbox[0])) // 2
y = (img.height - (bbox[3] - bbox[1])) // 2
# Draw with white stroke for visibility
draw.text((x, y), text, fill="white", font=font,
stroke_width=2, stroke_fill="black")
img.save("text_demo.png")
Flood Fill
The ImageDraw.floodfill() function fills a bounded region of an image with a colour. Note: this is a function, not a Draw method.
Flood Fill
from PIL import ImageDraw
# Fill all connected pixels matching img.getpixel((x,y)) with red
ImageDraw.floodfill(img, xy=(50, 50), value=(255, 0, 0))
Full Example: Annotated Image
Draw Annotation Overlay
from PIL import Image, ImageDraw, ImageFont
img = Image.open("photo.jpg").convert("RGBA")
overlay = Image.new("RGBA", img.size, (0,0,0,0))
draw = ImageDraw.Draw(overlay)
# Bounding box annotation
draw.rectangle([100,100,300,300], outline=(255,0,0,255), width=3)
# Semi-transparent fill overlay
draw.rectangle([100,100,300,120], fill=(255,0,0,180))
# Label text
font = ImageFont.load_default()
draw.text((105,103), "Object: Cat (0.97)", fill="white", font=font)
# Composite and save
result = Image.alpha_composite(img, overlay).convert("RGB")
result.save("annotated.jpg")