- How to Add Text to Images in Python (via PIL Library)
- Adding Text on Images with Python in 4 Steps
- Step 1: Creating a New Image
- Step 2: Creating a Draw Object
- Step 3: Preparing Text Elements
- Step 4: Adding Text to the Image
- Built-in Color Names in PIL (Pillow)
- Adjusting Text Color
- Example 1: Font Size and Type
- Managing Fonts for Python PIL — (Linux)
- Managing Fonts for Python PIL — (Mac OS & Windows)
- Как правильно рассчитать размер текста в изображениях PIL
- Эта проблема
- Решение
- Практический пример
- Заключение
How to Add Text to Images in Python (via PIL Library)
In this Python tutorial we will show how to add text to images in Python using the PIL image manipulation library.
Our tutorial will gradually get more sophisticated and we will supplement it with creative examples towards the end for inspiration and as demonstration of more advanced Python applications.
We are going to be using Image, the ImageDraw and the ImageFont module from the PIL library mainly. We will also refer to ImageColor to see some available built-in color options. So, let’s start with importing those Python libraries first.
from PIL import Image, ImageDraw, ImageFont, ImageColor
Adding Text on Images with Python in 4 Steps
We can break up adding text to images to 4 steps.
Step 1: Creating a New Image
You can create a new image using PIL’s .new() method as below. It’s important to pay attention to color modes here as they can significantly impact the image manipulations that can be done on them as well as image saving options.
Here is a new image example with .new() method. First parameter is the color mode of the image while the second parameter in a tuple is the dimensions (how to get dimensions of an image) of the image.
We are going to also need an image object to write text on. We have a couple options for obtaining an image object in pillow image manipulation library.
Using the PIL library, we can “create a new image” or we can “open an existing image” as an image object in Python. Let’s start with creating a simple image object for the sake of simplicity.
Here is a new image example using PIL’s or pillow’s Image module. So, mode and size arguments are mandatory while we can also pass an optional color argument as below to energize this Python tutorial a bit.
img = Image.new(mode="RGBA", size=(400,300), color='darkorange') img.show()
You can see a full list of available color names and their hex codes in the Python color tutorial below as well as discover various colormaps and how to derive discrete colors from them.
Additionally, we have an in-depth Python tutorial about color modes and how to use them with Python images using the PIL (pillow) digital image editing library.
Step 2: Creating a Draw Object
Creating a draw object is as simple as it gets. We will use ImageDraw module we’ve already imported and Draw class from this module.
The most important nuance at this point is the fact that we are using Draw class on the image we have already created (or opened). This Draw class item will act as a handle to write our text in the following steps.
Here is the Python code to create a draw object with PIL.
(And we have an extensive, well-researched tutorial about drawing geometric shapes in images with Python.)
Step 3: Preparing Text Elements
Next we can assign our text to a variable.
Alternatively, you can pass a string directly to the draw function below without using an additional variable.
Step 4: Adding Text to the Image
Finally, using the draw object we’ve created earlier, we can add our text element to the image. Here, we need to pass minimum two arguments. These are x, y coordinates of the text and the text itself.
draw.text((140, 100), text) img.show()
So, at the most basic level Python code for adding text to images looks like this:
img = Image.new(mode="RGBA", size=(400,300), color='darkorange') draw = ImageDraw.Draw(img) draw.text((140, 100), "Hello World!") img.show()
Built-in Color Names in PIL (Pillow)
Darkorange is a lovely built-in color name in pillow’s color repertoire. Moreover you can choose from a plethora of cool built-in colors that are available in PIL.ImageColor class.
Pillow uses a superset of HTML 4.0 color names used in CSS 1. To get a full list of these color names you can refer to the colormap attribute inside ImageColor module. Here is the Python code for that:
colors=ImageColor.colormap for i in colors.keys(): print(i)
* keys() is a useful method for dictionaries in Python that provides only the keys in a dictionary. Since colormap attribute of ImageColor class is a dictionary of key-value pairs where keys are built-in color names and values are their hex codes. You can visit our dictionary exercises and dictionary lessons if you need to polish your Python dictionary knowledge.
Adjusting Text Color
Adjusting the color of the text being added to the image is also very simple. Just use fill argument and pass a built-in color name or a hex color code to this optional argument when using the draw function.
draw.text((140, 100), text, fill='black') img.show()
Example 1: Font Size and Type
So far we covered a minimalist Python implementation to add text on images which can be achieved with a few lines of Python code. Our code up to this point uses whatever default font and font size can be recalled by the pillow library since we didn’t assign any specific font settings.
However, there can be many merits to defining a specific font type and a font size while using the draw function to add text to an image or a manipulate batch of images.
text="Hello World!" font = ImageFont.truetype('Inconsolata-Light.ttf', 162) draw.text((1240, 1600), text, font=font, fill='white') img.show()
With proper image and font style the result looks a lot more appealing already.
Managing Fonts for Python PIL — (Linux)
A quick font file explanation might be useful here. We are using Inconsolata-Light.ttf that’s already installed in our Linux system.
If you are using Linux, you can check out the available fonts installed in your system by running fc-list command in your terminal.
You can simply install new font files by placing .ttf or .otf font files in your system’s /usr/share/fonts directory. Don’t forget to run fc-cache command to refresh your font registry and then you can list available font by running fc-list again.
There are incredibly cool font options for free at Google Fonts. You can also search for specific font styles such as Serif, Sans Serif, Display, Handwriting or Monospace. You can download the font’s zip file and then extract it in your operating system.
Managing Fonts for Python PIL — (Mac OS & Windows)
Users of Mac OS operating system can use the terminal to manage fonts although the Font Book software makes it a breeze to install new fonts to the system and all the user has to do is click install font after opening a new font file.
Similarly, Windows users can open the Font tool under Settings > Control Panel where they can see, list, manage, install and uninstall new font files.
You are free to install new fonts however, you can also just extract your fonts to a specific local folder and then specify that font’s full directory in the PIL code as well. Both ways should work fine.
Here is a quick explanation of font families:
- Serif : Serifs are the little pieces and tails attached to characters in a font. Serif font families appear authoritative and give a classic look to your text. They can be suitable for literature, legal and professional content.
- Sans Serif : Sans means “without” in French and Sans Serif are modern font families that give text a sleek, minimalist and modern look. Sans Serif fonts can be useful for tech, computer science, sports, fashion, gaming and any other content where author wishes to have a modern look.
- Handwriting : Self-explanatory handwriting fonts can be used for decorative text elements.
- Display : Display fonts are suitable for large size applications such as posters and big displays, big slogans, big titles etc.
- Monospace : Every character has the same width. Useful for environments without graphic servers such as computer terminals.
This is a quick rundown of font families and of course you can mix and match different font families and get as creative as you wish with fonts.
file_dir='/home/usa/Downloads/Wallpaperz/' file_name='billy-williams-8wz1Q4Q_XAg-unsplash.jpg' img = Image.open(file_dir+file_name) draw = ImageDraw.Draw(img) text1 = "100" text2 = 'Python' text3 = 'Tips & Tricks' font1 = ImageFont.truetype('Cantarell-VF.otf', 280) font2 = ImageFont.truetype('Inconsolata-Light.ttf', 280) font3 = ImageFont.truetype('Sacramento-Regular.ttf', 280) draw.text((140, 100), text1, font=font1, fill='black') draw.text((540, 120), text2, font=font2, fill='gray') draw.text((140, 520), text3, font=font3, fill='yellow') img.show()
Как правильно рассчитать размер текста в изображениях PIL
PIL — отличный пакет для создания и редактирования изображений в Python. Однако у него есть одна проблема — вычисление размера текста. Итак, сегодня я собираюсь показать вам короткий скрипт Python, используемый для рисования правильно центрированного текста в изображениях, созданных с помощью PIL.
Эта проблема
К сожалению, метод textsize интерфейса рисования не возвращает правильный размер текста строки.
Например, с этим образцом кода
img = Image.new("RGB", (width, height), color="white") draw_interface = ImageDraw.Draw(img) size_width, size_height = draw_interface.textsize("some string", font)
Решение
Итак, решение состоит в том, чтобы использовать разные вычисления для размера текста. Следуя решению, опубликованному в этой ветке переполнения стека (с некоторыми изменениями), я получил функцию, указанную ниже.
Теперь позвольте мне попытаться объяснить код.
Заимствуя приведенное выше изображение из этого потока Stack Overflow, я начинаю с получения некоторых показателей шрифта с помощью font.getmetrics . Возвращает подъем и спуск, то есть согласно документации PIL
«Расстояние от базовой линии до самой высокой точки контура» и «расстояние от базовой линии до самой нижней точки контура, отрицательное значение»
Другими словами, font.getmetrics возвращает кортеж с красной и синей областями этого изображения соответственно.
Черный прямоугольник задается параметром font.getmask(text_string).getbox() , который возвращает кортеж из четырех элементов: горизонтальное смещение, вертикальное смещение, ширина прямоугольника и высота прямоугольника.
Теперь, когда у нас есть спуск и размеры черного прямоугольника, высота определяется как:
font.getmask(text_string).getbox()[3] + descent
font.getmask(text_string).getbox()[2]
Это означает, что высота рассчитывается путем суммирования высоты всех областей в этом изображении, а ширина — это просто ширина черного прямоугольника.
Практический пример
Наконец, давайте применим полученные знания для создания изображения PIL с центрированным текстом.
get_y_and_heights — это адаптация функции get_text_dimensions из предыдущего кода. Таким образом, функции возвращают вертикальную координату, с которой начинается рисование текста, а также список высот каждой текстовой строки. И поскольку эта новая функция также возвращает список с высотой каждой строки, я также добавил вертикальное поле к вычислениям высоты. Таким образом, при прохождении по строкам текста для их рисования (строки с 55 по 65) можно добавить высоту текста в переменную y , чтобы найти следующую вертикальную координату.
Остальная часть кода представляет собой стандартный код для создания нового изображения PIL и рисования на нем текста.
Заключение
Надеюсь, этот код будет полезен для вашей будущей работы с PIL. Все эти текстовые метрики все еще сбивают меня с толку, и то, что они не включены в документацию PIL, не помогает (а именно функция getbox ).
В любом случае, я думаю, что это хорошее решение, которое достигает цели: правильно рассчитывать размер текста строки, нарисованной с помощью определенного шрифта.
Как обычно, код для этой статьи доступен в моем репозитории GitHub.
Для дополнительного чтения я рекомендую ознакомиться с публикацией блога Essential Pillow (Pillow) Image Tutorial (for Machine Learning People), где подробно описаны функции PIL.