Прямоугольники вместо текста при использовании нестандартных шрифтов

Мне нужно вставлять имена пользователей на изображение, порой у них бывают имена с "нестандартными" шрифтами, из-за чего вместо текста появляются прямоугольники. Смена шрифта не помогла.

Вот код:

from PIL import Image, ImageFont, ImageDraw
import discord

size_card = (885, 215) 
сolor_card = (30, 30, 30)

font3 = ImageFont.truetype("files/img/calibri.ttf", 38)
card = Image.new("RGB", size_card, color_card)
draw = ImageDraw.Draw(card)
user = discord.Member

draw.text((239, 98), f"{str(user.name)} #{str(user.discriminator)}", (255, 255, 255), font=font3)

Ответы (2 шт):

Автор решения: MaxU

Ваш код работает правильно:

from collections import namedtuple
from PIL import Image, ImageFont, ImageDraw

User = namedtuple('User', 'name discriminator')

user = User(name="Jonh", discriminator=123)

size_card = (885, 215)
color_card = (30, 30, 30)

font3 = ImageFont.truetype("files/img/calibri.ttf", 38)
card = Image.new("RGB", size_card, color_card)
draw = ImageDraw.Draw(card)
draw.text((239, 98), f"{str(user.name)} #{str(user.discriminator)}", (255, 255, 255), font=font3)

card.show()

PS для воспроизведения, я создал объект user с типом namedtuple с соответствующими полями

результат:

введите сюда описание изображения


UPD: вырезка из docstring для метода ImageFont.truetype(font, size, ...):

:param font: A filename or file-like object containing a TrueType font.
             If the file is not found in this filename, the loader may also
             search in other directories, such as the :file:`fonts/`
             directory on Windows or :file:`/Library/Fonts/`,
             :file:`/System/Library/Fonts/` and :file:`~/Library/Fonts/` on
             macOS.

Т.е. в качестве значения в параметр font вы должны передавать либо путь к файлу шрифта в OS либо file-object (указатель на открытый файл шрифта).

→ Ссылка
Автор решения: Fixator10

Немного ошибок терминологии: То что вы называете "шрифтами", является символами Unicode'а.

В вашем случае, шрифт (*.ttf-файл, в данном случае), не поддерживает указанных вами символов юникода (А если быть точнее - полноширинных символов).

Либо поменяйте шрифт на поддерживающий необходимые символы, либо проверяйте каждый символ на наличие в шрифте, и в случае его отсутствия, берите символ из другого шрифта. Например, через библиотеку fonttools:

def char_in_font(unicode_char, font):
    for cmap in font["cmap"].tables:
        if cmap.isUnicode():
            if ord(unicode_char) in cmap.cmap:
                return True
    return False

check_font = TTFont(font_path)  # font_path - путь к файлу шрифта на диске
for c in your_string:
    if char_in_font(c, check_font):
        ... # рисуем символ стандартным шрифтом
    else:
        ... # рисуем символ "аварийным" шрифтом

В качестве "аварийного" шрифта могу посоветовать Symbola

→ Ссылка