Files
2026-08-10 22:06:49 +02:00

124 lines
4.2 KiB
Python

#!/usr/bin/env python3
"""
Génère les deux images de l'installeur NSIS à partir du logo de l'app.
python scripts/installer-art.py
NSIS impose du BMP à des tailles fixes :
· sidebar.bmp 164 x 314 — panneau de gauche (accueil et fin)
· header.bmp 150 x 57 — bandeau des pages intermédiaires
Les images sont versionnées dans src-tauri/installer/ : ce script n'est à
relancer que si le logo ou les couleurs de marque changent (il demande
Pillow, qui n'est PAS une dépendance du projet).
"""
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont
ROOT = Path(__file__).resolve().parent.parent
OUT = ROOT / "src-tauri" / "installer"
ICON = ROOT / "src-tauri" / "icons" / "128x128@2x.png"
# Dégradé du logo (public/logo.svg)
INDIGO = (99, 102, 241)
TEAL = (20, 184, 166)
INK = (16, 16, 24)
INK_SOFT = (30, 29, 48)
def font(size: int, bold: bool = False):
"""Segoe UI si disponible, repli sur la police par défaut de Pillow."""
for name in (["segoeuib.ttf", "seguisb.ttf"] if bold else ["segoeui.ttf"]):
try:
return ImageFont.truetype(f"C:/Windows/Fonts/{name}", size)
except OSError:
continue
return ImageFont.load_default()
def lerp(a, b, t):
return tuple(round(a[i] + (b[i] - a[i]) * t) for i in range(3))
def vertical_gradient(size, top, bottom):
w, h = size
img = Image.new("RGB", size)
d = ImageDraw.Draw(img)
for y in range(h):
d.line([(0, y), (w, y)], fill=lerp(top, bottom, y / max(h - 1, 1)))
return img
def horizontal_gradient(size, left, right):
w, h = size
img = Image.new("RGB", size)
d = ImageDraw.Draw(img)
for x in range(w):
d.line([(x, 0), (x, h)], fill=lerp(left, right, x / max(w - 1, 1)))
return img
def logo(px: int) -> Image.Image:
return Image.open(ICON).convert("RGBA").resize((px, px), Image.LANCZOS)
# ---------------------------------------------------------------------
# Panneau latéral 164 x 314 — fond sombre, logo, nom, liseré de marque
# ---------------------------------------------------------------------
def sidebar() -> Image.Image:
W, H = 164, 314
img = vertical_gradient((W, H), INK_SOFT, INK)
d = ImageDraw.Draw(img, "RGBA")
# Halo indigo diffus derrière le logo, pour éviter le fond plat.
cx, cy = W // 2, 96
for r in range(92, 0, -4):
alpha = int(30 * (1 - r / 92) ** 2)
d.ellipse([cx - r, cy - r, cx + r, cy + r], fill=(*INDIGO, alpha))
mark = logo(76)
img.paste(mark, (cx - 38, cy - 38), mark)
title = font(15, bold=True)
sub = font(11)
d.text((cx, 168), "GameDev", font=title, fill=(255, 255, 255), anchor="mm")
d.text((cx, 186), "Tracker", font=title, fill=(255, 255, 255), anchor="mm")
d.text((cx, 210), "Gestion de projet", font=sub, fill=(150, 148, 170), anchor="mm")
d.text((cx, 225), "de jeu vidéo", font=sub, fill=(150, 148, 170), anchor="mm")
# Liseré dégradé en pied de panneau : la signature visuelle de la marque.
bar = horizontal_gradient((W, 4), INDIGO, TEAL)
img.paste(bar, (0, H - 4))
return img
# ---------------------------------------------------------------------
# Bandeau 150 x 57 — fond SOMBRE, accordé à MUI_BGCOLOR du template
# ---------------------------------------------------------------------
def header() -> Image.Image:
W, H = 150, 57
img = Image.new("RGB", (W, H), INK)
d = ImageDraw.Draw(img)
mark = logo(34)
img.paste(mark, (W - 34 - 12, (H - 34) // 2), mark)
name = font(11, bold=True)
d.text((W - 56, H // 2 - 7), "GameDev", font=name, fill=(255, 255, 255), anchor="rm")
d.text((W - 56, H // 2 + 7), "Tracker", font=name, fill=(255, 255, 255), anchor="rm")
bar = horizontal_gradient((W, 3), INDIGO, TEAL)
img.paste(bar, (0, H - 3))
return img
OUT.mkdir(parents=True, exist_ok=True)
for name, image in (("sidebar", sidebar()), ("header", header())):
path = OUT / f"{name}.bmp"
# BMP 24 bits sans alpha : le seul format que NSIS accepte partout.
image.convert("RGB").save(path, "BMP")
print(f" {path.relative_to(ROOT)} {image.width}x{image.height}")
print("\nImages générées.")