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

42

当我在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文件?


如果字体是TrueType(.ttf),你是否将其放置在/usr/share/fonts/ TrueType子目录中?我现在想尝试,但是我暂时无法访问Ubuntu机器。 - EML
6个回答

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

输出与上述相同:

enter image description here


15
根据PIL文档,只有Windows字体目录会被搜索:
在Windows上,如果给定的文件名不存在,加载器还会在Windows字体目录中查找。

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

所以你需要编写自己的代码来在Linux上搜索完整路径。
然而,Pillow,即PIL分支,目前有一个PR用于搜索Linux目录。目前还不清楚要搜索哪些目录适用于所有Linux变体,但是您可以在此处查看代码并可能为PR做出贡献:

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


4
看起来这个问题已在https://github.com/python-pillow/Pillow/pull/1054中得到解决,因此Linux和macOS会在没有绝对路径的情况下搜索字体。 - Russell Gallop
对于Windows操作系统 - 在Windows字体目录中安装字体。这样你的Python代码就可以开始工作了。 - Abhay Bh

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

3
这个包在更现代的Python 3版本上不起作用。我用3.10测试了你的示例,可惜它不再起作用了。这绝对不是一个坏答案。但我想留下这些信息以防有人卡住了。 - Willem Meints

4
在Mac上,我只需将字体文件Arial.ttf复制到项目目录中,一切都可以正常工作。

15
不好的想法。你有分发该字体的权利吗?每个应用程序都应该复制它使用的所有系统字体吗? - Tom Swirly
2
是的,为那种字体制作NFT并出售它。 - Artem Bernatskyi

1
在使用 Visual Code 时,我需要按照以下步骤才能使其在 Windows 10 上正常工作。
font = ImageFont.truetype(os.environ['LOCALAPPDATA'] + "/Microsoft/Windows/Fonts/Dance Floor.ttf", 10)

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

所以我像这样通过了维拉

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

您也可以获得这样的字体,但是它的尺寸太小了。
font = ImageFont.load_default()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接