使用Pillow将长文本拆分为多行

3
我正在创建一个小型的Python程序,用于在一个128x48像素的小图片上绘制文本。对于宽度不超过120的文本,程序可以正常工作,但我无法想出如何将更长的文本拆分成另一行。该怎么做呢?
我尝试使用textwrap3,但是与Pillow协作时无法使其工作。
该程序会创建一个黑色背景和黄色居中文本的128x48像素图像文件,稍后将在输出高达480i的设备上查看,因此简单地让文本变得小得多以适应额外的文本宽度并没有帮助。目前使用的字体是Arial 18。
以下是用于创建图像的当前代码:
from PIL import Image, ImageDraw, ImageFont

AppName = "TextGoesHere"
Font = ImageFont.truetype('./assets/Arial.ttf', 18)
img = Image.new('RGB', (128, 48), color='black')
d = ImageDraw.Draw(img)

# Get width and height of text
w, h = d.textsize(AppName, font=Font)

# Draw text
d.text(((128-w)/2, (48-h)/2), AppName, font=Font, fill=(255, 255, 0))

img.save('icon.png')

上面的代码输出的图片如下所示:

一只忙碌的猫

文本长度超过图片宽度时,输出的结果如下(长文本在这里):

一只忙碌的猫

所需的结果应该类似于这样:

一只忙碌的猫


你的单词之间真的没有空格吗?那么怎么能让人们知道在哪里合理地分割它们呢?你是否考虑过改变字体大小以及跨越多行来排版呢? - Mark Setchell
2个回答

5
这里有一段使用PIL/Pillow进行二分搜索的代码,将文本分成适合的部分。
def break_fix(text, width, font, draw):
    if not text:
        return
    lo = 0
    hi = len(text)
    while lo < hi:
        mid = (lo + hi + 1) // 2
        t = text[:mid]
        w, h = draw.textsize(t, font=font)
        if w <= width:
            lo = mid
        else:
            hi = mid - 1
    t = text[:lo]
    w, h = draw.textsize(t, font=font)
    yield t, w, h
    yield from break_fix(text[lo:], width, font, draw)

def fit_text(img, text, color, font):
    width = img.size[0] - 2
    draw = ImageDraw.Draw(img)
    pieces = list(break_fix(text, width, font, draw))
    height = sum(p[2] for p in pieces)
    if height > img.size[1]:
        raise ValueError("text doesn't fit")
    y = (img.size[1] - height) // 2
    for t, w, h in pieces:
        x = (img.size[0] - w) // 2
        draw.text((x, y), t, font=font, fill=color)
        y += h

img = Image.new('RGB', (128, 48), color='black')
fit_text(img, 'LongerTextGoesHere', (255,255,0), Font)
img.show()

enter image description here


1
我有一个小问题,如果我想把这些文本块切成不同的行,同时最好在有空格的地方切割,以保留其含义。 - French Noodles
@FrenchNoodles 我按照问题的要求回答了。如果你有不同的问题,请提出来 - 如果需要,你可以参考这个问题。 - Mark Ransom

2

如果你使用安装在大多数Linux发行版上并且可以在macOS和Windows上使用的ImageMagick,那么你可以很容易地完成这项任务而无需编写任何Python代码。所以,在终端中输入:

convert -size 128x48 -background black -font Arial -fill yellow -gravity center caption:"Some Text" result.png

在此输入图片描述

或者,使用更长的文本字符串:

convert -size 128x48 -background black -font Arial -fill yellow -gravity center caption:"Some Really Really Long Text" result.png

enter image description here

如果您真的非常想写Python,Wand是一个用于ImageMagick的Python绑定,其中函数名称将与上述使用的名称相对应。


我更喜欢使用PIL或Pillow,以避免需要外部依赖。 - Guy Twig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接