sas*_*nin 109
使用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")
Run Code Online (Sandbox Code Playgroud)
结果:
如果您的fontsize不同,请包含以下字体:
myFont = ImageFont.truetype("my-font.ttf", 16)
draw.textsize(msg, font=myFont)
Run Code Online (Sandbox Code Playgroud)
unu*_*tbu 60
下面是一些示例代码,它使用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')
Run Code Online (Sandbox Code Playgroud)
Sin*_*rus 18
应该注意Draw.textsize方法是不准确的.我正在处理低像素图像,经过一些测试,结果发现textize认为每个字符都是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")
Run Code Online (Sandbox Code Playgroud)
用于Edilio的链接.
ImageDraw.text的PIL 文档是一个很好的起点,但不要回答您的问题。
下面是如何将文本居中放置在任意边界框中的示例,而不是图像的中心。边界框定义为:(x1, y1)
= 左上角和(x2, y2)
= 右下角。
from PIL import Image, ImageDraw, ImageFont
# Create blank rectangle to write on
image = Image.new('RGB', (300, 300), (63, 63, 63, 0))
draw = ImageDraw.Draw(image)
message = 'Stuck in\nthe middle\nwith you'
bounding_box = [20, 30, 110, 160]
x1, y1, x2, y2 = bounding_box # For easy reading
font = ImageFont.truetype('Consolas.ttf', size=12)
# Calculate the width and height of the text to be drawn, given font size
w, h = draw.textsize(message, font=font)
# Calculate the mid points and offset by the upper left corner of the bounding box
x = (x2 - x1 - w)/2 + x1
y = (y2 - y1 - h)/2 + y1
# Write the text to the image, where (x,y) is the top left corner of the text
draw.text((x, y), message, align='center', font=font)
# Draw the bounding box to show that this works
draw.rectangle([x1, y1, x2, y2])
image.show()
image.save('text_center_multiline.png')
Run Code Online (Sandbox Code Playgroud)
是单行还是多行消息不再重要,因为 PIL 包含了align='center'
参数。但是,它仅适用于多行文本。如果消息是单行,则需要手动居中。如果消息是多行的,align='center'
则在后续行中为您工作,但您仍然必须手动将文本块居中。这两种情况在上面的代码中都得到了解决。
如果您使用的是PIL 8.0.0或更高版本,一个简单的解决方案:文本锚点
width, height = # image width and height
draw = ImageDraw.draw(my_image)
draw.text((width/2, height/2), "my text", font=my_font, anchor="mm")
Run Code Online (Sandbox Code Playgroud)
mm
意味着使用文本的中间作为锚,水平和垂直。
有关其他类型的锚定,请参阅锚点页面。例如,如果您只想水平居中,您可能需要使用ma
.
归档时间: |
|
查看次数: |
32834 次 |
最近记录: |