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

使用Pillow实现多行文本居中且不超出1080x1080图像

问题

我正在开发一个Sigma Male表情包生成器,需求是将预设的Sigma Male段子/语录叠加到1080x1080固定尺寸的Sigma Male图像上,格式要求:

  • 居中显示一行Sigma-Male Rule #X标题
  • 标题下方展示搞笑生活建议(比如Don't be part of the problem, be the whole problem)

目前遇到的问题:添加生活建议文本时容易超出图像范围,手动换行能解决但无法自动化。希望实现自动换行+多行文本居中,同时单行段子也能相对于标题保持合适的居中位置。

原代码:

import numpy as np
import cv2
from PIL import Image, ImageDraw, ImageFont
import textwrap

my_image = Image.open("Bateman1Raw resized.jpg")
title_font = ImageFont.truetype('Bebas-Regular.ttf', 100)

title_text = "Sigma Male Rule #1"
text_test='Don\'t be part of the\n problem, be the whole problem'


image_editable = ImageDraw.Draw(my_image)
image_editable.text((200,400), title_text, (255, 255, 255), font=title_font,stroke_width=2,stroke_fill='black')
image_editable.text((0,500), words,(255, 255, 255),align='center',font=title_font,stroke_width=2,stroke_fill='black')

my_image.save("result.jpg")
解决方案

核心思路是利用textwrap自动计算换行,结合PIL的文本尺寸计算功能,实现标题和正文的自动居中排版:

from PIL import Image, ImageDraw, ImageFont
import textwrap

# 加载固定尺寸图像
img = Image.open("Bateman1Raw resized.jpg")
img_width, img_height = img.size  # 1080x1080

# 设置字体(正文字号可按需调整,避免溢出)
title_font = ImageFont.truetype('Bebas-Regular.ttf', 100)
body_font = ImageFont.truetype('Bebas-Regular.ttf', 70)

# 文本内容
title_text = "Sigma Male Rule #1"
body_text = "Don't be part of the problem, be the whole problem"

draw = ImageDraw.Draw(img)

# --- 处理标题:水平居中 ---
title_bbox = draw.textbbox((0,0), title_text, font=title_font)
title_width = title_bbox[2] - title_bbox[0]
title_x = (img_width - title_width) // 2
title_y = 300  # 可根据视觉需求调整标题垂直位置
draw.text((title_x, title_y), title_text, (255,255,255), font=title_font, stroke_width=2, stroke_fill='black')

# --- 处理正文:自动换行+居中 ---
# 计算每行最大字符数(留20%左右的边距,避免贴边)
max_line_length = int(img_width * 0.8 / body_font.getsize('A')[0])
wrapped_text = textwrap.fill(body_text, width=max_line_length)

# 计算换行后正文的整体尺寸
body_bbox = draw.textbbox((0,0), wrapped_text, font=body_font)
body_width = body_bbox[2] - body_bbox[0]

# 正文位置:水平居中,垂直在标题下方预留间距
body_x = (img_width - body_width) // 2
body_y = title_y + (title_bbox[3] - title_bbox[1]) + 50  # 标题与正文间留50px间距

draw.text((body_x, body_y), wrapped_text, (255,255,255), font=body_font, stroke_width=2, stroke_fill='black', align='center')

img.save("result.jpg")

关键改进点:

  • 用textbbox准确计算文本宽高,替代老旧的getsize方法
  • 自动计算标题和正文的水平居中坐标,无需硬写固定值
  • 通过textwrap.fill根据图像宽度自动换行,完全实现自动化
  • 正文与标题的间距根据标题高度动态计算,保证排版一致性
  • 单独设置正文字号,进一步降低溢出风险(可根据需求调整)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 05:15:35