# -*- coding: utf-8 -*- """生成 Windows .ico 和安卓图标,用 _build/icon_source.png 作为源图。 原来是自己画一个蓝色圆角方块(lanremote.ui.make_icon_image)。 现在改成用作者给的那张图。 产物: windows/app.ico 给 PyInstaller android/res/drawable-{m,h,xh,xxh,xxx}dpi/ic_launcher.png (并删掉旧的矢量 res/drawable/ic_launcher.xml,不然同名资源会冲突) 源图是方形线稿,安卓启动图标习惯留点边距,所以缩到 88% 再居中放。 """ from __future__ import annotations import sys from pathlib import Path ROOT = Path(__file__).resolve().parent.parent SOURCE = ROOT / "_build" / "icon_source.png" ICO = ROOT / "windows" / "app.ico" RES = ROOT / "android" / "res" PREVIEW = ROOT / "_build" / "icon_preview.png" ANDROID_SIZES = { "drawable-mdpi": 48, "drawable-hdpi": 72, "drawable-xhdpi": 96, "drawable-xxhdpi": 144, "drawable-xxxhdpi": 192, } ICO_SIZES = [16, 24, 32, 48, 64, 128, 256] def load_source(): from PIL import Image if not SOURCE.is_file(): raise SystemExit(f"找不到图标源图:{SOURCE}") return Image.open(SOURCE).convert("RGBA") def square(image): """居中裁成正方形,缩放才不会变形。""" width, height = image.size side = min(width, height) left = (width - side) // 2 top = (height - side) // 2 return image.crop((left, top, left + side, top + side)) def rounded(image, size: int, radius_ratio: float = 0.22): """缩到 size 并做圆角。""" from PIL import Image, ImageDraw scaled = image.resize((size, size), Image.LANCZOS) mask = Image.new("L", (size, size), 0) ImageDraw.Draw(mask).rounded_rectangle( (0, 0, size - 1, size - 1), radius=int(size * radius_ratio), fill=255) out = Image.new("RGBA", (size, size), (0, 0, 0, 0)) out.paste(scaled, (0, 0), mask) return out def main() -> int: from PIL import Image source = square(load_source()) print(f" 源图: {SOURCE.name} {source.size[0]}x{source.size[1]}") # ---------- 1. Windows .ico ---------- ICO.parent.mkdir(parents=True, exist_ok=True) rounded(source, 256).save(ICO, format="ICO", sizes=[(s, s) for s in ICO_SIZES]) print(f" windows/app.ico {ICO.stat().st_size} 字节 " f"({', '.join(str(s) for s in ICO_SIZES)})") # ---------- 2. 安卓图标 ---------- for folder, size in ANDROID_SIZES.items(): target_dir = RES / folder target_dir.mkdir(parents=True, exist_ok=True) inner = int(size * 0.88) # 留边 icon = rounded(source, inner) canvas = Image.new("RGBA", (size, size), (0, 0, 0, 0)) offset = (size - inner) // 2 canvas.paste(icon, (offset, offset), icon) canvas.save(target_dir / "ic_launcher.png") print(f" {folder}/ic_launcher.png {size}x{size}") # ---------- 3. 删掉旧矢量图(同名会冲突)---------- old_xml = RES / "drawable" / "ic_launcher.xml" if old_xml.is_file(): old_xml.unlink() print(" 删掉旧的 res/drawable/ic_launcher.xml(矢量图)") # ---------- 4. 预览 ---------- rounded(source, 256).save(PREVIEW) print(f" 预览: {PREVIEW.name}") return 0 if __name__ == "__main__": sys.exit(main())