How I can load a font file with PIL.ImageFont.truetype without specifying the absolute path?

Question:

When I write the code in Windows, this code can load the font file just fine:

ImageFont.truetype(filename='msyhbd.ttf', size=30);

I guess the font location is registered in Windows registry.
But when I move the code to Ubuntu, and copy the font file over to /usr/share/fonts/, the code cannot locate the font:

 self.font = core.getfont(font, size, index, encoding)
 IOError: cannot open resource

How can I get PIL to find the ttf file without specifying the absolute path?

Asked By: NeoWang

||

Answers:

According to the PIL documentation, only Windows font directory is searched:

On Windows, if the given file name does not exist, the loader also looks in Windows fonts directory.

http://effbot.org/imagingbook/imagefont.htm

So you need to write your own code to search for the full path on Linux.

However, Pillow, the PIL fork, currently has a PR to search a Linux directory. It’s not exactly clear yet which directories to search for all Linux variants, but you can see the code here and perhaps contribute to the PR:

https://github.com/python-pillow/Pillow/pull/682

Answered By: Hugo

To me worked this on xubuntu:

from PIL import Image,ImageDraw,ImageFont

# sample text and font
unicode_text = u"Hello World!"
font = ImageFont.truetype("/usr/share/fonts/truetype/freefont/FreeMono.ttf", 28, encoding="unic")

# get the line size
text_width, text_height = font.getsize(unicode_text)

# create a blank canvas with extra space between lines
canvas = Image.new('RGB', (text_width + 10, text_height + 10), "orange")

# draw the text onto the text canvas, and use blue as the text color
draw = ImageDraw.Draw(canvas)
draw.text((5,5), u'Hello World!', 'blue', font)

# save the blank canvas to a file
canvas.save("unicode-text.png", "PNG")
canvas.show()

enter image description here

Windows version

from PIL import Image, ImageDraw, ImageFont

unicode_text = u"Hello World!"
font = ImageFont.truetype("arial.ttf", 28, encoding="unic")
text_width, text_height = font.getsize(unicode_text)
canvas = Image.new('RGB', (text_width + 10, text_height + 10), "orange")
draw = ImageDraw.Draw(canvas)
draw.text((5, 5), u'Hello World!', 'blue', font)
canvas.save("unicode-text.png", "PNG")
canvas.show()

The output is the same as above:

enter image description here

Answered By: PythonProgrammi

On mac, I simply copy the font file Arial.ttf to the project directory and everything works.

Answered By: Rick

There is a Python fontconfig package, whereby one can access system font configuration, The code posted by Jeeg_robot can be changed like so:

from PIL import Image,ImageDraw,ImageFont
import fontconfig

# find a font file
fonts = fontconfig.query(lang='en')
for i in range(1, len(fonts)):
    if fonts[i].fontformat == 'TrueType':
        absolute_path = fonts[i].file
        break

# the rest is like the original code:
# sample text and font
unicode_text = u"Hello World!"
font = ImageFont.truetype(absolute_path, 28, encoding="unic")

# get the line size
text_width, text_height = font.getsize(unicode_text)

# create a blank canvas with extra space between lines
canvas = Image.new('RGB', (text_width + 10, text_height + 10), "orange")

# draw the text onto the text canvas, and use black as the text color
draw = ImageDraw.Draw(canvas)
draw.text((5,5), u'Hello World!', 'blue', font)

# save the blank canvas to a file
canvas.save("unicode-text.png", "PNG")
canvas.show()
Answered By: Ale

On Mac I had some fonts in the project dependencies

$ find . -name *.ttf*
./venv/lib/python3.7/site-packages/werkzeug/debug/shared/ubuntu.ttf
./venv/lib/python3.7/site-packages/reportlab/fonts/Vera.ttf
./venv/lib/python3.7/site-packages/reportlab/fonts/VeraBI.ttf
./venv/lib/python3.7/site-packages/reportlab/fonts/VeraBd.ttf
./venv/lib/python3.7/site-packages/reportlab/fonts/VeraIt.ttf

so I passed in Vera like so

font = ImageFont.truetype(r'./venv/lib/python3.7/site-packages/reportlab/fonts/Vera.ttf', 50)

you can also get a font like this but the size was too small

font = ImageFont.load_default()
Answered By: Harry Moreno

In Windows 10 while using Visual code, i had to do as below to make it work.

font = ImageFont.truetype(os.environ['LOCALAPPDATA'] + "/Microsoft/Windows/Fonts/Dance Floor.ttf", 10)
Answered By: prakashkc