""" 生成 SSHClient 应用图标 - 深色圆角方块背景 - 终端窗口 + >_ 提示符 + SSH 连接线 输出: resources/icon.ico (多尺寸) + resources/icon.png (256x256) """ import os from PIL import Image, ImageDraw, ImageFont OUT_DIR = os.path.join(os.path.dirname(__file__), "resources") os.makedirs(OUT_DIR, exist_ok=True) SIZE = 256 def draw_icon(size: int) -> Image.Image: """绘制指定尺寸的图标""" img = Image.new("RGBA", (size, size), (0, 0, 0, 0)) d = ImageDraw.Draw(img) pad = int(size * 0.06) rect = [pad, pad, size - pad, size - pad] radius = int(size * 0.18) # 背景渐变(模拟,用两层半透明) d.rounded_rectangle(rect, radius=radius, fill=(30, 30, 46, 255)) # 上半部分亮色渐变 inner = [pad + 4, pad + 4, size - pad - 4, size // 2] d.rounded_rectangle(inner, radius=radius - 2, fill=(40, 40, 60, 255)) # 终端窗口 tw_margin = int(size * 0.16) tw_top = int(size * 0.20) tw_bottom = int(size * 0.78) tw_left = tw_margin tw_right = size - tw_margin tw_radius = int(size * 0.04) # 终端窗口阴影 shadow_offset = max(2, size // 64) d.rounded_rectangle( [tw_left + shadow_offset, tw_top + shadow_offset, tw_right + shadow_offset, tw_bottom + shadow_offset], radius=tw_radius, fill=(0, 0, 0, 60) ) # 终端窗口背景 d.rounded_rectangle( [tw_left, tw_top, tw_right, tw_bottom], radius=tw_radius, fill=(12, 12, 20, 255) ) # 终端标题栏 tb_height = int(size * 0.055) d.rounded_rectangle( [tw_left, tw_top, tw_right, tw_top + tb_height], radius=tw_radius, fill=(50, 50, 70, 255) ) # 底部直角覆盖(标题栏只有上面圆角) d.rectangle( [tw_left, tw_top + tb_height - tw_radius, tw_right, tw_top + tb_height], fill=(50, 50, 70, 255) ) # 三个小圆点(macOS 风格窗口按钮) dot_r = max(2, int(size * 0.016)) dot_y = tw_top + tb_height // 2 dot_start = tw_left + int(size * 0.04) dot_gap = int(size * 0.045) for i, color in enumerate([(239, 83, 80), (255, 167, 38), (102, 187, 106)]): cx = dot_start + i * dot_gap d.ellipse([cx - dot_r, dot_y - dot_r, cx + dot_r, dot_y + dot_r], fill=color) # >_ 提示符 cx = tw_left + int(size * 0.06) cy = tw_top + tb_height + int(size * 0.10) line_w = max(2, int(size * 0.022)) arrow_len = int(size * 0.08) gap = int(size * 0.02) # > 符号 d.line([cx, cy, cx + arrow_len, cy + arrow_len // 2], fill=(102, 187, 106), width=line_w) d.line([cx, cy + arrow_len, cx + arrow_len, cy + arrow_len // 2], fill=(102, 187, 106), width=line_w) # _ 光标 cursor_x = cx + arrow_len + gap cursor_w = int(size * 0.06) cursor_h = max(2, int(size * 0.018)) d.rounded_rectangle( [cursor_x, cy + arrow_len // 2 - cursor_h // 2, cursor_x + cursor_w, cy + arrow_len // 2 + cursor_h // 2], radius=max(1, cursor_h // 3), fill=(137, 180, 250) ) # SSH 连接线(底部装饰) line_y = tw_bottom + int(size * 0.05) if line_y < size - pad: # 连接节点 node_r = max(2, int(size * 0.012)) n1 = (tw_left + int(size * 0.04), line_y) n2 = (tw_right - int(size * 0.04), line_y) d.ellipse([n1[0]-node_r, n1[1]-node_r, n1[0]+node_r, n1[1]+node_r], fill=(137, 180, 250)) d.ellipse([n2[0]-node_r, n2[1]-node_r, n2[0]+node_r, n2[1]+node_r], fill=(137, 180, 250)) d.line([n1[0]+node_r, n1[1], n2[0]-node_r, n2[1]], fill=(137, 180, 250, 160), width=max(1, line_w // 2)) return img def main(): # 生成 256x256 主图 icon = draw_icon(SIZE) png_path = os.path.join(OUT_DIR, "icon.png") icon.save(png_path) print(f"Saved {png_path} ({SIZE}x{SIZE})") # 生成多尺寸 ICO(Pillow 自动从 256x256 缩放到各尺寸) sizes = [(16, 16), (24, 24), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)] ico_path = os.path.join(OUT_DIR, "icon.ico") icon.save(ico_path, format="ICO", sizes=sizes) print(f"Saved {ico_path} (sizes: {[s[0] for s in sizes]})") print("Done!") if __name__ == "__main__": main()