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

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?



Solution 1:[1]

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

Solution 2:[2]

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

Solution 3:[3]

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()

Solution 4:[4]

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

Solution 5:[5]

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()

Solution 6:[6]

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)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Hugo
Solution 2 CivFan
Solution 3 Ale
Solution 4 Rick
Solution 5
Solution 6 prakashkc