我将如何计算在 PIL 中的 2 个绘制句子之间保持 space 所需的 X 坐标?

How would I calculate the X coordinate required to keep space between 2 drawn sentences in PIL?

我正在尝试制作一个 Python 脚本来生成虚假的 Discord 消息,这是我目前的代码:

from PIL import Image, ImageFont, ImageDraw

text = "Hello"
name = "A username...."
date = "Today at 10:30 AM"

comment = Image.open("message.png")

text_font = ImageFont.truetype("whitneybook.otf", 31)
name_font = ImageFont.truetype("whitneymedium.otf", 32)
date_font = ImageFont.truetype("whitneymedium.otf", 25)
    
draw = ImageDraw.Draw(comment)

draw.text((129, 70), text, (215, 215, 215), font=text_font)
draw.text((129, 25), name, (250, 250, 250), font=name_font)
draw.text((356, 32), date, (120, 120, 120), font=date_font)

comment.show()

这是结果:

此代码有效,但我希望时间和名称能够是动态的。如果我将 name 变量更改为“一个很长的用户名”,我会得到这样的结果:

如何计算阻止用户名和日期重叠所需的 X 坐标?

字体对象有一个 getsize 方法,应该可以满足您的目的。无论如何,这可以解决您所有的问题。

在最简单的情况下,您只想找到日期的 x 坐标:

date_x = name_font.getsize(name)[0] + 129 + 32
draw.text((date_x, 32), date, (120, 120, 120), font=date_font)

date_x中文本的左偏移量为 129,名称-日期填充为 32。

现在您可能不想 运行 您的约会对象超出图像的边缘。事实上,假设您希望始终确保它有 10px 的右边距。在这种情况下,您可能需要通过在其他两行之间插入以下内容来稍微调整 x 坐标:

max_date_x = comment.width - 10 -  date_font.getsize(date)[0]
date_x = min(date_x, max_date_x)

最后,如果用户名超过一定长度,您可能想要 运行对其进行分类。这有点不那么琐碎,因为每个字母的大小都不同。您定位的 space 的数量是 date_x - 129,但也考虑了 t运行 名称后的省略号和一些填充。让我们做一个线性搜索:

name_width = name_font.getsize(name)[0]
name_space = date_x - 129 - 10
n = 0
while name_width > name_space:
    n += 1
    name_width = name_font.getsize(name[:-n] + '...')
display_name = name[:-n] + '...' if n else name

您可以通过二分查找 n 的正确值来做同样的事情。不要忘记在此版本中绘制 display_name 而不是 name