import gradio as gr import os from PIL import Image, ImageEnhance, ImageFilter import requests import io import gc import json import logging from dotenv import load_dotenv from typing import Tuple, Optional, Dict, Any, List import numpy as np from dataclasses import dataclass from reportlab.lib import colors from reportlab.lib.pagesizes import A4 from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image as RLImage, Table, TableStyle from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.lib.units import inch from datetime import datetime import tempfile # Configuration du logging logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger("ArtistEquityPDF") class PDFGenerator: def __init__(self): self.styles = getSampleStyleSheet() self._create_custom_styles() def _create_custom_styles(self): """Création des styles personnalisés pour le PDF""" self.styles.add(ParagraphStyle( name='Title', fontSize=24, spaceAfter=30, alignment=1 )) self.styles.add(ParagraphStyle( name='Heading1', fontSize=18, spaceAfter=12, textColor=colors.HexColor('#1a365d') )) self.styles.add(ParagraphStyle( name='Heading2', fontSize=14, spaceAfter=8, textColor=colors.HexColor('#2d4a8a') )) self.styles.add(ParagraphStyle( name='Normal', fontSize=11, spaceAfter=6 )) def _format_metrics(self, metrics: Dict) -> List[List[str]]: """Formate les métriques pour le tableau PDF""" table_data = [] for category, values in metrics.items(): if isinstance(values, dict): for key, value in values.items(): if isinstance(value, float): formatted_value = f"{value:.2%}" else: formatted_value = str(value) table_data.append([category.replace('_', ' ').title(), key.replace('_', ' ').title(), formatted_value]) else: table_data.append([category.replace('_', ' ').title(), str(values), ""]) return table_data def generate_pdf(self, image: Image.Image, params: Dict[str, Any], metrics: Dict[str, Any], output_path: str) -> str: """Génère un PDF détaillé avec l'image et les métriques""" try: doc = SimpleDocTemplate( output_path, pagesize=A4, rightMargin=72, leftMargin=72, topMargin=72, bottomMargin=72 ) # Préparation des éléments du document elements = [] # En-tête elements.append(Paragraph( "Artist Equity - Rapport de Création", self.styles['Title'] )) # Date et informations de base elements.append(Paragraph( f"Généré le : {datetime.now().strftime('%d/%m/%Y %H:%M')}", self.styles['Normal'] )) elements.append(Spacer(1, 12)) # Paramètres de génération elements.append(Paragraph("Paramètres de Génération", self.styles['Heading1'])) params_table = Table([ ["Style", params['style']], ["Qualité", params['quality_preset']], ["Description", params['subject']] ]) params_table.setStyle(TableStyle([ ('BACKGROUND', (0, 0), (0, -1), colors.HexColor('#f8fafc')), ('TEXTCOLOR', (0, 0), (-1, -1), colors.HexColor('#1a365d')), ('ALIGN', (0, 0), (-1, -1), 'LEFT'), ('FONTNAME', (0, 0), (-1, -1), 'Helvetica'), ('FONTSIZE', (0, 0), (-1, -1), 10), ('BOTTOMPADDING', (0, 0), (-1, -1), 12), ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#e2e8f0')), ('GRID', (0, 0), (-1, -1), 1, colors.HexColor('#cbd5e1')) ])) elements.append(params_table) elements.append(Spacer(1, 20)) # Image générée # Sauvegarde temporaire de l'image temp_img_path = "temp_image.png" image.save(temp_img_path, "PNG") # Ajout de l'image au PDF avec dimensionnement automatique img_width = doc.width * 0.8 # 80% de la largeur de page img = RLImage(temp_img_path, width=img_width, height=img_width) elements.append(img) elements.append(Spacer(1, 20)) # Métriques de qualité elements.append(Paragraph("Métriques de Qualité", self.styles['Heading1'])) # Formatage des métriques en tableau metrics_data = self._format_metrics(metrics) metrics_table = Table( [["Catégorie", "Métrique", "Valeur"]] + metrics_data, colWidths=[doc.width/3.0]*3 ) metrics_table.setStyle(TableStyle([ ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#1a365d')), ('TEXTCOLOR', (0, 0), (-1, 0), colors.white), ('ALIGN', (0, 0), (-1, -1), 'CENTER'), ('FONTNAME', (0, 0), (-1, -1), 'Helvetica'), ('FONTSIZE', (0, 0), (-1, -1), 10), ('BOTTOMPADDING', (0, 0), (-1, -1), 12), ('GRID', (0, 0), (-1, -1), 1, colors.HexColor('#cbd5e1')), ('ROWBACKGROUNDS', (0, 1), (-1, -1), [colors.HexColor('#f8fafc'), colors.white]) ])) elements.append(metrics_table) # Génération du PDF doc.build(elements) # Nettoyage os.remove(temp_img_path) return output_path except Exception as e: logger.error(f"Erreur lors de la génération du PDF: {str(e)}") raise class ArtistEquityGeneratorPDF(ArtistEquityGenerator): def __init__(self): super().__init__() self.pdf_generator = PDFGenerator() def generate_with_pdf(self, params: Dict[str, Any]) -> Tuple[Optional[Image.Image], str, str]: """Génère l'image et un PDF détaillé""" try: # Génération de l'image image, metrics = super().generate(params) if image is None: return None, None, "Erreur lors de la génération de l'image" # Création du PDF timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") pdf_filename = f"artist_equity_creation_{timestamp}.pdf" self.pdf_generator.generate_pdf( image=image, params=params, metrics=metrics, output_path=pdf_filename ) return image, pdf_filename, "✨ Création artistique et rapport PDF générés avec succès!" except Exception as e: logger.exception("Erreur lors de la génération:") return None, None, f"⚠️ Erreur: {str(e)}" def create_interface(): """Interface utilisateur avec support PDF""" generator = ArtistEquityGeneratorPDF() with gr.Blocks(theme=gr.themes.Soft(primary_hue="indigo")) as interface: gr.HTML("""
Création Artistique avec Documentation PDF