我目前正在编写一个程序,可以在课程完成时打印证书。证书采用
.png
格式,我使用 Pandas 从 Excel 电子表格中读取人员姓名,然后将该姓名写在 .png
图像证书上。
我遇到的问题是某些学生姓名的长度,我希望我的程序能够调整字体大小以适合自动提供的空间中的学生姓名。
我有在
.png
图像上开始写入文本的位置(以像素为单位)以及文本应结束的坐标。理想情况下我想:
任何人都可以建议解决这个问题的最佳方法吗?
示例代码:
im = Image.open("C:\\Documents\\Certificate\\Effort.png")
d = ImageDraw.Draw(im)
Start_location = (553, 3023)
d.text(Start_location, "Test User")
上面的代码从我指定的位置开始(从 A4 纸的左侧开始),但它没有居中对齐,因此右侧有很多空间,尤其是在名称很短的情况下。
我用下面的代码尝试了它,并且成功了。我从 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')