You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用Python的Pillow实现长文本按单词自动换行(避免侧边截断)

实现Pillow文本的单词自动换行(Word Wrap)

我之前也踩过Pillow文本截断的坑!默认的draw.text()只会在指定宽度处直接截断字符,完全不管单词完整性。要实现按单词换行的效果,我们可以自己封装一个文本处理函数,先把文本拆分成符合宽度要求的多行,再逐行绘制。

核心思路

  • 将原始文本按空格拆分为单词列表
  • 逐个累加单词,用draw.textlength()计算当前行的宽度
  • 当加入下一个单词会超过指定宽度时,就把当前行作为一行,开始新的一行
  • 额外处理单个单词超长的边界情况(避免一行完全放不下一个单词的尴尬)

完整代码示例

from PIL import Image, ImageDraw, ImageFont

def wrap_text(draw, text, font, max_width):
    # 拆分文本为单词列表
    words = text.split()
    if not words:
        return []
    
    wrapped_lines = []
    current_line = words[0]
    current_width = draw.textlength(current_line, font=font)
    
    for word in words[1:]:
        word_width = draw.textlength(word, font=font)
        # 计算加上当前单词和空格后的总宽度
        combined_width = current_width + draw.textlength(' ', font=font) + word_width
        
        if combined_width <= max_width:
            # 可以加入当前行,更新行内容和宽度
            current_line += ' ' + word
            current_width = combined_width
        else:
            # 超过宽度,先把当前行存入结果,开始新行
            wrapped_lines.append(current_line)
            current_line = word
            current_width = word_width
            
            # 处理单个单词超长的情况:强制拆分字符
            if current_width > max_width:
                temp_line = ''
                temp_width = 0
                for char in current_line:
                    char_width = draw.textlength(char, font=font)
                    if temp_width + char_width <= max_width:
                        temp_line += char
                        temp_width += char_width
                    else:
                        wrapped_lines.append(temp_line)
                        temp_line = char
                        temp_width = char_width
                wrapped_lines.append(temp_line)
                current_line = ''
                current_width = 0
    
    # 把最后一行加入结果
    if current_line:
        wrapped_lines.append(current_line)
    
    return wrapped_lines

# 测试示例
if __name__ == '__main__':
    # 创建空白图片
    img = Image.new('RGB', (400, 300), color='white')
    draw = ImageDraw.Draw(img)
    
    # 设置字体(可替换成你本地的字体路径,或用默认字体)
    try:
        font = ImageFont.truetype('arial.ttf', 20)
    except:
        font = ImageFont.load_default(size=20)
    
    # 需要绘制的长文本
    long_text = "When using the Pillow library in Python to write text, the default generated text will be truncated on the side. I need to achieve the effect of automatic truncation from the end of the word, that is, to implement the word wrap function."
    
    # 调用换行函数,指定最大宽度为380(留10px左右边距)
    wrapped_lines = wrap_text(draw, long_text, font, 380)
    
    # 逐行绘制文本,自定义行间距
    y_position = 20
    line_spacing = 25
    for line in wrapped_lines:
        draw.text((10, y_position), line, font=font, fill='black')
        y_position += line_spacing
    
    # 保存结果图片
    img.save('word_wrap_text.png')

关键细节说明

  • draw.textlength()是Pillow 9.1.0+新增的方法,用来计算文本宽度,比旧版的textsize()更准确(textsize()已被官方废弃)
  • 函数里额外处理了单个单词超长的场景,避免出现一行完全放不下一个单词的问题
  • 你可以根据需求调整line_spacing(行间距)和边距数值,让文本显示更美观

这样处理后,文本就会自动在单词末尾换行,再也不会出现截断半个单词的情况啦!

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

火山引擎 最新活动