Equityone commited on
Commit
d20b726
·
verified ·
1 Parent(s): f5f8164

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +102 -219
app.py CHANGED
@@ -19,119 +19,61 @@ logger = logging.getLogger(__name__)
19
  # Chargement des variables d'environnement
20
  load_dotenv()
21
 
22
- # Styles artistiques enrichis avec optimisations
23
  ART_STYLES = {
24
  # Styles Réalistes
25
  "Ultra Réaliste": {
26
- "prompt_prefix": """ultra realistic photograph, stunning photorealistic quality, unreal engine 5 quality,
27
- octane render, ray tracing, volumetric lighting, subsurface scattering, 8k UHD, cinema quality,
28
- masterpiece, perfect composition, award winning photography, professional lighting""",
29
- "negative_prompt": """artificial, digital art, illustration, painting, drawing, artistic, cartoon,
30
- anime, unreal, fake, low quality, blurry, soft, deformed, noisy, unclear, imperfect, amateur""",
31
- "quality_multiplier": 1.2
32
  },
33
  "Photoréaliste": {
34
- "prompt_prefix": """hyperrealistic photograph, extremely detailed, studio quality, professional photography,
35
- 8k uhd, perfect lighting, high-end camera, professional grade lens, expert composition""",
36
- "negative_prompt": """artistic, painterly, abstract, cartoon, illustration, low quality,
37
- amateur, imperfect, blurry, noise""",
38
- "quality_multiplier": 1.1
39
  },
40
-
41
- # Styles Artistiques
42
  "Expressionniste": {
43
- "prompt_prefix": """expressive painting style, intense emotional art, bold brushstrokes, vibrant colors,
44
- van gogh inspired, artistic masterpiece, deep emotional impact, dynamic composition""",
45
- "negative_prompt": """realistic, subtle, photographic, clean lines, digital art, flat, unemotional,
46
- generic, weak composition""",
47
- "quality_multiplier": 1.0
48
  },
49
  "Impressionniste": {
50
- "prompt_prefix": """impressionist painting style, soft light, visible brushstrokes, outdoor scene,
51
- monet inspired, artistic mastery, natural lighting, atmospheric effect""",
52
- "negative_prompt": """sharp details, high contrast, digital, modern, artificial, harsh,
53
- unrealistic colors""",
54
- "quality_multiplier": 1.0
 
55
  },
56
-
57
- # Styles Modernes
58
  "Art Moderne": {
59
- "prompt_prefix": """modern art style poster, professional design, contemporary aesthetic,
60
- trending on artstation, perfect composition, high-end production""",
61
- "negative_prompt": """traditional, cluttered, busy design, vintage, amateur, low quality,
62
- unprofessional""",
63
- "quality_multiplier": 1.1
64
  },
65
  "Minimaliste": {
66
- "prompt_prefix": """minimalist design poster, clean composition, elegant simplicity,
67
- perfect balance, sophisticated style, high-end design""",
68
- "negative_prompt": """complex, detailed, ornate, busy, cluttered, chaotic, unbalanced,
69
- amateur""",
70
- "quality_multiplier": 1.0
71
- },
72
-
73
- # Styles Spéciaux
74
- "Cyberpunk": {
75
- "prompt_prefix": """cyberpunk style, neon lights, futuristic design, high-tech aesthetic,
76
- detailed machinery, holographic elements, cinematic lighting""",
77
- "negative_prompt": """vintage, natural, rustic, traditional, simple, flat, dull,
78
- low-tech""",
79
- "quality_multiplier": 1.1
80
- },
81
- "Art Déco": {
82
- "prompt_prefix": """art deco style, geometric patterns, luxury design, 1920s aesthetic,
83
- golden age glamour, sophisticated composition""",
84
- "negative_prompt": """modern, minimalist, casual, contemporary, simple, rustic,
85
- unrefined""",
86
- "quality_multiplier": 1.0
87
  }
88
  }
89
 
