- Replace logo source with new glassy gradient H (heicode-logo.jpg)
- Regen all icon sizes via scripts/rebuild-icons.py (PIL + ICO + ICNS):
32/64/128/128@2x/icon.png + Square{30,44,71,89,107,142,150,284,310}+StoreLogo
+ multi-res icon.ico + icon.icns
- Update public/app-icon.png to 1024×1024 derived
- Align cc-haha/desktop/scripts/build-macos-arm64.sh to Heicode branding:
APP_BUNDLE_NAME=HeiCode.app, APP_BUNDLE_ID=com.heicode.desktop,
DMG volume=Heicode, default DMG=Heicode_0.1.0_aarch64.dmg,
cleanup paths use heicode-desktop crate name (mirrors Cargo.toml rename)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
84 lines
2.9 KiB
Python
84 lines
2.9 KiB
Python
"""Regenerate Tauri/desktop icons from heicode-logo.jpg."""
|
|
from pathlib import Path
|
|
from PIL import Image
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
SRC = ROOT / "heicode-logo.jpg"
|
|
TAURI_ICONS = ROOT / "cc-haha" / "desktop" / "src-tauri" / "icons"
|
|
PUBLIC = ROOT / "cc-haha" / "desktop" / "public"
|
|
|
|
def load_trimmed_square():
|
|
img = Image.open(SRC).convert("RGB")
|
|
# Find bbox of non-white pixels (treat >=250 RGB as white).
|
|
gray = img.convert("L")
|
|
mask = gray.point(lambda v: 0 if v >= 250 else 255)
|
|
bbox = mask.getbbox()
|
|
if bbox:
|
|
img = img.crop(bbox)
|
|
# Pad to square on white.
|
|
w, h = img.size
|
|
side = max(w, h)
|
|
canvas = Image.new("RGB", (side, side), (255, 255, 255))
|
|
canvas.paste(img, ((side - w) // 2, (side - h) // 2))
|
|
return canvas
|
|
|
|
def to_rgba_with_transparent_white(img: Image.Image, threshold: int = 248) -> Image.Image:
|
|
rgba = img.convert("RGBA")
|
|
pixels = rgba.load()
|
|
w, h = rgba.size
|
|
for y in range(h):
|
|
for x in range(w):
|
|
r, g, b, _ = pixels[x, y]
|
|
if r >= threshold and g >= threshold and b >= threshold:
|
|
pixels[x, y] = (r, g, b, 0)
|
|
return rgba
|
|
|
|
def main():
|
|
base = load_trimmed_square()
|
|
print(f"Trimmed source: {base.size}")
|
|
|
|
# PNG outputs (RGB on white → looks correct on any background, matches glass edges).
|
|
sizes = {
|
|
TAURI_ICONS / "32x32.png": 32,
|
|
TAURI_ICONS / "64x64.png": 64,
|
|
TAURI_ICONS / "128x128.png": 128,
|
|
TAURI_ICONS / "128x128@2x.png": 256,
|
|
TAURI_ICONS / "icon.png": 1024,
|
|
PUBLIC / "app-icon.png": 1024,
|
|
}
|
|
for path, size in sizes.items():
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
base.resize((size, size), Image.LANCZOS).save(path, "PNG")
|
|
print(f"wrote {path} ({size})")
|
|
|
|
# Windows Square*Logo / StoreLogo
|
|
win_sizes = {
|
|
"Square30x30Logo.png": 30,
|
|
"Square44x44Logo.png": 44,
|
|
"Square71x71Logo.png": 71,
|
|
"Square89x89Logo.png": 89,
|
|
"Square107x107Logo.png": 107,
|
|
"Square142x142Logo.png": 142,
|
|
"Square150x150Logo.png": 150,
|
|
"Square284x284Logo.png": 284,
|
|
"Square310x310Logo.png": 310,
|
|
"StoreLogo.png": 50,
|
|
}
|
|
for name, size in win_sizes.items():
|
|
path = TAURI_ICONS / name
|
|
base.resize((size, size), Image.LANCZOS).save(path, "PNG")
|
|
print(f"wrote {path} ({size})")
|
|
|
|
# ICO with multi-resolution.
|
|
ico_path = TAURI_ICONS / "icon.ico"
|
|
base.save(ico_path, format="ICO", sizes=[(16,16),(24,24),(32,32),(48,48),(64,64),(128,128),(256,256)])
|
|
print(f"wrote {ico_path}")
|
|
|
|
# ICNS (PIL supports it). Required sizes: 16,32,64,128,256,512,1024.
|
|
icns_path = TAURI_ICONS / "icon.icns"
|
|
base.save(icns_path, format="ICNS", sizes=[(16,16),(32,32),(64,64),(128,128),(256,256),(512,512),(1024,1024)])
|
|
print(f"wrote {icns_path}")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|