import gradio as gr import threading import os import shutil import tempfile import time from util import process_multi_image_edit, process_local_image_edit, download_and_check_result_nsfw from nfsw import NSFWDetector # Configuration parameters FREE_TRY_N = 3 # Free phase: first 20 tries without restrictions SLOW_TRY_N = 5 # Slow phase start: 30 tries SLOW2_TRY_N = 8 # Slow phase start: 30 tries RATE_LIMIT_60 = 10 # Full restriction: blocked after 60 tries # Time window configuration (minutes) PHASE_1_WINDOW = 5 # 20-30 tries: 3 minutes PHASE_2_WINDOW = 10 # 30-40 tries: 6 minutes PHASE_3_WINDOW = 15 # 40-60 tries: 10 minutes MAX_IMAGES_PER_WINDOW = 2 # Max images per time window # Restricted countries configuration RESTRICTED_COUNTRIES = ["印度", "巴基斯坦", "俄罗斯", "中国"] RESTRICTED_COUNTRY_LIMIT = 1 # Max usage for restricted countries IP_Dict = {} # IP generation statistics and time window tracking IP_Generation_Count = {} # Record total generation count for each IP IP_Rate_Limit_Track = {} # Record generation count and timestamp in current time window for each IP IP_Active_Tasks = {} # Track active tasks for each IP (to prevent concurrent submissions) IP_Country_Cache = {} # Cache IP country information to avoid repeated queries def query_ip_country(client_ip): """ Query IP address geo information with robust error handling Returns: dict: {"country": str, "region": str, "city": str} """ # Check cache first if client_ip in IP_Country_Cache: print(f"Using cached IP data for {client_ip}") return IP_Country_Cache[client_ip] # Validate IP address if not client_ip or client_ip in ["127.0.0.1", "localhost", "::1"]: print(f"Invalid or local IP address: {client_ip}, using default") default_geo = {"country": "Unknown", "region": "Unknown", "city": "Unknown"} IP_Country_Cache[client_ip] = default_geo return default_geo # Query API with robust error handling print(f"Querying IP geolocation for {client_ip}...") try: import requests from requests.exceptions import Timeout, ConnectionError, RequestException api_url = f"https://api.vore.top/api/IPdata?ip={client_ip}" # Make request with 3 second timeout response = requests.get(api_url, timeout=3) if response.status_code == 200: data = response.json() if data.get("code") == 200 and "ipdata" in data: ipdata = data["ipdata"] geo_info = { "country": ipdata.get("info1", "Unknown"), "region": ipdata.get("info2", "Unknown"), "city": ipdata.get("info3", "Unknown") } IP_Country_Cache[client_ip] = geo_info print(f"Successfully detected location for {client_ip}: {geo_info['country']}") return geo_info except Exception as e: print(f"Error querying IP {client_ip}: {e}, using default") # All failures lead here default_geo = {"country": "Unknown", "region": "Unknown", "city": "Unknown"} IP_Country_Cache[client_ip] = default_geo return default_geo def is_restricted_country_ip(client_ip): """ Check if IP is from a restricted country Returns: bool: True if from restricted country """ geo_info = query_ip_country(client_ip) country = geo_info["country"] return country in RESTRICTED_COUNTRIES def get_ip_max_limit(client_ip): """ Get max usage limit for IP based on country Returns: int: Max usage limit """ if is_restricted_country_ip(client_ip): return RESTRICTED_COUNTRY_LIMIT else: return RATE_LIMIT_60 def get_ip_generation_count(client_ip): """ Get IP generation count """ if client_ip not in IP_Generation_Count: IP_Generation_Count[client_ip] = 0 return IP_Generation_Count[client_ip] def increment_ip_generation_count(client_ip): """ Increment IP generation count """ if client_ip not in IP_Generation_Count: IP_Generation_Count[client_ip] = 0 IP_Generation_Count[client_ip] += 1 return IP_Generation_Count[client_ip] def get_ip_phase(client_ip): """ Get current phase for IP Returns: str: 'free', 'rate_limit_1', 'rate_limit_2', 'rate_limit_3', 'blocked' """ count = get_ip_generation_count(client_ip) max_limit = get_ip_max_limit(client_ip) # For restricted countries, check if they've reached their limit (1 task) if is_restricted_country_ip(client_ip): if count >= max_limit: return 'blocked' else: return 'free' # Only 1 free task for restricted countries # For normal countries, use standard limits if count < FREE_TRY_N: # 0-2 tries return 'free' elif count < SLOW_TRY_N: # 3-4 tries return 'rate_limit_1' # NSFW blur + 5 minutes 2 images elif count < SLOW2_TRY_N: # 5-7 tries return 'rate_limit_2' # NSFW blur + 10 minutes 2 images elif count < max_limit: # 8-9 tries return 'rate_limit_3' # NSFW blur + 15 minutes 2 images else: # 10+ tries return 'blocked' # Generation blocked def check_rate_limit_for_phase(client_ip, phase): """ Check rate limit for specific phase Returns: tuple: (is_limited, wait_time_minutes, current_count) """ if phase not in ['rate_limit_1', 'rate_limit_2', 'rate_limit_3']: return False, 0, 0 # Determine time window if phase == 'rate_limit_1': window_minutes = PHASE_1_WINDOW # 3 minutes elif phase == 'rate_limit_2': window_minutes = PHASE_2_WINDOW # 6 minutes else: # rate_limit_3 window_minutes = PHASE_3_WINDOW # 10 minutes current_time = time.time() window_key = f"{client_ip}_{phase}" # Clean expired records if window_key in IP_Rate_Limit_Track: track_data = IP_Rate_Limit_Track[window_key] # Check if within current time window if current_time - track_data['start_time'] > window_minutes * 60: # Time window expired, reset IP_Rate_Limit_Track[window_key] = { 'count': 0, 'start_time': current_time, 'last_generation': current_time } else: # Initialize IP_Rate_Limit_Track[window_key] = { 'count': 0, 'start_time': current_time, 'last_generation': current_time } track_data = IP_Rate_Limit_Track[window_key] # Check if exceeded limit if track_data['count'] >= MAX_IMAGES_PER_WINDOW: # Calculate remaining wait time elapsed = current_time - track_data['start_time'] wait_time = (window_minutes * 60) - elapsed wait_minutes = max(0, wait_time / 60) return True, wait_minutes, track_data['count'] return False, 0, track_data['count'] def has_active_task(client_ip): """ Check if IP has an active task in progress Returns: bool: True if IP has an active task """ return client_ip in IP_Active_Tasks and IP_Active_Tasks[client_ip] def set_active_task(client_ip, active=True): """ Set or clear active task status for IP Args: client_ip (str): Client IP address active (bool): True to mark as active, False to clear """ if active: IP_Active_Tasks[client_ip] = True print(f"🔒 Task locked for IP: {client_ip}") else: if client_ip in IP_Active_Tasks: del IP_Active_Tasks[client_ip] print(f"🔓 Task unlocked for IP: {client_ip}") def record_generation_attempt(client_ip, phase): """ Record generation attempt """ # Increment total count increment_ip_generation_count(client_ip) # Record time window count if phase in ['rate_limit_1', 'rate_limit_2', 'rate_limit_3']: window_key = f"{client_ip}_{phase}" current_time = time.time() if window_key in IP_Rate_Limit_Track: IP_Rate_Limit_Track[window_key]['count'] += 1 IP_Rate_Limit_Track[window_key]['last_generation'] = current_time else: IP_Rate_Limit_Track[window_key] = { 'count': 1, 'start_time': current_time, 'last_generation': current_time } def apply_gaussian_blur_to_image_url(image_url, blur_strength=50): """ Apply Gaussian blur to image URL Args: image_url (str): Original image URL blur_strength (int): Blur strength, default 50 (heavy blur) Returns: PIL.Image: Blurred PIL Image object """ try: import requests from PIL import Image, ImageFilter import io # Download image response = requests.get(image_url, timeout=30) if response.status_code != 200: return None # Convert to PIL Image image_data = io.BytesIO(response.content) image = Image.open(image_data) # Apply heavy Gaussian blur blurred_image = image.filter(ImageFilter.GaussianBlur(radius=blur_strength)) return blurred_image except Exception as e: print(f"⚠️ Failed to apply Gaussian blur: {e}") return None # Initialize NSFW detector (download from Hugging Face) try: nsfw_detector = NSFWDetector() # Auto download falconsai_yolov9_nsfw_model_quantized.pt from Hugging Face print("✅ NSFW detector initialized successfully") except Exception as e: print(f"❌ NSFW detector initialization failed: {e}") nsfw_detector = None def edit_image_interface(input_image1, input_image2, input_image3, prompt, aspect_ratio, request: gr.Request, progress=gr.Progress()): """ Interface function for processing multi-image editing with phase-based limitations """ try: # Extract user IP client_ip = request.client.host x_forwarded_for = dict(request.headers).get('x-forwarded-for') if x_forwarded_for: client_ip = x_forwarded_for if client_ip not in IP_Dict: IP_Dict[client_ip] = 0 IP_Dict[client_ip] += 1 # Validate input images input_images = [input_image1, input_image2, input_image3] valid_images = [img for img in input_images if img is not None] if len(valid_images) < 2: return None, "Please upload at least 2 images", gr.update(visible=False) if len(valid_images) > 3: return None, "Maximum 3 images allowed", gr.update(visible=False) if not prompt or prompt.strip() == "": return None, "Please enter editing prompt", gr.update(visible=False) # Check if prompt length is greater than 3 characters if len(prompt.strip()) <= 3: return None, "❌ Editing prompt must be more than 3 characters", gr.update(visible=False) except Exception as e: print(f"⚠️ Request preprocessing error: {e}") return None, "❌ Request processing error", gr.update(visible=False) # Check if user has an active task in progress if has_active_task(client_ip): concurrent_button_html = f"""
⏰ Process Multiple Tasks Simultaneously
""" return None, "❌ You have a task in progress. Please wait for it to complete before submitting a new task. Or visit https://omnicreator.net/multi-image-edit#generator to process multiple tasks simultaneously.", gr.update(value=concurrent_button_html, visible=True) # Get user current phase current_phase = get_ip_phase(client_ip) current_count = get_ip_generation_count(client_ip) geo_info = IP_Country_Cache.get(client_ip, {"country": "Unknown", "region": "Unknown", "city": "Unknown"}) is_restricted = is_restricted_country_ip(client_ip) print(f"📊 User phase info - IP: {client_ip}, Location: {geo_info['country']}/{geo_info['region']}/{geo_info['city']}, Phase: {current_phase}, Count: {current_count}, Restricted: {is_restricted}, Active task: {has_active_task(client_ip)}") # Check if completely blocked if current_phase == 'blocked': # Generate blocked limit button blocked_button_html = f"""
🚀 Unlimited Generation
""" return None, f"❌ You have reached Hugging Face's free generation limit. Please visit https://omnicreator.net/multi-image-edit#generator for unlimited generation", gr.update(value=blocked_button_html, visible=True) # Check rate limit (applies to rate_limit phases) if current_phase in ['rate_limit_1', 'rate_limit_2', 'rate_limit_3']: is_limited, wait_minutes, window_count = check_rate_limit_for_phase(client_ip, current_phase) if is_limited: wait_minutes_int = int(wait_minutes) + 1 # Generate rate limit button rate_limit_button_html = f"""
⏰ Skip Wait - Unlimited Generation
""" return None, f"❌ You have reached Hugging Face's free generation limit. Please visit https://omnicreator.net/multi-image-edit#generator for unlimited generation, or wait {wait_minutes_int} minutes before generating again", gr.update(value=rate_limit_button_html, visible=True) # Parse aspect ratio to get width and height width, height = 0, 0 # Default to auto sizing if aspect_ratio and aspect_ratio != "Auto": aspect_ratios = { "16:9": (1364, 768), "4:3": (1182, 887), "1:1": (1024, 1024), "3:4": (887, 1182), "9:16": (768, 1364) } if aspect_ratio in aspect_ratios: width, height = aspect_ratios[aspect_ratio] # Handle NSFW detection based on phase is_nsfw_task = False # Track if this task involves NSFW content # Skip NSFW detection in free phase - check first image for NSFW if current_phase != 'free' and nsfw_detector is not None and valid_images: try: nsfw_result = nsfw_detector.predict_pil_label_only(valid_images[0]) if nsfw_result.lower() == "nsfw": is_nsfw_task = True print(f"🔍 Input NSFW detected in {current_phase} phase: ❌❌❌ {nsfw_result} - IP: {client_ip} (will blur result)") else: print(f"🔍 Input NSFW check passed: ✅✅✅ {nsfw_result} - IP: {client_ip}") except Exception as e: print(f"⚠️ Input NSFW detection failed: {e}") # Allow continuation when detection fails result_url = None status_message = "" def progress_callback(message): try: nonlocal status_message status_message = message # Add error handling to prevent progress update failure if progress is not None: progress(0.5, desc=message) except Exception as e: print(f"⚠️ Progress update failed: {e}") try: # Record generation attempt (before actual generation to ensure correct count) record_generation_attempt(client_ip, current_phase) updated_count = get_ip_generation_count(client_ip) # Mark this IP as having an active task set_active_task(client_ip, active=True) print(f"✅ Multi-image processing started - IP: {client_ip}, phase: {current_phase}, total count: {updated_count}, images: {len(valid_images)}, size: {width}x{height}, prompt: {prompt.strip()}", flush=True) # Determine priority (only the first task for each IP gets priority) task_priority = 1 if current_count == 0 else 0 # Call multi-image editing processing function result_url, message, task_uuid = process_multi_image_edit(valid_images, prompt.strip(), width, height, progress_callback, priority=task_priority, client_ip=client_ip) if result_url: print(f"✅ Processing completed successfully - IP: {client_ip}, result_url: {result_url}, task_uuid: {task_uuid}", flush=True) # Detect result image NSFW content (only in rate limit phases) if nsfw_detector is not None and current_phase != 'free': try: if progress is not None: progress(0.9, desc="Checking result image...") is_nsfw, nsfw_error = download_and_check_result_nsfw(result_url, nsfw_detector) if nsfw_error: print(f"⚠️ Result image NSFW detection error - IP: {client_ip}, error: {nsfw_error}") elif is_nsfw: is_nsfw_task = True # Mark task as NSFW print(f"🔍 Result image NSFW detected in {current_phase} phase: ❌❌❌ - IP: {client_ip} (will blur result)") else: print(f"🔍 Result image NSFW check passed: ✅✅✅ - IP: {client_ip}") except Exception as e: print(f"⚠️ Result image NSFW detection exception - IP: {client_ip}, error: {str(e)}") # Apply blur if this is an NSFW task in rate limit phases should_blur = False if current_phase in ['rate_limit_1', 'rate_limit_2', 'rate_limit_3'] and is_nsfw_task: should_blur = True # Apply blur processing if should_blur: if progress is not None: progress(0.95, desc="Applying content filter...") blurred_image = apply_gaussian_blur_to_image_url(result_url) if blurred_image is not None: final_result = blurred_image # Return PIL Image object final_message = f"⚠️ NSFW content detected, content filter applied. NSFW content is prohibited by Hugging Face, but you can generate unlimited content at our official website https://omnicreator.net/multi-image-edit#generator" print(f"🔒 Applied Gaussian blur for NSFW content - IP: {client_ip}") else: # Blur failed, return original URL with warning final_result = result_url final_message = f"⚠️ NSFW content detected, but content filter failed. Please visit https://omnicreator.net/multi-image-edit#generator for better experience" # Generate NSFW button for blurred content nsfw_action_buttons_html = f"""
🔥 Unlimited NSFW Generation
""" return final_result, final_message, gr.update(value=nsfw_action_buttons_html, visible=True) else: final_result = result_url final_message = "✅ " + message try: if progress is not None: progress(1.0, desc="Processing completed") except Exception as e: print(f"⚠️ Final progress update failed: {e}") # Generate action buttons HTML like Trump AI Voice action_buttons_html = "" if task_uuid: task_detail_url = f"https://omnicreator.net/my-creations/task/{task_uuid}" action_buttons_html = f"""
🖼️ Download HD Image 🚀 Unlimited Generation
""" return final_result, final_message, gr.update(value=action_buttons_html, visible=True) else: print(f"❌ Processing failed - IP: {client_ip}, error: {message}", flush=True) return None, "❌ " + message, gr.update(visible=False) except Exception as e: print(f"❌ Processing exception - IP: {client_ip}, error: {str(e)}") return None, f"❌ Error occurred during processing: {str(e)}", gr.update(visible=False) finally: # Always clear active task status when done (success or failure) set_active_task(client_ip, active=False) # Create Gradio interface def create_app(): with gr.Blocks( title="AI Image Editor", theme=gr.themes.Soft(), css=""" .main-container { max-width: 1200px; margin: 0 auto; } .upload-area { border: 2px dashed #ccc; border-radius: 10px; padding: 20px; text-align: center; } .result-area { margin-top: 20px; padding: 20px; border-radius: 10px; background-color: #f8f9fa; } .use-as-input-btn { margin-top: 10px; width: 100%; } """, # Improve concurrency performance configuration head=""" """ ) as app: # Main title - styled like Trump AI Voice gr.HTML("""

🎨 AI Multi-Image Editor

""", padding=False) # Powered by line below title - styled like Trump AI Voice gr.HTML("""

powered by omnicreator.net

""", padding=False) with gr.Tabs(): # Multi-image editing tab with gr.Tab("🖼️ Multi-Image Editing"): with gr.Row(): with gr.Column(scale=1): gr.Markdown("### 📸 Upload Images (2-3 images)") # Multiple image inputs with gr.Row(): input_image1 = gr.Image( label="Image 1 *", type="pil", height=200, elem_classes=["upload-area"] ) input_image2 = gr.Image( label="Image 2 *", type="pil", height=200, elem_classes=["upload-area"] ) input_image3 = gr.Image( label="Image 3 (optional)", type="pil", height=200, elem_classes=["upload-area"] ) gr.Markdown("### 📐 Output Size") aspect_ratio_selector = gr.Radio( choices=["Auto", "16:9", "4:3", "1:1", "3:4", "9:16"], value="Auto", label="Select aspect ratio", info="Choose output dimensions or Auto for original sizing" ) gr.Markdown("### ✍️ Multi-Image Editing Instructions") prompt_input = gr.Textbox( label="Enter multi-image editing prompt", placeholder="For example: combine these images into a single scene, merge the best parts from each image, create a collage with artistic transitions...", lines=4, max_lines=6 ) edit_button = gr.Button( "🚀 Start Multi-Image Editing", variant="primary", size="lg" ) with gr.Column(scale=1): gr.Markdown("### 🎯 Multi-Image Editing Result") output_image = gr.Image( label="Multi-image edited result", height=400, elem_classes=["result-area"] ) # Add "Use as Input" button use_as_input_btn = gr.Button( "🔄 Use as Input", variant="secondary", size="sm", elem_classes=["use-as-input-btn"] ) status_output = gr.Textbox( label="Processing status", lines=2, max_lines=3, interactive=False ) # Action buttons that will show after task completion action_buttons = gr.HTML(visible=False) # Example area gr.Markdown("### 💡 Multi-Image Editing Examples") # Helper function to load example images def load_example_1(): """Load dancing cats example""" try: from PIL import Image img1 = Image.open("datas/data01/tom02.webp") img2 = Image.open("datas/data01/tom.webp") return img1, img2, None, "Let the 2 cats dance together", "16:9" except Exception as e: print(f"Failed to load example 1 images: {e}") return None, None, None, "Let the 2 cats dance together", "16:9" def load_example_2(): """Load fashion try-on example""" try: from PIL import Image img1 = Image.open("datas/data02/girl.jpg") img2 = Image.open("datas/data02/cloth.jpeg") return img1, img2, None, "Let the girl in first image, wear the dress in second image", "9:16" except Exception as e: print(f"Failed to load example 2 images: {e}") return None, None, None, "Let the girl in first image, wear the dress in second image", "9:16" def load_example_3(): """Load beach bikini example""" try: from PIL import Image img1 = Image.open("datas/data03/girl.webp") img2 = Image.open("datas/data03/cloth.jpg") return img1, img2, None, "Let the girl in first image, wear the bikini in second image, lying on the beach", "1:1" except Exception as e: print(f"Failed to load example 3 images: {e}") return None, None, None, "Let the girl in first image, wear the bikini in second image, lying on the beach", "1:1" # Example 1: Cats dancing gr.Markdown("#### 🐱 Example 1: Dancing Cats (2 images)") with gr.Row(): with gr.Column(scale=2): # Preview images for example 1 with gr.Row(): try: gr.Image("datas/data01/tom02.webp", label="Cat 1", height=100, width=100, show_label=False, interactive=False) gr.Image("datas/data01/tom.webp", label="Cat 2", height=100, width=100, show_label=False, interactive=False) except: gr.Markdown("*Preview images not available*") gr.Markdown("**Prompt**: Let the 2 cats dance together \n**Size**: 16:9") with gr.Column(scale=1): gr.Button( "🎭 Load Dancing Cats Example", size="lg", variant="secondary" ).click( fn=load_example_1, outputs=[input_image1, input_image2, input_image3, prompt_input, aspect_ratio_selector] ) # Example 2: Girl wearing dress gr.Markdown("#### 👗 Example 2: Fashion Try-on (2 images)") with gr.Row(): with gr.Column(scale=2): # Preview images for example 2 with gr.Row(): try: gr.Image("datas/data02/girl.jpg", label="Girl", height=100, width=100, show_label=False, interactive=False) gr.Image("datas/data02/cloth.jpeg", label="Dress", height=100, width=100, show_label=False, interactive=False) except: gr.Markdown("*Preview images not available*") gr.Markdown("**Prompt**: Let the girl in first image, wear the dress in second image \n**Size**: 9:16") with gr.Column(scale=1): gr.Button( "👗 Load Fashion Try-on Example", size="lg", variant="secondary" ).click( fn=load_example_2, outputs=[input_image1, input_image2, input_image3, prompt_input, aspect_ratio_selector] ) # Example 3: Beach bikini gr.Markdown("#### 🏖️ Example 3: Beach Style (2 images)") with gr.Row(): with gr.Column(scale=2): # Preview images for example 3 with gr.Row(): try: gr.Image("datas/data03/girl.webp", label="Girl", height=100, width=100, show_label=False, interactive=False) gr.Image("datas/data03/cloth.jpg", label="Bikini", height=100, width=100, show_label=False, interactive=False) except: gr.Markdown("*Preview images not available*") gr.Markdown("**Prompt**: Let the girl in first image, wear the bikini in second image, lying on the beach \n**Size**: 1:1") with gr.Column(scale=1): gr.Button( "🏖️ Load Beach Style Example", size="lg", variant="secondary" ).click( fn=load_example_3, outputs=[input_image1, input_image2, input_image3, prompt_input, aspect_ratio_selector] ) # Additional quick prompt examples gr.Markdown("#### ✨ Quick Prompts") with gr.Row(): additional_prompts = [ "Combine these images into a single artistic scene", "Create a collage with artistic transitions between images", "Blend these images into a cohesive composition" ] for prompt in additional_prompts: gr.Button( prompt, size="sm" ).click( lambda p=prompt: p, outputs=prompt_input ) # Bind button click events - simplified, remove state management edit_button.click( fn=edit_image_interface, inputs=[input_image1, input_image2, input_image3, prompt_input, aspect_ratio_selector], outputs=[output_image, status_output, action_buttons], show_progress=True, # Increase concurrency settings concurrency_limit=8, # Limit concurrent requests for multi-image processing api_name="multi_image_edit" ) # Simplify "Use as Input" button, use result as first image def simple_use_as_input(output_img): if output_img is not None: return output_img, None, None # Set as first image, clear others return None, None, None use_as_input_btn.click( fn=simple_use_as_input, inputs=[output_image], outputs=[input_image1, input_image2, input_image3] ) # # Local editing tab # with gr.Tab("🖌️ Local Editing"): # with gr.Row(): # with gr.Column(scale=1): # gr.Markdown("### 📸 Upload Image and Draw Edit Area") # local_input_image = gr.ImageEditor( # label="Upload image and draw mask", # type="pil", # height=512, # brush=gr.Brush(colors=["#ff0000"], default_size=180), # elem_classes=["upload-area"] # ) # gr.Markdown("### ✍️ Editing Instructions") # local_prompt_input = gr.Textbox( # label="Enter local editing prompt", # placeholder="For example: change selected area hair to golden, add patterns to selected object, change selected area color, etc...", # lines=3, # max_lines=5 # ) # local_edit_button = gr.Button( # "🎯 Start Local Editing", # variant="primary", # size="lg" # ) # with gr.Column(scale=1): # gr.Markdown("### 🎯 Editing Result") # local_output_image = gr.Image( # label="Local edited image", # height=320, # elem_classes=["result-area"] # ) # # Add "Use as Input" button # local_use_as_input_btn = gr.Button( # "🔄 Use as Input", # variant="secondary", # size="sm", # elem_classes=["use-as-input-btn"] # ) # local_status_output = gr.Textbox( # label="Processing status", # lines=2, # max_lines=3, # interactive=False # ) # Action buttons that will show after task completion # local_action_buttons = gr.HTML(visible=False) # # Local editing examples # gr.Markdown("### 💡 Local Editing Prompt Examples") # with gr.Row(): # local_example_prompts = [ # "Change selected area hair to golden", # "Add pattern designs to selected clothing", # "Change selected area to different material", # "Add decorations to selected object", # "Change selected area color and style" # ] # for prompt in local_example_prompts: # gr.Button( # prompt, # size="sm" # ).click( # lambda p=prompt: p, # outputs=local_prompt_input # ) # # Bind local edit button click events - simplified, remove state management # local_edit_button.click( # fn=local_edit_interface, # inputs=[local_input_image, local_prompt_input], # outputs=[local_output_image, local_status_output, local_action_buttons], # show_progress=True, # # Increase concurrency settings # concurrency_limit=8, # Local editing is more complex, allow fewer concurrent requests # api_name="local_edit" # ) # # Simplify local edit "Use as Input" button # def simple_local_use_as_input(output_img): # if output_img is not None: # # Create simple ImageEditor format # editor_data = { # "background": output_img, # "layers": [], # "composite": output_img # } # return editor_data # return None # local_use_as_input_btn.click( # fn=simple_local_use_as_input, # inputs=[local_output_image], # outputs=[local_input_image] # ) # SEO Content Section gr.HTML("""

🎨 Unlimited AI Image Generation & Editing

Experience the ultimate freedom in AI image creation! Generate and edit unlimited images without restrictions, including NSFW content, with our premium AI image editing platform.

🚀 Get Unlimited Access Now

Join thousands of creators who trust Omni Creator for unrestricted AI image generation!

🌟 Professional AI Multi-Image Editor - No Restrictions

Transform multiple images into stunning compositions with our advanced AI multi-image editing platform. Combine, merge, and blend 2-3 images to create artistic masterpieces, collages, and seamless compositions with complete creative freedom and professional quality results.

🎯 Unlimited Generation

Premium users enjoy unlimited image generation without daily limits, rate restrictions, or content barriers. Create as many images as you need, whenever you need them.

🔓 No Content Restrictions

Generate and edit any type of content without NSFW filters or content limitations. Complete creative freedom for artists, designers, and content creators.

⚡ Lightning Fast Processing

Advanced AI infrastructure delivers high-quality results in seconds. No waiting in queues, no processing delays - just instant, professional-grade image editing.

🎨 Advanced Editing Tools

Global transformations, precision local editing, style transfer, object removal, background replacement, and dozens of other professional editing capabilities.

💎 Premium Quality

State-of-the-art AI models trained on millions of images deliver exceptional quality and realism. Professional results suitable for commercial use and high-end projects.

🌍 Multi-Modal Support

Support for all image formats, styles, and use cases. From photorealistic portraits to artistic creations, product photography to digital art - we handle everything.

💎 Why Choose Omni Creator Premium?

🚫 No Rate Limits

Generate unlimited images without waiting periods or daily restrictions

🎭 Unrestricted Content

Create any type of content without NSFW filters or censorship

⚡ Priority Processing

Skip queues and get instant results with dedicated processing power

🎨 Advanced Features

Access to latest AI models and cutting-edge editing capabilities

🌟 Start Creating Now

💡 Pro Tips for Best Results

📝 Clear Descriptions:

Use detailed, specific prompts for better results. Describe colors, styles, lighting, and composition clearly.

🎯 Local Editing:

Use precise brush strokes to select areas for local editing. Smaller, focused edits often yield better results.

⚡ Iterative Process:

Use "Use as Input" feature to refine results. Multiple iterations can achieve complex transformations.

🖼️ Image Quality:

Higher resolution input images (up to 10MB) generally produce better editing results and finer details.

🚀 Perfect For Every Creative Need

🎨 Digital Art

  • Character design
  • Concept art
  • Style transfer
  • Artistic effects

📸 Photography

  • Background replacement
  • Object removal
  • Lighting adjustment
  • Portrait enhancement

🛍️ E-commerce

  • Product photography
  • Lifestyle shots
  • Color variations
  • Context placement

📱 Social Media

  • Content creation
  • Meme generation
  • Brand visuals
  • Viral content
🎯 Start Your Project Now

Powered by Omni Creator

The ultimate AI image generation and editing platform • Unlimited creativity, zero restrictions

""", padding=False) # Load IP country information on page load def on_load(request: gr.Request): """ Load page and query IP country information """ try: # Extract client IP client_ip = request.client.host headers = dict(request.headers) if hasattr(request, 'headers') else {} x_forwarded_for = headers.get('x-forwarded-for') or headers.get('X-Forwarded-For') if x_forwarded_for: client_ip = x_forwarded_for.split(',')[0].strip() print(f"Loading page for IP: {client_ip}") # Query IP country information (cached for subsequent requests) query_ip_country(client_ip) except Exception as e: print(f"Error in on_load: {e}") app.load( on_load, inputs=None, outputs=None ) return app if __name__ == "__main__": app = create_app() # Improve queue configuration to handle high concurrency and prevent SSE connection issues app.queue( default_concurrency_limit=20, # Default concurrency limit max_size=50, # Maximum queue size api_open=False # Close API access to reduce resource consumption ) app.launch( server_name="0.0.0.0", show_error=True, # Show detailed error information quiet=False, # Keep log output max_threads=40, # Increase thread pool size height=800, favicon_path=None # Reduce resource loading )