Python Pillow实现文本精准居中问题求助:大字号下居中失效解决方案
解决PIL大字号文本无法精准居中的问题
我懂你这个痛点!大字号下直接用font_size计算居中位置真的不靠谱——不同字体、字重的字符实际占的空间和字号本身差异很大,尤其是像Helvetica Neu Bold这种粗体,偏差会特别明显。加上你用的draw.textsize()已经被PIL官方弃用了,这也是导致不准的原因之一。
下面是修正后的代码,能完美实现任何字号文本的精准居中:
from PIL import Image, ImageFont, ImageDraw # 图像尺寸 W, H = (2480, 1754) msg = "hello" bg_color = "yellow" font_name = 'Helvetica Neu Bold.ttf' font_size = 500 # 创建图像和绘图对象 im = Image.new("RGBA", (W, H), bg_color) draw = ImageDraw.Draw(im) # 加载字体 myFont = ImageFont.truetype(font_name, font_size) # 获取文本实际的边界框:返回 (left, top, right, bottom) 四个坐标 text_bbox = draw.textbbox((0, 0), msg, font=myFont) # 计算文本真实宽高 text_width = text_bbox[2] - text_bbox[0] text_height = text_bbox[3] - text_bbox[1] # 计算精准居中坐标 center_x = (W - text_width) / 2 center_y = (H - text_height) / 2 # 绘制文本 draw.text((center_x, center_y), msg, fill="black", font=myFont) im.save("hello.png", "PNG")
为什么这个方法靠谱?
textbbox()是PIL推荐的获取文本边界的方法,它会准确返回文本实际占据的矩形范围,不管字号多大、字体是什么,都能拿到真实的宽高数据- 用图像尺寸减去文本真实尺寸再除以2,得到的就是绝对居中的坐标,完全适配各种场景
额外:多行文本的居中处理
如果需要处理换行的文本,结合textwrap和multiline_textbbox()就能搞定多行文本的整体居中:
from PIL import Image, ImageFont, ImageDraw import textwrap W, H = (2480, 1754) msg = "Hello World!\nThis is multi-line text test" bg_color = "yellow" font_name = 'Helvetica Neu Bold.ttf' font_size = 200 im = Image.new("RGBA", (W, H), bg_color) draw = ImageDraw.Draw(im) myFont = ImageFont.truetype(font_name, font_size) # 自动换行处理 wrapped_text = textwrap.fill(msg, width=12) # 获取多行文本的整体边界框 multi_bbox = draw.multiline_textbbox((0, 0), wrapped_text, font=myFont) multi_width = multi_bbox[2] - multi_bbox[0] multi_height = multi_bbox[3] - multi_bbox[1] # 计算居中坐标 center_x = (W - multi_width) / 2 center_y = (H - multi_height) / 2 # 绘制多行文本,同时设置内部对齐为居中 draw.multiline_text((center_x, center_y), wrapped_text, fill="black", font=myFont, align="center") im.save("multiline_hello.png", "PNG")
这样不管是单行大字号还是多行文本,都能稳稳居中啦!
内容的提问来源于stack exchange,提问作者anamul




