簡體   English   中英

使用 PIL 居中/居中對齊文本?

[英]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.textPIL 文檔是一個很好的起點,但不要回答您的問題。

下面是如何將文本居中放置在任意邊界框中的示例,而不是圖像的中心。 邊界框定義為: (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'會在后續行中為您工作,但您仍然必須手動將文本塊居中。 這兩種情況在上面的代碼中都得到了解決。

如果您使用的是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")

mm表示使用文本的中間作為錨點,水平和垂直。

有關其他類型的錨定,請參閱錨點頁面。 例如,如果您只想水平居中,您可能需要使用ma

您可以在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM