如何使用PIL'ImageFont获取字体像素高度?

bin*_*ang 8 python fonts pillow

我正在使用PIL的ImageFont模块来加载字体以生成文本图像.我希望文本紧密绑定到边缘,但是,当使用ImageFont获取字体高度时,它似乎包含了角色的填充.正如红色矩形所示.在此输入图像描述

c = 'A'
font = ImageFont.truetype(font_path, font_size)
width = font.getsize(c)[0]
height = font.getsize(c)[1]
im = Image.new("RGBA", (width, height), (0, 0, 0))
draw = ImageDraw.Draw(im)
draw.text((0, 0), 'A', (255, 255, 255), font=font)
im.show('charimg')
Run Code Online (Sandbox Code Playgroud)

如果我可以获得角色的实际高度,那么我可以跳过底部矩形中的边界行,这些信息可以从字体中得到吗?谢谢.

imo*_*mos 31

确切的大小取决于许多因素.我将向您展示如何计算不同的字体指标.

font = ImageFont.truetype('arial.ttf', font_size)
ascent, descent = font.getmetrics()
(width, baseline), (offset_x, offset_y) = font.font.getsize(text)
Run Code Online (Sandbox Code Playgroud)
  • 红色区域的高度: offset_y
  • 绿地高度: ascent - offset_y
  • 蓝色区域的高度: descent
  • 黑色矩形: font.getmask(text).getbbox()

希望能帮助到你.

  • 更正:`(宽度,高度),(offset_x,offset_y) = font.font.getsize(text)`。另外,“font.getmask(text)”将返回一个大小为“(width, height)”的图像,而“image_draw.text((0, 0), text, font)”基本上绘制了“mask”(由 `getmask` 返回),偏移量为 `(offset_x, offset_y)`。 (2认同)

Nul*_*ano 24

得票最高的答案已过时。Pillow 8.0.0 中有一个新功能:ImageDraw.textbbox。请参阅Pillow 8.0.0 中添加的其他与文本相关的功能的发行说明。

请注意ImageDraw.textsize, 、ImageFont.getsizeImageFont.getoffset已损坏,并且 不应用于新代码。这些已被具有更清晰 API 的新函数有效取代。有关详细信息,请参阅文档。

要获得整个字符串的紧密边界框,您可以使用以下代码:

from PIL import Image, ImageDraw, ImageFont
image = Image.new("RGB", (200, 80))
draw = ImageDraw.Draw(image)
font = ImageFont.truetype("arial.ttf", 30)

draw.text((20, 20), "Hello World", font=font)
bbox = draw.textbbox((20, 20), "Hello World", font=font)
draw.rectangle(bbox, outline="red")
print(bbox)
# (20, 26, 175, 48)

image.show()
Run Code Online (Sandbox Code Playgroud)

边界框示例


您可以将其与新的结合起来ImageDraw.textlength以获得每个字母的单独边界框:


from PIL import Image, ImageDraw, ImageFont
image = Image.new("RGB", (200, 80))
draw = ImageDraw.Draw(image)
font = ImageFont.truetype("arial.ttf", 30)

xy = (20, 20)
text = "Example"
draw.text(xy, text, font=font)

x, y = xy
for c in text:
  bbox = draw.textbbox((x, y), c, font=font)
  draw.rectangle(bbox, outline="red")
  x += draw.textlength(c, font=font)

image.show()
Run Code Online (Sandbox Code Playgroud)

字母边界框示例

请注意,这忽略了字距调整的影响。目前,基本文本布局的字距调整已被破坏,但 Raqm 布局可能会出现轻微的不准确情况。要解决此问题,您可以添加字母对的文本长度:

for a, b in zip(text, text[1:] + " "):
  bbox = draw.textbbox((x, y), a, font=font)
  draw.rectangle(bbox, outline="red")
  x += draw.textlength(a + b, font=font) - draw.textlength(b, font=font)
Run Code Online (Sandbox Code Playgroud)

  • 您(或某人)能否提供一个链接,解释为什么替代方案“被破坏”、以何种方式被破坏以及违反了哪些细节? (2认同)