我将如何计算在 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
。
我正在尝试制作一个 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
。