文件
Henglianshutong/scripts/generate_hd_icons.py

98 行
4.0 KiB
Python

import os
from PIL import Image, ImageDraw, ImageFont, ImageFilter
font_song = "/System/Library/Fonts/Supplemental/Songti.ttc"
font_hei = "/System/Library/Fonts/STHeiti Medium.ttc"
font_hei_bold = "/System/Library/Fonts/Supplemental/Arial Unicode.ttf"
# 清新渐变配色方案
items = [
('menu_city_center', '市级', '运营', (68, 165, 255), (28, 118, 240), False),
('menu_city_partner', '市级', '合伙', (255, 115, 96), (235, 60, 68), False),
('menu_province_center', '省级', '服务', (58, 202, 148), (22, 160, 108), False),
('menu_province_partner', '省级', '合伙', (172, 118, 238), (128, 72, 210), False),
('menu_region_branch', '大区', '分公司', (252, 180, 68), (225, 132, 30), True),
]
def generate_icons(size=320, font_family="song"):
f_main_path = font_song if font_family == "song" else font_hei
f_sub_path = font_hei
font_main = ImageFont.truetype(f_main_path, 96)
font_sub = ImageFont.truetype(f_sub_path, 48)
font_sub_3 = ImageFont.truetype(f_sub_path, 42)
out_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '../public/uploads/decorate'))
os.makedirs(out_dir, exist_ok=True)
generated_images = []
for base_name, t1, t2, c1, c2, is_3 in items:
# 画布尺寸
img = Image.new('RGBA', (size, size), (0, 0, 0, 0))
# 1. 垂直柔和渐变底色
grad = Image.new('RGBA', (size, size))
for y in range(size):
r = y / float(size)
cr = int(c1[0] * (1 - r) + c2[0] * r)
cg = int(c1[1] * (1 - r) + c2[1] * r)
cb = int(c1[2] * (1 - r) + c2[2] * r)
for x in range(size):
grad.putpixel((x, y), (cr, cg, cb, 255))
# 2. 圆形遮罩(留 12px 边距防抗锯齿边缘裁切)
pad = 12
mask = Image.new('L', (size, size), 0)
m_draw = ImageDraw.Draw(mask)
m_draw.ellipse([pad, pad, size - pad, size - pad], fill=255)
img.paste(grad, (0, 0), mask)
d = ImageDraw.Draw(img)
# 3. 外层高光细环 + 内层细光环
d.ellipse([pad, pad, size - pad, size - pad], outline=(255, 255, 255, 230), width=6)
d.ellipse([pad + 16, pad + 16, size - pad - 16, size - pad - 16], outline=(255, 255, 255, 110), width=2)
# 4. 顶部晨光弧光
d.arc([pad + 20, pad + 20, size - pad - 20, size - pad - 20], start=210, end=330, fill=(255, 255, 255, 150), width=4)
# 5. 标题 1 居中绘制 (大字 96px)
bbox1 = d.textbbox((0, 0), t1, font=font_main)
w1 = bbox1[2] - bbox1[0]
h1 = bbox1[3] - bbox1[1]
y1 = 66
d.text(((size - w1) / 2.0, y1), t1, font=font_main, fill=(255, 255, 255, 255))
# 6. 标题 2 居中绘制 (大字 48px / 42px)
cur_sub_font = font_sub_3 if is_3 else font_sub
bbox2 = d.textbbox((0, 0), t2, font=cur_sub_font)
w2 = bbox2[2] - bbox2[0]
y2 = 192 if is_3 else 188
d.text(((size - w2) / 2.0, y2), t2, font=cur_sub_font, fill=(255, 255, 255, 245))
# 保存原文件名及 v2 版本文件名
p_base = os.path.join(out_dir, f"{base_name}.png")
p_v2 = os.path.join(out_dir, f"{base_name}_v2.png")
img.save(p_base)
img.save(p_v2)
generated_images.append((base_name, img))
print(f"Generated {p_base} and {p_v2} (size: {size}x{size})")
# 生成一条 5 个横排在一起的整体预览图 (5 * 320 = 1600 宽)
strip_w = size * len(items) + 80
strip_h = size + 60
strip = Image.new('RGBA', (strip_w, strip_h), (246, 248, 250, 255))
s_draw = ImageDraw.Draw(strip)
for idx, (name, icon) in enumerate(generated_images):
pos_x = 40 + idx * size
pos_y = 30
strip.paste(icon, (pos_x, pos_y), icon)
strip_path = os.path.join(out_dir, "fresh_hd_strip_preview.png")
strip.save(strip_path)
print(f"Preview strip saved to {strip_path}")
if __name__ == '__main__':
generate_icons(320, "song")