98 行
4.0 KiB
Python
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")
|