import logging from pathlib import Path from PIL import Image, ImageDraw from backend.config import DOSSIER_EXPORTS, charger_config log = logging.getLogger("photobooth.collage") # Format 10x15cm a 300dpi LARGEUR_10x15 = 1200 HAUTEUR_10x15 = 1800 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] # 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: img_crop = _crop_center(img, ratio_cellule) img_redim = img_crop.resize((largeur_cellule, hauteur_cellule), Image.LANCZOS) images_redim.append(img_redim) # 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 += hauteur_cellule + marge nom = f"strip_{photos[0].stem}.jpg" chemin = DOSSIER_EXPORTS / nom 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 = 25, couleur_fond: str = "#ffffff") -> Path: """Cree un collage en grille au format 10x15cm.""" nb = len(photos) images = [Image.open(p) for p in photos] 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 = _crop_center(img, ratio_cellule) img_redim = img_crop.resize((largeur_cellule, hauteur_cellule), Image.LANCZOS) images_redim.append(img_redim) # 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 lig = i // colonnes x = marge + col * (largeur_cellule + marge) y = marge + lig * (hauteur_cellule + marge) collage.paste(img, (x, y)) nom = f"collage_{photos[0].stem}.jpg" chemin = DOSSIER_EXPORTS / nom collage.save(chemin, "JPEG", quality=95, dpi=(300, 300)) log.info(f"Collage 10x15 cree : {chemin} ({nb} photos, {colonnes}x{lignes})") return chemin