generart / app.py
Equityone's picture
Update app.py
d8bdd06 verified
raw
history blame
9.62 kB
import gradio as gr
import os
from PIL import Image, ImageDraw, ImageFont
import requests
import io
# Styles artistiques optimisés pour le texte
ART_STYLES = {
"Neo Vintage": {
"prompt_prefix": "vintage propaganda poster style, retro advertisement design",
"text_style": "clear vintage typography, screen printing style lettering, clean text layout",
"guidance": 12.5,
"steps": 70,
"negative_prompt": "blurry text, illegible writing, damaged letters, distorted fonts, gibberish"
},
"Art Déco": {
"prompt_prefix": "art deco poster design, 1920s luxury advertisement style",
"text_style": "elegant art deco typography, decorative lettering, geometric text design",
"guidance": 13.0,
"steps": 75,
"negative_prompt": "modern fonts, messy text, unclear letters, random characters"
},
"Moderne": {
"prompt_prefix": "modern minimalist poster design, contemporary professional layout",
"text_style": "clean sans-serif typography, precise text placement, minimal design",
"guidance": 11.5,
"steps": 65,
"negative_prompt": "cluttered text, unreadable fonts, messy layout, poor typography"
},
"Pop Art": {
"prompt_prefix": "pop art style poster, comic book inspired design",
"text_style": "bold comic book typography, dynamic text placement, retro lettering",
"guidance": 11.0,
"steps": 60,
"negative_prompt": "subtle text, unclear typography, messy letters"
}
}
# CSS personnalisé
CUSTOM_CSS = """
.container { max-width: 1200px; margin: auto; }
.welcome { text-align: center; margin: 20px 0; padding: 20px; background: #1e293b; border-radius: 10px; }
.quality-controls { margin: 10px 0; padding: 10px; background: #2d3748; border-radius: 5px; }
.text-input { background: #2d3748; padding: 15px; border-radius: 5px; margin: 10px 0; }
"""
def generate_enhanced_prompt(subject, style, title="", subtitle="", additional_details=""):
"""Génère un prompt optimisé pour le texte"""
style_config = ART_STYLES[style]
# Construction du prompt de base
base_prompt = f"{style_config['prompt_prefix']}, {subject}"
# Ajout des éléments de texte si présents
text_elements = []
if title:
text_elements.append(f"with main title text '{title}'")
if subtitle:
text_elements.append(f"subtitle text '{subtitle}'")
text_prompt = ", ".join(text_elements)
if text_prompt:
base_prompt += f", {text_prompt}, {style_config['text_style']}"
if additional_details:
base_prompt += f", {additional_details}"
return base_prompt, style_config['negative_prompt']
def generate_image(format_size, orientation, subject, style, title, subtitle, quality, creativity, additional_details=""):
API_URL = "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-xl-base-1.0"
headers = {"Authorization": f"Bearer {os.getenv('HUGGINGFACE_TOKEN')}"}
try:
# Dimensions optimisées
width, height = (768, 1024) if format_size == "A4" else (1024, 1024)
if orientation == "Paysage":
width, height = height, width
# Génération du prompt optimisé
enhanced_prompt, negative_prompt = generate_enhanced_prompt(
subject, style, title, subtitle, additional_details
)
print(f"Prompt: {enhanced_prompt}") # Debug
print(f"Negative prompt: {negative_prompt}") # Debug
# Configuration de la requête
payload = {
"inputs": enhanced_prompt,
"parameters": {
"negative_prompt": negative_prompt,
"num_inference_steps": int(ART_STYLES[style]['steps'] * (quality/100)),
"guidance_scale": ART_STYLES[style]['guidance'] * (creativity/10),
"width": width,
"height": height
}
}
response = requests.post(API_URL, headers=headers, json=payload, timeout=60)
if response.status_code == 200:
image = Image.open(io.BytesIO(response.content))
return image, f"✨ Création {style} réussie avec texte intégré!"
else:
print(f"Erreur API: {response.text}") # Debug
return None, f"⚠️ Erreur {response.status_code}: Ajustez les paramètres"
except Exception as e:
print(f"Exception: {str(e)}") # Debug
return None, f"⚠️ Erreur: {str(e)}"
def create_interface():
with gr.Blocks(css=CUSTOM_CSS) as app:
gr.HTML("""
<div class="welcome">
<h1>🤖 Equity Artisan 3.0</h1>
<p>Créez des affiches professionnelles étape par étape avec notre assistant créatif augmenté.</p>
</div>
""")
with gr.Column(elem_classes="container"):
# Étape 1: Format
with gr.Group():
gr.Markdown("### 📏 Étape 1: Format et Orientation")
with gr.Row():
format_choice = gr.Dropdown(
choices=["A4", "A3", "A2", "A1", "A0"],
value="A4",
label="Format"
)
orientation = gr.Radio(
choices=["Portrait", "Paysage"],
value="Portrait",
label="Orientation"
)
# Étape 2: Création Visuelle
with gr.Group():
gr.Markdown("### 🎨 Étape 2: Création Visuelle")
with gr.Row():
with gr.Column():
style = gr.Dropdown(
choices=list(ART_STYLES.keys()),
value="Neo Vintage",
label="Style artistique",
info="Choisissez le style de votre affiche"
)
subject = gr.Textbox(
label="Sujet principal",
placeholder="Ex: loup, paysage urbain...",
info="Décrivez l'élément principal"
)
# Nouvelle section texte
with gr.Group(elem_classes="text-input"):
gr.Markdown("#### 📝 Texte de l'affiche")
title = gr.Textbox(
label="Titre principal",
placeholder="Texte principal qui apparaîtra sur l'affiche",
info="Ce texte sera intégré de manière lisible"
)
subtitle = gr.Textbox(
label="Sous-titre (optionnel)",
placeholder="Texte secondaire plus petit",
info="Texte complémentaire"
)
additional_details = gr.Textbox(
lines=2,
label="Détails additionnels (optionnel)",
placeholder="Ajoutez des détails pour enrichir l'image...",
info="Plus de détails = meilleur résultat"
)
with gr.Group(elem_classes="quality-controls"):
quality = gr.Slider(
minimum=30,
maximum=50,
value=35,
step=5,
label="Qualité",
info="Influence le niveau de détail"
)
creativity = gr.Slider(
minimum=5,
maximum=15,
value=7.5,
step=0.5,
label="Créativité",
info="Balance entre fidélité et créativité"
)
generate_btn = gr.Button("✨ Générer", variant="primary")
clear_btn = gr.Button("🗑️ Effacer", variant="secondary")
image_output = gr.Image(
label="Aperçu",
type="pil"
)
# Statut
status = gr.Textbox(
label="Status",
interactive=False,
value="Prêt à générer"
)
# Événements
generate_btn.click(
generate_image,
inputs=[
format_choice,
orientation,
subject,
style,
title,
subtitle,
quality,
creativity,
additional_details
],
outputs=[image_output, status]
)
clear_btn.click(
lambda: (None, "Image effacée"),
outputs=[image_output, status]
)
return app
if __name__ == "__main__":
app = create_interface()
app.launch()