| | import os |
| | from config.settings import ( |
| | OPENAI_API_KEY, ANTHROPIC_API_KEY, REMOVE_BG_API_KEY, DEEPSEEK_API_KEY, |
| | GRADIO_SERVER_NAME, GRADIO_SERVER_PORT |
| | ) |
| | from config.logging_config import setup_logging |
| | from src.image_processing import ImageProcessor |
| | from src.ai_image_generator import AIImageGenerator |
| | from src.background_removal import BackgroundRemover |
| | from src.image_analysis import ImageAnalysis |
| | from src.custom_filters import apply_custom_filter |
| | from src.resize_crop import resize_crop_image |
| | import logging |
| | import io |
| | import zipfile |
| | import tempfile |
| | from PIL import Image |
| |
|
| | setup_logging() |
| | logger = logging.getLogger(__name__) |
| |
|
| | import gradio as gr |
| |
|
| | SUPPORTED_FORMATS = [ |
| | "JPEG", "JPG", "PNG", "BMP", "TIFF", "TIF", "WEBP", "GIF", |
| | "ICO", "EPS", "PDF", "PSD", "SVG", "HEIC", "AVIF", "JXL" |
| | ] |
| | ENHANCEMENT_OPTIONS = [ |
| | "AI Super Resolution", "Noise Reduction", "Color Enhancement", "Brightness/Contrast", "Sharpening", "HDR Effect", "Vintage Filter", "Black & White", "Sepia", "Vignette", "Blur Background" |
| | ] |
| |
|
| | processor = ImageProcessor() |
| | ai_generator = AIImageGenerator(openai_key=OPENAI_API_KEY, anthropic_key=ANTHROPIC_API_KEY) |
| | bg_remover = BackgroundRemover() |
| |
|
| | |
| | AI_MODELS = { |
| | "OpenAI DALL-E 3": "dall-e-3", |
| | "OpenAI DALL-E 2": "dall-e-2", |
| | "Anthropic Claude (via API)": "claude-3-5-sonnet-20241022", |
| | "DeepSeek": "deepseek-chat" |
| | } |
| | BG_REMOVAL_SERVICES = { |
| | "Remove.bg": "removebg", |
| | "Removal.ai": "removelai", |
| | "Local rembg": "local", |
| | "Clipdrop": "clipdrop" |
| | } |
| |
|
| | |
| | ANDROID_ICON_SIZES = { |
| | "mdpi": 48, |
| | "hdpi": 72, |
| | "xhdpi": 96, |
| | "xxhdpi": 144, |
| | "xxxhdpi": 192, |
| | } |
| |
|
| | def make_android_icons_zip(image: Image.Image) -> str: |
| | import tempfile |
| | with tempfile.NamedTemporaryFile(suffix=".zip", delete=False) as tmp: |
| | with zipfile.ZipFile(tmp, mode="w") as zf: |
| | for density, size in ANDROID_ICON_SIZES.items(): |
| | icon = image.resize((size, size), Image.LANCZOS) |
| | icon_bytes = io.BytesIO() |
| | icon.save(icon_bytes, format="PNG") |
| | icon_bytes.seek(0) |
| | zf.writestr(f"ic_launcher_{density}.png", icon_bytes.read()) |
| | return tmp.name |
| |
|
| | |
| | with gr.Blocks(title="Advanced Image Processing Suite") as demo: |
| | |
| | gr.Markdown("# Advanced Image Processing Suite") |
| | gr.Markdown("Professional-grade image processing, AI generation, and enhancement tools") |
| | |
| | with gr.Tabs() as tabs: |
| | |
| | with gr.Tab("Format"): |
| | gr.Markdown("### Convert images between multiple formats with advanced options") |
| | |
| | with gr.Row(): |
| | with gr.Column(): |
| | conv_input = gr.Image(label="Upload Image", type="filepath") |
| | conv_format = gr.Dropdown( |
| | choices=SUPPORTED_FORMATS, |
| | value="PNG", |
| | label="Target Format" |
| | ) |
| | conv_quality = gr.Slider( |
| | minimum=10, maximum=100, value=95, |
| | label="Quality (for JPEG/WebP)", step=5 |
| | ) |
| | conv_btn = gr.Button("Convert Image", variant="primary") |
| | |
| | with gr.Column(): |
| | conv_output = gr.File(label="Download Converted Image") |
| | conv_status = gr.Textbox(label="Status", interactive=False) |
| | |
| | conv_btn.click( |
| | fn=lambda img, fmt, qual: processor.convert_image(img, fmt, qual) if img else (None, "Please upload an image"), |
| | inputs=[conv_input, conv_format, conv_quality], |
| | outputs=[conv_output, conv_status] |
| | ) |
| | |
| | |
| | with gr.Tab("AI Gen"): |
| | gr.Markdown("### Generate stunning images using state-of-the-art AI models") |
| | |
| | with gr.Row(): |
| | with gr.Column(): |
| | gr.Markdown("#### API Configuration") |
| | openai_key = gr.Textbox( |
| | label="OpenAI API Key", |
| | type="password", |
| | placeholder="sk-..." |
| | ) |
| | anthropic_key = gr.Textbox( |
| | label="Anthropic API Key", |
| | type="password", |
| | placeholder="sk-ant-..." |
| | ) |
| | deepseek_key = gr.Textbox( |
| | label="DeepSeek API Key", |
| | type="password", |
| | placeholder="sk-..." |
| | ) |
| | |
| | save_keys_btn = gr.Button("Save API Keys") |
| | key_status = gr.Textbox(label="Key Status", interactive=False) |
| | |
| | with gr.Row(): |
| | with gr.Column(): |
| | ai_prompt = gr.Textbox( |
| | label="Image Prompt", |
| | placeholder="A serene landscape with mountains and a lake at sunset...", |
| | lines=3 |
| | ) |
| | ai_model = gr.Dropdown( |
| | choices=list(AI_MODELS.keys()), |
| | value="OpenAI DALL-E 3", |
| | label="AI Model" |
| | ) |
| | ai_size = gr.Dropdown( |
| | choices=["256x256", "512x512", "1024x1024", "1792x1024", "1024x1792"], |
| | value="1024x1024", |
| | label="Image Size" |
| | ) |
| | |
| | generate_btn = gr.Button("Generate Image", variant="primary") |
| | |
| | with gr.Column(): |
| | ai_output = gr.Image(label="Generated Image") |
| | ai_status = gr.Textbox(label="Generation Status", interactive=False) |
| | |
| | |
| | def save_api_keys(openai, anthropic, deepseek): |
| | ai_generator.openai_key = openai |
| | ai_generator.anthropic_key = anthropic |
| | |
| | saved_keys = [] |
| | if openai: |
| | saved_keys.append("OpenAI") |
| | if anthropic: |
| | saved_keys.append("Anthropic") |
| | if deepseek: |
| | saved_keys.append("DeepSeek") |
| | if saved_keys: |
| | return f"Saved keys for: {', '.join(saved_keys)}" |
| | return "No keys provided" |
| |
|
| | save_keys_btn.click( |
| | fn=save_api_keys, |
| | inputs=[openai_key, anthropic_key, deepseek_key], |
| | outputs=key_status |
| | ) |
| |
|
| | |
| | def generate_image(prompt, model, size, openai, anthropic): |
| | if not prompt: |
| | return None, "Please enter a prompt" |
| | if "OpenAI" in model: |
| | model_name = AI_MODELS[model] |
| | temp_gen = AIImageGenerator(openai_key=openai, anthropic_key=anthropic) |
| | return temp_gen.generate_image_openai(prompt, model_name, size) |
| | elif "Anthropic" in model: |
| | temp_gen = AIImageGenerator(openai_key=openai, anthropic_key=anthropic) |
| | return temp_gen.generate_image_anthropic(prompt) |
| | else: |
| | return None, f"{model} not yet implemented" |
| |
|
| | generate_btn.click( |
| | fn=generate_image, |
| | inputs=[ai_prompt, ai_model, ai_size, openai_key, anthropic_key], |
| | outputs=[ai_output, ai_status] |
| | ) |
| | |
| | |
| | with gr.Tab("Enhance"): |
| | gr.Markdown("### Enhance your images with professional-grade filters and AI") |
| | |
| | with gr.Row(): |
| | with gr.Column(): |
| | enhance_input = gr.Image(label="Upload Image to Enhance", type="filepath") |
| | enhance_type = gr.Dropdown( |
| | choices=ENHANCEMENT_OPTIONS, |
| | value="Color Enhancement", |
| | label="Enhancement Type" |
| | ) |
| | enhance_intensity = gr.Slider( |
| | minimum=0.1, maximum=2.0, value=1.0, step=0.1, |
| | label="Enhancement Intensity" |
| | ) |
| | enhance_btn = gr.Button("Enhance Image", variant="primary") |
| | |
| | with gr.Column(): |
| | enhance_output = gr.Image(label="Enhanced Image") |
| | enhance_status = gr.Textbox(label="Enhancement Status", interactive=False) |
| | |
| | enhance_btn.click( |
| | fn=lambda img, enh_type, intensity: processor.enhance_image(img, enh_type, intensity) if img else (None, "Please upload an image"), |
| | inputs=[enhance_input, enhance_type, enhance_intensity], |
| | outputs=[enhance_output, enhance_status] |
| | ) |
| | |
| | |
| | with gr.Tab("BG Remove"): |
| | gr.Markdown("### Remove backgrounds instantly with AI-powered tools") |
| | |
| | with gr.Row(): |
| | with gr.Column(): |
| | gr.Markdown("#### API Keys for Premium Services") |
| | removebg_key = gr.Textbox( |
| | label="Remove.bg API Key", |
| | type="password", |
| | placeholder="Your Remove.bg API key" |
| | ) |
| | save_bg_key_btn = gr.Button("Save Remove.bg Key") |
| | bg_key_status = gr.Textbox(label="API Status", interactive=False) |
| | |
| | with gr.Row(): |
| | with gr.Column(): |
| | bg_input = gr.Image(label="Upload Image", type="filepath") |
| | bg_service = gr.Dropdown( |
| | choices=list(BG_REMOVAL_SERVICES.keys()), |
| | value="Local rembg", |
| | label="Background Removal Service" |
| | ) |
| | bg_btn = gr.Button("Remove Background", variant="primary") |
| | |
| | with gr.Column(): |
| | bg_output = gr.Image(label="Result (Transparent Background)") |
| | bg_status = gr.Textbox(label="Processing Status", interactive=False) |
| | |
| | |
| | def save_bg_api_key(key): |
| | bg_remover.removebg_key = key |
| | if key: |
| | return "Remove.bg API key saved" |
| | return "No key provided" |
| | save_bg_key_btn.click( |
| | fn=save_bg_api_key, |
| | inputs=removebg_key, |
| | outputs=bg_key_status |
| | ) |
| | |
| | def remove_bg(img, service, removebg): |
| | if not img: |
| | return None, "Please upload an image" |
| | service_key = BG_REMOVAL_SERVICES.get(service, "local") |
| | if service_key == "local": |
| | return bg_remover.remove_local(img) |
| | elif service_key == "removebg": |
| | temp_remover = BackgroundRemover(removebg_key=removebg) |
| | return temp_remover.remove_with_removebg(img) |
| | else: |
| | return None, f"{service} not implemented" |
| | bg_btn.click( |
| | fn=remove_bg, |
| | inputs=[bg_input, bg_service, removebg_key], |
| | outputs=[bg_output, bg_status] |
| | ) |
| | |
| | |
| | with gr.Tab("Batch"): |
| | gr.Markdown("### Process multiple images simultaneously") |
| | |
| | with gr.Row(): |
| | with gr.Column(): |
| | batch_files = gr.Files(label="Upload Multiple Images", file_types=["image"]) |
| | batch_operation = gr.Dropdown( |
| | choices=["Format Conversion", "Enhancement", "Background Removal"], |
| | value="Format Conversion", |
| | label="Batch Operation" |
| | ) |
| | batch_btn = gr.Button("Process Batch", variant="primary") |
| | |
| | with gr.Column(): |
| | batch_output = gr.Files(label="Download Processed Images") |
| | batch_status = gr.Textbox(label="Batch Status", interactive=False, lines=5) |
| | |
| | |
| | def process_batch(files, operation): |
| | if not files: |
| | return None, "Please upload images for batch processing" |
| | results = [] |
| | status_messages = [] |
| | for i, file in enumerate(files): |
| | try: |
| | if operation == "Format Conversion": |
| | result, msg = processor.convert_image(file.name, "PNG") |
| | elif operation == "Enhancement": |
| | result, msg = processor.enhance_image(file.name, "Color Enhancement") |
| | elif operation == "Background Removal": |
| | result, msg = bg_remover.remove_local(file.name) |
| | if result: |
| | results.append(result) |
| | status_messages.append(f"File {i+1}: {msg}") |
| | except Exception as e: |
| | status_messages.append(f"File {i+1}: Error - {str(e)}") |
| | return results if results else None, "\n".join(status_messages) |
| | batch_btn.click( |
| | fn=process_batch, |
| | inputs=[batch_files, batch_operation], |
| | outputs=[batch_output, batch_status] |
| | ) |
| | |
| | |
| | with gr.Tab("Tools"): |
| | gr.Markdown("### Professional image analysis and specialized processing") |
| | |
| | with gr.Tabs(): |
| | with gr.Tab("Image Analysis"): |
| | with gr.Row(): |
| | with gr.Column(): |
| | analysis_input = gr.Image(label="Upload Image for Analysis", type="filepath") |
| | analysis_btn = gr.Button("Analyze Image", variant="primary") |
| | |
| | with gr.Column(): |
| | analysis_output = gr.JSON(label="Image Analysis Results") |
| | |
| | |
| | def analyze_image(img_path): |
| | return ImageAnalysis.analyze_image(img_path) |
| | analysis_btn.click( |
| | fn=analyze_image, |
| | inputs=analysis_input, |
| | outputs=analysis_output |
| | ) |
| | |
| | with gr.Tab("Custom Filters"): |
| | with gr.Row(): |
| | with gr.Column(): |
| | filter_input = gr.Image(label="Upload Image", type="filepath") |
| | |
| | |
| | brightness = gr.Slider(-100, 100, 0, label="Brightness") |
| | contrast = gr.Slider(-100, 100, 0, label="Contrast") |
| | saturation = gr.Slider(-100, 100, 0, label="Saturation") |
| | hue_shift = gr.Slider(-180, 180, 0, label="Hue Shift") |
| | |
| | apply_filter_btn = gr.Button("Apply Custom Filter", variant="primary") |
| | |
| | with gr.Column(): |
| | filter_output = gr.Image(label="Filtered Image") |
| | filter_status = gr.Textbox(label="Filter Status", interactive=False) |
| | |
| | |
| | apply_filter_btn.click( |
| | fn=apply_custom_filter, |
| | inputs=[filter_input, brightness, contrast, saturation, hue_shift], |
| | outputs=[filter_output, filter_status] |
| | ) |
| | |
| | with gr.Tab("Resize & Crop"): |
| | with gr.Row(): |
| | with gr.Column(): |
| | resize_input = gr.Image(label="Upload Image", type="filepath") |
| | |
| | resize_mode = gr.Radio( |
| | choices=["Resize", "Crop", "Smart Crop", "Canvas Resize"], |
| | value="Resize", |
| | label="Operation Mode" |
| | ) |
| | |
| | new_width = gr.Number(label="Width", value=800) |
| | new_height = gr.Number(label="Height", value=600) |
| | |
| | maintain_ratio = gr.Checkbox(label="Maintain Aspect Ratio", value=True) |
| | resize_quality = gr.Dropdown( |
| | choices=["NEAREST", "LANCZOS", "BILINEAR", "BICUBIC"], |
| | value="LANCZOS", |
| | label="Resize Quality" |
| | ) |
| | |
| | resize_btn = gr.Button("Process Image", variant="primary") |
| | |
| | with gr.Column(): |
| | resize_output = gr.Image(label="Processed Image") |
| | resize_status = gr.Textbox(label="Processing Status", interactive=False) |
| | |
| | |
| | resize_btn.click( |
| | fn=resize_crop_image, |
| | inputs=[resize_input, resize_mode, new_width, new_height, maintain_ratio, resize_quality], |
| | outputs=[resize_output, resize_status] |
| | ) |
| | |
| | |
| | with gr.Tab("Android Icons"): |
| | gr.Markdown("### Generate all Android app icon sizes and download as a ZIP") |
| | |
| | with gr.Row(): |
| | with gr.Column(): |
| | android_icon_input = gr.Image(type="pil", label="Upload Icon Source Image") |
| | android_icon_btn = gr.Button("Generate Android Icons", variant="primary") |
| | |
| | with gr.Column(): |
| | android_icon_zip = gr.File(label="Download Icons ZIP") |
| | android_status = gr.Textbox(label="Generation Status", interactive=False) |
| |
|
| | def handle_android_icon(image): |
| | if image is None: |
| | return None, "Please upload an image" |
| | try: |
| | zip_path = make_android_icons_zip(image) |
| | return zip_path, "Android icons generated successfully!" |
| | except Exception as e: |
| | return None, f"Error generating icons: {str(e)}" |
| |
|
| | android_icon_btn.click( |
| | fn=handle_android_icon, |
| | inputs=android_icon_input, |
| | outputs=[android_icon_zip, android_status] |
| | ) |
| |
|
| |
|
| | |
| | if __name__ == "__main__": |
| | |
| | |
| | launch_kwargs = {} |
| | |
| | if os.environ.get("GRADIO_SHARE", "false").lower() == "true": |
| | launch_kwargs["share"] = True |
| | if os.environ.get("GRADIO_FAVICON_PATH"): |
| | launch_kwargs["favicon_path"] = os.environ["GRADIO_FAVICON_PATH"] |
| | if os.environ.get("GRADIO_SSL_VERIFY", "false").lower() == "true": |
| | launch_kwargs["ssl_verify"] = True |
| | if os.environ.get("GRADIO_SHOW_API", "false").lower() == "true": |
| | launch_kwargs["show_api"] = True |
| | demo.launch(**launch_kwargs) |