Astridkraft commited on
Commit
1df8fa0
·
verified ·
1 Parent(s): 0a9b06c

Update ui.py

Browse files
Files changed (1) hide show
  1. ui.py +174 -165
ui.py CHANGED
@@ -12,15 +12,13 @@ def mock_text_to_image(prompt, model_id, steps, guidance_scale, progress=None):
12
  print(f"📝 Mock text_to_image aufgerufen: '{prompt[:50]}...'")
13
 
14
  if progress:
15
- for i in range(10): # Simuliere Fortschritt
16
  time.sleep(0.05)
17
  progress((i+1)/10, desc="Mock-Generierung läuft...")
18
 
19
- # Erstelle einfaches Farbbild
20
  colors = ["lightblue", "lightgreen", "lavender", "peachpuff"]
21
  img = Image.new('RGB', (512, 512), color=random.choice(colors))
22
 
23
- # Füge Text hinzu (simulierter Prompt)
24
  draw = ImageDraw.Draw(img)
25
  text = f"Mock: {prompt[:30]}..." if len(prompt) > 30 else f"Mock: {prompt}"
26
  draw.text((50, 256), text, fill="black")
@@ -41,11 +39,9 @@ def mock_img_to_image(image, prompt, neg_prompt, strength, steps, guidance_scale
41
  time.sleep(0.05)
42
  progress((i+1)/10, desc=f"Mock-{mode} läuft...")
43
 
44
- # Kopiere Bild und füge Effekte hinzu
45
  img = image.copy().convert("RGB")
46
  draw = ImageDraw.Draw(img)
47
 
48
- # Rahmen basierend auf Modus
49
  colors = {
50
  "environment_change": "green",
51
  "focus_change": "orange",
@@ -53,22 +49,18 @@ def mock_img_to_image(image, prompt, neg_prompt, strength, steps, guidance_scale
53
  }
54
  border_color = colors.get(mode, "blue")
55
 
56
- # Zeichne Rahmen
57
  draw.rectangle([20, 20, img.width-20, img.height-20],
58
  outline=border_color, width=10)
59
 
60
- # BBox visualisieren (falls angegeben)
61
  if all(v is not None for v in [bbox_x1, bbox_y1, bbox_x2, bbox_y2]):
62
  x1, y1 = min(bbox_x1, bbox_x2), min(bbox_y1, bbox_y2)
63
  x2, y2 = max(bbox_x1, bbox_x2), max(bbox_y1, bbox_y2)
64
  draw.rectangle([x1, y1, x2, y2], outline="yellow", width=5)
65
  draw.text((x1+5, y1+5), f"{mode}", fill="white")
66
 
67
- # Text hinzufügen
68
  draw.text((30, 30), f"Mock: {mode}", fill=border_color)
69
  draw.text((30, 60), f"Strength: {strength}", fill="black")
70
 
71
- # Mock-Masken (einfache Platzhalter)
72
  mask_preview = Image.new('RGB', (256, 256), color='gray')
73
  controlnet_map = Image.new('RGB', (256, 256), color='darkblue')
74
  canny_map = Image.new('RGB', (256, 256), color='black')
@@ -78,24 +70,91 @@ def mock_img_to_image(image, prompt, neg_prompt, strength, steps, guidance_scale
78
 
79
  return img, mask_preview, mask_preview, controlnet_map, canny_map
80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
 
82
  def mock_update_live_preview(image, bbox_x1, bbox_y1, bbox_x2, bbox_y2, mode):
83
  """Mock für Live-Vorschau MIT dynamischen Rahmen"""
84
  if not image:
85
  return None
86
 
87
- # Koordinaten sortieren
88
  bbox_coords = sort_coordinates(bbox_x1, bbox_y1, bbox_x2, bbox_y2)
89
-
90
- # Verbesserte Vorschau mit dynamischen Rahmen
91
  return create_preview_image(image, bbox_coords, mode)
92
 
93
-
94
-
95
  def mock_process_image_upload(image):
96
- """Mock für Bild-Upload: Setzt BBox in der Mitte"""
97
  if not image:
98
- return None, 100, 300, 100, 300
99
 
100
  w, h = image.size
101
  bbox_size = min(w, h) * 0.3
@@ -104,8 +163,9 @@ def mock_process_image_upload(image):
104
  x2 = x1 + bbox_size
105
  y2 = y1 + bbox_size * 1.2
106
 
107
- preview = mock_update_live_preview(image, x1, y1, x2, y2, "environment_change")
108
- return preview, int(x1), int(y1), int(x2), int(y2) # Reihenfolge x1, x2, y1, y2
 
109
 
110
  def mock_update_slider_for_image(image):
111
  """Mock für Slider-Update"""
@@ -140,130 +200,11 @@ def mock_update_model_settings(model_id):
140
  def mock_update_info(mode):
141
  """Mock für Prompt-Info-Update"""
142
  if mode == "environment_change":
143
- return (
144
- "`[STIL-MOTIV], [UMGEBUNG], [VOR/HINTERGRUND]`",
145
- "`[GESICHTER/ANATOMIE], [FEHLER]`"
146
- )
147
- elif mode == "focus_change":
148
- return (
149
- "`[GESICHTSBESCHREIBUNG], [KLEIDUNG], [POSITION]`",
150
- "`[DEFORMIERT], [UNSCHÄRFE], [ANATOMIEFEHLER]`"
151
- )
152
- else:
153
- return (
154
- "`[HAARFARBE], [AUGEN], [GESICHTSAUSDRUCK]`",
155
- "`[UNREALISTISCH], [ASYMETRISCH]`"
156
- )
157
-
158
- def sort_coordinates(x1, y1, x2, y2):
159
- """Sortiert Koordinaten, so dass x1 <= x2 und y1 <= y2"""
160
- sorted_x1 = min(x1, x2)
161
- sorted_x2 = max(x1, x2)
162
- sorted_y1 = min(y1, y2)
163
- sorted_y2 = max(y1, y2)
164
- return sorted_x1, sorted_y1, sorted_x2, sorted_y2
165
-
166
- #Rahmendicke für alle Bildgrößen
167
- def create_preview_image(image, bbox_coords, mode):
168
- """
169
- ERWEITERTE FUNKTION: Erstellt Vorschau mit dynamischer Rahmendicke
170
-
171
- Die Rahmendicke skaliert basierend auf der Bildgröße:
172
- - Kleine Bilder: Mindestdicke 8px
173
- - Große Bilder: Dicke = Bildbreite / 200 (z.B. 4096px → ~20px Dicke)
174
- """
175
- if image is None:
176
- return None
177
-
178
- preview = image.copy()
179
- draw = ImageDraw.Draw(preview)
180
-
181
- # Farben basierend auf Modus
182
- if mode == "environment_change":
183
- border_color = (0, 255, 0, 180) # Grün für Umgebung
184
- mode_text = "UMGEBUNG ÄNDERN (Bereich geschützt)"
185
- box_color = (255, 255, 0, 200) # Gelb für geschützten Bereich
186
- text_bg_color = (0, 128, 0, 160) # Dunkelgrün
187
-
188
  elif mode == "focus_change":
189
- border_color = (255, 165, 0, 180) # Orange für Focus
190
- mode_text = "FOCUS VERÄNDERN (Bereich+Körper)"
191
- box_color = (255, 0, 0, 200) # Rot für Veränderungsbereich
192
- text_bg_color = (255, 140, 0, 160) # Dunkelorange
193
-
194
- elif mode == "face_only_change":
195
- border_color = (255, 0, 0, 180) # Rot für nur Gesicht
196
- mode_text = "NUR BEREICH VERÄNDERN"
197
- box_color = (255, 0, 0, 200) # Rot für Veränderungsbereich
198
- text_bg_color = (128, 0, 0, 160) # Dunkelrot
199
  else:
200
- # Fallback
201
- border_color = (128, 128, 128, 180)
202
- mode_text = "UNBEKANNTER MODUS"
203
- box_color = (128, 128, 128, 200)
204
- text_bg_color = (64, 64, 64, 160)
205
-
206
- # ==============================================
207
- # WICHTIG: DYNAMISCHE RAHMENDICKE
208
- # ==============================================
209
- # Basierend auf Bildgröße skalieren
210
- # Formel: Mindestens 8px, bei großen Bildern dicker (Breite/200)
211
- border_width = max(8, image.width // 200)
212
- box_width = max(3, image.width // 400) # BBox-Rahmen etwas dünner
213
-
214
- print(f"📐 Dynamische Rahmendicke für {image.width}x{image.height}:")
215
- print(f" - Außenrahmen: {border_width}px")
216
- print(f" - BBox-Rahmen: {box_width}px")
217
-
218
- # 1. ÄUßERER RAHMEN (um gesamtes Bild)
219
- draw.rectangle([0, 0, preview.width-1, preview.height-1],
220
- outline=border_color, width=border_width)
221
-
222
- if bbox_coords and all(coord is not None for coord in bbox_coords):
223
- # Sortiere Koordinaten
224
- x1, y1, x2, y2 = sort_coordinates(*bbox_coords)
225
-
226
- # Stelle sicher, dass die Koordinaten innerhalb des Bildes liegen
227
- x1 = max(0, min(x1, preview.width-1))
228
- y1 = max(0, min(y1, preview.height-1))
229
- x2 = max(0, min(x2, preview.width-1))
230
- y2 = max(0, min(y2, preview.height-1))
231
-
232
- # Nur zeichnen, wenn die Bounding Box gültig ist
233
- if x2 > x1 and y2 > y1:
234
- # 2. BBOX-RAHMEN (mit dynamischer Dicke)
235
- draw.rectangle([x1, y1, x2, y2], outline=box_color, width=box_width)
236
-
237
- text_color = (255, 255, 255)
238
-
239
- # 3. TEXT-LABEL (skaliert auch Schriftgröße optional)
240
- text_y = max(0, y1 - 25)
241
-
242
- # Verwende textbbox um Textgröße zu berechnen
243
- from PIL import ImageFont
244
- try:
245
- # Versuche eine skalierbare Schrift
246
- font_size = max(12, image.width // 50) # Dynamische Schriftgröße
247
- font = ImageFont.truetype("arial.ttf", font_size)
248
- text_bbox = draw.textbbox((x1, text_y), mode_text, font=font)
249
- draw.text((x1, text_y), mode_text, fill=text_color, font=font)
250
- except:
251
- # Fallback ohne spezielle Schrift
252
- text_bbox = draw.textbbox((x1, text_y), mode_text)
253
- draw.text((x1, text_y), mode_text, fill=text_color)
254
-
255
- # Hintergrund für Text
256
- draw.rectangle([text_bbox[0]-5, text_bbox[1]-2,
257
- text_bbox[2]+5, text_bbox[3]+2],
258
- fill=text_bg_color)
259
-
260
- # Text nochmal darüber zeichnen
261
- try:
262
- draw.text((x1, text_y), mode_text, fill=text_color, font=font)
263
- except:
264
- draw.text((x1, text_y), mode_text, fill=text_color)
265
-
266
- return preview
267
 
268
  # ==================== UI-DEFINITION ====================
269
  def main_ui():
@@ -272,11 +213,82 @@ def main_ui():
272
  title="AI Image Generator - Mock Version",
273
  theme=gr.themes.Base(),
274
  css="""
275
- .info-box { background: #f8fafc; padding: 8px 12px; border-radius: 6px; margin-bottom: 6px; }
276
- .model-info-box { background: #e8f4fd; padding: 12px; border-radius: 6px; margin: 10px 0; border-left: 4px solid #2196f3; }
277
- #generate-button { background-color: #0080FF !important; margin: 20px auto !important; width: 280px; }
278
- .radio-group { background: #f8f9fa; padding: 15px; border-radius: 8px; margin: 10px 0; }
279
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
280
  ) as demo:
281
 
282
  with gr.Tab("Text zu Bild"):
@@ -333,7 +345,6 @@ def main_ui():
333
  height=400
334
  )
335
 
336
- # Event-Handler
337
  model_dropdown.change(
338
  fn=mock_update_model_settings,
339
  inputs=[model_dropdown],
@@ -382,37 +393,35 @@ def main_ui():
382
  with gr.Row():
383
  gr.Markdown("### 📐 Bildelementbereich anpassen")
384
 
 
385
  with gr.Row():
386
  with gr.Column():
387
  bbox_x1 = gr.Slider(
388
  label="← Links (x1)",
389
- minimum=0, maximum=4096, value=100, step=1,
390
- info="Linke Kante des Bildelementbereichs"
391
  )
392
  with gr.Column():
393
- bbox_x2 = gr.Slider(
394
  label="→ Rechts (x2)",
395
- minimum=0, maximum=4096, value=100, step=1,
396
- info="Rechte Kante des Bildelementbereichs"
397
  )
 
398
  with gr.Row():
399
  with gr.Column():
400
- bbox_y1 = gr.Slider(
401
  label="↑ Oben (y1)",
402
- minimum=0, maximum=4096, value=300, step=1,
403
- info="Obere Kante des Bildelementbereichs"
404
  )
405
  with gr.Column():
406
  bbox_y2 = gr.Slider(
407
  label="↓ Unten (y2)",
408
- minimum=0, maximum=4096, value=300, step=1,
409
- info="Untere Kante des Bildelementbereichs"
410
  )
411
 
412
  with gr.Row():
413
  with gr.Column():
414
  pos_info = gr.Markdown(
415
- value="`[STIL-MOTIV], [UMGEBUNG], [VOR/HINTERGRUND]`",
416
  elem_classes=["info-box"]
417
  )
418
  img_prompt = gr.Textbox(
@@ -424,7 +433,7 @@ def main_ui():
424
  )
425
  with gr.Column():
426
  neg_info = gr.Markdown(
427
- value="`[GESICHTER/ANATOMIE], [FEHLER]`",
428
  elem_classes=["info-box"]
429
  )
430
  img_neg_prompt = gr.Textbox(
@@ -492,20 +501,20 @@ def main_ui():
492
  show_download_button=False
493
  )
494
 
495
- # Event-Handler
 
 
496
  img_input.upload(
497
  fn=mock_process_image_upload,
498
  inputs=[img_input],
499
- outputs=[preview_output, bbox_x1, bbox_y1, bbox_x2, bbox_y2]
500
  ).then(
501
  fn=mock_update_slider_for_image,
502
  inputs=[img_input],
503
- outputs=[bbox_x1, bbox_y1, bbox_x2, bbox_y2]
504
  )
505
 
506
- coordinate_inputs = [img_input, bbox_x1, bbox_y1, bbox_x2, bbox_y2, mode_radio]
507
-
508
- for slider in [bbox_x1, bbox_y1, bbox_x2, bbox_y2]:
509
  slider.release(
510
  fn=mock_update_live_preview,
511
  inputs=coordinate_inputs,
@@ -527,7 +536,7 @@ def main_ui():
527
  inputs=[
528
  img_input, img_prompt, img_neg_prompt,
529
  strength_slider, img_steps, img_guidance,
530
- mode_radio, bbox_x1, bbox_y1, bbox_x2, bbox_y2
531
  ],
532
  outputs=[img_output, sam_raw_mask_output, processed_mask_output,
533
  pose_map_output, canny_map_output],
 
12
  print(f"📝 Mock text_to_image aufgerufen: '{prompt[:50]}...'")
13
 
14
  if progress:
15
+ for i in range(10):
16
  time.sleep(0.05)
17
  progress((i+1)/10, desc="Mock-Generierung läuft...")
18
 
 
19
  colors = ["lightblue", "lightgreen", "lavender", "peachpuff"]
20
  img = Image.new('RGB', (512, 512), color=random.choice(colors))
21
 
 
22
  draw = ImageDraw.Draw(img)
23
  text = f"Mock: {prompt[:30]}..." if len(prompt) > 30 else f"Mock: {prompt}"
24
  draw.text((50, 256), text, fill="black")
 
39
  time.sleep(0.05)
40
  progress((i+1)/10, desc=f"Mock-{mode} läuft...")
41
 
 
42
  img = image.copy().convert("RGB")
43
  draw = ImageDraw.Draw(img)
44
 
 
45
  colors = {
46
  "environment_change": "green",
47
  "focus_change": "orange",
 
49
  }
50
  border_color = colors.get(mode, "blue")
51
 
 
52
  draw.rectangle([20, 20, img.width-20, img.height-20],
53
  outline=border_color, width=10)
54
 
 
55
  if all(v is not None for v in [bbox_x1, bbox_y1, bbox_x2, bbox_y2]):
56
  x1, y1 = min(bbox_x1, bbox_x2), min(bbox_y1, bbox_y2)
57
  x2, y2 = max(bbox_x1, bbox_x2), max(bbox_y1, bbox_y2)
58
  draw.rectangle([x1, y1, x2, y2], outline="yellow", width=5)
59
  draw.text((x1+5, y1+5), f"{mode}", fill="white")
60
 
 
61
  draw.text((30, 30), f"Mock: {mode}", fill=border_color)
62
  draw.text((30, 60), f"Strength: {strength}", fill="black")
63
 
 
64
  mask_preview = Image.new('RGB', (256, 256), color='gray')
65
  controlnet_map = Image.new('RGB', (256, 256), color='darkblue')
66
  canny_map = Image.new('RGB', (256, 256), color='black')
 
70
 
71
  return img, mask_preview, mask_preview, controlnet_map, canny_map
72
 
73
+ def sort_coordinates(x1, y1, x2, y2):
74
+ """Sortiert Koordinaten, so dass x1 <= x2 und y1 <= y2"""
75
+ sorted_x1 = min(x1, x2)
76
+ sorted_x2 = max(x1, x2)
77
+ sorted_y1 = min(y1, y2)
78
+ sorted_y2 = max(y1, y2)
79
+ return sorted_x1, sorted_y1, sorted_x2, sorted_y2
80
+
81
+ def create_preview_image(image, bbox_coords, mode):
82
+ """Vorschau mit dynamischer Rahmendicke"""
83
+ if image is None:
84
+ return None
85
+
86
+ preview = image.copy()
87
+ draw = ImageDraw.Draw(preview)
88
+
89
+ if mode == "environment_change":
90
+ border_color = (0, 255, 0, 180)
91
+ mode_text = "UMGEBUNG ÄNDERN"
92
+ box_color = (255, 255, 0, 200)
93
+ text_bg_color = (0, 128, 0, 160)
94
+ elif mode == "focus_change":
95
+ border_color = (255, 165, 0, 180)
96
+ mode_text = "FOCUS VERÄNDERN"
97
+ box_color = (255, 0, 0, 200)
98
+ text_bg_color = (255, 140, 0, 160)
99
+ elif mode == "face_only_change":
100
+ border_color = (255, 0, 0, 180)
101
+ mode_text = "NUR BEREICH"
102
+ box_color = (255, 0, 0, 200)
103
+ text_bg_color = (128, 0, 0, 160)
104
+ else:
105
+ border_color = (128, 128, 128, 180)
106
+ mode_text = "UNBEKANNT"
107
+ box_color = (128, 128, 128, 200)
108
+ text_bg_color = (64, 64, 64, 160)
109
+
110
+ border_width = max(8, image.width // 200)
111
+ box_width = max(3, image.width // 400)
112
+
113
+ draw.rectangle([0, 0, preview.width-1, preview.height-1],
114
+ outline=border_color, width=border_width)
115
+
116
+ if bbox_coords and all(coord is not None for coord in bbox_coords):
117
+ x1, y1, x2, y2 = sort_coordinates(*bbox_coords)
118
+ x1 = max(0, min(x1, preview.width-1))
119
+ y1 = max(0, min(y1, preview.height-1))
120
+ x2 = max(0, min(x2, preview.width-1))
121
+ y2 = max(0, min(y2, preview.height-1))
122
+
123
+ if x2 > x1 and y2 > y1:
124
+ draw.rectangle([x1, y1, x2, y2], outline=box_color, width=box_width)
125
+ text_color = (255, 255, 255)
126
+ text_y = max(0, y1 - 25)
127
+
128
+ try:
129
+ from PIL import ImageFont
130
+ font_size = max(12, image.width // 50)
131
+ font = ImageFont.truetype("arial.ttf", font_size)
132
+ text_bbox = draw.textbbox((x1, text_y), mode_text, font=font)
133
+ draw.rectangle([text_bbox[0]-5, text_bbox[1]-2,
134
+ text_bbox[2]+5, text_bbox[3]+2],
135
+ fill=text_bg_color)
136
+ draw.text((x1, text_y), mode_text, fill=text_color, font=font)
137
+ except:
138
+ text_bbox = draw.textbbox((x1, text_y), mode_text)
139
+ draw.rectangle([text_bbox[0]-5, text_bbox[1]-2,
140
+ text_bbox[2]+5, text_bbox[3]+2],
141
+ fill=text_bg_color)
142
+ draw.text((x1, text_y), mode_text, fill=text_color)
143
+
144
+ return preview
145
 
146
  def mock_update_live_preview(image, bbox_x1, bbox_y1, bbox_x2, bbox_y2, mode):
147
  """Mock für Live-Vorschau MIT dynamischen Rahmen"""
148
  if not image:
149
  return None
150
 
 
151
  bbox_coords = sort_coordinates(bbox_x1, bbox_y1, bbox_x2, bbox_y2)
 
 
152
  return create_preview_image(image, bbox_coords, mode)
153
 
 
 
154
  def mock_process_image_upload(image):
155
+ """Mock für Bild-Upload: Setzt BBox in der Mitte - KORRIGIERTE REIHENFOLGE"""
156
  if not image:
157
+ return None, 100, 300, 100, 300 # x1, x2, y1, y2
158
 
159
  w, h = image.size
160
  bbox_size = min(w, h) * 0.3
 
163
  x2 = x1 + bbox_size
164
  y2 = y1 + bbox_size * 1.2
165
 
166
+ # KORREKTUR: x1, x2, y1, y2 Reihenfolge
167
+ preview = mock_update_live_preview(image, x1, x2, y1, y2, "environment_change")
168
+ return preview, int(x1), int(x2), int(y1), int(y2) # x1, x2, y1, y2
169
 
170
  def mock_update_slider_for_image(image):
171
  """Mock für Slider-Update"""
 
200
  def mock_update_info(mode):
201
  """Mock für Prompt-Info-Update"""
202
  if mode == "environment_change":
203
+ return ("Format: [Stil], [Umgebung], [Details]", "Vermeide: [Fehler], [Unerwünschtes]")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  elif mode == "focus_change":
205
+ return ("Format: [Gesicht/Kleidung], [Details]", "Vermeide: [Anatomiefehler], [Unschärfe]")
 
 
 
 
 
 
 
 
 
206
  else:
207
+ return ("Format: [Gesichtsdetails], [Ausdruck]", "Vermeide: [Unrealistisch], [Asymmetrie]")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
 
209
  # ==================== UI-DEFINITION ====================
210
  def main_ui():
 
213
  title="AI Image Generator - Mock Version",
214
  theme=gr.themes.Base(),
215
  css="""
216
+ /* ===== VERBESSERTE INFO-BOXEN ===== */
217
+ .info-box {
218
+ background: #f8fafc !important;
219
+ padding: 4px 8px !important;
220
+ border-radius: 4px !important;
221
+ border: 1px solid #e2e8f0 !important;
222
+ margin-bottom: 2px !important;
223
+ font-size: 11px !important;
224
+ line-height: 1.2 !important;
225
+ height: auto !important;
226
+ min-height: 35px !important;
227
+ color: #64748b !important;
228
+ display: block !important;
229
+ text-align: left !important;
230
+ font-family: 'Segoe UI', monospace !important;
231
+ opacity: 0.9 !important;
232
+ }
233
+
234
+ .info-box code {
235
+ background: #ffffff !important;
236
+ padding: 1px 3px !important;
237
+ border-radius: 2px !important;
238
+ font-size: 10px !important;
239
+ border: 1px solid #e2e8f0 !important;
240
+ color: #475569 !important;
241
+ font-weight: normal !important;
242
+ }
243
+
244
+ /* ===== TEXTBOXEN HERAUSHEBEN ===== */
245
+ .prompt-box textarea {
246
+ min-height: 90px !important;
247
+ border-radius: 6px !important;
248
+ border: 2px solid #3b82f6 !important;
249
+ padding: 10px !important;
250
+ font-size: 14px !important;
251
+ background: white !important;
252
+ box-shadow: 0 1px 3px rgba(0,0,0,0.05) !important;
253
+ }
254
+
255
+ .prompt-box textarea:focus {
256
+ border-color: #1d4ed8 !important;
257
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1) !important;
258
+ }
259
+
260
+ /* ===== VISUELLE HIERARCHIE ===== */
261
+ .gr-column:first-child .info-box {
262
+ border-left: 3px solid #3b82f6 !important;
263
+ background: #f0f9ff !important;
264
+ }
265
+
266
+ .gr-column:last-child .info-box {
267
+ border-left: 3px solid #ef4444 !important;
268
+ background: #fef2f2 !important;
269
+ }
270
+
271
+ .model-info-box {
272
+ background: #e8f4fd;
273
+ padding: 12px;
274
+ border-radius: 6px;
275
+ margin: 10px 0;
276
+ border-left: 4px solid #2196f3;
277
+ }
278
+
279
+ #generate-button {
280
+ background-color: #0080FF !important;
281
+ margin: 20px auto !important;
282
+ width: 280px;
283
+ }
284
+
285
+ .radio-group {
286
+ background: #f8f9fa;
287
+ padding: 15px;
288
+ border-radius: 8px;
289
+ margin: 10px 0;
290
+ }
291
+ """
292
  ) as demo:
293
 
294
  with gr.Tab("Text zu Bild"):
 
345
  height=400
346
  )
347
 
 
348
  model_dropdown.change(
349
  fn=mock_update_model_settings,
350
  inputs=[model_dropdown],
 
393
  with gr.Row():
394
  gr.Markdown("### 📐 Bildelementbereich anpassen")
395
 
396
+ # KORREKTUR: x1/x2 zuerst (oben), y1/y2 danach (unten)
397
  with gr.Row():
398
  with gr.Column():
399
  bbox_x1 = gr.Slider(
400
  label="← Links (x1)",
401
+ minimum=0, maximum=4096, value=100, step=1
 
402
  )
403
  with gr.Column():
404
+ bbox_x2 = gr.Slider( # KORREKT: x2, nicht y1
405
  label="→ Rechts (x2)",
406
+ minimum=0, maximum=4096, value=300, step=1 # KORREKT: 300 > 100
 
407
  )
408
+
409
  with gr.Row():
410
  with gr.Column():
411
+ bbox_y1 = gr.Slider( # KORREKT: y1, nicht x2
412
  label="↑ Oben (y1)",
413
+ minimum=0, maximum=4096, value=100, step=1 # KORREKT: 100 < 300
 
414
  )
415
  with gr.Column():
416
  bbox_y2 = gr.Slider(
417
  label="↓ Unten (y2)",
418
+ minimum=0, maximum=4096, value=300, step=1
 
419
  )
420
 
421
  with gr.Row():
422
  with gr.Column():
423
  pos_info = gr.Markdown(
424
+ value="Format: [Stil], [Umgebung], [Details]",
425
  elem_classes=["info-box"]
426
  )
427
  img_prompt = gr.Textbox(
 
433
  )
434
  with gr.Column():
435
  neg_info = gr.Markdown(
436
+ value="Vermeide: [Fehler], [Unerwünschtes]",
437
  elem_classes=["info-box"]
438
  )
439
  img_neg_prompt = gr.Textbox(
 
501
  show_download_button=False
502
  )
503
 
504
+ # KORREKTUR: coordinate_inputs in richtiger Reihenfolge (x1, x2, y1, y2)
505
+ coordinate_inputs = [img_input, bbox_x1, bbox_x2, bbox_y1, bbox_y2, mode_radio]
506
+
507
  img_input.upload(
508
  fn=mock_process_image_upload,
509
  inputs=[img_input],
510
+ outputs=[preview_output, bbox_x1, bbox_x2, bbox_y1, bbox_y2]
511
  ).then(
512
  fn=mock_update_slider_for_image,
513
  inputs=[img_input],
514
+ outputs=[bbox_x1, bbox_x2, bbox_y1, bbox_y2]
515
  )
516
 
517
+ for slider in [bbox_x1, bbox_x2, bbox_y1, bbox_y2]:
 
 
518
  slider.release(
519
  fn=mock_update_live_preview,
520
  inputs=coordinate_inputs,
 
536
  inputs=[
537
  img_input, img_prompt, img_neg_prompt,
538
  strength_slider, img_steps, img_guidance,
539
+ mode_radio, bbox_x1, bbox_x2, bbox_y1, bbox_y2
540
  ],
541
  outputs=[img_output, sam_raw_mask_output, processed_mask_output,
542
  pose_map_output, canny_map_output],