90
- # Paramètres de composition enrichis
91
  COMPOSITION_PARAMS = {
92
  "Layouts": {
93
- "Centré": {
94
- "description": "centered composition, balanced layout, harmonious arrangement",
95
- "weight": 1.2
96
- },
97
- "Asymétrique": {
98
- "description": "dynamic asymmetrical composition, creative balance, artistic flow",
99
- "weight": 1.1
100
- },
101
- "Grille": {
102
- "description": "grid-based layout, structured composition, organized design, perfect alignment",
103
- "weight": 1.0
104
- },
105
- "Diagonal": {
106
- "description": "diagonal dynamic composition, energetic flow, dramatic arrangement",
107
- "weight": 1.1
108
- },
109
- "Minimaliste": {
110
- "description": "minimal composition, lots of whitespace, elegant spacing, perfect balance",
111
- "weight": 1.0
112
- }
113
  },
114
  "Ambiances": {
115
- "Dramatique": {
116
- "description": "dramatic lighting, high contrast, intense mood, cinematic atmosphere",
117
- "weight": 1.2
118
- },
119
- "Doux": {
120
- "description": "soft lighting, gentle atmosphere, subtle mood, delicate ambiance",
121
- "weight": 1.0
122
- },
123
- "Vibrant": {
124
- "description": "vibrant colors, energetic mood, dynamic atmosphere, bold presence",
125
- "weight": 1.1
126
- },
127
- "Mystérieux": {
128
- "description": "mysterious atmosphere, moody lighting, enigmatic feel, intriguing shadows",
129
- "weight": 1.1
130
- },
131
- "Serein": {
132
- "description": "peaceful atmosphere, calm mood, tranquil setting, harmonious lighting",
133
- "weight": 1.0
134
- }
135
  }
136
  }
137
 
@@ -144,87 +86,54 @@ class ImageGenerator:
144
  self.headers = {"Authorization": f"Bearer {token}"}
145
  logger.info("ImageGenerator initialisé")
146
 
147
- def _optimize_prompt(self, params: Dict[str, Any]) -> Tuple[str, str]:
148
- """Optimisation avancée des prompts avec gestion contextuelle"""
149
- style_info = ART_STYLES.get(params["style"], ART_STYLES["Art Moderne"])
150
- layout_info = COMPOSITION_PARAMS["Layouts"].get(params["layout"])
151
- ambiance_info = COMPOSITION_PARAMS["Ambiances"].get(params["ambiance"])
152
-
153
- # Construction du prompt principal
154
- base_prompt = f"{params['subject']}"
155
- if params.get('title'):
156
- base_prompt += f", with text '{params['title']}'"
157
-
158
- # Ajout des éléments de composition
159
- composition_elements = [
160
- style_info["prompt_prefix"],
161
- layout_info["description"],
162
- ambiance_info["description"]
163
- ]
164
-
165
- # Calcul du multiplicateur de qualité
166
- quality_multiplier = (
167
- style_info.get("quality_multiplier", 1.0) *
168
- layout_info.get("weight", 1.0) *
169
- ambiance_info.get("weight", 1.0)
170
- )
171
-
172
- # Construction du prompt final optimisé
173
- enhanced_prompt = f"{base_prompt}, {', '.join(composition_elements)}"
174
-
175
- # Construction du negative prompt optimisé
176
- negative_prompt = f"{style_info['negative_prompt']}, low quality, bad anatomy, worst quality, low resolution"
177
-
178
- return enhanced_prompt, negative_prompt, quality_multiplier
179
-
180
- def _enhance_image(self, image: Image.Image, params: Dict[str, Any]) -> Image.Image:
181
- """Post-traitement avancé des images"""
182
  try:
