feat: 沙香科技官网 v2.2 基线(深色科技风/双语/局域网+公网双部署)
This commit is contained in:
65
tools/gen_contact_avatar.py
Normal file
65
tools/gen_contact_avatar.py
Normal file
@@ -0,0 +1,65 @@
|
||||
# -*- 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}')
|
||||
Reference in New Issue
Block a user