You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决PIL中ImageDraw绘制文本超出期望长度的问题

解决方案

Pillow的ImageDraw.text()没有内置自动换行参数,你可以通过调用文本宽度测量方法实现自动换行,实现逻辑简单,不需要手动统计字符数量:

实现思路

  • 预设文本最大展示宽度(可根据你的画布需求自定义,比如设置为图片宽度减左右边距)
  • 将文本按空格拆分为单词(如果是中文可以直接拆分为单个字符)
  • 逐词拼接当前行,每次拼接前计算拼接后文本的总宽度,超过最大宽度则换行存储当前行,从下一行开始拼接当前单词
  • 逐行绘制文本,每行的Y坐标按行高递进,行高可通过字体属性直接获取

可直接运行的修改后代码

from PIL import Image, ImageDraw, ImageFont

# 导入图片
picture = Image.open("examplefile.png")
d1 = ImageDraw.Draw(picture)
myFont = ImageFont.truetype('./Roboto/Roboto-Medium.ttf', 50)
text = "Lorem ipsum dolor sit amet quod voluptas illum illo quas at inventore eos nostrum. Voluptatem commodi dignissimos sed consequatur. Rerum qui numquam nobis quo distinctio."

# 自定义配置:文本最大宽度、起始绘制坐标、行间距系数
max_width = 800  # 这里改成你需要的预设宽度
start_x = 0
start_y = 0
line_spacing = 1.2  # 行高为字体大小乘以该系数,可调整

# 自动换行处理
lines = []
current_line = ""
for word in text.split():
    # 测试拼接当前单词后的宽度
    test_line = current_line + word + " "
    test_width = d1.textlength(test_line, font=myFont)
    if test_width <= max_width:
        current_line = test_line
    else:
        lines.append(current_line)
        current_line = word + " "
# 加入最后一行
lines.append(current_line)

# 逐行绘制文本
y_offset = start_y
font_height = myFont.getmetrics()[0]
for line in lines:
    d1.text((start_x, y_offset), line, fill=(0, 0, 0), font=myFont)
    y_offset += font_height * line_spacing

# 保存测试
picture.save("output.png")

补充说明

如果需要处理中英混合文本,只需要调整拆分逻辑,中文部分按单字符拆分、英文按单词拆分即可,测量宽度的逻辑通用。

内容的提问来源于stack exchange,提问作者EncryptEx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 08:30:02