如何用PIL实现文本居中对齐?
我该如何在使用PIL时让文字居中对齐(并且垂直居中)呢?
11 个回答
39
需要注意的是,Draw.textsize
这个方法并不准确。我在处理低像素的图片时,经过一些测试发现,textsize
认为每个字符都是6个像素宽,但实际上一个 I
字母最多只占2个像素,而一个 W
字母最少占8个像素(在我的情况下)。所以,根据我输入的文本,有时候它根本没有居中。不过,我想“6”可能是个平均值,所以如果你处理的是长文本和大图片,应该还是可以的。
但是,如果你想要真正准确的结果,最好使用你要用的字体对象的 getsize
方法:
arial = ImageFont.truetype("arial.ttf", 9)
w,h = arial.getsize(msg)
draw.text(((W-w)/2,(H-h)/2), msg, font=arial, fill="black")
就像在Edilio的链接中使用的那样。
88
这里有一段示例代码,它使用了textwrap这个工具来把一行很长的文字分成几段,然后用textsize
这个方法来计算每段文字的位置。
from PIL import Image, ImageDraw, ImageFont
import textwrap
astr = '''The rain in Spain falls mainly on the plains.'''
para = textwrap.wrap(astr, width=15)
MAX_W, MAX_H = 200, 200
im = Image.new('RGB', (MAX_W, MAX_H), (0, 0, 0, 0))
draw = ImageDraw.Draw(im)
font = ImageFont.truetype(
'/usr/share/fonts/truetype/msttcorefonts/Arial.ttf', 18)
current_h, pad = 50, 10
for line in para:
w, h = draw.textsize(line, font=font)
draw.text(((MAX_W - w) / 2, current_h), line, font=font)
current_h += h + pad
im.save('test.png')
222
弃用警告: textsize 这个功能已经被弃用,并将在 Pillow 10 版本中移除(2023-07-01)。请使用 textbbox 或 textlength 来代替。
使用 textbbox
来替代 textsize
的代码。
from PIL import Image, ImageDraw, ImageFont
def create_image(size, bgColor, message, font, fontColor):
W, H = size
image = Image.new('RGB', size, bgColor)
draw = ImageDraw.Draw(image)
_, _, w, h = draw.textbbox((0, 0), message, font=font)
draw.text(((W-w)/2, (H-h)/2), message, font=font, fill=fontColor)
return image
myFont = ImageFont.truetype('Roboto-Regular.ttf', 16)
myMessage = 'Hello World'
myImage = create_image((300, 200), 'yellow', myMessage, myFont, 'black')
myImage.save('hello_world.png', "PNG")
结果
使用 Draw.textsize
方法 来计算文本的大小,并相应地重新计算位置。
这里有一个例子:
from PIL import Image, ImageDraw
W, H = (300,200)
msg = "hello"
im = Image.new("RGBA",(W,H),"yellow")
draw = ImageDraw.Draw(im)
w, h = draw.textsize(msg)
draw.text(((W-w)/2,(H-h)/2), msg, fill="black")
im.save("hello.png", "PNG")
以及结果:
如果你的字体大小不同,可以像这样包含字体:
myFont = ImageFont.truetype("my-font.ttf", 16)
draw.textsize(msg, font=myFont)