#!/usr/bin/env python3 """Génère src/mask-data.ts à partir de assets/mask.png (nécessite Pillow : pip install pillow). Usage : python3 scripts/make-mask.py [taille] (32 par défaut ; l'image affichée fait taille × taille pixels, soit taille colonnes × taille/2 lignes de terminal) Le fond uni (couleur des coins) est rendu transparent, l'image est recadrée au carré puis réduite en moyennant les couleurs : aucune pixelisation par blocs, aucune réduction de palette. """ import sys from collections import deque from pathlib import Path from PIL import Image N = int(sys.argv[1]) if len(sys.argv) > 1 else 32 root = Path(__file__).resolve().parent.parent im = Image.open(root / "assets" / "mask.png").convert("RGB") W, H = im.size px = im.load() bg = px[0, 0] near = lambda c: all(abs(c[i] - bg[i]) <= 12 for i in range(3)) # Fond = zone connectée aux coins et proche de la couleur du fond (le visage crème est isolé par son contour noir). transparent = [[False] * W for _ in range(H)] queue = deque([(0, 0), (W - 1, 0), (0, H - 1), (W - 1, H - 1)]) while queue: x, y = queue.popleft() if x < 0 or y < 0 or x >= W or y >= H or transparent[y][x] or not near(px[x, y]): continue transparent[y][x] = True queue.extend([(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)]) xs = [x for y in range(H) for x in range(W) if not transparent[y][x]] ys = [y for y in range(H) for x in range(W) if not transparent[y][x]] x0, x1, y0, y1 = min(xs), max(xs) + 1, min(ys), max(ys) + 1 side = max(x1 - x0, y1 - y0) ox = x0 - (side - (x1 - x0)) // 2 oy = y0 - (side - (y1 - y0)) // 2 rows = [] for gy in range(N): row = "" for gx in range(N): total = opaque = 0 acc = [0, 0, 0] for y in range(int(oy + gy * side / N), int(oy + (gy + 1) * side / N) + 1): for x in range(int(ox + gx * side / N), int(ox + (gx + 1) * side / N) + 1): total += 1 if 0 <= x < W and 0 <= y < H and not transparent[y][x]: opaque += 1 for i in range(3): acc[i] += px[x, y][i] # moyenne des pixels opaques uniquement (évite le liseré clair du fond) ; transparent si moins de la moitié est opaque row += "......" if opaque * 2 < total or opaque == 0 else "".join("%02x" % round(a / opaque) for a in acc) rows.append(row) lines = "\n".join(f' "{r}",' for r in rows) (root / "src" / "mask-data.ts").write_text( "// Fichier généré par scripts/make-mask.py à partir de assets/mask.png : ne pas modifier à la main.\n" "// Une chaîne par ligne de pixels ; chaque pixel = 6 chiffres hexadécimaux rrggbb, \"......\" = transparent.\n" f"export const MASK_SIZE = {N};\n\n" f"export const MASK_DATA: string[] = [\n{lines}\n];\n", encoding="utf-8", ) print(f"{N}x{N} écrit dans src/mask-data.ts")