0
# Drawing and Graphics
1
2
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.
3
4
## Capabilities
5
6
### Drawing Context Creation
7
8
Create drawing contexts for image manipulation.
9
10
```python { .api }
11
def Draw(im, mode=None):
12
"""
13
Creates a drawing context for the given image.
14
15
Parameters:
16
- im (Image): The image to draw on
17
- mode (str): Optional mode override
18
19
Returns:
20
ImageDraw: Drawing context object
21
"""
22
23
def floodfill(image, xy, value, border=None, thresh=0):
24
"""
25
Fills a region with a given color using flood fill algorithm.
26
27
Parameters:
28
- image (Image): Target image (will be modified)
29
- xy (tuple): Starting point as (x, y)
30
- value (int | tuple | str): Fill color
31
- border (int | tuple | str): Border color to stop at
32
- thresh (int): Threshold for color matching
33
34
Returns:
35
int: Number of pixels changed
36
"""
37
```
38
39
### Line Drawing
40
41
Draw lines and connected line segments.
42
43
```python { .api }
44
class ImageDraw:
45
def line(self, xy, fill=None, width=0, joint=None):
46
"""
47
Draws a line between given coordinates.
48
49
Parameters:
50
- xy (sequence): Sequence of 2-tuples for coordinates or 4-tuple (x1, y1, x2, y2)
51
- fill (int | tuple | str): Line color
52
- width (int): Line width in pixels
53
- joint (str): Line joint style ("curve" or None)
54
"""
55
56
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):
57
"""
58
Draws multiline text.
59
60
Parameters:
61
- xy (tuple): Starting position as (x, y)
62
- text (str): Text to draw (can contain newlines)
63
- fill (int | tuple | str): Text color
64
- font (FreeTypeFont): Font to use
65
- anchor (str): Text anchor relative to xy coordinate
66
- spacing (int): Line spacing in pixels
67
- align (str): Multiline alignment ("left", "center", "right")
68
- direction (str): Text direction ("ltr", "rtl", "ttb")
69
- features (list): OpenType features
70
- language (str): Language code
71
- stroke_width (int): Text stroke width
72
- stroke_fill (int | tuple | str): Text stroke color
73
"""
74
```
75
76
### Shape Drawing
77
78
Draw basic geometric shapes.
79
80
```python { .api }
81
class ImageDraw:
82
def rectangle(self, xy, fill=None, outline=None, width=1):
83
"""
84
Draws a rectangle.
85
86
Parameters:
87
- xy (sequence): Bounding box as 4-tuple (x1, y1, x2, y2) or 2-tuples ((x1, y1), (x2, y2))
88
- fill (int | tuple | str): Interior color
89
- outline (int | tuple | str): Outline color
90
- width (int): Outline width
91
"""
92
93
def rounded_rectangle(self, xy, radius=0, fill=None, outline=None, width=1):
94
"""
95
Draws a rounded rectangle.
96
97
Parameters:
98
- xy (sequence): Bounding box as 4-tuple (x1, y1, x2, y2)
99
- radius (int | tuple): Corner radius (int for all corners, 4-tuple for individual corners)
100
- fill (int | tuple | str): Interior color
101
- outline (int | tuple | str): Outline color
102
- width (int): Outline width
103
"""
104
105
def ellipse(self, xy, fill=None, outline=None, width=1):
106
"""
107
Draws an ellipse inside the given bounding box.
108
109
Parameters:
110
- xy (sequence): Bounding box as 4-tuple (x1, y1, x2, y2)
111
- fill (int | tuple | str): Interior color
112
- outline (int | tuple | str): Outline color
113
- width (int): Outline width
114
"""
115
116
def circle(self, xy, radius, fill=None, outline=None, width=1):
117
"""
118
Draws a circle.
119
120
Parameters:
121
- xy (tuple): Center point as (x, y)
122
- radius (int): Circle radius
123
- fill (int | tuple | str): Interior color
124
- outline (int | tuple | str): Outline color
125
- width (int): Outline width
126
"""
127
128
def polygon(self, xy, fill=None, outline=None, width=1):
129
"""
130
Draws a polygon connecting given coordinates.
131
132
Parameters:
133
- xy (sequence): Sequence of 2-tuples for polygon vertices
134
- fill (int | tuple | str): Interior color
135
- outline (int | tuple | str): Outline color
136
- width (int): Outline width
137
"""
138
139
def regular_polygon(self, bounding_circle, n_sides, rotation=0, fill=None, outline=None, width=1):
140
"""
141
Draws a regular polygon inscribed in a circle.
142
143
Parameters:
144
- bounding_circle (tuple): Circle as ((center_x, center_y), radius)
145
- n_sides (int): Number of sides (3 or more)
146
- rotation (float): Rotation angle in degrees
147
- fill (int | tuple | str): Interior color
148
- outline (int | tuple | str): Outline color
149
- width (int): Outline width
150
"""
151
```
152
153
### Arc and Chord Drawing
154
155
Draw arc segments and chords.
156
157
```python { .api }
158
class ImageDraw:
159
def arc(self, xy, start, end, fill=None, width=1):
160
"""
161
Draws an arc (part of circle outline) inside the given bounding box.
162
163
Parameters:
164
- xy (sequence): Bounding box as 4-tuple (x1, y1, x2, y2)
165
- start (float): Starting angle in degrees
166
- end (float): Ending angle in degrees
167
- fill (int | tuple | str): Arc color
168
- width (int): Arc width
169
"""
170
171
def chord(self, xy, start, end, fill=None, outline=None, width=1):
172
"""
173
Draws a chord (filled arc with straight line connecting endpoints).
174
175
Parameters:
176
- xy (sequence): Bounding box as 4-tuple (x1, y1, x2, y2)
177
- start (float): Starting angle in degrees
178
- end (float): Ending angle in degrees
179
- fill (int | tuple | str): Interior color
180
- outline (int | tuple | str): Outline color
181
- width (int): Outline width
182
"""
183
184
def pieslice(self, xy, start, end, fill=None, outline=None, width=1):
185
"""
186
Draws a pie slice (filled arc with lines to center).
187
188
Parameters:
189
- xy (sequence): Bounding box as 4-tuple (x1, y1, x2, y2)
190
- start (float): Starting angle in degrees
191
- end (float): Ending angle in degrees
192
- fill (int | tuple | str): Interior color
193
- outline (int | tuple | str): Outline color
194
- width (int): Outline width
195
"""
196
```
197
198
### Text Rendering
199
200
Render text with various typography options.
201
202
```python { .api }
203
class ImageDraw:
204
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):
205
"""
206
Draws text at given position.
207
208
Parameters:
209
- xy (tuple): Starting position as (x, y)
210
- text (str): Text to draw
211
- fill (int | tuple | str): Text color
212
- font (FreeTypeFont): Font to use
213
- anchor (str): Text anchor relative to xy ("la", "lt", "ma", "mt", "ra", "rt", etc.)
214
- spacing (int): Line spacing for multiline text
215
- align (str): Multiline text alignment ("left", "center", "right")
216
- direction (str): Text direction ("ltr", "rtl", "ttb")
217
- features (list): OpenType features to apply
218
- language (str): Language code for text shaping
219
- stroke_width (int): Text stroke width
220
- stroke_fill (int | tuple | str): Text stroke color
221
- embedded_color (bool): Whether to use embedded color fonts
222
"""
223
224
def textsize(self, text, font=None, spacing=4, direction=None, features=None, language=None, stroke_width=0):
225
"""
226
Get the size of given text (deprecated, use textbbox).
227
228
Parameters:
229
- text (str): Text to measure
230
- font (FreeTypeFont): Font to use
231
- spacing (int): Line spacing
232
- direction (str): Text direction
233
- features (list): OpenType features
234
- language (str): Language code
235
- stroke_width (int): Text stroke width
236
237
Returns:
238
tuple: Text size as (width, height)
239
"""
240
241
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):
242
"""
243
Get the bounding box of given text.
244
245
Parameters:
246
- xy (tuple): Starting position as (x, y)
247
- text (str): Text to measure
248
- font (FreeTypeFont): Font to use
249
- anchor (str): Text anchor
250
- spacing (int): Line spacing
251
- align (str): Text alignment
252
- direction (str): Text direction
253
- features (list): OpenType features
254
- language (str): Language code
255
- stroke_width (int): Text stroke width
256
- embedded_color (bool): Whether to use embedded color fonts
257
258
Returns:
259
tuple: Bounding box as (left, top, right, bottom)
260
"""
261
262
def textlength(self, text, font=None, direction=None, features=None, language=None, embedded_color=False):
263
"""
264
Get the length of given text in pixels.
265
266
Parameters:
267
- text (str): Text to measure
268
- font (FreeTypeFont): Font to use
269
- direction (str): Text direction
270
- features (list): OpenType features
271
- language (str): Language code
272
- embedded_color (bool): Whether to use embedded color fonts
273
274
Returns:
275
float: Text length in pixels
276
"""
277
```
278
279
### Bitmap Operations
280
281
Work with bitmap patterns and masks.
282
283
```python { .api }
284
class ImageDraw:
285
def bitmap(self, xy, bitmap, fill=None):
286
"""
287
Draws a bitmap at given position.
288
289
Parameters:
290
- xy (tuple): Position as (x, y)
291
- bitmap (Image): 1-bit bitmap image
292
- fill (int | tuple | str): Color for "1" pixels
293
"""
294
295
def point(self, xy, fill=None):
296
"""
297
Draws one or more individual pixels.
298
299
Parameters:
300
- xy (sequence): Sequence of coordinate tuples
301
- fill (int | tuple | str): Pixel color
302
"""
303
```
304
305
## Usage Examples
306
307
### Basic Shape Drawing
308
309
```python
310
from PIL import Image, ImageDraw
311
312
# Create a new image
313
img = Image.new("RGB", (400, 300), "white")
314
draw = ImageDraw.Draw(img)
315
316
# Draw various shapes
317
draw.rectangle([50, 50, 150, 100], fill="red", outline="black", width=2)
318
draw.ellipse([200, 50, 300, 150], fill="blue", outline="darkblue", width=3)
319
draw.polygon([(350, 50), (375, 100), (325, 100)], fill="green")
320
321
# Draw lines
322
draw.line([50, 200, 350, 200], fill="purple", width=5)
323
draw.line([(50, 220), (150, 250), (250, 220), (350, 250)], fill="orange", width=3)
324
325
img.save("shapes.png")
326
```
327
328
### Text Rendering with Fonts
329
330
```python
331
from PIL import Image, ImageDraw, ImageFont
332
333
# Create image
334
img = Image.new("RGB", (500, 200), "white")
335
draw = ImageDraw.Draw(img)
336
337
# Load font
338
try:
339
font = ImageFont.truetype("arial.ttf", 24)
340
title_font = ImageFont.truetype("arial.ttf", 36)
341
except OSError:
342
font = ImageFont.load_default()
343
title_font = font
344
345
# Draw text with different alignments
346
draw.text((250, 50), "Centered Title", font=title_font, fill="black", anchor="mm")
347
draw.text((50, 100), "Left aligned text", font=font, fill="blue", anchor="la")
348
draw.text((450, 100), "Right aligned text", font=font, fill="red", anchor="ra")
349
350
# Multiline text
351
multiline_text = "This is a long text\\nthat spans multiple lines\\nwith custom spacing"
352
draw.multiline_text((250, 140), multiline_text, font=font, fill="darkgreen",
353
anchor="mm", align="center", spacing=10)
354
355
img.save("text_example.png")
356
```
357
358
### Creating Complex Graphics
359
360
```python
361
from PIL import Image, ImageDraw
362
import math
363
364
# Create image for a logo
365
img = Image.new("RGBA", (300, 300), (255, 255, 255, 0)) # Transparent background
366
draw = ImageDraw.Draw(img)
367
368
# Draw a sun-like shape
369
center = (150, 150)
370
sun_radius = 60
371
ray_length = 40
372
373
# Draw sun rays
374
for angle in range(0, 360, 30):
375
rad = math.radians(angle)
376
start_x = center[0] + sun_radius * math.cos(rad)
377
start_y = center[1] + sun_radius * math.sin(rad)
378
end_x = center[0] + (sun_radius + ray_length) * math.cos(rad)
379
end_y = center[1] + (sun_radius + ray_length) * math.sin(rad)
380
381
draw.line([start_x, start_y, end_x, end_y], fill="orange", width=4)
382
383
# Draw sun body
384
draw.ellipse([center[0] - sun_radius, center[1] - sun_radius,
385
center[0] + sun_radius, center[1] + sun_radius],
386
fill="yellow", outline="orange", width=3)
387
388
# Add a smile
389
smile_y = center[1] + 10
390
draw.arc([center[0] - 25, smile_y - 15, center[0] + 25, smile_y + 15],
391
start=0, end=180, fill="orange", width=3)
392
393
# Add eyes
394
draw.circle((center[0] - 15, center[1] - 15), 5, fill="orange")
395
draw.circle((center[0] + 15, center[1] - 15), 5, fill="orange")
396
397
img.save("sun_logo.png")
398
```
399
400
### Drawing with Gradients and Patterns
401
402
```python
403
from PIL import Image, ImageDraw
404
405
# Create gradient background
406
def create_gradient(width, height, color1, color2):
407
img = Image.new("RGB", (width, height))
408
draw = ImageDraw.Draw(img)
409
410
for y in range(height):
411
# Interpolate between colors
412
ratio = y / height
413
r = int(color1[0] * (1 - ratio) + color2[0] * ratio)
414
g = int(color1[1] * (1 - ratio) + color2[1] * ratio)
415
b = int(color1[2] * (1 - ratio) + color2[2] * ratio)
416
417
draw.line([(0, y), (width, y)], fill=(r, g, b))
418
419
return img
420
421
# Create gradient background
422
img = create_gradient(400, 300, (255, 200, 100), (100, 150, 255))
423
draw = ImageDraw.Draw(img)
424
425
# Draw pattern of circles
426
for x in range(50, 400, 80):
427
for y in range(50, 300, 80):
428
draw.circle((x, y), 20, fill=(255, 255, 255, 128), outline="white", width=2)
429
430
img.save("gradient_pattern.png")
431
```
432
433
### Annotation and Labeling
434
435
```python
436
from PIL import Image, ImageDraw, ImageFont
437
438
# Open an existing image
439
img = Image.open("photo.jpg")
440
draw = ImageDraw.Draw(img)
441
442
# Load font for annotations
443
try:
444
font = ImageFont.truetype("arial.ttf", 16)
445
except OSError:
446
font = ImageFont.load_default()
447
448
# Add annotations
449
annotations = [
450
((100, 50), "Mountain Peak", "red"),
451
((200, 150), "Lake", "blue"),
452
((300, 200), "Forest", "green")
453
]
454
455
for pos, label, color in annotations:
456
# Draw arrow pointing to feature
457
draw.line([pos[0], pos[1], pos[0] + 30, pos[1] - 20], fill=color, width=2)
458
459
# Draw text box background
460
bbox = draw.textbbox((pos[0] + 35, pos[1] - 25), label, font=font)
461
draw.rectangle([bbox[0] - 5, bbox[1] - 2, bbox[2] + 5, bbox[3] + 2],
462
fill="white", outline=color, width=1)
463
464
# Draw text
465
draw.text((pos[0] + 35, pos[1] - 25), label, font=font, fill=color)
466
467
img.save("annotated_photo.jpg")
468
```