[英]Center-/middle-align text with PIL?
使用 PIL 時如何居中對齊(和中間垂直對齊)文本?
使用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)
下面是一些示例代碼,它使用 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')
需要注意的是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 的鏈接中使用。
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')
是單行還是多行消息不再重要,因為 PIL 合並了align='center'
參數。 但是,它僅適用於多行文本。 如果消息是單行,則需要手動居中。 如果消息是多行的,則align='center'
會在后續行中為您工作,但您仍然必須手動將文本塊居中。 這兩種情況在上面的代碼中都得到了解決。
您可以在http://tools.jedutils.com/tools/center-text-image找到此實現
您可以使用該頁面在那里創建圖像,而不是自己實現例程,但使用的代碼也包含在頁面中。
在實際繪制文本對象之前,使用textsize
方法(請參閱文檔)確定文本對象的尺寸。 然后從適當的坐標開始繪制它。
這是在圖像中心添加文本的簡單示例
from PIL import Image, ImageDraw, ImageFilter
msg = "hello"
img = Image.open('image.jpg')
W, H = img.size
box_image = img.filter(ImageFilter.BoxBlur(4))
draw = ImageDraw.Draw(box_image)
w, h = draw.textsize(msg)
draw.text(((W - w) / 2, (H - h) / 2), msg, fill="black")
box_image.show()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.