File size: 20,426 Bytes
d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 2d6593a d5aa3ec 0177267 2d6593a 0177267 2d6593a d5aa3ec 2d6593a 0177267 2d6593a 0177267 2d6593a d5aa3ec 0177267 d5aa3ec d91be70 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 |
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()
# Restore AI_MODELS and BG_REMOVAL_SERVICES constants
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 (density: size in px)
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 # Return the file path for gr.File
# Main Gradio Interface
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:
# Tab 1: Format
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]
)
# Tab 2: AI Gen
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)
# API key saving (refactored)
def save_api_keys(openai, anthropic, deepseek):
ai_generator.openai_key = openai
ai_generator.anthropic_key = anthropic
# DeepSeek can be added to ai_generator if implemented
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
)
# Image generation (fixed: pass API keys directly)
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]
)
# Tab 3: Enhance
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]
)
# Tab 4: BG Remove
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)
# Save background removal API key (refactored)
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
)
# Background removal (fixed: pass Remove.bg key directly)
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]
)
# Tab 5: Batch
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)
# Batch processing (refactored)
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]
)
# Tab 6: Tools
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")
# Advanced Tools: Image Analysis (refactored)
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")
# Custom filter controls
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)
# Advanced Tools: Custom Filters (refactored)
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)
# Advanced Tools: Resize & Crop (refactored)
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]
)
# Tab 7: Android Icons
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]
)
# Launch configuration
if __name__ == "__main__":
# For Hugging Face Spaces, do not set server_name or server_port
# Use environment variables or defaults for other options
launch_kwargs = {}
# Optionally allow share, favicon_path, ssl_verify, show_api to be set via env
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) |