Files
homepage/tools/gen_contact_avatar.py

66 lines
2.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
"""
生成 contact 公共邮箱头像:品牌深底 + 青→红渐变 @ 符号
视觉规范与官网一致(assets/css/style.css 的 --bg/--cyan/--brand)
用法: uv run --with pillow python3 tools/gen_contact_avatar.py
"""
from PIL import Image, ImageDraw, ImageFilter, ImageFont
SIZE = 512
BG = (7, 11, 22) # 官网 --bg-1
CYAN = (76, 195, 255) # 官网 --cyan
RED = (255, 61, 90) # 官网 --brand
OUT = 'assets/brand/contact-avatar.png'
# ---------- 背景:深底 + 左上青辉光 / 右下红辉光 ----------
bg = Image.new('RGB', (SIZE, SIZE), BG)
def glow_blob(box, blur):
blob = Image.new('L', (SIZE, SIZE), 0)
ImageDraw.Draw(blob).ellipse(box, fill=80)
return blob.filter(ImageFilter.GaussianBlur(blur))
bg.paste(Image.new('RGB', (SIZE, SIZE), CYAN), (0, 0), glow_blob((-220, -220, 240, 240), 100))
bg.paste(Image.new('RGB', (SIZE, SIZE), RED), (0, 0), glow_blob((SIZE - 240, SIZE - 240, SIZE + 220, SIZE + 220), 100))
# ---------- 对角渐变图(青 → 红),用作 @ 的填充色 ----------
c1, c2 = CYAN, RED
span = 2 * (SIZE - 1)
grad = Image.new('RGB', (SIZE, SIZE))
grad.putdata([
(
round(c1[0] + (c2[0] - c1[0]) * (x + y) / span),
round(c1[1] + (c2[1] - c1[1]) * (x + y) / span),
round(c1[2] + (c2[2] - c1[2]) * (x + y) / span),
)
for y in range(SIZE) for x in range(SIZE)
])
# ---------- 渲染 @ 文字 mask ----------
# macOS 西文字体按优先级找,@ 字形各字体差异不大
FONT_CANDIDATES = [
'/System/Library/Fonts/SFNS.ttf',
'/System/Library/Fonts/SFNSText.ttf',
'/System/Library/Fonts/Helvetica.ttc',
]
font_path = next((p for p in FONT_CANDIDATES if __import__('os').path.exists(p)), None)
if not font_path:
raise SystemExit('找不到可用系统字体: ' + ', '.join(FONT_CANDIDATES))
font = ImageFont.truetype(font_path, 400)
mask = Image.new('L', (SIZE, SIZE), 0)
ImageDraw.Draw(mask).text((SIZE // 2, SIZE // 2), '@', font=font, fill=255, anchor='mm')
# 自检:@ 必须真的渲染出来了,否则静默输出空底图
ink = sum(1 for v in mask.getdata() if v > 0)
ratio = ink / (SIZE * SIZE)
if not 0.05 < ratio < 0.45:
raise SystemExit(f'@ 渲染异常,墨迹占比 {ratio:.1%}(预期 5%~45%),检查字体 {font_path}')
bg.paste(grad, (0, 0), mask)
import os
os.makedirs(os.path.dirname(OUT), exist_ok=True)
bg.save(OUT, 'PNG', optimize=True)
print(f'完成: {OUT} {SIZE}x{SIZE} @{ratio:.0%} 字体={font_path}')