PIL如何根据图像的大小缩放文本大小

Shp*_*gle 27 python fonts scaling image-manipulation python-imaging-library

我正在尝试动态缩放文本以放置在不同但已知尺寸的图像上.该文本将作为水印应用.有没有办法缩放与图像尺寸相关的文本?我不要求文本占据整个表面区域,只要足够可见,以便易于识别且难以移除.我正在使用Python Imaging Library 1.1.7版.在Linux上.

我希望能够设置文本大小与图像尺寸的比例,比如大小的1/10.

我一直在寻找字体大小属性来改变大小但我没有运气来创建算法来扩展它.我想知道是否有更好的方法.

有关如何实现这一目标的任何想法?

谢谢

Pau*_*aul 56

您可以只增加字体大小,直到找到合适的方式. font.getsize()是一个函数,告诉你渲染文本有多大.

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
Run Code Online (Sandbox Code Playgroud)

如果这对你来说效率不高,你可以实现一个根查找方案,但我猜测这个font.getsize()函数与其他图像编辑过程相比是小土豆.

  • `OSError:无法打开资源`。我必须先从某处下载字体吗? (7认同)
  • 嗨保罗,这就是诀窍.谢谢您的帮助 (4认同)

Nac*_*alb 10

我知道这是一个老问题,我也用过的解决方案已经回答了这个问题。谢谢,@保罗!

尽管每次迭代将字体大小增加 1 可能会很耗时(至少对于我在我可怜的小服务器上)。所以例如。小文本(如“Foo”)大约需要 1 - 2 秒,具体取决于图像大小。

为了解决这个问题,我调整了 Pauls 代码,使其搜索数字有点像二进制搜索。

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
Run Code Online (Sandbox Code Playgroud)

像这样,它增加字体大小,直到它高于断点,然后从那里向上和向下(每次向下将跳转大小减半)直到它具有正确的大小。

有了这个,我可以将步骤从大约 200+ 减少到大约 10,因此从大约 1-2 秒减少到 0.04 到 0.08 秒。

这是 Pauls 代码的直接替换(对于while语句及其后的 2 行,因为您已经在 中获得了正确的字体大小while

这是在几分钟内完成的,因此感谢任何改进!我希望这可以帮助一些正在寻找性能更好的友好解决方案的人。

  • `int(jumpsize / 2)` 可以替换为 `jumpsize // 2`。 (2认同)

Pha*_*aun 7

通常,当您更改字体大小时,它不会是字体大小的线性更改.

非线性缩放

现在这通常取决于软件,字体等......这个例子取自Typophile并使用LaTex + Computer Modern字体.正如您所看到的,它不完全是线性缩放.因此,如果您在使用非线性字体缩放时遇到问题,那么我不确定如何解决它,但有一个建议可能是.

  1. 将字体渲染为您想要的大小,然后通过常规图像缩放算法向上/向下缩放...
  2. 只是接受它不会完全是线性缩放并尝试创建某种表/算法,它将选择最接近的字体大小以匹配图像大小.