"""根据 bg.png 模板生成带姓名/账号/密码的邀请函图片""" from PIL import Image, ImageDraw, ImageFont import json import os DATA_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "data") BG_PATH = os.path.join(DATA_DIR, "bg.png") FONT_PATH = os.path.join(DATA_DIR, "WenDaoGeTeSong.ttf") OUTPUT_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "output", "invitations") # 文字位置配置(可通过 invitation_tuner.html 调整后粘贴回来) CONFIG = { "name": {"x": 582, "y": 1192, "size": 52, "color": "#ffd586"}, "account": {"x": 572, "y": 1293, "size": 44, "color": "#ffffff"}, "password": {"x": 575, "y": 1394, "size": 44, "color": "#ffffff"}, } def hex_to_rgb(hex_color): hex_color = hex_color.lstrip('#') return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4)) def generate_invitation(name, account, password, output_path=None): img = Image.open(BG_PATH).copy() draw = ImageDraw.Draw(img) fields = { "name": name, "account": account, "password": password, } for field_key, text in fields.items(): cfg = CONFIG[field_key] font = ImageFont.truetype(FONT_PATH, cfg["size"]) color = hex_to_rgb(cfg["color"]) # textAlign center + textBaseline top 对应 Pillow 的 anchor='mt' draw.text((cfg["x"], cfg["y"]), text, fill=color, font=font, anchor="mt") if not output_path: os.makedirs(OUTPUT_DIR, exist_ok=True) safe_name = name.replace("/", "_").replace("\\", "_") output_path = os.path.join(OUTPUT_DIR, f"invite_{safe_name}.png") img.save(output_path, quality=95) return output_path if __name__ == "__main__": import argparse parser = argparse.ArgumentParser() parser.add_argument("--name", default="测试用户") parser.add_argument("--account", default="20250580") parser.add_argument("--password", default="123456") parser.add_argument("--output", default=None) args = parser.parse_args() path = generate_invitation(args.name, args.account, args.password, args.output) print(f"Generated: {path}") print(f"Font: {FONT_PATH}")