import gradio as gr import numpy as np from PIL import Image, ImageDraw, ImageFont import io import os from typing import Optional, Tuple, List import re # Mock OCR function (in real implementation, you'd use pytesseract or similar) def detect_text_in_image(image: np.ndarray) -> List[str]: """Mock function to detect existing text in image""" # In a real implementation, this would use OCR like pytesseract # For demo purposes, we'll return some sample detected text return ["Sample text detected", "Another text element"] def add_text_to_image( image: np.ndarray, new_text: str, text_position: str, font_size: int, text_color: str, background_color: str, detect_existing: bool, accessibility_description: str ) -> Tuple[np.ndarray, str, str]: """ Add text overlay to image with accessibility features """ if image is None: return None, "Please upload an image first", "" # Convert numpy array to PIL Image pil_image = Image.fromarray(image.astype('uint8'), 'RGB') # Detect existing text if requested existing_text_info = "" if detect_existing: try: detected_texts = detect_text_in_image(image) if detected_texts: existing_text_info = "Detected existing text:\n" + "\n".join(f"â€ĸ {text}" for text in detected_texts) else: existing_text_info = "No existing text detected in the image." except Exception as e: existing_text_info = f"Text detection failed: {str(e)}" # Add new text overlay draw = ImageDraw.Draw(pil_image) # Create font (you might want to use a proper font file in production) try: font = ImageFont.truetype("arial.ttf", font_size) except: font = ImageFont.load_default() # Get image dimensions img_width, img_height = pil_image.size # Calculate text position text_bbox = draw.textbbox((0, 0), new_text, font=font) text_width = text_bbox[2] - text_bbox[0] text_height = text_bbox[3] - text_bbox[1] position_map = { "top-left": (10, 10), "top-center": ((img_width - text_width) // 2, 10), "top-right": (img_width - text_width - 10, 10), "center-left": (10, (img_height - text_height) // 2), "center": ((img_width - text_width) // 2, (img_height - text_height) // 2), "center-right": (img_width - text_width - 10, (img_height - text_height) // 2), "bottom-left": (10, img_height - text_height - 10), "bottom-center": ((img_width - text_width) // 2, img_height - text_height - 10), "bottom-right": (img_width - text_width - 10, img_height - text_height - 10) } x, y = position_map.get(text_position, position_map["bottom-center"]) # Add background rectangle for better readability (optional) if background_color != "transparent": # Convert hex color to RGB if background_color.startswith('#'): bg_rgb = tuple(int(background_color[i:i+2], 16) for i in (1, 3, 5)) else: bg_rgb = (0, 0, 0) # default black # Draw background rectangle padding = 5 draw.rectangle([ x - padding, y - padding, x + text_width + padding, y + text_height + padding ], fill=bg_rgb) # Convert text color to RGB if text_color.startswith('#'): text_rgb = tuple(int(text_color[i:i+2], 16) for i in (1, 3, 5)) else: text_rgb = (255, 255, 255) # default white # Draw text draw.text((x, y), new_text, fill=text_rgb, font=font) # Convert back to numpy array result_image = np.array(pil_image) # Generate accessibility description if not accessibility_description: accessibility_description = f"Image with text overlay: '{new_text}' positioned at {text_position}" # Combine all information for accessibility full_accessibility_info = f"Accessibility Description: {accessibility_description}\n\n" if existing_text_info: full_accessibility_info += f"{existing_text_info}\n\n" full_accessibility_info += f"Added text: '{new_text}' at {text_position} with font size {font_size}" return result_image, full_accessibility_info, existing_text_info # Create the Gradio interface with gr.Blocks(title="Premium Image Text Overlay - Accessibility Edition") as demo: gr.HTML("""

đŸ–ŧī¸ Premium Image Text Overlay

Enhanced accessibility for visually impaired users with text detection

Built with anycoder

""") with gr.Tabs(): with gr.Tab("đŸ–ŧī¸ Image Editor"): with gr.Row(): with gr.Column(): input_image = gr.Image( label="Upload Image", type="numpy", height=400, interactive=True ) with gr.Accordion("🔍 Text Detection Settings", open=True): detect_existing = gr.Checkbox( label="Detect existing text in image", value=True, info="Automatically detect and display any text already present in the uploaded image" ) existing_text_display = gr.Textbox( label="Existing Text Detection Results", interactive=False, max_lines=5, placeholder="Existing text will appear here after detection..." ) with gr.Column(): output_image = gr.Image( label="Result Image", type="numpy", height=400, interactive=False ) accessibility_output = gr.Textbox( label="â™ŋ Accessibility Information", interactive=False, max_lines=8, placeholder="Comprehensive accessibility description will appear here..." ) with gr.Accordion("âœī¸ Add New Text", open=True): with gr.Row(): new_text = gr.Textbox( label="Text to Add", placeholder="Enter your text here...", max_lines=3 ) text_position = gr.Dropdown( choices=[ "top-left", "top-center", "top-right", "center-left", "center", "center-right", "bottom-left", "bottom-center", "bottom-right" ], value="bottom-center", label="Text Position" ) with gr.Row(): font_size = gr.Slider( minimum=10, maximum=100, value=24, step=2, label="Font Size" ) text_color = gr.ColorPicker( value="#FFFFFF", label="Text Color" ) background_color = gr.ColorPicker( value="#000000", label="Background Color", info="Set to transparent for no background" ) accessibility_description = gr.Textbox( label="Custom Accessibility Description", placeholder="Add a custom description for screen readers (optional)...", max_lines=3 ) with gr.Row(): process_btn = gr.Button( "✨ Add Text & Generate Accessibility Info", variant="primary", size="lg" ) clear_btn = gr.Button("đŸ—‘ī¸ Clear All", variant="secondary") with gr.Tab("â„šī¸ How to Use"): gr.Markdown(""" ### đŸŽ¯ Premium Features for Accessibility **For Visually Impaired Users:** - **Automatic Text Detection**: Our system automatically detects existing text in your uploaded images - **Comprehensive Descriptions**: Get detailed accessibility information including detected text and added overlays - **Screen Reader Friendly**: All outputs are optimized for screen reader compatibility **How It Works:** 1. **Upload** your image using the file picker or drag-and-drop 2. **Enable** "Detect existing text in image" to automatically find text already present 3. **Add** your new text with customizable position, size, and colors 4. **Review** the accessibility information that combines detected text and your additions 5. **Download** the final image with complete accessibility metadata **Accessibility Best Practices:** - Always provide meaningful custom descriptions when possible - Use high contrast colors for better visibility - Consider the context of existing text when adding new overlays - The accessibility information is designed to be read by screen readers """) # Event handlers process_btn.click( fn=add_text_to_image, inputs=[ input_image, new_text, text_position, font_size, text_color, background_color, detect_existing, accessibility_description ], outputs=[ output_image, accessibility_output, existing_text_display ] ) clear_btn.click( fn=lambda: (None, "", "", ""), inputs=[], outputs=[ input_image, output_image, accessibility_output, existing_text_display ] ) # Auto-detect existing text when image is uploaded (if detection is enabled) input_image.change( fn=lambda img, detect: (detect_text_in_image(img) if detect and img is not None else []) if detect else [], inputs=[input_image, detect_existing], outputs=existing_text_display ) # Launch the app if __name__ == "__main__": demo.launch()