Python Imaging Library (Fork) providing comprehensive image processing capabilities for reading, writing, and manipulating images across dozens of formats.
—
Vector graphics capabilities for drawing shapes, text, and other graphical elements on images. The ImageDraw module provides a comprehensive set of drawing primitives and text rendering functions with font support.
Create drawing contexts for image manipulation.
def Draw(im, mode=None):
"""
Creates a drawing context for the given image.
Parameters:
- im (Image): The image to draw on
- mode (str): Optional mode override
Returns:
ImageDraw: Drawing context object
"""
def floodfill(image, xy, value, border=None, thresh=0):
"""
Fills a region with a given color using flood fill algorithm.
Parameters:
- image (Image): Target image (will be modified)
- xy (tuple): Starting point as (x, y)
- value (int | tuple | str): Fill color
- border (int | tuple | str): Border color to stop at
- thresh (int): Threshold for color matching
Returns:
int: Number of pixels changed
"""Draw lines and connected line segments.
class ImageDraw:
def line(self, xy, fill=None, width=0, joint=None):
"""
Draws a line between given coordinates.
Parameters:
- xy (sequence): Sequence of 2-tuples for coordinates or 4-tuple (x1, y1, x2, y2)
- fill (int | tuple | str): Line color
- width (int): Line width in pixels
- joint (str): Line joint style ("curve" or None)
"""
def multiline_text(self, xy, text, fill=None, font=None, anchor=None, spacing=4, align="left", direction=None, features=None, language=None, stroke_width=0, stroke_fill=None):
"""
Draws multiline text.
Parameters:
- xy (tuple): Starting position as (x, y)
- text (str): Text to draw (can contain newlines)
- fill (int | tuple | str): Text color
- font (FreeTypeFont): Font to use
- anchor (str): Text anchor relative to xy coordinate
- spacing (int): Line spacing in pixels
- align (str): Multiline alignment ("left", "center", "right")
- direction (str): Text direction ("ltr", "rtl", "ttb")
- features (list): OpenType features
- language (str): Language code
- stroke_width (int): Text stroke width
- stroke_fill (int | tuple | str): Text stroke color
"""Draw basic geometric shapes.
class ImageDraw:
def rectangle(self, xy, fill=None, outline=None, width=1):
"""
Draws a rectangle.
Parameters:
- xy (sequence): Bounding box as 4-tuple (x1, y1, x2, y2) or 2-tuples ((x1, y1), (x2, y2))
- fill (int | tuple | str): Interior color
- outline (int | tuple | str): Outline color
- width (int): Outline width
"""
def rounded_rectangle(self, xy, radius=0, fill=None, outline=None, width=1):
"""
Draws a rounded rectangle.
Parameters:
- xy (sequence): Bounding box as 4-tuple (x1, y1, x2, y2)
- radius (int | tuple): Corner radius (int for all corners, 4-tuple for individual corners)
- fill (int | tuple | str): Interior color
- outline (int | tuple | str): Outline color
- width (int): Outline width
"""
def ellipse(self, xy, fill=None, outline=None, width=1):
"""
Draws an ellipse inside the given bounding box.
Parameters:
- xy (sequence): Bounding box as 4-tuple (x1, y1, x2, y2)
- fill (int | tuple | str): Interior color
- outline (int | tuple | str): Outline color
- width (int): Outline width
"""
def circle(self, xy, radius, fill=None, outline=None, width=1):
"""
Draws a circle.
Parameters:
- xy (tuple): Center point as (x, y)
- radius (int): Circle radius
- fill (int | tuple | str): Interior color
- outline (int | tuple | str): Outline color
- width (int): Outline width
"""
def polygon(self, xy, fill=None, outline=None, width=1):
"""
Draws a polygon connecting given coordinates.
Parameters:
- xy (sequence): Sequence of 2-tuples for polygon vertices
- fill (int | tuple | str): Interior color
- outline (int | tuple | str): Outline color
- width (int): Outline width
"""
def regular_polygon(self, bounding_circle, n_sides, rotation=0, fill=None, outline=None, width=1):
"""
Draws a regular polygon inscribed in a circle.
Parameters:
- bounding_circle (tuple): Circle as ((center_x, center_y), radius)
- n_sides (int): Number of sides (3 or more)
- rotation (float): Rotation angle in degrees
- fill (int | tuple | str): Interior color
- outline (int | tuple | str): Outline color
- width (int): Outline width
"""Draw arc segments and chords.
class ImageDraw:
def arc(self, xy, start, end, fill=None, width=1):
"""
Draws an arc (part of circle outline) inside the given bounding box.
Parameters:
- xy (sequence): Bounding box as 4-tuple (x1, y1, x2, y2)
- start (float): Starting angle in degrees
- end (float): Ending angle in degrees
- fill (int | tuple | str): Arc color
- width (int): Arc width
"""
def chord(self, xy, start, end, fill=None, outline=None, width=1):
"""
Draws a chord (filled arc with straight line connecting endpoints).
Parameters:
- xy (sequence): Bounding box as 4-tuple (x1, y1, x2, y2)
- start (float): Starting angle in degrees
- end (float): Ending angle in degrees
- fill (int | tuple | str): Interior color
- outline (int | tuple | str): Outline color
- width (int): Outline width
"""
def pieslice(self, xy, start, end, fill=None, outline=None, width=1):
"""
Draws a pie slice (filled arc with lines to center).
Parameters:
- xy (sequence): Bounding box as 4-tuple (x1, y1, x2, y2)
- start (float): Starting angle in degrees
- end (float): Ending angle in degrees
- fill (int | tuple | str): Interior color
- outline (int | tuple | str): Outline color
- width (int): Outline width
"""Render text with various typography options.
class ImageDraw:
def text(self, 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):
"""
Draws text at given position.
Parameters:
- xy (tuple): Starting position as (x, y)
- text (str): Text to draw
- fill (int | tuple | str): Text color
- font (FreeTypeFont): Font to use
- anchor (str): Text anchor relative to xy ("la", "lt", "ma", "mt", "ra", "rt", etc.)
- spacing (int): Line spacing for multiline text
- align (str): Multiline text alignment ("left", "center", "right")
- direction (str): Text direction ("ltr", "rtl", "ttb")
- features (list): OpenType features to apply
- language (str): Language code for text shaping
- stroke_width (int): Text stroke width
- stroke_fill (int | tuple | str): Text stroke color
- embedded_color (bool): Whether to use embedded color fonts
"""
def textsize(self, text, font=None, spacing=4, direction=None, features=None, language=None, stroke_width=0):
"""
Get the size of given text (deprecated, use textbbox).
Parameters:
- text (str): Text to measure
- font (FreeTypeFont): Font to use
- spacing (int): Line spacing
- direction (str): Text direction
- features (list): OpenType features
- language (str): Language code
- stroke_width (int): Text stroke width
Returns:
tuple: Text size as (width, height)
"""
def textbbox(self, xy, text, font=None, anchor=None, spacing=4, align="left", direction=None, features=None, language=None, stroke_width=0, embedded_color=False):
"""
Get the bounding box of given text.
Parameters:
- xy (tuple): Starting position as (x, y)
- text (str): Text to measure
- font (FreeTypeFont): Font to use
- anchor (str): Text anchor
- spacing (int): Line spacing
- align (str): Text alignment
- direction (str): Text direction
- features (list): OpenType features
- language (str): Language code
- stroke_width (int): Text stroke width
- embedded_color (bool): Whether to use embedded color fonts
Returns:
tuple: Bounding box as (left, top, right, bottom)
"""
def textlength(self, text, font=None, direction=None, features=None, language=None, embedded_color=False):
"""
Get the length of given text in pixels.
Parameters:
- text (str): Text to measure
- font (FreeTypeFont): Font to use
- direction (str): Text direction
- features (list): OpenType features
- language (str): Language code
- embedded_color (bool): Whether to use embedded color fonts
Returns:
float: Text length in pixels
"""Work with bitmap patterns and masks.
class ImageDraw:
def bitmap(self, xy, bitmap, fill=None):
"""
Draws a bitmap at given position.
Parameters:
- xy (tuple): Position as (x, y)
- bitmap (Image): 1-bit bitmap image
- fill (int | tuple | str): Color for "1" pixels
"""
def point(self, xy, fill=None):
"""
Draws one or more individual pixels.
Parameters:
- xy (sequence): Sequence of coordinate tuples
- fill (int | tuple | str): Pixel color
"""from PIL import Image, ImageDraw
# Create a new image
img = Image.new("RGB", (400, 300), "white")
draw = ImageDraw.Draw(img)
# Draw various shapes
draw.rectangle([50, 50, 150, 100], fill="red", outline="black", width=2)
draw.ellipse([200, 50, 300, 150], fill="blue", outline="darkblue", width=3)
draw.polygon([(350, 50), (375, 100), (325, 100)], fill="green")
# Draw lines
draw.line([50, 200, 350, 200], fill="purple", width=5)
draw.line([(50, 220), (150, 250), (250, 220), (350, 250)], fill="orange", width=3)
img.save("shapes.png")from PIL import Image, ImageDraw, ImageFont
# Create image
img = Image.new("RGB", (500, 200), "white")
draw = ImageDraw.Draw(img)
# Load font
try:
font = ImageFont.truetype("arial.ttf", 24)
title_font = ImageFont.truetype("arial.ttf", 36)
except OSError:
font = ImageFont.load_default()
title_font = font
# Draw text with different alignments
draw.text((250, 50), "Centered Title", font=title_font, fill="black", anchor="mm")
draw.text((50, 100), "Left aligned text", font=font, fill="blue", anchor="la")
draw.text((450, 100), "Right aligned text", font=font, fill="red", anchor="ra")
# Multiline text
multiline_text = "This is a long text\\nthat spans multiple lines\\nwith custom spacing"
draw.multiline_text((250, 140), multiline_text, font=font, fill="darkgreen",
anchor="mm", align="center", spacing=10)
img.save("text_example.png")from PIL import Image, ImageDraw
import math
# Create image for a logo
img = Image.new("RGBA", (300, 300), (255, 255, 255, 0)) # Transparent background
draw = ImageDraw.Draw(img)
# Draw a sun-like shape
center = (150, 150)
sun_radius = 60
ray_length = 40
# Draw sun rays
for angle in range(0, 360, 30):
rad = math.radians(angle)
start_x = center[0] + sun_radius * math.cos(rad)
start_y = center[1] + sun_radius * math.sin(rad)
end_x = center[0] + (sun_radius + ray_length) * math.cos(rad)
end_y = center[1] + (sun_radius + ray_length) * math.sin(rad)
draw.line([start_x, start_y, end_x, end_y], fill="orange", width=4)
# Draw sun body
draw.ellipse([center[0] - sun_radius, center[1] - sun_radius,
center[0] + sun_radius, center[1] + sun_radius],
fill="yellow", outline="orange", width=3)
# Add a smile
smile_y = center[1] + 10
draw.arc([center[0] - 25, smile_y - 15, center[0] + 25, smile_y + 15],
start=0, end=180, fill="orange", width=3)
# Add eyes
draw.circle((center[0] - 15, center[1] - 15), 5, fill="orange")
draw.circle((center[0] + 15, center[1] - 15), 5, fill="orange")
img.save("sun_logo.png")from PIL import Image, ImageDraw
# Create gradient background
def create_gradient(width, height, color1, color2):
img = Image.new("RGB", (width, height))
draw = ImageDraw.Draw(img)
for y in range(height):
# Interpolate between colors
ratio = y / height
r = int(color1[0] * (1 - ratio) + color2[0] * ratio)
g = int(color1[1] * (1 - ratio) + color2[1] * ratio)
b = int(color1[2] * (1 - ratio) + color2[2] * ratio)
draw.line([(0, y), (width, y)], fill=(r, g, b))
return img
# Create gradient background
img = create_gradient(400, 300, (255, 200, 100), (100, 150, 255))
draw = ImageDraw.Draw(img)
# Draw pattern of circles
for x in range(50, 400, 80):
for y in range(50, 300, 80):
draw.circle((x, y), 20, fill=(255, 255, 255, 128), outline="white", width=2)
img.save("gradient_pattern.png")from PIL import Image, ImageDraw, ImageFont
# Open an existing image
img = Image.open("photo.jpg")
draw = ImageDraw.Draw(img)
# Load font for annotations
try:
font = ImageFont.truetype("arial.ttf", 16)
except OSError:
font = ImageFont.load_default()
# Add annotations
annotations = [
((100, 50), "Mountain Peak", "red"),
((200, 150), "Lake", "blue"),
((300, 200), "Forest", "green")
]
for pos, label, color in annotations:
# Draw arrow pointing to feature
draw.line([pos[0], pos[1], pos[0] + 30, pos[1] - 20], fill=color, width=2)
# Draw text box background
bbox = draw.textbbox((pos[0] + 35, pos[1] - 25), label, font=font)
draw.rectangle([bbox[0] - 5, bbox[1] - 2, bbox[2] + 5, bbox[3] + 2],
fill="white", outline=color, width=1)
# Draw text
draw.text((pos[0] + 35, pos[1] - 25), label, font=font, fill=color)
img.save("annotated_photo.jpg")Install with Tessl CLI
npx tessl i tessl/pypi-pillow