Equityone commited on
Commit
f5c41f4
·
verified ·
1 Parent(s): d8bdd06

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +132 -121
app.py CHANGED
@@ -1,89 +1,85 @@
1
  import gradio as gr
2
  import os
3
- from PIL import Image, ImageDraw, ImageFont
4
  import requests
5
  import io
 
6
 
7
- # Styles artistiques optimisés pour le texte
8
- ART_STYLES = {
9
- "Neo Vintage": {
10
- "prompt_prefix": "vintage propaganda poster style, retro advertisement design",
11
- "text_style": "clear vintage typography, screen printing style lettering, clean text layout",
12
- "guidance": 12.5,
13
- "steps": 70,
14
- "negative_prompt": "blurry text, illegible writing, damaged letters, distorted fonts, gibberish"
15
- },
16
- "Art Déco": {
17
- "prompt_prefix": "art deco poster design, 1920s luxury advertisement style",
18
- "text_style": "elegant art deco typography, decorative lettering, geometric text design",
19
- "guidance": 13.0,
20
- "steps": 75,
21
- "negative_prompt": "modern fonts, messy text, unclear letters, random characters"
22
- },
23
- "Moderne": {
24
- "prompt_prefix": "modern minimalist poster design, contemporary professional layout",
25
- "text_style": "clean sans-serif typography, precise text placement, minimal design",
26
- "guidance": 11.5,
27
- "steps": 65,
28
- "negative_prompt": "cluttered text, unreadable fonts, messy layout, poor typography"
29
- },
30
- "Pop Art": {
31
- "prompt_prefix": "pop art style poster, comic book inspired design",
32
- "text_style": "bold comic book typography, dynamic text placement, retro lettering",
33
- "guidance": 11.0,
34
- "steps": 60,
35
- "negative_prompt": "subtle text, unclear typography, messy letters"
36
- }
37
- }
38
 
39
- # CSS personnalisé
40
  CUSTOM_CSS = """
41
  .container { max-width: 1200px; margin: auto; }
42
  .welcome { text-align: center; margin: 20px 0; padding: 20px; background: #1e293b; border-radius: 10px; }
43
  .quality-controls { margin: 10px 0; padding: 10px; background: #2d3748; border-radius: 5px; }
44
- .text-input { background: #2d3748; padding: 15px; border-radius: 5px; margin: 10px 0; }
 
 
 
45
  """
46
 
47
- def generate_enhanced_prompt(subject, style, title="", subtitle="", additional_details=""):
48
- """Génère un prompt optimisé pour le texte"""
49
  style_config = ART_STYLES[style]
 
50
 
51
  # Construction du prompt de base
52
  base_prompt = f"{style_config['prompt_prefix']}, {subject}"
53
 
54
- # Ajout des éléments de texte si présents
55
- text_elements = []
56
- if title:
57
- text_elements.append(f"with main title text '{title}'")
58
- if subtitle:
59
- text_elements.append(f"subtitle text '{subtitle}'")
60
-
61
- text_prompt = ", ".join(text_elements)
62
- if text_prompt:
63
- base_prompt += f", {text_prompt}, {style_config['text_style']}"
64
 
 
 
 
 
 
 
 
 
 
 
65
  if additional_details:
66
  base_prompt += f", {additional_details}"
67
 
68
- return base_prompt, style_config['negative_prompt']
 
 
 
 
 
69
 
70
- def generate_image(format_size, orientation, subject, style, title, subtitle, quality, creativity, additional_details=""):
 
 
71
  API_URL = "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-xl-base-1.0"
72
  headers = {"Authorization": f"Bearer {os.getenv('HUGGINGFACE_TOKEN')}"}
73
 
74
  try:
75
- # Dimensions optimisées
76
- width, height = (768, 1024) if format_size == "A4" else (1024, 1024)
77
- if orientation == "Paysage":
78
- width, height = height, width
79
-
 
 
 
 
 
 
80
  # Génération du prompt optimisé
81
- enhanced_prompt, negative_prompt = generate_enhanced_prompt(
82
- subject, style, title, subtitle, additional_details
83
  )
84
 
85
- print(f"Prompt: {enhanced_prompt}") # Debug
86
- print(f"Negative prompt: {negative_prompt}") # Debug
 
 
 
 
 
87
 
88
  # Configuration de la requête