183
- # Amélioration de la netteté basée sur le style
184
- sharpness_factor = 1.2 if params["style"] in ["Ultra Réaliste", "Photoréaliste"] else 1.1
185
- enhancer = ImageEnhance.Sharpness(image)
186
- image = enhancer.enhance(sharpness_factor)
187
-
188
- # Ajustement du contraste selon l'ambiance
189
- contrast_factor = 1.2 if params["ambiance"] == "Dramatique" else 1.1
190
- enhancer = ImageEnhance.Contrast(image)
191
- image = enhancer.enhance(contrast_factor)
 
 
 
 
 
 
 
 
 
192
 
193
- return image
194
  except Exception as e:
195
- logger.warning(f"Erreur lors de l'amélioration de l'image: {str(e)}")
196
- return image
197
 
198
  def generate(self, params: Dict[str, Any]) -> Tuple[Optional[Image.Image], str]:
199
- """Génération d'image avec optimisations avancées"""
200
  try:
201
  logger.info(f"Début de génération avec paramètres: {json.dumps(params, indent=2)}")
202
 
203
  if 'Bearer None' in self.headers['Authorization']:
204
  return None, "⚠️ Erreur: Token Hugging Face non configuré"
205
 
206
- # Optimisation des prompts
207
- enhanced_prompt, negative_prompt, quality_multiplier = self._optimize_prompt(params)
208
-
209
- # Configuration des paramètres de génération
210
- generation_params = {
211
- "num_inference_steps": min(int(50 * quality_multiplier), 60),
212
- "guidance_scale": min(8.5 * (params["creativity"]/10), 12.0),
213
- "width": 1024 if params.get("quality", 35) > 40 else 768,
214
- "height": 1024 if params["orientation"] == "Portrait" else 768
215
- }
216
 
217
  payload = {
218
- "inputs": enhanced_prompt,
219
  "parameters": {
220
- **generation_params,
221
- "negative_prompt": negative_prompt
 
 
 
222
  }
223
  }
224
 
225
- logger.debug(f"Payload final: {json.dumps(payload, indent=2)}")
226
 
