"""一次性脚本:生成多尺寸 icon.ico(芯片轮廓 + 绿色对勾,蓝色 Material 风格)。 生成正确的多帧 ICO 文件(手工写 ICONDIR + PNG 帧),避免 PIL 的 ICO writer 只保留单帧的 bug。 """ import struct from io import BytesIO from pathlib import Path from PIL import Image, ImageDraw def make_base(size: int) -> Image.Image: """画一张 size×size 的图标 base image。""" img = Image.new("RGBA", (size, size), (0, 0, 0, 0)) draw = ImageDraw.Draw(img) # 圆角方形背景 + 垂直蓝色渐变 for y in range(size): t = y / size r = int(25 + (66 - 25) * t) g = int(118 + (165 - 118) * t) b = int(210 + (245 - 210) * t) draw.rectangle((0, y, size, y + 1), fill=(r, g, b, 255)) # 圆角裁切 mask = Image.new("L", (size, size), 0) ImageDraw.Draw(mask).rounded_rectangle( (0, 0, size - 1, size - 1), radius=int(size * 0.19), fill=255) img.putalpha(mask) # IC 芯片轮廓 s = size chip_box = (int(s * 0.265), int(s * 0.352), int(s * 0.735), int(s * 0.648)) line_w = max(2, int(s * 0.024)) draw.rectangle(chip_box, outline=(255, 255, 255), width=line_w) pin_w = max(2, int(s * 0.024)) pin_l = max(2, int(s * 0.047)) cx_left, cy_top, cx_right, cy_bot = chip_box chip_w = cx_right - cx_left chip_h = cy_bot - cy_top # 上下引脚(5 根) for i in range(5): x = cx_left + int(chip_w * (0.117 + 0.192 * i)) draw.rectangle((x - pin_w // 2, cy_top - pin_l, x + pin_w // 2, cy_top), fill=(255, 255, 255)) draw.rectangle((x - pin_w // 2, cy_bot, x + pin_w // 2, cy_bot + pin_l), fill=(255, 255, 255)) # 左右引脚(3 根) for i in range(3): y = cy_top + int(chip_h * (0.185 + 0.302 * i)) draw.rectangle((cx_left - pin_l, y - pin_w // 2, cx_left, y + pin_w // 2), fill=(255, 255, 255)) draw.rectangle((cx_right, y - pin_w // 2, cx_right + pin_l, y + pin_w // 2), fill=(255, 255, 255)) # 中心:绿色对勾 check_pts = [ (int(s * 0.359), int(s * 0.492)), (int(s * 0.453), int(s * 0.578)), (int(s * 0.648), int(s * 0.383)), ] check_w_max = max(3, int(s * 0.055)) for w in range(check_w_max, max(2, check_w_max - 6), -2): draw.line(check_pts, fill=(76, 175, 80, 255), width=w, joint="curve") # 白色细描边 draw.line(check_pts, fill=(255, 255, 255, 220), width=max(1, int(s * 0.008)), joint="curve") return img def write_ico(path: Path, sizes): """手工构造一个多帧 ICO 文件(每帧用 PNG 编码,Windows Vista+ 通用)。""" images_png = [] for sz in sizes: img = make_base(sz) buf = BytesIO() img.save(buf, format="PNG") images_png.append((sz, buf.getvalue())) with open(path, "wb") as f: # ICONDIR f.write(struct.pack("