89
  payload = {
@@ -92,8 +88,9 @@ def generate_image(format_size, orientation, subject, style, title, subtitle, qu
92
  "negative_prompt": negative_prompt,
93
  "num_inference_steps": int(ART_STYLES[style]['steps'] * (quality/100)),
94
  "guidance_scale": ART_STYLES[style]['guidance'] * (creativity/10),
95
- "width": width,
96
- "height": height
 
97
  }
98
  }
99
 
@@ -101,7 +98,7 @@ def generate_image(format_size, orientation, subject, style, title, subtitle, qu
101
 
102
  if response.status_code == 200:
103
  image = Image.open(io.BytesIO(response.content))
104
- return image, f"✨ Création {style} réussie avec texte intégré!"
105
  else:
106
  print(f"Erreur API: {response.text}") # Debug
107
  return None, f"⚠️ Erreur {response.status_code}: Ajustez les paramètres"
@@ -112,17 +109,18 @@ def generate_image(format_size, orientation, subject, style, title, subtitle, qu
112
 
113
  def create_interface():
114
  with gr.Blocks(css=CUSTOM_CSS) as app:
 
115
  gr.HTML("""
116
  <div class="welcome">
117
  <h1>🤖 Equity Artisan 3.0</h1>
118
- <p>Créez des affiches professionnelles étape par étape avec notre assistant créatif augmenté.</p>
119
  </div>
120
  """)
121
 
122
  with gr.Column(elem_classes="container"):
123
  # Étape 1: Format
124
- with gr.Group():
125
- gr.Markdown("### 📏 Étape 1: Format et Orientation")
126
  with gr.Row():
127
  format_choice = gr.Dropdown(
128
  choices=["A4", "A3", "A2", "A1", "A0"],
@@ -135,78 +133,89 @@ def create_interface():
135
  label="Orientation"
136
  )
137
 
138
- # Étape 2: Création Visuelle
139
- with gr.Group():
140
- gr.Markdown("### 🎨 Étape 2: Création Visuelle")
141
  with gr.Row():
142
- with gr.Column():
143
  style = gr.Dropdown(
144
  choices=list(ART_STYLES.keys()),
145
  value="Neo Vintage",
146
  label="Style artistique",
147
- info="Choisissez le style de votre affiche"
148
  )
149
-
 
 
 
 
 
 
 
 
 
 
 
 
150
  subject = gr.Textbox(
151
  label="Sujet principal",
152
- placeholder="Ex: loup, paysage urbain...",
153
- info="Décrivez l'élément principal"
154
  )
155
-
156
- # Nouvelle section texte
157
- with gr.Group(elem_classes="text-input"):
158
- gr.Markdown("#### 📝 Texte de l'affiche")
159
- title = gr.Textbox(
160
- label="Titre principal",
161
- placeholder="Texte principal qui apparaîtra sur l'affiche",
162
- info="Ce texte sera intégré de manière lisible"
163
- )
164
- subtitle = gr.Textbox(
165
- label="Sous-titre (optionnel)",
166
- placeholder="Texte secondaire plus petit",
167
- info="Texte complémentaire"
168
- )
169
-
170
  additional_details = gr.Textbox(
171
  lines=2,
172
  label="Détails additionnels (optionnel)",
173
- placeholder="Ajoutez des détails pour enrichir l'image...",
174
- info="Plus de détails = meilleur résultat"
175
  )
176
-
177
- with gr.Group(elem_classes="quality-controls"):
178
- quality = gr.Slider(
179
- minimum=30,
180
- maximum=50,
181
- value=35,
182
- step=5,
183
- label="Qualité",
184
- info="Influence le niveau de détail"
185
- )
186
-
187
- creativity = gr.Slider(
188
- minimum=5,
189
- maximum=15,
190
- value=7.5,
191
- step=0.5,
192
- label="Créativité",
193
- info="Balance entre fidélité et créativité"
194
- )
195
-
196
- generate_btn = gr.Button("✨ Générer", variant="primary")
197
- clear_btn = gr.Button("🗑️ Effacer", variant="secondary")
198
-
199
- image_output = gr.Image(
200
- label="Aperçu",
201
- type="pil"
202
  )
203
-
204
- # Statut
205
- status = gr.Textbox(
206
- label="Status",
207
- interactive=False,
208
- value="Prêt à générer"
209
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
 
211
  # Événements
212
  generate_btn.click(
@@ -216,6 +225,8 @@ def create_interface():
216
  orientation,
217
  subject,
218
  style,
 
 
219
  title,
220
  subtitle,
221
  quality,
 
1
  import gradio as gr
2
  import os
3
+ from PIL import Image, ImageDraw, ImageFont, ImageEnhance
4
  import requests
5
  import io
6
+ import json
7
 
8
+ # [Insérer ici le code des ART_STYLES, TEXT_EFFECTS, et THEME_COLLECTIONS précédents]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
+ # Interface utilisateur améliorée avec CSS personnalisé
11
  CUSTOM_CSS = """
12
  .container { max-width: 1200px; margin: auto; }
13
  .welcome { text-align: center; margin: 20px 0; padding: 20px; background: #1e293b; border-radius: 10px; }
14
  .quality-controls { margin: 10px 0; padding: 10px; background: #2d3748; border-radius: 5px; }
15
+ .style-group { background: #2d3748; padding: 15px; border-radius: 5px; margin: 10px 0; }
16
+ .text-effects { background: #374151; padding: 12px; border-radius: 5px; margin: 8px 0; }
17
+ .preview-panel { position: relative; }
18
+ .parameters { display: flex; gap: 10px; }
19
  """
20
 
21
+ def enhance_prompt(subject, style, text_effect, collection=None, additional_details=""):
22
+ """Génération de prompt optimisée"""
23
  style_config = ART_STYLES[style]
24
+ text_config = TEXT_EFFECTS[text_effect]
25
 
26
  # Construction du prompt de base
27
  base_prompt = f"{style_config['prompt_prefix']}, {subject}"
28
 
29
+ # Ajout des effets de texte
30
+ if text_effect != "Standard":
31
+ base_prompt += f", {text_config['prompt_suffix']}"
 
 
 
 
 
 
 
32
 
33
+ # Ajout des éléments de collection
34
+ if collection and collection in THEME_COLLECTIONS:
35
+ collection_data = THEME_COLLECTIONS[collection]
36
+ collection_elements = (
37
+ collection_data["prompts"] +
38
+ collection_data["styles"]
39
+ )
40
+ base_prompt += f", {', '.join(collection_elements)}"
41
+
42
+ # Ajout des détails supplémentaires
43
  if additional_details:
44
  base_prompt += f", {additional_details}"
45
 
46
+ # Construction du prompt négatif
47
+ negative_prompt = style_config['negative_prompt']
48
+ if collection:
49
+ negative_prompt += f", {THEME_COLLECTIONS[collection]['negative']}"
50
+
51
+ return base_prompt, negative_prompt
52
 
53
+ def generate_image(format_size, orientation, subject, style, text_effect, collection,
54
+ title, subtitle, quality, creativity, additional_details=""):
55
+ """Fonction de génération d'image améliorée"""
56
  API_URL = "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-xl-base-1.0"
57
  headers = {"Authorization": f"Bearer {os.getenv('HUGGINGFACE_TOKEN')}"}
58
 
59
  try:
60
+ # Optimisation des dimensions
61
+ base_width = 1024
62
+ base_height = 1024
63
+ if format_size in ["A4", "A3"]:
64
+ if orientation == "Portrait":
65
+ base_width = 768
66
+ base_height = 1024
67
+ else:
68
+ base_width = 1024
69
+ base_height = 768
70
+
71
  # Génération du prompt optimisé
72
+ enhanced_prompt, negative_prompt = enhance_prompt(
73
+ subject, style, text_effect, collection, additional_details
74
  )
75
 
76
+ # Ajout des textes si présents
77
+ if title or subtitle:
78
+ enhanced_prompt += f", with text elements: '{title}'"
79
+ if subtitle:
80
+ enhanced_prompt += f" and subtitle: '{subtitle}'"
81
+
82
+ print(f"Prompt final: {enhanced_prompt}") # Debug
83
 
84
  # Configuration de la requête
85
  payload = {
 
88
  "negative_prompt": negative_prompt,
89
  "num_inference_steps": int(ART_STYLES[style]['steps'] * (quality/100)),
90
  "guidance_scale": ART_STYLES[style]['guidance'] * (creativity/10),
91
+ "width": base_width,
92
+ "height": base_height,
93
+ "seed": int(creativity * 1000) # Pour la reproductibilité
94
  }
95
  }
96
 
 
98
 
99
  if response.status_code == 200:
100
  image = Image.open(io.BytesIO(response.content))
101
+ return image, f"✨ Création {style} avec effet {text_effect} réussie!"
102
  else:
103
  print(f"Erreur API: {response.text}") # Debug
104
  return None, f"⚠️ Erreur {response.status_code}: Ajustez les paramètres"
 
109
 
110
  def create_interface():
111
  with gr.Blocks(css=CUSTOM_CSS) as app:
112
+ # En-tête
113
  gr.HTML("""
114
  <div class="welcome">
115
  <h1>🤖 Equity Artisan 3.0</h1>
116
+ <p>Créez des affiches artistiques professionnelles avec notre assistant créatif augmenté.</p>
117
  </div>
118
  """)
119
 
120
  with gr.Column(elem_classes="container"):
121
  # Étape 1: Format
122
+ with gr.Group(elem_classes="style-group"):
123
+ gr.Markdown("### 📏 Format et Orientation")
124
  with gr.Row():
125
  format_choice = gr.Dropdown(
126
  choices=["A4", "A3", "A2", "A1", "A0"],
 
133
  label="Orientation"
134
  )
135
 
136
+ # Étape 2: Style et Contenu
137
+ with gr.Group(elem_classes="style-group"):
138
+ gr.Markdown("### 🎨 Style et Contenu")
139
  with gr.Row():
140
+ with gr.Column(scale=1):
141
  style = gr.Dropdown(
142
  choices=list(ART_STYLES.keys()),
143
  value="Neo Vintage",
144
  label="Style artistique",
145
+ info="Choisissez le style visuel"
146
  )
147
+ text_effect = gr.Dropdown(
148
+ choices=list(TEXT_EFFECTS.keys()),
149
+ value="Standard",
150
+ label="Effet de texte",
151
+ info="Style du texte"
152
+ )
153
+ collection = gr.Dropdown(
154
+ choices=list(THEME_COLLECTIONS.keys()),
155
+ label="Collection thématique",
156
+ info="Thème global"
157
+ )
158
+
159
+ with gr.Column(scale=2):
160
  subject = gr.Textbox(
161
  label="Sujet principal",
162
+ placeholder="Ex: loup, paysage urbain..."
 
163
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  additional_details = gr.Textbox(
165
  lines=2,
166
  label="Détails additionnels (optionnel)",
167
+ placeholder="Ajoutez des détails spécifiques..."
 
168
  )
169
+
170
+ # Étape 3: Texte
171
+ with gr.Group(elem_classes="text-effects"):
172
+ gr.Markdown("### ✍️ Texte de l'affiche")
173
+ with gr.Row():
174
+ title = gr.Textbox(
175
+ label="Titre principal",
176
+ placeholder="Texte principal de l'affiche"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  )
178
+ subtitle = gr.Textbox(
179
+ label="Sous-titre (optionnel)",
180
+ placeholder="Texte secondaire"
181
+ )
182
+
183
+ # Étape 4: Paramètres de génération
184
+ with gr.Group(elem_classes="style-group"):
185
+ gr.Markdown("### ⚙️ Paramètres")
186
+ with gr.Row():
187
+ quality = gr.Slider(
188
+ minimum=30,
189
+ maximum=50,
190
+ value=35,
191
+ step=5,
192
+ label="Qualité",
193
+ info="Niveau de détail"
194
+ )
195
+ creativity = gr.Slider(
196
+ minimum=5,
197
+ maximum=15,
198
+ value=7.5,
199
+ step=0.5,
200
+ label="Créativité",
201
+ info="Balance entre fidélité et originalité"
202
+ )
203
+
204
+ # Boutons de génération
205
+ with gr.Row():
206
+ generate_btn = gr.Button("✨ Générer", variant="primary")
207
+ clear_btn = gr.Button("🗑️ Effacer", variant="secondary")
208
+
209
+ # Zone de prévisualisation
210
+ with gr.Group(elem_classes="preview-panel"):
211
+ image_output = gr.Image(
212
+ label="Aperçu",
213
+ type="pil"
214
+ )
215
+ status = gr.Textbox(
216
+ label="Statut",
217
+ interactive=False
218
+ )
219
 
220
  # Événements
221
  generate_btn.click(
 
225
  orientation,
226
  subject,
227
  style,
228
+ text_effect,
229
+ collection,
230
  title,
231
  subtitle,
232
  quality,