首页 > 解决方案 > PIL(Pillow)getsize_multiline()在while循环中进入无限循环?

问题描述

为什么这几行代码会陷入死循环?这似乎是我的代码唯一可能有问题的部分,因为在将其注释掉后,其他一切都可以正常工作。

#Increase the font size till the text is just a little too wide
while selected_font.getsize_multiline(beautiful_text)[0] < (0.8 * img.size[0]):
    selected_font.size += 2

#If the text is too long, reduce the font size a little...
while selected_font.getsize_multiline(beautiful_text)[1] > (0.7 * img.size[1]):
    selected_font.size -= 2
    #..and then increase the number of characters per line till it's wide enough...
    while selected_font.getsize_multiline(beautiful_text)[0] < (0.8 * img.size[0]):
        wrapper.width += 2
        beautiful_text = wrapper.fill(input_text)
    #...rewrap the text, test again, and keep repeating till it sits well

我知道这selected_font.getsize_multiline(beautiful_text)是一个有效的调用,它返回一个元组,对于img.size. 增加字体大小后,文本框的宽度肯定会增加,那么为什么会导致无限循环呢?

标签: pythonpython-imaging-library

解决方案


我修复了这个错误。问题在于ImageFont.truetype('fontfile', size = desired_size) (在本例中为 object selected_font)返回的字体对象具有不可变的 size 属性。

selected_font = ImageFont.truetype('Arial.ttf', size = 20)
print(selected_font.size)       #output: 20
selected_font.size = 10         #doesn't raise an error
print(selected_font.size)       #output: 20

因此这一行不会更新我在循环中检查的变量

selected_font.size += 2         #does nothing, and raises no errors

更令人困惑的是,TextWrapper 模块的线宽变量确实具有可变大小属性

wrapper.width += 5              #works as you'd expect

不管怎样,我用这段代码解决了我的问题

fontsize = 10

while selected_font.getsize_multiline(beautiful_text)[1] > (0.7 * img.size[1]):
    fontsize -= 2
    selected_font = ImageFont.truetype("src/CaviarDreams.ttf", size = fontsize)

其他循环也是如此。


推荐阅读