Spaces:
Runtime error
Runtime error
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(""" | |
<div style="text-align: center; padding: 20px;"> | |
<h1>🎨 Artist Equity Studio Pro</h1> | |
<p>Création Artistique avec Documentation PDF</p> | |
</div> | |
""") | |
with gr.Row(): | |
with gr.Column(scale=1): | |
# Contrôles de génération | |
style = gr.Dropdown( | |
choices=list(ART_STYLES.keys()), | |
value="Renaissance Numérique", | |
label="Style Artistique" | |
) | |
quality = gr.Radio( | |
choices=list(QUALITY_PRESETS.keys()), | |
value="Maître", | |
label="Qualité" | |
) | |
prompt = gr.Textbox( | |
label="Description", | |
placeholder="Décrivez votre vision artistique...", | |
lines=3 | |
) | |
with gr.Accordion("Paramètres Avancés", open=False): | |
detail_level = gr.Slider( | |
minimum=0.8, | |
maximum=1.0, | |
value=0.9, | |
label="Niveau de Détail" | |
) | |
color_accuracy = gr.Slider( | |
minimum=0.8, | |
maximum=1.0, | |
value=0.9, | |
label="Précision des Couleurs" | |
) | |
generate_btn = gr.Button("✨ Créer", variant="primary") | |
with gr.Column(scale=2): | |
# Résultats | |
image_output = gr.Image(label="Création Artistique") | |
pdf_output = gr.File(label="Rapport PDF") | |
status = gr.Textbox(label="Statut", interactive=False) | |
# Logique de génération | |
def generate_complete(*params): | |
generation_params = { | |
"style": params[0], | |
"quality_preset": params[1], | |
"subject": params[2], | |
"detail_level": params[3], | |
"color_accuracy": params[4] | |
} | |
image, pdf_path, status_msg = generator.generate_with_pdf(generation_params) | |
return image, pdf_path, status_msg | |
generate_btn.click( | |
generate_complete, | |
inputs=[style, quality, prompt, detail_level, color_accuracy], | |
outputs=[image_output, pdf_output, status] | |
) | |
return interface | |
if __name__ == "__main__": | |
app = create_interface() | |
app.launch( | |
share=False, | |
server_name="0.0.0.0", | |
server_port=7860, | |
show_error=True | |
) |