Как измерить длину текста в PIL в пикселях?
Я генерирую изображения, используя библиотеку PIL. Мне надо сделать так, чтобы после текста, который может быть разной длины, на фиксированном расстоянии была картинка, а за ней на фиксированном расстоянии ещё текст. Подскажите, как грамотно это сделать? Может быть, есть встроенная функция для измерения предполагаемой длины текста без нанесения на холст?
Допустим, есть текст "1", тогда остальные элементы должны будут находиться на небольшом расстоянии от левой стенки. А может быть текст "12883626667255", тогда расстояние от края будет другим.
Ответы (2 шт):
В качестве основы для Вашей дальнейшей разработки. Скажу сразу, что pillow - слабенькая идея для решения такой задачи. pdf или html делают такие документы выглядящими куда более профессионально. Это видно по "работе" модуля pillow со шрифтами.
from PIL import Image, ImageDraw, ImageFont
# Задаем параметры изображения
v_width, v_height = 500, 400
v_image = Image.new("RGB", (v_width, v_height), "white")
v_draw = ImageDraw.Draw(v_image)
# Загружаем шрифт
v_font_path = "C:/Windows/Fonts/arial.ttf" # Проверьте путь к шрифту
v_font_size = 20
v_font = ImageFont.truetype(v_font_path, v_font_size)
# Задаем текст
v_text_top = ["Это первый текст,", "он занимает две строки."]
v_text_bottom = ["Это второй текст,", "который занимает три строки,", "чтобы всё выглядело аккуратно."]
v_image_path = "example.png"
v_spacing = 10
# Определяем высоту первого текста
v_text_top_position = (50, v_spacing)
v_text_top_height = sum(v_font.getbbox(line)[3] - v_font.getbbox(line)[1] for line in v_text_top)
# Определяем положение изображения
v_image_position = (50, v_text_top_position[1] + v_text_top_height + v_spacing)
# Открываем изображение
try:
v_img = Image.open(v_image_path)
v_img.thumbnail((100, 100))
v_image.paste(v_img, v_image_position)
v_image_height = v_img.size[1]
except FileNotFoundError:
print("Ошибка: Файл изображения не найден!")
v_image_height = 0
# Определяем положение второго текста сразу после изображения
v_text_bottom_position = (50, v_image_position[1] + v_image_height + v_spacing)
# Рисуем первый текст по строкам
v_y = v_text_top_position[1]
for line in v_text_top:
v_draw.text((50, v_y), line, fill="black", font=v_font)
v_y += v_font.getbbox(line)[3] - v_font.getbbox(line)[1]
# Рисуем второй текст по строкам
v_y = v_text_bottom_position[1]
for line in v_text_bottom:
v_draw.text((50, v_y), line, fill="black", font=v_font)
v_y += v_font.getbbox(line)[3] - v_font.getbbox(line)[1]
# Сохраняем и показываем изображение
v_output_path = "output.png"
v_image.save(v_output_path)
v_image.show()
Скрипт для определения длины текста:
from PIL import ImageFont
# Загружаем шрифт
v_font_path = "C:/Windows/Fonts/arial.ttf"
v_font_size = 20
v_font = ImageFont.truetype(v_font_path, v_font_size)
# Текст для измерения
v_text = "Пример текста"
# Определяем длину текста
v_text_width = v_font.getlength(v_text) # Новый метод (если поддерживается)
# Или:
v_bbox = v_font.getbbox(v_text)
v_text_width_bbox = v_bbox[2] - v_bbox[0] # Длина текста
print(f"Длина текста (getlength): {v_text_width} пикселей")
print(f"Длина текста (getbbox): {v_text_width_bbox} пикселей")
В документации нашёл методы textlength и getbbox
- textlength - возвращает длину в пикселях.
- getbbox - возвращает ограничивающую рамку (в пикселях). Что при желании легко можно перевести в ширину\высоту.
from PIL import Image, ImageDraw, ImageFont
width, height = 500, 400
image = Image.new("RGB", (width, height), "white")
draw = ImageDraw.Draw(image)
font = ImageFont.truetype("arial.ttf", 24)
text = "12883626667255"
text_width = draw.textlength(text, font=font)
print("Ширина", text_width)
bbox = font.getbbox(text)
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]
print("Ширина: ", text_width, " Высота: ", text_height)
Вывод:
Ширина 182.0
Ширина: 182 Высота: 17