Astridkraft commited on
Commit
3cc8b5d
·
verified ·
1 Parent(s): 16305ce

Update text_integration.py

Browse files
Files changed (1) hide show
  1. text_integration.py +88 -152
text_integration.py CHANGED
@@ -1,202 +1,132 @@
1
  from PIL import Image, ImageDraw, ImageFont
2
  import gradio as gr
3
  import numpy as np
4
- import os
5
- import requests
6
- import tempfile
7
-
8
- # URLs zu freien Schriftarten auf GitHub
9
- FONT_URLS = {
10
-
11
- "Roboto": "https://raw.githubusercontent.com/google/fonts/main/apache/roboto/Roboto-Regular.ttf",
12
- "Open Sans": "https://raw.githubusercontent.com/google/fonts/main/apache/opensans/OpenSans-Regular.ttf",
13
- "DejaVu Sans": "https://raw.githubusercontent.com/dejavu-fonts/dejavu-fonts/master/ttf/DejaVuSans.ttf"
14
- }
15
-
16
- def download_font(font_name):
17
- """Lädt eine Schriftart von GitHub herunter und gibt den lokalen Pfad zurück"""
18
- try:
19
- if font_name not in FONT_URLS:
20
- return None
21
-
22
- # Temporäre Datei erstellen
23
- temp_dir = tempfile.gettempdir()
24
- font_path = os.path.join(temp_dir, f"{font_name.replace(' ', '_')}.ttf")
25
-
26
- # Wenn bereits vorhanden, wiederverwenden
27
- if os.path.exists(font_path):
28
- print(f"✅ Schriftart bereits vorhanden: {font_path}")
29
- return font_path
30
-
31
- # Schriftart von GitHub downloaden
32
- print(f"⬇️ Lade Schriftart herunter: {font_name}")
33
- response = requests.get(FONT_URLS[font_name], timeout=30)
34
- response.raise_for_status()
35
-
36
- # Schriftart speichern
37
- with open(font_path, 'wb') as f:
38
- f.write(response.content)
39
-
40
- print(f"✅ Schriftart heruntergeladen: {font_path}")
41
- return font_path
42
-
43
- except Exception as e:
44
- print(f"❌ Fehler beim Download von {font_name}: {e}")
45
- return None
46
-
47
- def get_available_font():
48
- """Gibt eine verfügbare Schriftart zurück (Download falls nötig)"""
49
- # Versuche zuerst Roboto
50
- roboto_path = download_font("Roboto")
51
- if roboto_path:
52
- return roboto_path
53
-
54
- # Fallback zu Open Sans
55
- open_sans_path = download_font("Open Sans")
56
- if open_sans_path:
57
- return open_sans_path
58
-
59
- # Letzter Fallback zu DejaVu Sans
60
- dejavu_path = download_font("DejaVu Sans")
61
- if dejavu_path:
62
- return dejavu_path
63
-
64
- return None
65
 
66
  def add_text_to_image(image, text, text_x, text_y, font_size="80px", font_family="Roboto", font_color="Weiß"):
67
- """Fügt Text mit PIL zum Bild hinzu mit Formatierungsoptionen"""
68
  if image is None or not text:
69
  return image
70
 
71
  try:
72
- # Konvertiere numpy array zu PIL Image falls nötig
73
  if isinstance(image, np.ndarray):
74
- image = Image.fromarray(image)
75
-
76
- image_with_text = image.copy()
77
- draw = ImageDraw.Draw(image_with_text)
78
 
79
- # Schriftgröße direkt aus dem Dropdown-Wert extrahieren
80
  try:
81
  pixel_size = int(font_size.replace("px", ""))
82
- print(f"Schriftgröße direkt: {font_size} -> {pixel_size}px")
 
83
  except:
84
- pixel_size = 80
85
 
