MagicCode/packages/ui/scripts/make-mask.py
2026-10-16 00:54:08 +02:00

65 lines
2.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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")