carokann17
carokann17

Reputation: 391

Python pillow/PIL doesn't recognize the attribute "textsize" of the object "imagedraw"

I already checked python version on my environment (sublime text) and it is 3.11.0, the latest, I checked pillow version which is 10.0.0, the latest, and my code looks similar to other examples online.

the code has a part in Italian, but its pretty understandable.

the problem is at "disegno.textsize(testo, font=font)

after I run the code:

line 14, in metti_testo_su_sfondo
    text_width, text_height = disegno.textsize(testo, font=font)
                              ^^^^^^^^^^^^^^^^
AttributeError: 'ImageDraw' object has no attribute 'textsize'

its strange because imagedraw should have the textsize attribute. I'm a novice, I hope I didn't miss anything blatant


from PIL import Image, ImageDraw, ImageFont

def metti_testo_su_sfondo(testo, sfondo, posizione=(10, 10), colore_testo=(0, 0, 0), dimensione_font=25):
# Apri l'immagine dello sfondo
immagine_sfondo = Image.open(sfondo)


disegno = ImageDraw.Draw(immagine_sfondo)


font = ImageFont.truetype("ARIAL.TTF", dimensione_font)


text_width, text_height = disegno.textsize(testo, font=font)

# Calcola le coordinate del testo centrato
x = (immagine_sfondo.width - text_width) // 2
y = (immagine_sfondo.height - text_height) // 2


disegno.text((x, y), testo, fill=colore_testo, font=font)


immagine_sfondo.save("spotted.png")


testo_da_inserire = "Ciao, mondo!"
sfondo_da_utilizzare = "spotted_bianco.jpg" 

metti_testo_su_sfondo(testo_da_inserire, sfondo_da_utilizzare)

The objective is a code that makes me images automatically without needing to edit them manually. I checked build system, python version and pillow version. when I run the code through cmd though it gives me this error:

from PIL import Image, ImageDraw, ImageFont
ModuleNotFoundError: No module named 'PIL'

Upvotes: 15

Views: 38984

Answers (7)

Kacper Podpora
Kacper Podpora

Reputation: 173

Several functions for computing the size and offset of rendered text have been removed in Pillow 10.0

Removed Use instead
FreeTypeFont.getsize() and FreeTypeFont.getoffset() FreeTypeFont.getbbox() and FreeTypeFont.getlength()
FreeTypeFont.getsize_multiline() ImageDraw.multiline_textbbox()
ImageFont.getsize() ImageFont.getbbox() and ImageFont.getlength()
TransposedFont.getsize() TransposedFont.getbbox() and TransposedFont.getlength()
ImageDraw.textsize() and ImageDraw.multiline_textsize() ImageDraw.textbbox(), ImageDraw.textlength() and ImageDraw.multiline_textbbox()
ImageDraw2.Draw.textsize() ImageDraw2.Draw.textbbox() and ImageDraw2.Draw.textlength()

In your case, according to the docs, correct code will be:

font = ImageFont.truetype("ARIAL.TTF", dimensione_font)
left, top, right, bottom = font.getbbox("testo")
width, height = right - left, bottom - top

But if you want to preserve pixel-perfect results between pillow versions, you have to acknowledge the fact that previous size methods returned a height that included the vertical offset:

In bbox methods, top measures the vertical distance above the text, while bottom measures that plus the vertical distance of the text itself. In size methods, height also measures the vertical distance above the text plus the vertical distance of the text itself.

So if you want to use inaccurate height from previous version, you shouldn't subtract top variable from bottom:

font = ImageFont.truetype("ARIAL.TTF", dimensione_font)
left, _, right, bottom = font.getbbox("testo")
width, height = right - left, bottom

Source: https://pillow.readthedocs.io/en/stable/deprecations.html

Upvotes: 0

carokann17
carokann17

Reputation: 391

textsize was deprecated, the correct attribute is textlength which gives you the width of the text. for the height use the fontsize * how many rows of text you wrote.

Example code:

w = draw.textlength(text, font=font)
h = fontSize * rows

Upvotes: 24

Ik32
Ik32

Reputation: 61

Use textlength instead.

Here is the example

from PIL import Image, ImageDraw,  ImageFont 
text='TEST'
font_size=16
font = ImageFont.truetype(r"path\OpenSans-Bold.ttf", font_size)
draw = ImageDraw.Draw(your_img)
textheight = font_size
textwidth = draw.textlength(text,font)  # don't forget to add font

Upvotes: 5

dust
dust

Reputation: 29

pip install pillow==9.5.0

version=9.5.0

It can still be used, but a warning will appear Use textbbox or textlength instead.

  c_width, c_height = draw.textsize(c, font=font)

Upvotes: 2

Luis Enrique Dalmau
Luis Enrique Dalmau

Reputation: 31

You can also use the font.getbbox(text) and it will returned a 4 element tuple (x1,y1,x2,y2)

width , heigth = (x2-x1, y2-y1)

Upvotes: 1

Hinson Chan
Hinson Chan

Reputation: 333

As other answers have mentioned, textsize is deprecated. There is no textheight, but you can use textlength.

If you just want a function that can test a given text and font pair, you can do something like this with textbbox:

def textsize(text, font):
    im = Image.new(mode="P", size=(0, 0))
    draw = ImageDraw.Draw(im)
    _, _, width, height = draw.textbbox((0, 0), text=text, font=font)
    return width, height

Which should work the same way.

Upvotes: 15

Tim Roberts
Tim Roberts

Reputation: 54767

It's no longer called textsize, it's called textlength.

Upvotes: 7

Related Questions