如何根据可用空间调整字体文本并居中

问题描述 投票:0回答:1

我目前正在编写一个程序,可以在课程完成时打印证书。证书采用

.png
格式,我使用 Pandas 从 Excel 电子表格中读取人员姓名,然后将该姓名写在
.png
图像证书上。

我遇到的问题是某些学生姓名的长度,我希望我的程序能够调整字体大小以适合自动提供的空间中的学生姓名。

我有在

.png
图像上开始写入文本的位置(以像素为单位)以及文本应结束的坐标。理想情况下我想:

  1. 从中间开始写学生的名字,这样名字的对齐方式也在中间
  2. 调整空间名称的字体大小

任何人都可以建议解决这个问题的最佳方法吗?

示例代码:

 im = Image.open("C:\\Documents\\Certificate\\Effort.png")
 d = ImageDraw.Draw(im)
 Start_location = (553, 3023)
 d.text(Start_location, "Test User")

上面的代码从我指定的位置开始(从 A4 纸的左侧开始),但它没有居中对齐,因此右侧有很多空间,尤其是在名称很短的情况下。

python image text python-imaging-library
1个回答
0
投票

我用下面的代码尝试了它,并且成功了。我从 BeFonts 下载了字体,从 Activity Shelter 下载了空证书,并使用 Behind the Name 生成了名称。

import os.path

from PIL import Image, ImageDraw, ImageFont
from PIL.ImageFont import FreeTypeFont

CUR_DIR = os.path.dirname(__file__)
BASE_DIR = os.path.dirname(os.path.dirname(CUR_DIR))
DATA_DIR = os.path.join(BASE_DIR, 'data', 'stack_overflow')
PATH_TO_EMPTY_CERTIFICATE = os.path.join(DATA_DIR, 'certificate.png')

MAX_WIDTH = 1000  # Hardcoded value to fit comfortably on the certificate
SIGNING_Y = 590  # Hardcoded value to place it just above the line


def name_to_code(name: str) -> str:
    result = ''.join([c.lower() if c.isalnum() else '_' for c in name])
    while '__' in result:
        result = result.replace('__', '_')
    return result.strip('_')


def sign_certificate(name: str):
    # Load the empty certificate and the font
    img = Image.open(PATH_TO_EMPTY_CERTIFICATE)
    draw = ImageDraw.Draw(img)
    font_file = os.path.join(DATA_DIR, 'fonts', 'cs-verity-font-1722652677-0',
                             'CSVerity-Regular_demo-BF66ab0975c331d.otf')

    # Define the correct font size for the text to fit on the certificate
    font_size = 73
    text_width = 1E9  # A very large number, to ensure we enter the while-loop below
    text_bbox: tuple[float, float, float, float] = (0, 0, 0, 0)
    font: FreeTypeFont | None = None
    print(f'Trying to fit {name} on the certificate...')
    while text_width > MAX_WIDTH:
        font_size -= 1
        font = ImageFont.truetype(font_file, font_size)
        text_bbox = font.getbbox(name)
        text_width = text_bbox[2] - text_bbox[0]
        print('Font size:', font_size, 'Text width:', text_width)
    text_height = text_bbox[3] - text_bbox[1]

    # Calculate the position of the text
    x = (img.width - text_width) / 2
    y = SIGNING_Y - text_height

    # Draw the text on the image
    draw.text((x, y), name, font=font, fill='black')

    # Save the signed certificate
    code = name_to_code(name)
    output_file = os.path.join(DATA_DIR, f'certificate_{code}.png')
    img.save(output_file)


if __name__ == '__main__':
    sign_certificate('Chione Reva')
    sign_certificate('Bora Ramadevi Bernadett Gizella Mac an Ghoill')

Empty certificate Certificate with short name Certificate with long name

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.