In this tutorial, we will learn how to center a multiline text string on an image using Python and the Pillow library. Pillow is a popular and powerful image processing library that allows us to manipulate images in various ways. One of the common tasks we might want to do is to add some text to an image, such as a caption, a title, or a watermark. However, adding text to an image is not as simple as it might seem, especially if we want to handle multiple lines of text and align them properly on the image. In this tutorial, we will see how to use some of the features of Pillow to achieve this goal.

To follow along, you will need to have Python 3 and Pillow installed on your system. Let’s get started!

Step 1: Install Pillow

If you don’t have Pillow installed on your system, you can install it using pip:

pip install pillow

Step 2: Import Pillow

To use Pillow in your Python script, you need to import it:

from PIL import Image, ImageDraw, ImageFont

Step 3: Load the Image

Next, you need to load the image that you want to add text to. You can use the Image.open() function to open an image file and return an Image object:

image = Image.open("image.jpg")

Alternatively, you could create an empty image from scratch using something like this:

image = Image.new("RGB", (600, 400), "blue")

Step 4: Create an ImageDraw Object

To draw text on the image, you need to create an ImageDraw object that provides various drawing methods:

draw = ImageDraw.Draw(image)

Code More, Distract Less: Support Our Ad-Free Site

You might have noticed we removed ads from our site - we hope this enhances your learning experience. To help sustain this, please take a look at our Python Developer Kit and our comprehensive cheat sheets. Each purchase directly supports this site, ensuring we can continue to offer you quality, distraction-free tutorials.


Step 5: Choose a Font and a Text Color

You also need to choose a font and a text color for your text. You can use the ImageFont.truetype() function to load a TrueType or OpenType font file and return an ImageFont object. You can specify the font size as the second argument. For the text color, you can use a tuple of RGB values:

font = ImageFont.truetype("arial.ttf", 32)
text_color = (255, 255, 255) # white

We use font size 32 in this example but you can adjust it so it looks nice on your image.

If you’re using Google Colab to follow along with this tutorial, a few default fonts are located here: /usr/share/fonts/truetype/. You would just update the code above with something like:

font = ImageFont.truetype("/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf", 32)
text_color = (255, 255, 255) # white

Step 6: Split the Text into Multiple Lines

To split the text into multiple lines, you can use the textwrap module from the standard library. The textwrap.wrap() function takes a string and a maximum width (in characters) and returns a list of strings that are wrapped at whitespace boundaries:

import textwrap
text = "Let's write a Python tutorial showing how to center a multiline string vertically and horizontally on an image using the Pillow library."
lines = textwrap.wrap(text, width=40)

Adjust the width argument to change the width of the lines before wrapping until it wraps the way you’d like it to wrap on your image.

Step 7: Calculate the Text Size and Position

To center the text vertically and horizontally on the image, you need to calculate the text size and position. You can use the ImageDraw.textsize() method to get the width and height of a single line of text in pixels. You can then use a loop to sum up the heights of all lines and find the maximum width. To center the text horizontally, you need to subtract half of the maximum width from half of the image width. To center the text vertically, you need to subtract half of the total height from half of the image height. You can then use another loop to calculate the position of each line by adding the height of each previous line:

max_width = 0
total_height = 0
for line in lines:
width, height = draw.textsize(line, font=font)
max_width = max(max_width, width)
total_height += height

x = (image.width - max_width) // 2
y = (image.height - total_height) // 2

line_heights = []
for line in lines:
width, height = draw.textsize(line, font=font)
line_heights.append(height)

line_y = y
for i in range(len(lines)):
line_x = x + (max_width - draw.textsize(lines[i], font=font)[0]) // 2
draw.text((line_x, line_y), lines[i], fill=text_color, font=font)
line_y += line_heights[i]

Step 8: Save the Image

Finally, you can save the modified image using the Image.save() method. Specify the output file name and format as arguments:

image.save("output.png", format="PNG")

Here’s the final image with our text wrapped and centered, just like we wanted:

Pillow image with text centered vertically and horizontally


We hope you have learned something useful from this tutorial. Feel free to subscribe below for more useful Python tutorials.


Code More, Distract Less: Support Our Ad-Free Site

You might have noticed we removed ads from our site - we hope this enhances your learning experience. To help sustain this, please take a look at our Python Developer Kit and our comprehensive cheat sheets. Each purchase directly supports this site, ensuring we can continue to offer you quality, distraction-free tutorials.