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>
This commit is contained in:
2026-06-03 21:38:31 +02:00
parent 6451f5774c
commit e3d1d9cc07
32 changed files with 1009 additions and 84 deletions

View File

@@ -4,21 +4,15 @@ from pathlib import Path
from PIL import Image, ImageEnhance, ImageFilter, ImageOps
from backend.config import DOSSIER_OVERLAYS, DOSSIER_EXPORTS, DOSSIER_FONDS
from backend.config import DOSSIER_OVERLAYS, DOSSIER_EXPORTS, DOSSIER_FONDS, DOSSIER_CADRES
log = logging.getLogger("photobooth.effects")
# Filtres disponibles
FILTRES = {
"original": "Original",
"nb": "Noir & Blanc",
"sepia": "Sepia",
"vintage": "Vintage",
"contraste": "Contraste fort",
"lumineux": "Lumineux",
"chaud": "Tons chauds",
"froid": "Tons froids",
"flou_artistique": "Flou artistique",
"original": "Couleur",
"nb": "Noir & Blanc",
"sepia": "Sepia",
}
@@ -127,6 +121,28 @@ def chroma_key(chemin_photo: Path, nom_fond: str | None = None,
return chemin_export
def appliquer_cadre_impression(img: Image.Image, format_papier: str, nom_cadre: str) -> Image.Image:
"""Composite un cadre PNG par-dessus l'image assemblée."""
chemin = DOSSIER_CADRES / format_papier / nom_cadre
if not chemin.exists():
log.warning(f"Cadre introuvable : {chemin}")
return img
cadre = Image.open(chemin).convert("RGBA")
if cadre.size != img.size:
cadre = cadre.resize(img.size, Image.LANCZOS)
base = img.convert("RGBA")
composite = Image.alpha_composite(base, cadre)
return composite.convert("RGB")
def lister_cadres(format_papier: str) -> list[str]:
"""Liste les cadres disponibles pour un format donné."""
dossier = DOSSIER_CADRES / format_papier
if not dossier.exists():
return []
return sorted(f.name for f in dossier.iterdir() if f.suffix.lower() == ".png")
def lister_overlays() -> list[str]:
"""Liste les overlays disponibles."""
if not DOSSIER_OVERLAYS.exists():