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)

Get Our Python Developer Kit for Free

I put together a Python Developer Kit with over 100 pre-built Python scripts covering data structures, Pandas, NumPy, Seaborn, machine learning, file processing, web scraping and a whole lot more - and I want you to have it for free. Enter your email address below and I'll send a copy your way.

Yes, I'll take a free Python Developer Kit

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.


Get Our Python Developer Kit for Free

I put together a Python Developer Kit with over 100 pre-built Python scripts covering data structures, Pandas, NumPy, Seaborn, machine learning, file processing, web scraping and a whole lot more - and I want you to have it for free. Enter your email address below and I'll send a copy your way.

Yes, I'll take a free Python Developer Kit