Files
photobooth/scripts/generer_cadres_demo.py
Jules e3d1d9cc07 Impression Mitsubishi K60 + cadres + interface admin distante
- Intégration selphy_print (backend CUPS dyesub Mitsubishi CP-K60DW-S)
- Formats impression : 15x20, 10x15, 10x15 2-strips avec cadre et orientation portrait/paysage
- Cadres d'impression par format (strip/10x15/15x20) : upload, sélection, aperçu live
- Cadres démo générés : pellicule noir/vintage/couleurs + bordures classique/doré/rose gold
- Écran de choix de cadre avant capture (clic direct, aperçu grand format)
- Filtres réduits à 3 (Couleur, N&B, Sépia) et appliqués sur tous les strips
- Port 80 via authbind, route /admin avec redirection auto depuis poste distant
- Autologin LightDM corrigé (pam-autologin-service)
- Bouton évacuer bourrage papier dans admin
- Fix : _gp_lock manquant dans Camera.__init__

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 21:38:31 +02:00

179 lines
6.8 KiB
Python

#!/usr/bin/env python3
"""Génère des cadres de démonstration pour chaque format d'impression."""
from pathlib import Path
from PIL import Image, ImageDraw
RACINE = Path(__file__).resolve().parent.parent
DOSSIER_CADRES = RACINE / "frontend" / "assets" / "cadres"
FORMATS = {
"strip": (600, 1800),
"10x15": (1200, 1800),
"15x20": (1800, 2400),
}
# ─── Cadres simples (tous formats) ───────────────────────────────────────────
def cadre_simple(largeur, hauteur, couleur_bord, epaisseur=30, couleur_coin=None):
img = Image.new("RGBA", (largeur, hauteur), (0, 0, 0, 0))
d = ImageDraw.Draw(img)
cc = couleur_coin or couleur_bord
ep = epaisseur
# 4 bords
d.rectangle([0, 0, largeur, ep], fill=couleur_bord)
d.rectangle([0, hauteur - ep, largeur, hauteur], fill=couleur_bord)
d.rectangle([0, 0, ep, hauteur], fill=couleur_bord)
d.rectangle([largeur - ep, 0, largeur, hauteur], fill=couleur_bord)
# coins
tc = ep + 20
for x, y in [(0, 0), (largeur - tc, 0), (0, hauteur - tc), (largeur - tc, hauteur - tc)]:
d.rectangle([x, y, x + tc, y + tc], fill=cc)
# ligne intérieure fine
m = ep + 8
d.rectangle([m, m, largeur - m, hauteur - m], outline=cc, width=2)
return img
# ─── Cadres pellicule (format strip uniquement) ───────────────────────────────
def cadre_pellicule(largeur, hauteur, couleur_bord=(15, 15, 15, 255),
couleur_perf=(50, 50, 50, 255), label=""):
"""Cadre pellicule avec perforations sur les côtés gauche et droit."""
img = Image.new("RGBA", (largeur, hauteur), (0, 0, 0, 0))
d = ImageDraw.Draw(img)
bord = 52 # largeur de la bande pellicule de chaque côté
perf_h = 22 # hauteur d'une perforation
perf_w = 16 # largeur d'une perforation
perf_r = 4 # rayon arrondi
perf_gap = 14 # espace entre perforations
# Bandes noires gauche et droite
d.rectangle([0, 0, bord, hauteur], fill=couleur_bord)
d.rectangle([largeur - bord, 0, largeur, hauteur], fill=couleur_bord)
# Bande fine haut et bas
bord_h = 10
d.rectangle([0, 0, largeur, bord_h], fill=couleur_bord)
d.rectangle([0, hauteur - bord_h, largeur, hauteur], fill=couleur_bord)
# Perforations gauche
y = perf_gap
while y + perf_h < hauteur:
x = (bord - perf_w) // 2
d.rounded_rectangle([x, y, x + perf_w, y + perf_h], radius=perf_r, fill=couleur_perf)
y += perf_h + perf_gap
# Perforations droite
y = perf_gap
while y + perf_h < hauteur:
x = largeur - bord + (bord - perf_w) // 2
d.rounded_rectangle([x, y, x + perf_w, y + perf_h], radius=perf_r, fill=couleur_perf)
y += perf_h + perf_gap
# Ligne intérieure fine pour délimiter la zone photo
m = bord + 4
d.rectangle([m, bord_h + 4, largeur - m, hauteur - bord_h - 4], outline=(80, 80, 80, 180), width=1)
return img
def cadre_pellicule_vintage(largeur, hauteur):
"""Pellicule couleur sépia avec numéros de frame."""
img = Image.new("RGBA", (largeur, hauteur), (0, 0, 0, 0))
d = ImageDraw.Draw(img)
bord = 58
bord_sepia = (40, 28, 12, 255)
perf_col = (90, 65, 30, 255)
perf_h, perf_w, perf_r, perf_gap = 20, 14, 3, 16
d.rectangle([0, 0, bord, hauteur], fill=bord_sepia)
d.rectangle([largeur - bord, 0, largeur, hauteur], fill=bord_sepia)
d.rectangle([0, 0, largeur, 8], fill=bord_sepia)
d.rectangle([0, hauteur - 8, largeur, hauteur], fill=bord_sepia)
for side in [0, 1]:
y = perf_gap
while y + perf_h < hauteur:
x = (bord - perf_w) // 2 if side == 0 else largeur - bord + (bord - perf_w) // 2
d.rounded_rectangle([x, y, x + perf_w, y + perf_h], radius=perf_r, fill=perf_col)
y += perf_h + perf_gap
# Filet intérieur
m = bord + 5
d.rectangle([m, 12, largeur - m, hauteur - 12], outline=(100, 75, 35, 200), width=2)
return img
def cadre_pellicule_couleur(largeur, hauteur, teinte=(220, 50, 50)):
"""Pellicule colorée style photobooth rétro."""
img = Image.new("RGBA", (largeur, hauteur), (0, 0, 0, 0))
d = ImageDraw.Draw(img)
bord = 50
r, g, b = teinte
col_bord = (r, g, b, 255)
col_perf = (min(255, r + 60), min(255, g + 60), min(255, b + 60), 255)
perf_h, perf_w, perf_r, perf_gap = 20, 14, 4, 14
d.rectangle([0, 0, bord, hauteur], fill=col_bord)
d.rectangle([largeur - bord, 0, largeur, hauteur], fill=col_bord)
d.rectangle([0, 0, largeur, 8], fill=col_bord)
d.rectangle([0, hauteur - 8, largeur, hauteur], fill=col_bord)
for side in [0, 1]:
y = perf_gap
while y + perf_h < hauteur:
x = (bord - perf_w) // 2 if side == 0 else largeur - bord + (bord - perf_w) // 2
d.rounded_rectangle([x, y, x + perf_w, y + perf_h], radius=perf_r, fill=col_perf)
y += perf_h + perf_gap
m = bord + 5
d.rectangle([m, 12, largeur - m, hauteur - 12], outline=col_perf, width=2)
return img
# ─── Main ─────────────────────────────────────────────────────────────────────
def main():
# Cadres simples pour tous les formats
SIMPLES = [
("classique_blanc.png", (255, 255, 255, 255), (210, 210, 210, 255), 30),
("elegant_noir.png", (20, 20, 20, 255), (70, 70, 70, 255), 40),
("rose_gold.png", (198, 143, 115, 255), (230, 180, 150, 255), 35),
("festif_dore.png", (212, 175, 55, 255), (255, 215, 0, 255), 32),
]
for fmt, (larg, haut) in FORMATS.items():
dossier = DOSSIER_CADRES / fmt
dossier.mkdir(parents=True, exist_ok=True)
for nom, col_bord, col_coin, ep in SIMPLES:
cadre = cadre_simple(larg, haut, col_bord, ep, col_coin)
cadre.save(dossier / nom, "PNG")
print(f" ✓ {fmt}/{nom}")
# Cadres pellicule — uniquement format strip
dossier_strip = DOSSIER_CADRES / "strip"
larg, haut = FORMATS["strip"]
pellicules = [
("pellicule_noir.png", cadre_pellicule(larg, haut)),
("pellicule_vintage.png", cadre_pellicule_vintage(larg, haut)),
("pellicule_rouge.png", cadre_pellicule_couleur(larg, haut, (200, 40, 40))),
("pellicule_bleu.png", cadre_pellicule_couleur(larg, haut, (30, 80, 180))),
("pellicule_vert.png", cadre_pellicule_couleur(larg, haut, (30, 140, 60))),
]
for nom, img in pellicules:
img.save(dossier_strip / nom, "PNG")
print(f" ✓ strip/{nom} (pellicule)")
if __name__ == "__main__":
print("Génération des cadres de démonstration...")
main()
print("Terminé.")