如何在不指定绝对路径的情况下使用PIL.ImageFont.truetype加载字体文件?

45 投票
7 回答
118791 浏览
提问于 2025-04-18 08:53

当我在Windows上写代码时,这段代码可以顺利加载字体文件:

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

我想字体的位置可能是在Windows的注册表里注册的。但是当我把代码移到Ubuntu上,并把字体文件复制到/usr/share/fonts/目录下时,代码却找不到这个字体:

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

我该怎么做才能让PIL找到这个ttf文件,而不需要指定绝对路径呢?

7 个回答

1

在Mac上,我在项目的依赖中有一些字体

$ 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

所以我这样传入了Vera字体

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

你也可以这样获取一种字体,但大小太小了

font = ImageFont.load_default()
4

在Mac电脑上,我只需把字体文件Arial.ttf复制到项目文件夹里,所有东西就都能正常工作了。

6

有一个叫做 Python fontconfig 的包,使用这个包可以访问系统的字体配置。Jeeg_robot 发的代码可以这样修改:

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

对我来说,这在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()

在这里输入图片描述

Windows版本

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

输出结果和上面的一样:

在这里输入图片描述

16

根据PIL的文档,只有Windows的字体目录会被搜索:

在Windows系统上,如果指定的文件名不存在,加载器会去Windows的字体目录找找。

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

所以在Linux上,你需要自己写代码来查找完整的路径。

不过,Pillow(PIL的一个分支)现在有一个请求,想要在Linux上搜索字体目录。现在还不太清楚要搜索哪些目录来适应所有的Linux版本,但你可以在这里查看代码,也许可以为这个请求贡献一些想法:

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

撰写回答