python - 如何在 Python PIL 中为绘制文本设置适当的线宽?

标签 python python-3.x python-imaging-library

我正在尝试使用 PIL 将文本绘制到具有任意分辨率的图像中。我现在的代码是引用下面两个问题的结果herehere .在这两个答案中,textwrap.wrap 的宽度值设置为:width=40。但是,任意更改参数 size_xsize_y 会导致图像范围过拟合或欠拟合。理想情况下,我需要一种方法将字体大小转换为 PIL 中的高度和宽度像素值,但我不确定该怎么做。这是我现在拥有的代码:

from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw 
import textwrap

size_x = 946 #This value can arbitrarily change
size_y = 300 #This value can arbitrarily change
font_size = 16 #This value can be adjusted to fit parameters of image if necessary

my_text = ['Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam scelerisque sapien convallis nisl facilisis, sed facilisis odio accumsan. Maecenas vel leo eu turpis porta dictum at vel neque. Donec sagittis felis non tellus lacinia facilisis. Vivamus vel nisi ullamcorper, feugiat lorem sagittis, pellentesque dolor. Curabitur est magna, feugiat ut nibh quis, blandit vestibulum nisl. Sed pulvinar condimentum purus et rutrum. Proin magna arcu, scelerisque at gravida ut, convallis quis orci. Mauris ipsum tortor, laoreet et leo ac, lacinia euismod tellus. Curabitur volutpat nisi a metus faucibus, vel iaculis nisl fermentum. Curabitur et orci id sapien porttitor dignissim at ac dolor. Donec nec mattis nisi. ']

tx = Image.new('RGB', (size_x, size_y),color=(255,255,255))
draw = ImageDraw.Draw(tx)

my_font = ImageFont.truetype('/Windows/Fonts/arial.ttf',size=font_size)
lines = textwrap.wrap(my_text[0], width = 130) #This width value needs to be set automatically
y_text = 0
for line in lines:
    width, height = my_font.getsize(line)
    draw.text((0, y_text), line, font = my_font, fill = (0,0,0))
    y_text += height

tx.show()

width=130 的示例图片填充得很好。

width = 130

width=200 的示例图像过度填充。

width = 200

最佳答案

PIL 的 textwrap.wrap() 采用 width 指定一行中的最大字符数。在我看来,这是糟糕的库设计,因为指定最大像素英寸 更有用。这很重要,因为您可能有一个以像素为单位的边界框,而可变宽度字体意味着字符数有点无用。

一种选择是使用固定宽度的字体。那么字数就是一个简单的除法。

另一种是搜索不会溢出您的框的最大宽度。我将其设置为二进制搜索,start=1end=len(string)pivot=(end+start)/2。 使用 width=pivot 进行换行,然后找到 max(font.getsize(line) for line in wrapping)

  • 如果 max 大于边界框,则向左递归。 (end=pivot)
  • 否则,重复 width=pivot+1。如果溢出,则您找到了最大宽度
  • 如果不是,则递归。 (开始=枢轴)

这通常不是最优的,因为个别行可能需要不同的换行宽度(因此我认为这个 API 很糟糕),但如果你正在做段落,那么它应该相当不错。

关于python - 如何在 Python PIL 中为绘制文本设置适当的线宽?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24021579/

相关文章:

python - 除了自变量之外,如何为 scipy.optimize.minimize 的目标函数提供额外的输入

python-3.x - 如何在 Python 3.5 上安装 Pillow?

Python PIL - 无法在 Windows 8 上使用 Python3.3 显示图片

python - 将 flask 请求/应用程序上下文复制到另一个进程

python - 仅将特定线程的标准输出重定向到文件

python - 如何在 aiomysql 中使用连接池

python-3.x - sqlite 将来自不同表的 2 个查询合并为一个

python - 当您使用 thumbnail() 然后 crop() 时,PIL 是否会在图像的底部边缘创建伪影?如果是这样,您的解决方法是什么?

python - 如何使用pygame识别PS4 Controller 上按下的是哪个按钮

python - 如何通过对列进行分区来高效地生成这个字典?