In the first post of this series, I introduced you to the basics of text drawing in Python by adding a greeting text on an image. I also highlighted examples of how I further extended this functionality to create some complex images at work.
If you haven’t already read the first part of this series (Putting Text on Images Using Python Part -1), I recommend you take a glance at it first, to get a better understanding of this post.
For now, we know how to draw text, change the font, and position the text on the image. In this post, we’ll discover how to draw multiline text and also discuss the challenges of doing so.
Often, while generating images, we come across situations where the text doesn’t fit in a single line. Python Pillow is not helpful here as it doesn’t automatically draw & push the text to a new line. In order to do this manually, we need to calculate the width and height of the text.
With the text-width, we determine when we need to move to the next line and with the text-height, we can figure how much space should be left in between the two lines:
The idea is to split the long sentences into multiple shorter sentences and draw each of these, one by one at the correct positions thereby making it look like a multiline text. To split a longer line, we‘ll use a Pillow function to calculate the size of the text passed to it as one of the parameters.
Calculate Text Width
For convenience, I’ve created a method text_wrap() to explain the line-split logic:
This function expects three parameters – the text to draw, an ImageFont class instance and the width of the background image on which the text is to be drawn.
The logic is pretty straightforward:
1. Check, if the sentence can fit in one line then just return it without splitting, else:
2. Split the sentence using spaces to fetch the words in it
3. Create shorter lines by appending words while the width is smaller than the image width
When we run this script it returns an array containing 2 shorter lines which fit within the width of the background image.
To draw these lines on the image we have to calculate the correct vertical position of each line.
Calculate Text Height
Whenever we write text, there is an equal amount of space between two lines. For example in this post, the lines have the constant spaces between them. While building this library I faced an issue of varying spaces with most of the input text:
Finding correct height for characters like g, j, p, q, y which are drawn below the Baseline and b, d, f, h, k, l which are drawn above the Median is a little tedious due to varying heights.
The best way to get the correct height of the text is to simply calculate the total height of “hg”. This trick works because h and g cover the height range of all the English characters.
For languages other than English, you might have to use different characters in place of h & g.
Since we have our wrapped/short lines and also the text height we can draw these on the image. We can do this by keeping a reference to the vertical position of the previously drawn line and then adding to it the line height to calculate the vertical position of the new line:
The text in the latter images looks much better and readable. At Haptik, we believe in experimentation and finding out the best possible way to solve problems. The above is one such example. In my next Blog post, I will be writing about how to center align text horizontally and vertically in an image using Python.
Think we did a good job? Let us know in the comments below.
Also, Haptik is hiring. Visit our careers section or get in touch with us at firstname.lastname@example.org.