PIL如何根据图像大小调整文本大小

68 投票
4 回答
131893 浏览
提问于 2025-04-16 11:15

我正在尝试动态调整文本的大小,以便将其放置在不同但已知尺寸的图片上。这个文本会作为水印使用。有没有办法根据图片的尺寸来调整文本的大小?我并不要求文本覆盖整个表面,只要它足够明显,容易识别,并且不容易被去掉就可以。我在Linux上使用的是Python Imaging Library 1.1.7版本。

我希望能够设置文本大小与图片尺寸的比例,比如说1/10的大小之类的。

我一直在查看字体大小的属性来改变大小,但我在创建一个算法来调整它方面没有成功。我在想有没有更好的方法。

有什么想法可以帮我实现这个吗?

谢谢

4 个回答

12

一般来说,当你改变字体大小的时候,字体的变化并不是线性的,也就是说,字体的大小变化不会是均匀的。

非线性缩放

这种情况通常取决于软件、字体等等。这个例子来自于Typophile,使用的是LaTex和Computer Modern字体。正如你所看到的,字体的缩放并不是完全线性的。所以如果你在处理非线性字体缩放时遇到问题,我也不太确定该怎么解决,但有几个建议可以试试。

  1. 尽量把字体渲染到你想要的大小,然后通过常规的图像缩放算法来放大或缩小它……
  2. 接受它不会完全是线性缩放,然后尝试创建一个表格或算法,来选择最接近的字体大小,以便与图像大小匹配。
17

我知道这个问题已经被回答过了,之前有一个解决方案,我也用过。谢谢你,@Paul!

不过,每次增加一个字体大小的做法对我来说有点耗时(尤其是在我那台小服务器上)。比如说,像“小字”(比如“Foo”)这样的文本,处理起来大约需要1到2秒,具体取决于图片的大小。

为了加快这个过程,我调整了Paul的代码,让它像二分查找那样来寻找合适的字体大小。

breakpoint = img_fraction * photo.size[0]
jumpsize = 75
while True:
    if font.getsize(text)[0] < breakpoint:
        fontsize += jumpsize
    else:
        jumpsize = jumpsize // 2
        fontsize -= jumpsize
    font = ImageFont.truetype(font_path, fontsize)
    if jumpsize <= 1:
        break

这样做的话,它会不断增加字体大小,直到超过某个临界值,然后再根据情况上下调整(每次减少的幅度减半),直到找到合适的大小。

通过这种方式,我把步骤从200多减少到了大约10步,处理时间也从1-2秒缩短到了0.04到0.08秒。

这是对Paul代码的一个替代方案(适用于while语句和后面两行,因为在while中你已经得到了正确的字体大小)。

这个调整花了我几分钟时间,所以如果有任何改进建议,我会很感激!希望这能帮助到一些寻找更高效解决方案的人。

107

你可以不断增大字体大小,直到找到合适的大小。font.getsize() 是一个可以告诉你渲染后文本大小的函数。

from PIL import ImageFont, ImageDraw, Image

image = Image.open('hsvwheel.png')
draw = ImageDraw.Draw(image)
txt = "Hello World"
fontsize = 1  # starting font size

# portion of image width you want text width to be
img_fraction = 0.50

font = ImageFont.truetype("arial.ttf", fontsize)
while font.getsize(txt)[0] < img_fraction*image.size[0]:
    # iterate until the text size is just larger than the criteria
    fontsize += 1
    font = ImageFont.truetype("arial.ttf", fontsize)

# optionally de-increment to be sure it is less than criteria
fontsize -= 1
font = ImageFont.truetype("arial.ttf", fontsize)

print('final font size',fontsize)
draw.text((10, 25), txt, font=font) # put the text on the image
image.save('hsvwheel_txt.png') # save it

如果这样的方法对你来说效率不够高,你可以尝试实现一个寻找根的方法,但我觉得 font.getsize() 这个函数在你其他的图像编辑过程中算是小事一桩。

撰写回答