Spaces:
Sleeping
Sleeping
| from PIL import Image, ImageDraw, ImageFont | |
| import gradio as gr | |
| import numpy as np | |
| import cv2 | |
| def add_text_to_image(image, text, text_x, text_y, font_size="80px", font_family="Standard", font_color="Weiß"): | |
| """Fügt Text mit OpenCV zum Bild hinzu - garantiert skalierbar!""" | |
| if image is None or not text: | |
| return image | |
| try: | |
| # Konvertiere PIL Image zu OpenCV Format | |
| if isinstance(image, np.ndarray): | |
| opencv_image = image | |
| else: | |
| opencv_image = np.array(image) | |
| opencv_image = cv2.cvtColor(opencv_image, cv2.COLOR_RGB2BGR) | |
| # Schriftgröße | |
| try: | |
| pixel_size = int(font_size.replace("px", "")) | |
| # OpenCV Font-Skala anpassen (empirische Werte) | |
| font_scale = pixel_size / 30.0 | |
| except: | |
| font_scale = 2.0 | |
| # Schriftfarbe | |
| color_mapping = { | |
| "Weiß": (255, 255, 255), | |
| "Schwarz": (0, 0, 0), | |
| "Rot": (0, 0, 255) | |
| } | |
| actual_color = color_mapping.get(font_color, (255, 255, 255)) | |
| # OpenCV Font basierend auf Auswahl | |
| font_mapping = { | |
| "Standard": cv2.FONT_HERSHEY_SIMPLEX, | |
| "Einfache Handschrift": cv2.FONT_HERSHEY_SCRIPT_SIMPLEX, | |
| "Verschnörkelte Handschrift": cv2.FONT_HERSHEY_SCRIPT_COMPLEX | |
| } | |
| font = font_mapping.get(font_family, cv2.FONT_HERSHEY_SIMPLEX) | |
| thickness = max(2, int(pixel_size / 20)) | |
| print(f"OpenCV Text: '{text}' an ({text_x}, {text_y}) - Schrift: {font_family}, Größe: {font_scale:.2f}, Dicke: {thickness}") | |
| # Text mit OpenCV hinzufügen | |
| cv2.putText( | |
| opencv_image, | |
| text, | |
| (int(text_x), int(text_y)), | |
| font, | |
| font_scale, | |
| actual_color, | |
| thickness, | |
| cv2.LINE_AA | |
| ) | |
| # Zurück zu PIL Format | |
| result_image = cv2.cvtColor(opencv_image, cv2.COLOR_BGR2RGB) | |
| return Image.fromarray(result_image) | |
| except Exception as e: | |
| print(f"Fehler beim Text hinzufügen mit OpenCV: {e}") | |
| # Fallback zu PIL | |
| try: | |
| if isinstance(image, np.ndarray): | |
| image = Image.fromarray(image) | |
| image_with_text = image.copy() | |
| draw = ImageDraw.Draw(image_with_text) | |
| draw.text((text_x, text_y), text, fill="white") | |
| return image_with_text | |
| except: | |
| return image | |
| def create_text_preview(image, text, text_x, text_y, font_size="80px", font_family="Standard", font_color="Weiß"): | |
| """Vorschau mit OpenCV""" | |
| if image is None: | |
| return image | |
| try: | |
| # Zu OpenCV konvertieren | |
| if isinstance(image, np.ndarray): | |
| opencv_image = image | |
| else: | |
| opencv_image = np.array(image) | |
| opencv_image = cv2.cvtColor(opencv_image, cv2.COLOR_RGB2BGR) | |
| preview = opencv_image.copy() | |
| # Rote Marker | |
| if text and text_x is not None and text_y is not None and (text_x != 100 or text_y != 100): | |
| cv2.circle(preview, (int(text_x), int(text_y)), 8, (0, 0, 255), -1) | |
| # Text zeichnen | |
| if text: | |
| try: | |
| pixel_size = int(font_size.replace("px", "")) | |
| font_scale = pixel_size / 30.0 | |
| except: | |
| font_scale = 2.0 | |
| color_mapping = { | |
| "Weiß": (255, 255, 255), | |
| "Schwarz": (0, 0, 0), | |
| "Rot": (0, 0, 255) | |
| } | |
| actual_color = color_mapping.get(font_color, (255, 255, 255)) | |
| # OpenCV Font basierend auf Auswahl | |
| font_mapping = { | |
| "Standard": cv2.FONT_HERSHEY_SIMPLEX, | |
| "Einfache Handschrift": cv2.FONT_HERSHEY_SCRIPT_SIMPLEX, | |
| "Verschnörkelte Handschrift": cv2.FONT_HERSHEY_SCRIPT_COMPLEX | |
| } | |
| font = font_mapping.get(font_family, cv2.FONT_HERSHEY_SIMPLEX) | |
| thickness = max(2, int(pixel_size / 20)) | |
| cv2.putText( | |
| preview, | |
| text, | |
| (int(text_x), int(text_y)), | |
| font, | |
| font_scale, | |
| actual_color, | |
| thickness, | |
| cv2.LINE_AA | |
| ) | |
| print(f"OpenCV Vorschau: Schrift {font_family}, Größe {font_scale:.2f}") | |
| # Zurück zu PIL | |
| result_image = cv2.cvtColor(preview, cv2.COLOR_BGR2RGB) | |
| return Image.fromarray(result_image) | |
| except Exception as e: | |
| print(f"Fehler bei OpenCV Vorschau: {e}") | |
| return image | |
| def update_text_preview_i2i(original_image, generated_image, text, text_x, text_y, font_size, font_family, font_color, target_selector): | |
| """Aktualisiert die Text-Vorschau für Bild-zu-Bild mit Formatierung""" | |
| if target_selector == "Originalbild": | |
| target_image = original_image | |
| else: | |
| target_image = generated_image | |
| print(f"Update Vorschau I2I - Größe: {font_size}, Schrift: {font_family}, Farbe: {font_color}, Ziel: {target_selector}") | |
| return create_text_preview(target_image, text, text_x, text_y, font_size, font_family, font_color) | |
| def update_text_preview_t2i(image, text, text_x, text_y, font_size, font_family, font_color): | |
| """Aktualisiert die Text-Vorschau für Text-zu-Bild mit Formatierung""" | |
| print(f"Update Vorschau T2I - Größe: {font_size}, Schrift: {font_family}, Farbe: {font_color}") | |
| return create_text_preview(image, text, text_x, text_y, font_size, font_family, font_color) | |
| def capture_click(event: gr.SelectData): | |
| """Handhabt Klicks in beiden Tabs""" | |
| if event and hasattr(event, 'index'): | |
| print(f"🎯 CLICK ERFOLGREICH: ({event.index[0]}, {event.index[1]})") | |
| return event.index[0], event.index[1] | |
| return 100, 100 | |
| def create_text_integration_section_t2i(): | |
| """Erstellt die UI-Komponenten für Text-Integration in Text-zu-Bild""" | |
| with gr.Row(): | |
| gr.Markdown("### 📝 Text auf Bild integrieren") | |
| with gr.Row(): | |
| text_input_t2i = gr.Textbox( | |
| label="Text eingeben", | |
| placeholder="Dein Text hier...", | |
| max_lines=2, | |
| scale=3 | |
| ) | |
| with gr.Row(): | |
| with gr.Column(): | |
| font_size_t2i = gr.Dropdown( | |
| choices=["120px", "80px", "40px"], | |
| value="80px", | |
| label="Schriftgröße" | |
| ) | |
| with gr.Column(): | |
| font_family_t2i = gr.Dropdown( | |
| choices=["Standard", "Einfache Handschrift", "Verschnörkelte Handschrift"], | |
| value="Standard", | |
| label="Schriftart" | |
| ) | |
| with gr.Column(): | |
| font_color_t2i = gr.Dropdown( | |
| choices=["Weiß", "Schwarz", "Rot"], | |
| value="Weiß", | |
| label="Schriftfarbe" | |
| ) | |
| with gr.Row(): | |
| text_x_t2i = gr.Number(value=None, visible=False) | |
| text_y_t2i = gr.Number(value=None, visible=False) | |
| with gr.Row(): | |
| text_btn_t2i = gr.Button("📝 Text auf generiertes Bild", variant="secondary") | |
| return text_input_t2i, text_x_t2i, text_y_t2i, font_size_t2i, font_family_t2i, font_color_t2i, text_btn_t2i | |
| def create_text_integration_section_i2i(): | |
| """Erstellt die UI-Komponenten für Text-Integration in Bild-zu-Bild""" | |
| with gr.Row(): | |
| gr.Markdown("### 📝 Text auf Bild integrieren") | |
| with gr.Row(): | |
| text_input_i2i = gr.Textbox( | |
| label="Text eingeben", | |
| placeholder="Dein Text hier...", | |
| max_lines=2, | |
| scale=3 | |
| ) | |
| with gr.Row(): | |
| text_x_i2i = gr.Number(value=None, visible=False) | |
| text_y_i2i = gr.Number(value=None, visible=False) | |
| with gr.Row(): | |
| target_selector = gr.Radio( | |
| choices=["Originalbild", "Generiertes Bild"], | |
| value="Generiertes Bild", | |
| label="Text auf welchem Bild?", | |
| scale=2 | |
| ) | |
| with gr.Row(): | |
| text_btn_i2i = gr.Button("📝 Text integrieren", variant="secondary") | |
| return text_input_i2i, text_x_i2i, text_y_i2i, target_selector, text_btn_i2i |