[Python] how to get the size of a text with line breaks with Pillow Python

Discussão em 'Python' iniciado por Stack, Abril 25, 2025.

  1. Stack

    Stack Membro Participativo

    I am trying to center a text inside a box using Pillow. I have followed the instructions in this stackoverflow post, which gives the desired result. However, if I add an line break between the words, the text does not get resized properly and it gets offcentered.

    Here an example of the code without the line break:

    title_text = "Hello World"

    img = Image.new(size=(400, 300), mode='RGB')
    draw = ImageDraw.Draw(img)
    font_path = "/content/Charlie don't surf.ttf"

    # draw white rectangle 200x100 with center in 200,150
    draw.rectangle((200-100, 150-50, 200+100, 150+50), fill='white')
    draw.line(((0, 150), (400, 150)), 'gray')
    draw.line(((200, 0), (200, 300)), 'gray')

    # find font size for text `"Hello World"` to fit in rectangle 200x100
    selected_size = 1
    for size in range(1, 150):
    title_font = ImageFont.FreeTypeFont(font_path, size=size)
    w, h = title_font.getsize(title_text)

    if w > 200 or h > 100:
    break

    selected_size = size

    # draw text in center of rectangle 200x100
    title_font = ImageFont.FreeTypeFont(font_path, size=selected_size)

    draw.text((200-(w//2), 150-h//2), title_text, fill='red', font=title_font)

    display(img)


    [​IMG]

    Note that the text is centered and resized as desired.

    But if I change title_text = "Hello World" to title_text = "Hello\nWorld" to add an line break. I get this:

    title_text = "Hello\nWorld"

    img = Image.new(size=(400, 300), mode='RGB')
    draw = ImageDraw.Draw(img)
    font_path = "/content/Charlie don't surf.ttf"

    # draw white rectangle 200x100 with center in 200,150
    draw.rectangle((200-100, 150-50, 200+100, 150+50), fill='white')
    draw.line(((0, 150), (400, 150)), 'gray')
    draw.line(((200, 0), (200, 300)), 'gray')

    # find font size for text `"Hello World"` to fit in rectangle 200x100
    selected_size = 1
    for size in range(1, 150):
    title_font = ImageFont.FreeTypeFont(font_path, size=size)
    w, h = title_font.getsize(title_text)

    if w > 200 or h > 100:
    break

    selected_size = size

    # draw text in center of rectangle 200x100
    title_font = ImageFont.FreeTypeFont(font_path, size=selected_size)

    draw.text((200-(w//2), 150-h//2), title_text, fill='red', font=title_font)

    display(img)


    [​IMG]

    Note that with the line break, the text is not properly resized and is also not centered. Apparently the .getsize() method does not handle line breaks well.

    I am using Pillow version 7.1.2 and running all this in a Google Colab Notebook (that is the reason why I am running display(img)).

    What can I do to fix this issue? My end goal is to use Python to create cards for a game. Some cards will have two words and other cards will have only one word. I would like my code to be able to resize and center the text regardless the number of words.

    Edit: After some test, I have noticed that .getsize() treats the string "Hello\nWorld" as a single line of text and not as two lines. My question could be: how to get the size of a text with line breaks?

    Continue reading...

Compartilhe esta Página