Supprimer GIF, multi-shot en format 10x15cm
- Suppression du mode GIF (gif_maker.py, routes, UI) - Multi-shot (strip/collage) produit maintenant des images 10x15cm (1200x1800px @ 300dpi) pret pour impression sublimation - Recadrage intelligent (crop centre) pour remplir les cellules Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,55 +7,80 @@ from backend.config import DOSSIER_EXPORTS, charger_config
|
||||
|
||||
log = logging.getLogger("photobooth.collage")
|
||||
|
||||
# Format 10x15cm a 300dpi
|
||||
LARGEUR_10x15 = 1200
|
||||
HAUTEUR_10x15 = 1800
|
||||
|
||||
def creer_strip(photos: list[Path], marge: int = 20, couleur_fond: str = "#ffffff") -> Path:
|
||||
"""Cree une bande verticale (strip) avec les photos."""
|
||||
|
||||
def _crop_center(img: Image.Image, ratio_cible: float) -> Image.Image:
|
||||
"""Recadre une image au centre pour correspondre au ratio cible."""
|
||||
ratio_img = img.width / img.height
|
||||
if ratio_img > ratio_cible:
|
||||
# Trop large, couper les cotes
|
||||
nouvelle_largeur = int(img.height * ratio_cible)
|
||||
offset = (img.width - nouvelle_largeur) // 2
|
||||
return img.crop((offset, 0, offset + nouvelle_largeur, img.height))
|
||||
else:
|
||||
# Trop haut, couper haut/bas
|
||||
nouvelle_hauteur = int(img.width / ratio_cible)
|
||||
offset = (img.height - nouvelle_hauteur) // 2
|
||||
return img.crop((0, offset, img.width, offset + nouvelle_hauteur))
|
||||
|
||||
|
||||
def creer_strip(photos: list[Path], marge: int = 30, couleur_fond: str = "#ffffff") -> Path:
|
||||
"""Cree une bande verticale (strip) au format 10x15cm."""
|
||||
nb = len(photos)
|
||||
images = [Image.open(p) for p in photos]
|
||||
|
||||
# Uniformiser la largeur
|
||||
largeur = min(img.width for img in images)
|
||||
# Calculer la taille de chaque cellule dans le format 10x15
|
||||
espace_disponible_h = HAUTEUR_10x15 - marge * (nb + 1)
|
||||
hauteur_cellule = espace_disponible_h // nb
|
||||
largeur_cellule = LARGEUR_10x15 - marge * 2
|
||||
ratio_cellule = largeur_cellule / hauteur_cellule
|
||||
|
||||
# Recadrer et redimensionner chaque photo
|
||||
images_redim = []
|
||||
for img in images:
|
||||
ratio = largeur / img.width
|
||||
hauteur = int(img.height * ratio)
|
||||
images_redim.append(img.resize((largeur, hauteur), Image.LANCZOS))
|
||||
img_crop = _crop_center(img, ratio_cellule)
|
||||
img_redim = img_crop.resize((largeur_cellule, hauteur_cellule), Image.LANCZOS)
|
||||
images_redim.append(img_redim)
|
||||
|
||||
hauteur_totale = sum(img.height for img in images_redim) + marge * (len(images_redim) + 1)
|
||||
largeur_totale = largeur + marge * 2
|
||||
|
||||
strip = Image.new("RGB", (largeur_totale, hauteur_totale), couleur_fond)
|
||||
# Assembler sur le canvas 10x15
|
||||
strip = Image.new("RGB", (LARGEUR_10x15, HAUTEUR_10x15), couleur_fond)
|
||||
y = marge
|
||||
for img in images_redim:
|
||||
strip.paste(img, (marge, y))
|
||||
y += img.height + marge
|
||||
y += hauteur_cellule + marge
|
||||
|
||||
nom = f"strip_{photos[0].stem}.jpg"
|
||||
chemin = DOSSIER_EXPORTS / nom
|
||||
strip.save(chemin, "JPEG", quality=95)
|
||||
log.info(f"Strip cree : {chemin}")
|
||||
strip.save(chemin, "JPEG", quality=95, dpi=(300, 300))
|
||||
log.info(f"Strip 10x15 cree : {chemin} ({nb} photos)")
|
||||
return chemin
|
||||
|
||||
|
||||
def creer_collage(photos: list[Path], colonnes: int = 2, marge: int = 15,
|
||||
def creer_collage(photos: list[Path], colonnes: int = 2, marge: int = 25,
|
||||
couleur_fond: str = "#ffffff") -> Path:
|
||||
"""Cree un collage en grille avec les photos."""
|
||||
"""Cree un collage en grille au format 10x15cm."""
|
||||
nb = len(photos)
|
||||
images = [Image.open(p) for p in photos]
|
||||
|
||||
# Taille uniforme pour chaque cellule
|
||||
largeur_cellule = min(img.width for img in images)
|
||||
hauteur_cellule = min(img.height for img in images)
|
||||
lignes = (nb + colonnes - 1) // colonnes
|
||||
|
||||
# Calculer la taille de chaque cellule
|
||||
largeur_cellule = (LARGEUR_10x15 - marge * (colonnes + 1)) // colonnes
|
||||
hauteur_cellule = (HAUTEUR_10x15 - marge * (lignes + 1)) // lignes
|
||||
ratio_cellule = largeur_cellule / hauteur_cellule
|
||||
|
||||
# Recadrer et redimensionner
|
||||
images_redim = []
|
||||
for img in images:
|
||||
img_crop = ImageDraw.Draw(img)
|
||||
img_redim = img.resize((largeur_cellule, hauteur_cellule), Image.LANCZOS)
|
||||
img_crop = _crop_center(img, ratio_cellule)
|
||||
img_redim = img_crop.resize((largeur_cellule, hauteur_cellule), Image.LANCZOS)
|
||||
images_redim.append(img_redim)
|
||||
|
||||
lignes = (len(images_redim) + colonnes - 1) // colonnes
|
||||
largeur_totale = colonnes * largeur_cellule + (colonnes + 1) * marge
|
||||
hauteur_totale = lignes * hauteur_cellule + (lignes + 1) * marge
|
||||
|
||||
collage = Image.new("RGB", (largeur_totale, hauteur_totale), couleur_fond)
|
||||
# Assembler sur le canvas 10x15
|
||||
collage = Image.new("RGB", (LARGEUR_10x15, HAUTEUR_10x15), couleur_fond)
|
||||
|
||||
for i, img in enumerate(images_redim):
|
||||
col = i % colonnes
|
||||
@@ -66,6 +91,6 @@ def creer_collage(photos: list[Path], colonnes: int = 2, marge: int = 15,
|
||||
|
||||
nom = f"collage_{photos[0].stem}.jpg"
|
||||
chemin = DOSSIER_EXPORTS / nom
|
||||
collage.save(chemin, "JPEG", quality=95)
|
||||
log.info(f"Collage cree : {chemin}")
|
||||
collage.save(chemin, "JPEG", quality=95, dpi=(300, 300))
|
||||
log.info(f"Collage 10x15 cree : {chemin} ({nb} photos, {colonnes}x{lignes})")
|
||||
return chemin
|
||||
|
||||
Reference in New Issue
Block a user