Of course! Here is a comprehensive guide to using the ImageFont API in Python, which is part of the Pillow library (a fork of the original PIL).

The Big Picture: What is ImageFont?
The ImageFont module in Pillow is used to load font files (like .ttf, .otf, etc.) so you can use them with the ImageDraw.text() method to draw text on an image.
Key Concept: You don't use ImageFont directly to draw text. Instead:
- You load a font using
ImageFont.truetype(). - You pass that loaded font object to the
textargument ofImageDraw.text().
Prerequisites: Install Pillow
If you don't have Pillow installed, open your terminal or command prompt and run:
pip install Pillow
Core API Functions
The most common function you'll use is truetype().

ImageFont.truetype(font_path, size, encoding='utf-8', ...) (Recommended)
This is the standard way to load a TrueType or OpenType font.
Parameters:
font_path(str): The path to the font file (e.g.,"arial.ttf"). You must provide this.size(int): The font size in points.encoding(str, optional): The text encoding.'utf-8'is the default and is almost always what you need.layout_engine(optional, Pillow 9.0+): Allows you to specify a layout engine for more advanced text rendering (e.g.,ImageFont.Layout.BASIC).
Returns:
- An
ImageFont.FreeTypeFontobject.
A Simple Example: Drawing Text on an Image
Let's walk through a complete, basic example.

Step 1: Get a Font File
You need a font file. Common ones are:
- System Fonts: These are already on your computer.
- Windows:
"C:/Windows/Fonts/arial.ttf" - macOS:
"/System/Library/Fonts/Arial.ttf" - Linux:
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"
- Windows:
- Download Fonts: You can download free fonts from sites like Google Fonts. For this example, let's use the "Roboto" font. Download the "Roboto-Regular.ttf" file and place it in the same directory as your Python script.
Step 2: The Python Code
from PIL import Image, ImageDraw, ImageFont
# 1. Create a blank image
# Mode 'RGB' for color, 'RGBA' for transparency
img = Image.new('RGB', (400, 200), color = 'white')
draw = ImageDraw.Draw(img)
# 2. Load the font
# Make sure 'Roboto-Regular.ttf' is in the same folder
try:
font = ImageFont.truetype("Roboto-Regular.ttf", 40)
except IOError:
# Fallback to a default font if the specified one is not found
font = ImageFont.load_default()
# 3. Draw text on the image
# The text to draw
text = "Hello, Pillow!"
# Get the size of the text to center it
text_width, text_height = draw.textsize(text, font=font) # Note: textsize is deprecated in Pillow 9.2+, use textbbox
# For Pillow 9.2+:
# bbox = draw.textbbox((0, 0), text, font=font)
# text_width = bbox[2] - bbox[0]
# text_height = bbox[3] - bbox[1]
# Calculate position to center the text
x = (img.width - text_width) / 2
y = (img.height - text_height) / 2
# The text() method draws the text
# xy: The top-left corner of the text
# fill: The color of the text
draw.text((x, y), text, font=font, fill='black')
# 4. Save the image
img.save("output.png")
print("Image created: output.png")
Step 3: Run the Code
After running this script, you will have a new file named output.png with the text "Hello, Pillow!" centered on it.
Advanced Features & Common Use Cases
A. Handling Different Font Weights and Styles
If you have different files (e.g., Roboto-Bold.ttf, Roboto-Italic.ttf), just load them separately.
from PIL import Image, ImageDraw, ImageFont
img = Image.new('RGB', (600, 150), color='white')
draw = ImageDraw.Draw(img)
# Load different font styles
font_regular = ImageFont.truetype("Roboto-Regular.ttf", 30)
font_bold = ImageFont.truetype("Roboto-Bold.ttf", 30)
font_italic = ImageFont.truetype("Roboto-Italic.ttf", 30)
draw.text((10, 10), "Regular Text", font=font_regular, fill='black')
draw.text((10, 50), "Bold Text", font=font_bold, fill='blue')
draw.text((10, 90), "Italic Text", font=font_italic, fill='green')
img.save("styled_text.png")
B. Handling Special Characters and Unicode
The encoding='utf-8' parameter is key here. It allows you to use characters from various languages, emojis, and symbols.
from PIL import Image, ImageDraw, ImageFont
img = Image.new('RGB', (400, 100), color='white')
draw = ImageDraw.Draw(img)
# Use a font that supports a wide range of characters (like Noto Sans)
# You can download Noto Sans from Google Fonts
font = ImageFont.truetype("NotoSans-Regular.ttf", 25)
# Text with special characters, emojis, and non-Latin scripts
text = "Hello 世界! 🚀"
draw.text((10, 10), text, font=font, fill='black')
img.save("unicode_text.png")
C. Getting Text Dimensions (Crucial for Layout)
As seen in the first example, you need to know the size of your text to position it correctly.
-
draw.textsize(text, font): (Older versions of Pillow)- Returns a tuple
(width, height). - Deprecated in Pillow 9.2. Use
textbboxinstead.
- Returns a tuple
-
draw.textbbox(xy, text, font): (Recommended for Pillow 9.2+)- Returns a bounding box tuple:
(left, top, right, bottom). - This is more accurate as it includes leading and descent.
width = right - leftheight = bottom - top
- Returns a bounding box tuple:
-
font.getmask(text).size: An alternative way to get dimensions.- Returns
(width, height)of the text mask. - This can be slightly faster than
textbboxif you only need the size and not the exact bounding box coordinates.
- Returns
Example with textbbox:
from PIL import Image, ImageDraw, ImageFont
img = Image.new('RGB', (300, 100), color='lightgray')
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("Roboto-Regular.ttf", 40)
text = "Measure Me"
bbox = draw.textbbox((0, 0), text, font=font)
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]
# Position text
x = (img.width - text_width) / 2
y = (img.height - text_height) / 2
draw.text((x, y), text, font=font, fill='black')
# Draw a rectangle to show the calculated bounding box
draw.rectangle(bbox, outline='red', width=2)
img.save("textbbox_demo.png")
This will draw the text and a red rectangle around the exact area it occupies.
D. Rotating Text
To rotate text, you must first create a transparent image for the text itself, rotate it, and then paste it onto your main image.
from PIL import Image, ImageDraw, ImageFont
# 1. Create main canvas
main_img = Image.new('RGB', (300, 300), color='white')
main_draw = ImageDraw.Draw(main_img)
# 2. Create a temporary image for the text
text_to_draw = "Rotated!"
font = ImageFont.truetype("Roboto-Regular.ttf", 40)
# Get text size to make the temp image big enough
bbox = main_draw.textbbox((0, 0), text_to_draw, font=font)
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]
temp_img = Image.new('RGBA', (text_width, text_height), (0, 0, 0, 0)) # Transparent
temp_draw = ImageDraw.Draw(temp_img)
# Draw text on the temporary image
temp_draw.text((0, 0), text_to_draw, font=font, fill=(255, 