bakyt92 commited on
Commit
cabda67
·
1 Parent(s): 298f88b

update app.py - add contour as an option

Browse files

color conversion is different ()
Handles both 6-digit (#RRGGBB) and 3-digit (#RGB) hex formats

Files changed (1) hide show
  1. app.py +88 -58
app.py CHANGED
@@ -71,7 +71,7 @@ def process_uploaded_image(image):
71
  return image, "Image uploaded successfully!", image
72
 
73
  # Text Overlay Functions
74
- def add_text_to_image(img, pattern, line1, line2, line3, font_size, color):
75
  """Overlay 2- or 3-line text on the image in a preset layout."""
76
  print("=== DEBUG: add_text_to_image called ===")
77
  print(f"Input image: {type(img)}")
@@ -79,6 +79,7 @@ def add_text_to_image(img, pattern, line1, line2, line3, font_size, color):
79
  print(f"Lines: [{line1!r}, {line2!r}, {line3!r}]")
80
  print(f"Font size: {font_size}")
81
  print(f"Color: {color!r}")
 
82
 
83
  if img is None:
84
  print("ERROR: No image provided")
@@ -92,7 +93,7 @@ def add_text_to_image(img, pattern, line1, line2, line3, font_size, color):
92
  draw = ImageDraw.Draw(image)
93
  print("ImageDraw created successfully")
94
 
95
- # More robust font loading with better fallbacks
96
  font = None
97
  font_paths = [
98
  "DejaVuSans-Bold.ttf",
@@ -112,7 +113,6 @@ def add_text_to_image(img, pattern, line1, line2, line3, font_size, color):
112
  print(f"FAILED: Font {font_path} - {e}")
113
  continue
114
 
115
- # Final fallback to default font
116
  if font is None:
117
  try:
118
  font = ImageFont.load_default()
@@ -144,22 +144,46 @@ def add_text_to_image(img, pattern, line1, line2, line3, font_size, color):
144
 
145
  print(f"Text positions calculated: {positions}")
146
 
147
- # Convert hex color to RGB tuple if needed
148
  original_color = color
149
- if isinstance(color, str) and color.startswith('#'):
150
- print(f"Converting hex color {color}")
151
- color = color.lstrip('#')
152
- if len(color) == 6:
153
- color = tuple(int(color[i:i+2], 16) for i in (0, 2, 4))
154
- print(f"Converted to RGB: {color}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  else:
156
- print("Invalid hex color, using white")
157
- color = (255, 255, 255)
158
- elif isinstance(color, str):
159
- print(f"Non-hex color string: {color}, using white")
160
- color = (255, 255, 255)
 
 
 
 
 
 
161
 
162
- # Draw text with better visibility
163
  lines = [line1, line2, line3][:len(positions)]
164
  print(f"Active lines: {lines}")
165
  text_drawn = False
@@ -168,71 +192,70 @@ def add_text_to_image(img, pattern, line1, line2, line3, font_size, color):
168
  if txt and txt.strip():
169
  print(f"Drawing line {i+1}: '{txt}' at position ({x}, {y})")
170
 
171
- # Add text stroke/outline for better visibility
172
- stroke_width = max(1, font_size // 20)
173
- print(f"Using stroke width: {stroke_width}")
174
-
175
- try:
176
  # Draw text outline (black)
177
  for dx in [-stroke_width, 0, stroke_width]:
178
  for dy in [-stroke_width, 0, stroke_width]:
179
  if dx != 0 or dy != 0:
180
  try:
181
  draw.text((x + dx, y + dy), txt, fill=(0, 0, 0), font=font, anchor="mm")
182
- except TypeError as e:
183
- print(f"Anchor not supported: {e}, using fallback")
184
- # Fallback for older PIL versions without anchor
185
  try:
186
  bbox = draw.textbbox((0, 0), txt, font=font)
187
  text_w = bbox[2] - bbox[0]
188
  text_h = bbox[3] - bbox[1]
189
  draw.text((x - text_w//2 + dx, y - text_h//2 + dy), txt, fill=(0, 0, 0), font=font)
190
- except Exception as bbox_e:
191
- print(f"Textbbox also failed: {bbox_e}, using basic positioning")
192
  draw.text((x + dx, y + dy), txt, fill=(0, 0, 0), font=font)
193
-
194
- # Draw main text
 
 
 
 
 
 
 
195
  try:
196
- draw.text((x, y), txt, fill=color, font=font, anchor="mm")
197
- print(f"Main text drawn with anchor at ({x}, {y})")
198
- except TypeError as e:
199
- print(f"Anchor not supported for main text: {e}, using fallback")
200
- # Fallback for older PIL versions
201
- try:
202
- bbox = draw.textbbox((0, 0), txt, font=font)
203
- text_w = bbox[2] - bbox[0]
204
- text_h = bbox[3] - bbox[1]
205
- fallback_x = x - text_w//2
206
- fallback_y = y - text_h//2
207
- draw.text((fallback_x, fallback_y), txt, fill=color, font=font)
208
- print(f"Fallback text drawn at ({fallback_x}, {fallback_y})")
209
- except Exception as bbox_e:
210
- print(f"Textbbox also failed: {bbox_e}, using basic positioning")
211
- draw.text((x, y), txt, fill=color, font=font)
212
-
213
- text_drawn = True
214
- print(f"Successfully drew line {i+1}")
215
-
216
  except Exception as e:
217
- print(f"ERROR drawing text line {i+1}: {e}")
218
- import traceback
219
- traceback.print_exc()
220
- else:
221
- print(f"Skipping empty line {i+1}")
 
 
 
 
 
222
 
223
  if not text_drawn:
224
  print("No text was drawn")
225
- return img, "No text to add (all lines were empty)", None
226
 
227
  print("=== Text drawing completed ===")
228
- print(f"Returning image with mode: {image.mode}, size: {image.size}")
229
- return image, f"Text added! Pattern: {pattern}, Font: {font_size}px, Color: {original_color}, Lines drawn: {sum(1 for line in lines if line and line.strip())}", None
230
 
231
  except Exception as e:
232
  print(f"CRITICAL ERROR in add_text_to_image: {e}")
233
  import traceback
234
  traceback.print_exc()
235
- return None, f"Error adding text: {str(e)}", None
236
 
237
  def test_text_overlay():
238
  """Test function to verify text overlay works"""
@@ -388,6 +411,13 @@ with gr.Blocks(title="AI Image Generator & Text Overlay") as demo:
388
  value="#FFFFFF"
389
  )
390
 
 
 
 
 
 
 
 
391
  add_text_btn = gr.Button("✨ Add Text to Image", variant="primary")
392
 
393
  with gr.Column():
@@ -397,7 +427,7 @@ with gr.Blocks(title="AI Image Generator & Text Overlay") as demo:
397
  # Event handler for Tab 2
398
  add_text_btn.click(
399
  add_text_to_image,
400
- inputs=[current_image, pattern, line1_inp, line2_inp, line3_inp, font_size, color],
401
  outputs=[text_image, status_message]
402
  )
403
 
 
71
  return image, "Image uploaded successfully!", image
72
 
73
  # Text Overlay Functions
74
+ def add_text_to_image(img, pattern, line1, line2, line3, font_size, color, add_outline):
75
  """Overlay 2- or 3-line text on the image in a preset layout."""
76
  print("=== DEBUG: add_text_to_image called ===")
77
  print(f"Input image: {type(img)}")
 
79
  print(f"Lines: [{line1!r}, {line2!r}, {line3!r}]")
80
  print(f"Font size: {font_size}")
81
  print(f"Color: {color!r}")
82
+ print(f"Add outline: {add_outline}")
83
 
84
  if img is None:
85
  print("ERROR: No image provided")
 
93
  draw = ImageDraw.Draw(image)
94
  print("ImageDraw created successfully")
95
 
96
+ # Font loading (same as before)
97
  font = None
98
  font_paths = [
99
  "DejaVuSans-Bold.ttf",
 
113
  print(f"FAILED: Font {font_path} - {e}")
114
  continue
115
 
 
116
  if font is None:
117
  try:
118
  font = ImageFont.load_default()
 
144
 
145
  print(f"Text positions calculated: {positions}")
146
 
147
+ # FIXED: Better color conversion
148
  original_color = color
149
+ final_color = (255, 255, 255) # Default white
150
+
151
+ if isinstance(color, str):
152
+ if color.startswith('#'):
153
+ print(f"Converting hex color {color}")
154
+ hex_color = color.lstrip('#')
155
+ if len(hex_color) == 6:
156
+ try:
157
+ final_color = tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
158
+ print(f"Successfully converted hex {color} to RGB: {final_color}")
159
+ except ValueError as e:
160
+ print(f"Invalid hex color {color}: {e}, using white")
161
+ final_color = (255, 255, 255)
162
+ elif len(hex_color) == 3:
163
+ # Short hex format #RGB -> #RRGGBB
164
+ try:
165
+ final_color = tuple(int(hex_color[i]*2, 16) for i in range(3))
166
+ print(f"Successfully converted short hex {color} to RGB: {final_color}")
167
+ except ValueError as e:
168
+ print(f"Invalid short hex color {color}: {e}, using white")
169
+ final_color = (255, 255, 255)
170
+ else:
171
+ print(f"Invalid hex color length {color}, using white")
172
+ final_color = (255, 255, 255)
173
  else:
174
+ # Try to parse as named color or other format
175
+ print(f"Non-hex color string: {color}, attempting to use directly")
176
+ final_color = color # Let PIL try to handle it
177
+ elif isinstance(color, (tuple, list)) and len(color) >= 3:
178
+ final_color = tuple(color[:3])
179
+ print(f"Using tuple/list color: {final_color}")
180
+ else:
181
+ print(f"Unrecognized color format: {color}, using white")
182
+ final_color = (255, 255, 255)
183
+
184
+ print(f"Final color for drawing: {final_color}")
185
 
186
+ # Draw text
187
  lines = [line1, line2, line3][:len(positions)]
188
  print(f"Active lines: {lines}")
189
  text_drawn = False
 
192
  if txt and txt.strip():
193
  print(f"Drawing line {i+1}: '{txt}' at position ({x}, {y})")
194
 
195
+ # Optional outline/stroke
196
+ if add_outline:
197
+ stroke_width = max(1, font_size // 20)
198
+ print(f"Adding outline with stroke width: {stroke_width}")
199
+
200
  # Draw text outline (black)
201
  for dx in [-stroke_width, 0, stroke_width]:
202
  for dy in [-stroke_width, 0, stroke_width]:
203
  if dx != 0 or dy != 0:
204
  try:
205
  draw.text((x + dx, y + dy), txt, fill=(0, 0, 0), font=font, anchor="mm")
206
+ except TypeError:
207
+ # Fallback for older PIL versions
 
208
  try:
209
  bbox = draw.textbbox((0, 0), txt, font=font)
210
  text_w = bbox[2] - bbox[0]
211
  text_h = bbox[3] - bbox[1]
212
  draw.text((x - text_w//2 + dx, y - text_h//2 + dy), txt, fill=(0, 0, 0), font=font)
213
+ except Exception:
 
214
  draw.text((x + dx, y + dy), txt, fill=(0, 0, 0), font=font)
215
+ else:
216
+ print("Skipping outline (disabled)")
217
+
218
+ # Draw main text
219
+ try:
220
+ draw.text((x, y), txt, fill=final_color, font=font, anchor="mm")
221
+ print(f"Main text drawn with color {final_color} at ({x}, {y})")
222
+ except TypeError:
223
+ # Fallback for older PIL versions
224
  try:
225
+ bbox = draw.textbbox((0, 0), txt, font=font)
226
+ text_w = bbox[2] - bbox[0]
227
+ text_h = bbox[3] - bbox[1]
228
+ fallback_x = x - text_w//2
229
+ fallback_y = y - text_h//2
230
+ draw.text((fallback_x, fallback_y), txt, fill=final_color, font=font)
231
+ print(f"Fallback text drawn with color {final_color} at ({fallback_x}, {fallback_y})")
232
+ except Exception:
233
+ draw.text((x, y), txt, fill=final_color, font=font)
234
+ print(f"Basic text drawn with color {final_color} at ({x}, {y})")
 
 
 
 
 
 
 
 
 
 
235
  except Exception as e:
236
+ print(f"ERROR drawing main text: {e}")
237
+ # Try with string color as last resort
238
+ try:
239
+ draw.text((x, y), txt, fill=original_color, font=font, anchor="mm")
240
+ print(f"Drew text with original color string: {original_color}")
241
+ except Exception as e2:
242
+ print(f"Even original color failed: {e2}")
243
+
244
+ text_drawn = True
245
+ print(f"Successfully drew line {i+1}")
246
 
247
  if not text_drawn:
248
  print("No text was drawn")
249
+ return img, "No text to add (all lines were empty)"
250
 
251
  print("=== Text drawing completed ===")
252
+ return image, f"Text added! Color: {original_color} -> {final_color}, Outline: {add_outline}"
 
253
 
254
  except Exception as e:
255
  print(f"CRITICAL ERROR in add_text_to_image: {e}")
256
  import traceback
257
  traceback.print_exc()
258
+ return None, f"Error adding text: {str(e)}"
259
 
260
  def test_text_overlay():
261
  """Test function to verify text overlay works"""
 
411
  value="#FFFFFF"
412
  )
413
 
414
+ # NEW: Add outline option
415
+ add_outline = gr.Checkbox(
416
+ label="Add black outline",
417
+ value=True,
418
+ info="Adds black outline for better text visibility"
419
+ )
420
+
421
  add_text_btn = gr.Button("✨ Add Text to Image", variant="primary")
422
 
423
  with gr.Column():
 
427
  # Event handler for Tab 2
428
  add_text_btn.click(
429
  add_text_to_image,
430
+ inputs=[current_image, pattern, line1_inp, line2_inp, line3_inp, font_size, color, add_outline],
431
  outputs=[text_image, status_message]
432
  )
433