227
- # Génération de l'image
228
  response = requests.post(
229
  self.API_URL,
230
  headers=self.headers,
@@ -234,7 +143,7 @@ class ImageGenerator:
234
 
235
  if response.status_code == 200:
236
  image = Image.open(io.BytesIO(response.content))
237
- # Post-traitement de l'image
238
  image = self._enhance_image(image, params)
239
  return image, "✨ Création réussie!"
240
  else:
@@ -249,50 +158,43 @@ class ImageGenerator:
249
  finally:
250
  gc.collect()
251
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
252
  def create_interface():
253
- """Création de l'interface utilisateur enrichie"""
254
  logger.info("Création de l'interface Gradio")
255
 
256
- # Styles CSS personnalisés
257
  css = """
258
  .container { max-width: 1200px; margin: auto; }
259
- .welcome {
260
- text-align: center;
261
- margin: 20px 0;
262
- padding: 20px;
263
- background: linear-gradient(135deg, #1e293b, #334155);
264
- border-radius: 10px;
265
- color: white;
266
- }
267
- .controls-group {
268
- background: #2d3748;
269
- padding: 15px;
270
- border-radius: 5px;
271
- margin: 10px 0;
272
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
273
- }
274
- .advanced-controls {
275
- background: #374151;
276
- padding: 12px;
277
- border-radius: 5px;
278
- margin: 8px 0;
279
- }
280
- .info-tooltip {
281
- color: #94a3b8;
282
- font-size: 0.9em;
283
- margin-top: 4px;
284
- }
285
  """
286
 
287
  generator = ImageGenerator()
288
 
289
  with gr.Blocks(css=css) as app:
290
- # En-tête et présentation
291
  gr.HTML("""
292
  <div class="welcome">
293
  <h1>🎨 Equity Artisan 3.0</h1>
294
  <p>Assistant de création d'affiches professionnelles</p>
295
- <p style="font-size: 0.9em; opacity: 0.8;">Powered by Stable Diffusion XL</p>
296
  </div>
297
  """)
298
 
@@ -305,19 +207,16 @@ def create_interface():
305
  3. Décrivez votre vision dans "Description"
306
  4. Ajustez les paramètres fins selon vos besoins
307
  5. Cliquez sur "Générer" !
308
-
309
- *💡 Pro Tip: Pour de meilleurs résultats, soyez précis dans votre description et expérimentez avec différents styles.*
310
  """)
311
 
312
- # Contrôles principaux
313
  with gr.Group(elem_classes="controls-group"):
314
  gr.Markdown("### 📐 Format et Orientation")
315
  with gr.Row():
316
  format_size = gr.Dropdown(
317
  choices=["A4", "A3", "A2", "A1", "A0"],
318
  value="A4",
319
- label="Format",
320
- info="Choisissez la taille de votre affiche"
321
  )
322
  orientation = gr.Radio(
323
  choices=["Portrait", "Paysage"],
@@ -325,7 +224,7 @@ def create_interface():
325
  label="Orientation"
326
  )
327
 
328
- # Style et composition
329
  with gr.Group(elem_classes="controls-group"):
330
  gr.Markdown("### 🎨 Style et Composition")
331
  with gr.Row():
@@ -347,17 +246,17 @@ def create_interface():
347
  label="Ambiance"
348
  )
349
  palette = gr.Dropdown(
350
- choices=["Monochrome", "Contrasté", "Pastel", "Terre", "Néon"],
351
  value="Contrasté",
352
  label="Palette"
353
  )
354
 
355
- # Description et contenu
356
  with gr.Group(elem_classes="controls-group"):
357
  gr.Markdown("### 📝 Contenu")
358
  subject = gr.Textbox(
359
  label="Description",
360
- placeholder="Ex: Une affiche moderne pour un festival de musique, avec des instruments colorés flottant dans l'espace",
361
  lines=3
362
  )
363
  title = gr.Textbox(
@@ -366,8 +265,6 @@ def create_interface():
366
  )
367
 
368
  # Contrôles avancés
369
- with gr.Group(elem_classes="advanced-controls"):
370
- gr.Markdown("### 🎯 Paramètres Av# Contrôles avancés
371
  with gr.Group(elem_classes="advanced-controls"):
372
  gr.Markdown("### 🎯 Paramètres Avancés")
373
  with gr.Row():
@@ -376,24 +273,21 @@ def create_interface():
376
  maximum=10,
377
  value=7,
378
  step=1,
379
- label="Niveau de Détail",
380
- info="Plus la valeur est élevée, plus l'image sera détaillée"
381
  )
382
  contrast = gr.Slider(
383
  minimum=1,
384
  maximum=10,
385
  value=5,
386
  step=1,
387
- label="Contraste",
388
- info="Influence l'intensité des couleurs et la différence entre les zones claires et sombres"
389
  )
390
  saturation = gr.Slider(
391
  minimum=1,
392
  maximum=10,
393
  value=5,
394
  step=1,
395
- label="Saturation",
396
- info="Contrôle la vivacité des couleurs"
397
  )
398
 
399
  # Paramètres de génération
@@ -404,32 +298,22 @@ def create_interface():
404
  minimum=30,
405
  maximum=50,
406
  value=35,
407
- label="Qualité",
408
- info="Influence la qualité finale de l'image. Une valeur plus élevée prend plus de temps"
409
  )
410
  creativity = gr.Slider(
411
  minimum=5,
412
  maximum=15,
413
  value=7.5,
414
- label="Créativité",
415
- info="Plus la valeur est élevée, plus l'IA prendra de libertés créatives"
416
  )
417
 
418
- # Boutons de contrôle
419
  with gr.Row():
420
  generate_btn = gr.Button("✨ Générer", variant="primary")
421
  clear_btn = gr.Button("🗑️ Effacer", variant="secondary")
422
 
423
  # Zone de résultat
424
- with gr.Group(elem_classes="controls-group"):
425
- gr.Markdown("### 🖼️ Résultat")
426
- image_output = gr.Image(label="Aperçu", height=512)
427
- status = gr.Textbox(label="Statut", interactive=False)
428
-
429
- # Zone d'historique
430
- with gr.Group(elem_classes="controls-group"):
431
- gr.Markdown("### 📋 Historique des Générations")
432
- history = gr.Gallery(label="Générations précédentes", show_label=True, columns=4, height=200)
433
 
434
  # Fonction de génération
435
  def generate(*args):
@@ -484,5 +368,4 @@ def create_interface():
484
 
485
  if __name__ == "__main__":
486
  app = create_interface()
487
- logger.info("Démarrage de l'application")
488
  app.launch()
 
19
  # Chargement des variables d'environnement
20
  load_dotenv()
21
 
22
+ # Styles artistiques complets
23
  ART_STYLES = {
24
  # Styles Réalistes
25
  "Ultra Réaliste": {
26
+ "prompt_prefix": "ultra realistic photograph, stunning photorealistic quality, unreal engine 5 quality, octane render, ray tracing, volumetric lighting, subsurface scattering, 8k UHD, cinema quality, masterpiece, perfect composition, award winning photography",
27
+ "negative_prompt": "artificial, digital art, illustration, painting, drawing, artistic, cartoon, anime, unreal, fake, low quality, blurry, soft, deformed"
 
 
 
 
28
  },
29
  "Photoréaliste": {
30
+ "prompt_prefix": "hyperrealistic photograph, extremely detailed, studio quality, professional photography, 8k uhd",
31
+ "negative_prompt": "artistic, painterly, abstract, cartoon, illustration, low quality"
 
 
 
32
  },
 
 
33
  "Expressionniste": {
34
+ "prompt_prefix": "expressive painting style, intense emotional art, bold brushstrokes, vibrant colors, van gogh inspired",
35
+ "negative_prompt": "realistic, subtle, photographic, clean lines, digital art"
 
 
 
36
  },
37
  "Impressionniste": {
38
+ "prompt_prefix": "impressionist painting style, soft light, visible brushstrokes, outdoor scene, monet inspired",
39
+ "negative_prompt": "sharp details, high contrast, digital, modern"
40
+ },
41
+ "Art Abstrait": {
42
+ "prompt_prefix": "abstract art, geometric shapes, non-representational, kandinsky style, pure artistic expression",
43
+ "negative_prompt": "realistic, figurative, photographic, literal"
44
  },
 
 
45
  "Art Moderne": {
46
+ "prompt_prefix": "modern art style poster, professional design, contemporary aesthetic",
47
+ "negative_prompt": "traditional, cluttered, busy design, vintage"
 
 
 
48
  },
49
  "Minimaliste": {
50
+ "prompt_prefix": "minimalist design poster, clean composition, elegant simplicity",
51
+ "negative_prompt": "complex, detailed, ornate, busy, cluttered"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  }
53
  }
54
 
55
+ # Paramètres de composition
56
  COMPOSITION_PARAMS = {
57
  "Layouts": {
58
+ "Centré": "centered composition, balanced layout, harmonious arrangement",
59
+ "Asymétrique": "dynamic asymmetrical composition, creative balance",
60
+ "Grille": "grid-based layout, structured composition, organized design",
61
+ "Diagonal": "diagonal dynamic composition, energetic flow",
62
+ "Minimaliste": "minimal composition, lots of whitespace, elegant spacing"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  },
64
  "Ambiances": {
65
+ "Dramatique": "dramatic lighting, high contrast, intense mood",
66
+ "Doux": "soft lighting, gentle atmosphere, subtle mood",
67
+ "Vibrant": "vibrant colors, energetic mood, dynamic atmosphere",
68
+ "Mystérieux": "mysterious atmosphere, moody lighting, enigmatic feel",
69
+ "Serein": "peaceful atmosphere, calm mood, tranquil setting"
70
+ },
71
+ "Palette": {
72
+ "Monochrome": "monochromatic color scheme, sophisticated tones",
73
+ "Contrasté": "high contrast color palette, bold color combinations",
74
+ "Pastel": "soft pastel color palette, gentle colors",
75
+ "Terre": "earthy color palette, natural tones",
76
+ "Néon": "neon color palette, vibrant glowing colors"
 
 
 
 
 
 
 
 
77
  }
78
  }
79
 
 
86
  self.headers = {"Authorization": f"Bearer {token}"}
87
  logger.info("ImageGenerator initialisé")
88
 
89
+ def _build_prompt(self, params: Dict[str, Any]) -> str:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  try:
91
+ style_info = ART_STYLES.get(params["style"], ART_STYLES["Art Moderne"])
92
+
93
+ # Construction du prompt de base
94
+ base_prompt = f"{params['subject']}"
95
+ if params.get('title'):
96
+ base_prompt += f", with text '{params['title']}'"
97
+
98
+ # Ajout des éléments de composition
99
+ composition_elements = [
100
+ style_info['prompt_prefix'],
101
+ COMPOSITION_PARAMS['Layouts'][params['layout']],
102
+ COMPOSITION_PARAMS['Ambiances'][params['ambiance']],
103
+ COMPOSITION_PARAMS['Palette'][params['palette']]
104
+ ]
105
+
106
+ enhanced_prompt = f"{base_prompt}, {', '.join(composition_elements)}"
107
+
108
+ return enhanced_prompt
109
 
 
110
  except Exception as e:
111
+ logger.error(f"Erreur dans la construction du prompt: {str(e)}")
112
+ return f"{style_info['prompt_prefix']}, {params['subject']}"
113
 
114
  def generate(self, params: Dict[str, Any]) -> Tuple[Optional[Image.Image], str]:
 
115
  try:
116
  logger.info(f"Début de génération avec paramètres: {json.dumps(params, indent=2)}")
117
 
118
  if 'Bearer None' in self.headers['Authorization']:
119
  return None, "⚠️ Erreur: Token Hugging Face non configuré"
120
 
121
+ prompt = self._build_prompt(params)
122
+ style_info = ART_STYLES[params["style"]]
 
 
 
 
 
 
 
 
123
 
124
  payload = {
125
+ "inputs": prompt,
126
  "parameters": {
127
+ "negative_prompt": style_info["negative_prompt"],
128
+ "num_inference_steps": min(int(35 * (params["quality"]/100)), 40),
129
+ "guidance_scale": min(7.5 * (params["creativity"]/10), 10.0),
130
+ "width": 1024 if params.get("quality", 35) > 40 else 768,
131
+ "height": 1024 if params["orientation"] == "Portrait" else 768
132
  }
133
  }
134
 
135
+ logger.debug(f"Payload: {json.dumps(payload, indent=2)}")
136
 
 
137
  response = requests.post(
138
  self.API_URL,
139
  headers=self.headers,
 
143
 
144
  if response.status_code == 200:
145
  image = Image.open(io.BytesIO(response.content))
146
+ # Post-traitement basé sur les paramètres
147
  image = self._enhance_image(image, params)
148
  return image, "✨ Création réussie!"
149
  else:
 
158
  finally:
159
  gc.collect()
160
 
161
+ def _enhance_image(self, image: Image.Image, params: Dict[str, Any]) -> Image.Image:
162
+ """Applique des améliorations post-génération à l'image"""
163
+ try:
164
+ # Ajustement du contraste
165
+ if params.get("contrast", 5) != 5:
166
+ enhancer = ImageEnhance.Contrast(image)
167
+ factor = params["contrast"] / 5
168
+ image = enhancer.enhance(factor)
169
+
170
+ # Ajustement de la saturation
171
+ if params.get("saturation", 5) != 5:
172
+ enhancer = ImageEnhance.Color(image)
173
+ factor = params["saturation"] / 5
174
+ image = enhancer.enhance(factor)
175
+
176
+ return image
177
+ except Exception as e:
178
+ logger.warning(f"Erreur lors de l'amélioration de l'image: {e}")
179
+ return image
180
+
181
  def create_interface():
 
182
  logger.info("Création de l'interface Gradio")
183
 
 
184
  css = """
185
  .container { max-width: 1200px; margin: auto; }
186
+ .welcome { text-align: center; margin: 20px 0; padding: 20px; background: #1e293b; border-radius: 10px; }
187
+ .controls-group { background: #2d3748; padding: 15px; border-radius: 5px; margin: 10px 0; }
188
+ .advanced-controls { background: #374151; padding: 12px; border-radius: 5px; margin: 8px 0; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
  """
190
 
191
  generator = ImageGenerator()
192
 
193
  with gr.Blocks(css=css) as app:
 
194
  gr.HTML("""
195
  <div class="welcome">
196
  <h1>🎨 Equity Artisan 3.0</h1>
197
  <p>Assistant de création d'affiches professionnelles</p>
 
198
  </div>
199
  """)
200
 
 
207
  3. Décrivez votre vision dans "Description"
208
  4. Ajustez les paramètres fins selon vos besoins
209
  5. Cliquez sur "Générer" !
 
 
210
  """)
211
 
212
+ # Format et Orientation
213
  with gr.Group(elem_classes="controls-group"):
214
  gr.Markdown("### 📐 Format et Orientation")
215
  with gr.Row():
216
  format_size = gr.Dropdown(
217
  choices=["A4", "A3", "A2", "A1", "A0"],
218
  value="A4",
219
+ label="Format"
 
220
  )
221
  orientation = gr.Radio(
222
  choices=["Portrait", "Paysage"],
 
224
  label="Orientation"
225
  )
226
 
227
+ # Style et Composition
228
  with gr.Group(elem_classes="controls-group"):
229
  gr.Markdown("### 🎨 Style et Composition")
230
  with gr.Row():
 
246
  label="Ambiance"
247
  )
248
  palette = gr.Dropdown(
249
+ choices=list(COMPOSITION_PARAMS["Palette"].keys()),
250
  value="Contrasté",
251
  label="Palette"
252
  )
253
 
254
+ # Contenu
255
  with gr.Group(elem_classes="controls-group"):
256
  gr.Markdown("### 📝 Contenu")
257
  subject = gr.Textbox(
258
  label="Description",
259
+ placeholder="Ex: Une affiche moderne pour un festival de musique...",
260
  lines=3
261
  )
262
  title = gr.Textbox(
 
265
  )
266
 
267
  # Contrôles avancés
 
 
268
  with gr.Group(elem_classes="advanced-controls"):
269
  gr.Markdown("### 🎯 Paramètres Avancés")
270
  with gr.Row():
 
273
  maximum=10,
274
  value=7,
275
  step=1,
276
+ label="Niveau de Détail"
 
277
  )
278
  contrast = gr.Slider(
279
  minimum=1,
280
  maximum=10,
281
  value=5,
282
  step=1,
283
+ label="Contraste"
 
284
  )
285
  saturation = gr.Slider(
286
  minimum=1,
287
  maximum=10,
288
  value=5,
289
  step=1,
290
+ label="Saturation"
 
291
  )
292
 
293
  # Paramètres de génération
 
298
  minimum=30,
299
  maximum=50,
300
  value=35,
301
+ label="Qualité"
 
302
  )
303
  creativity = gr.Slider(
304
  minimum=5,
305
  maximum=15,
306
  value=7.5,
307
+ label="Créativité"
 
308
  )
309
 
 
310
  with gr.Row():
311
  generate_btn = gr.Button("✨ Générer", variant="primary")
312
  clear_btn = gr.Button("🗑️ Effacer", variant="secondary")
313
 
314
  # Zone de résultat
315
+ image_output = gr.Image(label="Aperçu")
316
+ status = gr.Textbox(label="Statut", interactive=False)
 
 
 
 
 
 
 
317
 
318
  # Fonction de génération
319
  def generate(*args):
 
368
 
369
  if __name__ == "__main__":
370
  app = create_interface()
 
371
  app.launch()