86
- # Schriftfarbe Mapping
87
  color_mapping = {
88
- "Weiß": "white",
89
- "Schwarz": "black",
90
- "Rot": "red"
91
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
 
93
- actual_color = color_mapping.get(font_color, "white")
94
- print(f"Schriftfarbe Mapping: {font_color} -> {actual_color}")
95
-
96
- # NEU: Schriftart downloaden oder vorhandene verwenden
97
- font_path = download_font(font_family)
98
-
99
- if font_path:
100
- try:
101
- font = ImageFont.truetype(font_path, pixel_size)
102
- print(f"✅ TrueType-Schriftart geladen: {font_family} mit Größe {pixel_size}px")
103
- except Exception as e:
104
- print(f"❌ Fehler beim Laden der Schriftart {font_family}: {e}")
105
- # Fallback auf andere Schriftart
106
- fallback_font = get_available_font()
107
- if fallback_font:
108
- font = ImageFont.truetype(fallback_font, pixel_size)
109
- print(f"⚠️ Fallback auf: {fallback_font}")
110
- else:
111
- font = ImageFont.load_default()
112
- print("⚠️ Fallback auf Default-Schriftart (nicht skalierbar)")
113
- else:
114
- # Fallback falls Download fehlschlägt
115
- fallback_font = get_available_font()
116
- if fallback_font:
117
- font = ImageFont.truetype(fallback_font, pixel_size)
118
- print(f"⚠️ Download fehlgeschlagen - verwende Fallback: {fallback_font}")
119
- else:
120
- font = ImageFont.load_default()
121
- print("⚠️ Keine TrueType-Schriftart verfügbar - verwende Default (nicht skalierbar)")
122
-
123
- # Text zeichnen
124
- draw.text((text_x, text_y), text, fill=actual_color, font=font)
125
- print(f"Text '{text}' an Position ({text_x}, {text_y}) hinzugefügt - Größe: {pixel_size}px, Schrift: {font_family}, Farbe: {actual_color}")
126
- return image_with_text
127
 
128
  except Exception as e:
129
- print(f"Fehler beim Text hinzufügen: {e}")
130
- return image
 
 
 
 
 
 
 
 
 
131
 
132
  def create_text_preview(image, text, text_x, text_y, font_size="80px", font_family="Roboto", font_color="Weiß"):
133
- """Erstellt eine Vorschau mit Text und rotem Marker"""
134
  if image is None:
135
  return image
136
 
137
  try:
 
138
  if isinstance(image, np.ndarray):
139
- image = Image.fromarray(image)
 
 
 
140
 
141
- preview = image.copy()
142
- draw = ImageDraw.Draw(preview)
143
 
144
  # Rote Marker
145
  if text and text_x is not None and text_y is not None and (text_x != 100 or text_y != 100):
146
- marker_radius = 8
147
- marker_color = (255, 0, 0)
148
- draw.ellipse([
149
- text_x - marker_radius,
150
- text_y - marker_radius,
151
- text_x + marker_radius,
152
- text_y + marker_radius
153
- ], fill=marker_color)
154
 
155
  # Text zeichnen
156
  if text:
157
  try:
158
  pixel_size = int(font_size.replace("px", ""))
 
159
  except:
160
- pixel_size = 80
161
 
162
  color_mapping = {
163
- "Weiß": "white",
164
- "Schwarz": "black",
165
- "Rot": "red"
166
  }
 
167
 
168
- actual_color = color_mapping.get(font_color, "white")
 
169
 
170
- # Gleiche Schriftart-Logik wie oben
171
- font_path = download_font(font_family)
172
-
173
- if font_path:
174
- try:
175
- font = ImageFont.truetype(font_path, pixel_size)
176
- except:
177
- fallback_font = get_available_font()
178
- if fallback_font:
179
- font = ImageFont.truetype(fallback_font, pixel_size)
180
- else:
181
- font = ImageFont.load_default()
182
- else:
183
- fallback_font = get_available_font()
184
- if fallback_font:
185
- font = ImageFont.truetype(fallback_font, pixel_size)
186
- else:
187
- font = ImageFont.load_default()
188
 
189
- draw.text((text_x, text_y), text, fill=actual_color, font=font)
190
- print(f"Vorschau: Text mit Größe {pixel_size}px, Farbe {actual_color} gezeichnet")
191
 
192
- return preview
 
 
193
 
194
  except Exception as e:
195
- print(f"Fehler bei Text-Vorschau: {e}")
196
  return image
197
 
198
- # Rest der Funktionen bleibt gleich wie vorher...
199
  def update_text_preview_i2i(original_image, generated_image, text, text_x, text_y, target_selector):
 
200
  if target_selector == "Originalbild":
201
  target_image = original_image
202
  else:
@@ -204,16 +134,20 @@ def update_text_preview_i2i(original_image, generated_image, text, text_x, text_
204
  return create_text_preview(target_image, text, text_x, text_y)
205
 
206
  def update_text_preview_t2i(image, text, text_x, text_y, font_size, font_family, font_color):
 
207
  print(f"Update Vorschau - Größe: {font_size}, Schrift: {font_family}, Farbe: {font_color}")
208
  return create_text_preview(image, text, text_x, text_y, font_size, font_family, font_color)
209
 
210
  def capture_click(event: gr.SelectData):
 
211
  if event and hasattr(event, 'index'):
212
  print(f"🎯 CLICK ERFOLGREICH: ({event.index[0]}, {event.index[1]})")
213
  return event.index[0], event.index[1]
214
  return 100, 100
215
 
216
  def create_text_integration_section_t2i():
 
 
217
  with gr.Row():
218
  gr.Markdown("### 📝 Text auf Bild integrieren")
219
 
@@ -234,8 +168,8 @@ def create_text_integration_section_t2i():
234
  )
235
  with gr.Column():
236
  font_family_t2i = gr.Dropdown(
237
- choices=["Roboto", "Open Sans", "DejaVu Sans"],
238
- value="Roboto",
239
  label="Schriftart"
240
  )
241
  with gr.Column():
@@ -255,6 +189,8 @@ def create_text_integration_section_t2i():
255
  return text_input_t2i, text_x_t2i, text_y_t2i, font_size_t2i, font_family_t2i, font_color_t2i, text_btn_t2i
256
 
257
  def create_text_integration_section_i2i():
 
 
258
  with gr.Row():
259
  gr.Markdown("### 📝 Text auf Bild integrieren")
260
 
 
1
  from PIL import Image, ImageDraw, ImageFont
2
  import gradio as gr
3
  import numpy as np
4
+ import cv2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
  def add_text_to_image(image, text, text_x, text_y, font_size="80px", font_family="Roboto", font_color="Weiß"):
7
+ """Fügt Text mit OpenCV zum Bild hinzu - garantiert skalierbar!"""
8
  if image is None or not text:
9
  return image
10
 
11
  try:
12
+ # Konvertiere PIL Image zu OpenCV Format
13
  if isinstance(image, np.ndarray):
14
+ opencv_image = image
15
+ else:
16
+ opencv_image = np.array(image)
17
+ opencv_image = cv2.cvtColor(opencv_image, cv2.COLOR_RGB2BGR)
18
 
19
+ # Schriftgröße
20
  try:
21
  pixel_size = int(font_size.replace("px", ""))
22
+ # OpenCV Font-Skala anpassen (empirische Werte)
23
+ font_scale = pixel_size / 30.0
24
  except:
25
+ font_scale = 2.0
26
 
27
+ # Schriftfarbe
28
  color_mapping = {
29
+ "Weiß": (255, 255, 255),
30
+ "Schwarz": (0, 0, 0),
31
+ "Rot": (0, 0, 255)
32
  }
33
+ actual_color = color_mapping.get(font_color, (255, 255, 255))
34
+
35
+ # OpenCV Font - GARANTIERT verfügbar und skalierbar!
36
+ font = cv2.FONT_HERSHEY_SIMPLEX
37
+ thickness = max(2, int(pixel_size / 20))
38
+
39
+ print(f"OpenCV Text: '{text}' an ({text_x}, {text_y}) - Größe: {font_scale:.2f}, Dicke: {thickness}")
40
+
41
+ # Text mit OpenCV hinzufügen
42
+ cv2.putText(
43
+ opencv_image,
44
+ text,
45
+ (int(text_x), int(text_y)),
46
+ font,
47
+ font_scale,
48
+ actual_color,
49
+ thickness,
50
+ cv2.LINE_AA
51
+ )
52
 
53
+ # Zurück zu PIL Format
54
+ result_image = cv2.cvtColor(opencv_image, cv2.COLOR_BGR2RGB)
55
+ return Image.fromarray(result_image)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
 
57
  except Exception as e:
58
+ print(f"Fehler beim Text hinzufügen mit OpenCV: {e}")
59
+ # Fallback zu PIL
60
+ try:
61
+ if isinstance(image, np.ndarray):
62
+ image = Image.fromarray(image)
63
+ image_with_text = image.copy()
64
+ draw = ImageDraw.Draw(image_with_text)
65
+ draw.text((text_x, text_y), text, fill="white")
66
+ return image_with_text
67
+ except:
68
+ return image
69
 
70
  def create_text_preview(image, text, text_x, text_y, font_size="80px", font_family="Roboto", font_color="Weiß"):
71
+ """Vorschau mit OpenCV"""
72
  if image is None:
73
  return image
74
 
75
  try:
76
+ # Zu OpenCV konvertieren
77
  if isinstance(image, np.ndarray):
78
+ opencv_image = image
79
+ else:
80
+ opencv_image = np.array(image)
81
+ opencv_image = cv2.cvtColor(opencv_image, cv2.COLOR_RGB2BGR)
82
 
83
+ preview = opencv_image.copy()
 
84
 
85
  # Rote Marker
86
  if text and text_x is not None and text_y is not None and (text_x != 100 or text_y != 100):
87
+ cv2.circle(preview, (int(text_x), int(text_y)), 8, (0, 0, 255), -1)
 
 
 
 
 
 
 
88
 
89
  # Text zeichnen
90
  if text:
91
  try:
92
  pixel_size = int(font_size.replace("px", ""))
93
+ font_scale = pixel_size / 30.0
94
  except:
95
+ font_scale = 2.0
96
 
97
  color_mapping = {
98
+ "Weiß": (255, 255, 255),
99
+ "Schwarz": (0, 0, 0),
100
+ "Rot": (0, 0, 255)
101
  }
102
+ actual_color = color_mapping.get(font_color, (255, 255, 255))
103
 
104
+ font = cv2.FONT_HERSHEY_SIMPLEX
105
+ thickness = max(2, int(pixel_size / 20))
106
 
107
+ cv2.putText(
108
+ preview,
109
+ text,
110
+ (int(text_x), int(text_y)),
111
+ font,
112
+ font_scale,
113
+ actual_color,
114
+ thickness,
115
+ cv2.LINE_AA
116
+ )
 
 
 
 
 
 
 
 
117
 
118
+ print(f"OpenCV Vorschau: Größe {font_scale:.2f}")
 
119
 
120
+ # Zurück zu PIL
121
+ result_image = cv2.cvtColor(preview, cv2.COLOR_BGR2RGB)
122
+ return Image.fromarray(result_image)
123
 
124
  except Exception as e:
125
+ print(f"Fehler bei OpenCV Vorschau: {e}")
126
  return image
127
 
 
128
  def update_text_preview_i2i(original_image, generated_image, text, text_x, text_y, target_selector):
129
+ """Aktualisiert die Text-Vorschau für Bild-zu-Bild"""
130
  if target_selector == "Originalbild":
131
  target_image = original_image
132
  else:
 
134
  return create_text_preview(target_image, text, text_x, text_y)
135
 
136
  def update_text_preview_t2i(image, text, text_x, text_y, font_size, font_family, font_color):
137
+ """Aktualisiert die Text-Vorschau für Text-zu-Bild mit Formatierung"""
138
  print(f"Update Vorschau - Größe: {font_size}, Schrift: {font_family}, Farbe: {font_color}")
139
  return create_text_preview(image, text, text_x, text_y, font_size, font_family, font_color)
140
 
141
  def capture_click(event: gr.SelectData):
142
+ """Handhabt Klicks in beiden Tabs"""
143
  if event and hasattr(event, 'index'):
144
  print(f"🎯 CLICK ERFOLGREICH: ({event.index[0]}, {event.index[1]})")
145
  return event.index[0], event.index[1]
146
  return 100, 100
147
 
148
  def create_text_integration_section_t2i():
149
+ """Erstellt die UI-Komponenten für Text-Integration in Text-zu-Bild"""
150
+
151
  with gr.Row():
152
  gr.Markdown("### 📝 Text auf Bild integrieren")
153
 
 
168
  )
169
  with gr.Column():
170
  font_family_t2i = gr.Dropdown(
171
+ choices=["Standard"],
172
+ value="Standard",
173
  label="Schriftart"
174
  )
175
  with gr.Column():
 
189
  return text_input_t2i, text_x_t2i, text_y_t2i, font_size_t2i, font_family_t2i, font_color_t2i, text_btn_t2i
190
 
191
  def create_text_integration_section_i2i():
192
+ """Erstellt die UI-Komponenten für Text-Integration in Bild-zu-Bild"""
193
+
194
  with gr.Row():
195
  gr.Markdown("### 📝 Text auf Bild integrieren")
196