I'm trying to calculate the width and height of the glyphs in a monospaced font (which I'd expect to be consistent), but ImageFont.getsize()
returns different values given different single-character strings:
>>> from PIL import ImageFont
>>> font = ImageFont.truetype("consola.ttf", size=15)
>>> font.getsize(".")
(8, 12)
>>> font.getsize("@")
(9, 15)
ImageFont.getlength()
, on the other hand, does always return the same width for every character:
>>> font.getlength("@")
8.0
>>> font.getlength(".")
8.0
So what is getsize()
measuring, and why is it different to getlength()
?
From the ImageFont.py file:
getlength():
Returns length (in pixels with 1/64 precision) of given text when rendered in font with provided direction, features, and language. This is the amount by which following text should be offset. Text bounding box may extend past the length in some fonts, e.g. when using italics or accents. The result is returned as a float; it is a whole number if using basic layout.
getsize():
Returns width and height (in pixels) of given text if rendered in font with provided direction, features, and language.
The file explains the difference as:
Use :py:meth:
getlength()
to measure the offset of following text with 1/64 pixel precision.
What I understand from this is that getlength()
returns the offset (space) between the current text and the following text, while getsize()
returns the actual dimensions of the current (inputted) text.
From the Consola font family website:
... a monospaced font is specified. All characters have the same width ...
This means that each each character should be the same width, and each character should have the same space from the next. Which can be seen in the following script:
import PIL
from PIL import ImageFont
font = ImageFont.truetype("consola.ttf",size=15)
print(font.getsize("a"))
print(font.getsize("h"))
print(font.getsize("g"))
print(font.getsize("z"))
print(font.getsize("."))
print(font.getsize("@"))
print(font.getlength("a"))
print(font.getlength("h"))
print(font.getlength("g"))
print(font.getlength("z"))
print(font.getlength("."))
print(font.getlength("@"))
Which outputs:
(8, 12)
(8, 12)
(8, 15)
(8, 12)
(8, 12)
(9, 15)
8.0
8.0
8.0
8.0
8.0
8.0
Almost every character has a width of 8 and an offset of 8, however their heights were different because some had extending parts, such as the part of "g"" that extends down. The only exception to this is "@" which had a width of 9, and for that I have found no reason.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With