The-X-AI / app.py
Alpha123B's picture
Upload app.py
561e700 verified
Raw
History Blame Contribute Delete
33.1 kB
"""
╔══════════════════════════════════════════════════════════════╗
║ ╔╦╗╦ ╦╔═╗ ═╗ ╔═╗ ║
║ ║ ╠═╣║╣ ╔╩╦╝╚═╗ ║
║ ╩ ╩ ╩╚═╝ ╩ ╚═╚═╝ ║
║ ║
║ UNLIMITED AI IMAGE GENERATION & EDITING ║
║ Uncensored • Hyper-Detailed • Professional Grade ║
╚══════════════════════════════════════════════════════════════╝
"""
import gradio as gr
import torch
import random
import time
import os
from PIL import Image, ImageFilter, ImageEnhance
from diffusers import (
FluxPipeline,
FluxImg2ImgPipeline,
FluxInpaintPipeline,
FluxFillPipeline,
StableDiffusionInstructPix2PixPipeline,
)
import numpy as np
# ── Configuration ──────────────────────────────────────────────
MODELS = {
"flux_schnell": "black-forest-labs/FLUX.1-schnell",
"flux_dev": "black-forest-labs/FLUX.1-dev",
"flux_fill": "black-forest-labs/FLUX.1-Fill-dev",
"instruct_pix2pix": "timbrooks/instruct-pix2pix",
}
CACHED_PIPES = {}
# ── Quality Presets ────────────────────────────────────────────
QUALITY_PRESETS = {
"⚡ Speed (4 steps)": {"steps": 4, "guidance": 0.0, "desc": "Fast preview, ~3s"},
"🎯 Balanced (8 steps)": {"steps": 8, "guidance": 0.0, "desc": "Good quality, ~6s"},
"💎 Quality (15 steps)": {"steps": 15, "guidance": 0.0, "desc": "High quality, ~12s"},
"👑 Masterpiece (25 steps)": {"steps": 25, "guidance": 0.0, "desc": "Best quality, ~20s"},
"🔮 Ultra (50 steps)": {"steps": 50, "guidance": 3.5, "desc": "Ultimate detail (dev model)"},
}
STYLE_PRESETS = [
"hyper-realistic, 8k resolution, professional photography, ultra detailed, sharp focus,"
" cinematic lighting, masterpiece, award-winning",
"anime style, studio ghibli, vibrant colors, detailed background, beautiful composition",
"oil painting, renaissance style, dramatic lighting, textured brushstrokes, museum quality",
"cyberpunk, neon lights, futuristic city, blade runner aesthetic, high contrast, detailed",
"fantasy art, magic, ethereal, trending on artstation, digital painting, intricate details",
"dark gothic, moody atmosphere, chiaroscuro, dramatic shadows, horror aesthetic",
"minimalist, clean lines, pastel colors, modern design, elegant simplicity",
"photorealistic portrait, 85mm lens, f/1.4, golden hour, bokeh, professional photography",
"3D render, octane render, unreal engine 5, ray tracing, highly detailed textures",
"watercolor painting, soft edges, flowing colors, artistic, dreamy atmosphere",
"pencil sketch, charcoal drawing, detailed linework, artistic, monochrome",
"pop art, bold colors, comic style, Roy Lichtenstein inspired, halftone patterns",
]
# ── Negative Prompt Enhancer ───────────────────────────────────
NEGATIVE_PROMPT = (
"blurry, low quality, distorted, deformed, ugly, bad anatomy, bad proportions,"
" extra limbs, cloned face, disfigured, gross proportions, malformed limbs,"
" missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers,"
" long neck, watermark, signature, text, jpeg artifacts, lowres, error"
)
# ── Helper Functions ──────────────────────────────────────────
def get_pipe(model_key, model_id, pipeline_class, dtype=torch.bfloat16):
"""Load/cache pipeline."""
if model_key in CACHED_PIPES:
return CACHED_PIPES[model_key]
print(f"🚀 Loading {model_key}...")
pipe = pipeline_class.from_pretrained(
model_id,
torch_dtype=dtype,
)
pipe.enable_model_cpu_offload()
# Memory optimizations
if hasattr(pipe, "enable_vae_slicing"):
pipe.enable_vae_slicing()
if hasattr(pipe, "enable_vae_tiling"):
pipe.enable_vae_tiling()
CACHED_PIPES[model_key] = pipe
print(f"✅ {model_key} loaded!")
return pipe
def enhance_image_quality(img):
"""Post-process: enhance sharpness and contrast for hyper-detailed output."""
enhancer = ImageEnhance.Sharpness(img)
img = enhancer.enhance(1.3)
enhancer = ImageEnhance.Contrast(img)
img = enhancer.enhance(1.1)
enhancer = ImageEnhance.Color(img)
img = enhancer.enhance(1.05)
return img
def upscale_image(img, target_size):
"""Upscale image to target resolution using Lanczos."""
w, h = img.size
if w >= target_size[0] and h >= target_size[1]:
return img
# Calculate resize maintaining aspect ratio for minimum dimension
ratio = max(target_size[0] / w, target_size[1] / h)
new_w = int(w * ratio)
new_h = int(h * ratio)
return img.resize((new_w, new_h), Image.LANCZOS)
def apply_post(img, enhance, upscale_size):
"""Apply post-processing: enhance and/or upscale."""
if enhance:
img = enhance_image_quality(img)
if upscale_size and upscale_size != "Original":
target_sizes = {
"2K (2048px)": (2048, 2048),
"4K (3840px)": (3840, 3840),
"8K (7680px)": (7680, 7680),
}
if upscale_size in target_sizes:
img = upscale_image(img, target_sizes[upscale_size])
return img
# ═══════════════════════════════════════════════════════════════
# 🎨 TEXT-TO-IMAGE
# ═══════════════════════════════════════════════════════════════
def generate_text2img(
prompt,
negative_prompt,
style_prompt,
quality_preset,
width,
height,
seed,
num_images,
enhance,
upscale_size,
progress=gr.Progress(),
):
"""Generate images from text prompt using FLUX."""
if not prompt.strip():
return [], "❌ Please enter a prompt!"
# Build full prompt with style
full_prompt = prompt
if style_prompt and style_prompt != "None":
full_prompt = f"{prompt}, {style_prompt}"
# Get quality settings
q = QUALITY_PRESETS[quality_preset]
is_dev = "ultra" in quality_preset.lower() or q["steps"] >= 50
progress(0.1, desc="📥 Loading model...")
if is_dev:
pipe = get_pipe("flux_dev", MODELS["flux_dev"], FluxPipeline)
guidance = q["guidance"]
else:
pipe = get_pipe("flux_schnell", MODELS["flux_schnell"], FluxPipeline)
guidance = 0.0
# Generate images
results = []
for i in range(num_images):
progress(0.2 + (0.6 * i / max(num_images, 1)), desc=f"🎨 Generating image {i+1}/{num_images}...")
gen_seed = seed if seed >= 0 else random.randint(0, 2**32 - 1)
generator = torch.Generator("cpu").manual_seed(gen_seed)
with torch.inference_mode():
output = pipe(
prompt=full_prompt,
negative_prompt=negative_prompt if negative_prompt else NEGATIVE_PROMPT,
guidance_scale=guidance,
height=height,
width=width,
num_inference_steps=q["steps"],
max_sequence_length=256 if not is_dev else 512,
generator=generator,
)
img = output.images[0]
img = apply_post(img, enhance, upscale_size)
results.append(img)
progress(1.0, desc="✅ Done!")
status = f"✅ Generated {num_images} image(s) | Quality: {quality_preset} | Seed: {gen_seed}"
return results if len(results) > 1 else results, status
# ═══════════════════════════════════════════════════════════════
# 🖼️ IMAGE-TO-IMAGE / PROMPT EDITING
# ═══════════════════════════════════════════════════════════════
def edit_image_img2img(
input_image,
prompt,
negative_prompt,
style_prompt,
strength,
quality_preset,
seed,
enhance,
upscale_size,
progress=gr.Progress(),
):
"""Edit an image using prompt guidance via FLUX Img2Img."""
if input_image is None:
return None, "❌ Please upload an image!"
if not prompt.strip():
return None, "❌ Please enter an edit prompt!"
progress(0.05, desc="🖼️ Processing input image...")
# Resize input to match generation size (must be multiple of 64)
w, h = input_image.size
w = (w // 64) * 64
h = (h // 64) * 64
input_image = input_image.resize((w, h), Image.LANCZOS)
full_prompt = prompt
if style_prompt and style_prompt != "None":
full_prompt = f"{prompt}, {style_prompt}"
q = QUALITY_PRESETS[quality_preset]
progress(0.1, desc="📥 Loading model...")
pipe = get_pipe("flux_schnell_img2img", MODELS["flux_schnell"], FluxImg2ImgPipeline)
gen_seed = seed if seed >= 0 else random.randint(0, 2**32 - 1)
generator = torch.Generator("cpu").manual_seed(gen_seed)
progress(0.2, desc="🎨 Editing image...")
with torch.inference_mode():
output = pipe(
prompt=full_prompt,
image=input_image,
strength=strength,
guidance_scale=0.0,
num_inference_steps=q["steps"],
generator=generator,
)
img = output.images[0]
img = apply_post(img, enhance, upscale_size)
progress(1.0, desc="✅ Done!")
status = f"✅ Image edited | Strength: {strength} | Seed: {gen_seed}"
return img, status
# ═══════════════════════════════════════════════════════════════
# 📝 INSTRUCTION-BASED EDITING (InstructPix2Pix)
# ═══════════════════════════════════════════════════════════════
def edit_image_instruct(
input_image,
instruction,
image_cfg_scale,
text_cfg_scale,
steps,
seed,
enhance,
upscale_size,
progress=gr.Progress(),
):
"""Edit image using natural language instructions (InstructPix2Pix)."""
if input_image is None:
return None, "❌ Please upload an image!"
if not instruction.strip():
return None, "❌ Please enter an editing instruction!"
progress(0.05, desc="🖼️ Processing image...")
# Resize to 512 for InstructPix2Pix
input_image = input_image.resize((512, 512), Image.LANCZOS)
progress(0.1, desc="📥 Loading InstructPix2Pix model...")
pipe = get_pipe(
"instruct_pix2pix",
MODELS["instruct_pix2pix"],
StableDiffusionInstructPix2PixPipeline,
dtype=torch.float16,
)
gen_seed = seed if seed >= 0 else random.randint(0, 2**32 - 1)
generator = torch.Generator("cpu").manual_seed(gen_seed)
progress(0.2, desc="✏️ Applying edit instruction...")
with torch.inference_mode():
output = pipe(
prompt=instruction,
image=input_image,
num_inference_steps=steps,
image_guidance_scale=image_cfg_scale,
guidance_scale=text_cfg_scale,
generator=generator,
)
img = output.images[0]
img = apply_post(img, enhance, upscale_size)
progress(1.0, desc="✅ Done!")
status = f"✅ Instruction applied: '{instruction}' | Seed: {gen_seed}"
return img, status
# ═══════════════════════════════════════════════════════════════
# 🖌️ INPAINTING / MASKED EDITING
# ═══════════════════════════════════════════════════════════════
def handle_inpaint(
sketch_input,
prompt,
style_prompt,
quality_preset,
seed,
enhance,
upscale_size,
progress=gr.Progress(),
):
"""Handle inpaint from sketch component (dict with 'image' and 'mask' keys)."""
if sketch_input is None:
return None, "❌ Please upload an image and draw a mask!"
# sketch component returns dict {"image": PIL.Image, "mask": PIL.Image}
if isinstance(sketch_input, dict):
input_image = sketch_input.get("image")
mask_image = sketch_input.get("mask")
else:
# Fallback if it returns just an image
input_image = sketch_input
mask_image = None
if input_image is None:
return None, "❌ Please upload an image!"
if mask_image is None:
return None, "❌ Please draw a mask on the image!"
if not prompt.strip():
return None, "❌ Please describe what to generate in the masked area!"
full_prompt = prompt
if style_prompt and style_prompt != "None":
full_prompt = f"{prompt}, {style_prompt}"
q = QUALITY_PRESETS[quality_preset]
# Ensure dimensions are multiples of 64
w, h = input_image.size
new_w = (w // 64) * 64
new_h = (h // 64) * 64
input_image = input_image.resize((new_w, new_h), Image.LANCZOS)
mask_image = mask_image.resize((new_w, new_h), Image.LANCZOS)
progress(0.1, desc="📥 Loading FLUX Fill model...")
pipe = get_pipe("flux_fill", MODELS["flux_fill"], FluxFillPipeline)
gen_seed = seed if seed >= 0 else random.randint(0, 2**32 - 1)
generator = torch.Generator("cpu").manual_seed(gen_seed)
progress(0.2, desc="🖌️ Inpainting masked area...")
with torch.inference_mode():
output = pipe(
prompt=full_prompt,
image=input_image,
mask_image=mask_image,
height=new_h,
width=new_w,
guidance_scale=30.0,
num_inference_steps=q["steps"],
max_sequence_length=512,
generator=generator,
)
img = output.images[0]
img = apply_post(img, enhance, upscale_size)
progress(1.0, desc="✅ Done!")
status = f"✅ Inpainting complete | Seed: {gen_seed}"
return img, status
# ═══════════════════════════════════════════════════════════════
# 🔍 IMAGE UPSCALER
# ═══════════════════════════════════════════════════════════════
def upscale_standalone(
input_image,
target_size,
enhance,
progress=gr.Progress(),
):
"""Standalone upscaler with enhancement."""
if input_image is None:
return None, "❌ Please upload an image!"
progress(0.1, desc="🔍 Upscaling...")
target_sizes = {
"2K (2048px)": (2048, 2048),
"4K (3840px)": (3840, 3840),
"8K (7680px)": (7680, 7680),
}
size = target_sizes.get(target_size, (2048, 2048))
img = upscale_image(input_image, size)
if enhance:
progress(0.7, desc="✨ Enhancing...")
img = enhance_image_quality(img)
progress(1.0, desc="✅ Done!")
status = f"✅ Upscaled to {target_size} | Output: {img.size[0]}x{img.size[1]}px"
return img, status
# ═══════════════════════════════════════════════════════════════
# 🎨 THE-X GRADIO UI
# ═══════════════════════════════════════════════════════════════
CSS = """
:root {
--bg: #0a0a0f;
--card: #12121a;
--border: #1e1e30;
--accent: #7c3aed;
--accent2: #a855f7;
--text: #e2e8f0;
--text-muted: #94a3b8;
--gradient: linear-gradient(135deg, #7c3aed, #db2777);
}
body { background: var(--bg) !important; }
.gradio-container { max-width: 1400px !important; margin: 0 auto !important; }
#thex-header {
text-align: center;
padding: 2rem 1rem 1rem 1rem;
background: var(--gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-size: 3.5rem;
font-weight: 900;
letter-spacing: 0.05em;
margin-bottom: 0;
font-family: 'Segoe UI', system-ui, sans-serif;
}
#thex-subtitle {
text-align: center;
color: var(--text-muted);
font-size: 1.1rem;
margin-top: -0.5rem;
letter-spacing: 0.15em;
text-transform: uppercase;
}
.tab-nav {
background: var(--card) !important;
border: 1px solid var(--border) !important;
border-radius: 12px !important;
}
button {
background: var(--accent) !important;
color: white !important;
border: none !important;
border-radius: 8px !important;
font-weight: 600 !important;
transition: all 0.2s !important;
}
button:hover {
background: var(--accent2) !important;
transform: translateY(-1px);
box-shadow: 0 4px 20px rgba(124, 58, 237, 0.4);
}
.gr-form, .gr-box {
background: var(--card) !important;
border: 1px solid var(--border) !important;
border-radius: 12px !important;
}
.gr-input, .gr-text-input textarea, input[type="text"] {
background: #0a0a0f !important;
border: 1px solid var(--border) !important;
color: var(--text) !important;
border-radius: 8px !important;
}
label {
color: var(--text) !important;
font-weight: 500 !important;
}
.gr-panel { border: none !important; }
footer { display: none !important; }
"""
with gr.Blocks(
css=CSS,
title="The-X | Unlimited AI Image Studio",
theme=gr.themes.Soft(),
) as demo:
# Header
gr.HTML(
"""
<h1 id="thex-header">╔╦╗╦ ╦╔═╗ ═╗ ╔═╗</h1>
<p id="thex-subtitle">UNLIMITED AI IMAGE GENERATION & EDITING • UNCENSORED • 8K QUALITY</p>
"""
)
with gr.Tabs() as tabs:
# ═══════════════════════════════════════════════════════
# TAB 1: TEXT-TO-IMAGE
# ═══════════════════════════════════════════════════════
with gr.TabItem("🎨 Text-to-Image", id="txt2img"):
with gr.Row():
with gr.Column(scale=1):
prompt_input = gr.Textbox(
label="✨ Your Prompt",
placeholder="Describe the image you want to create in vivid detail...\n\nExample: A majestic dragon perched on a crystalline mountain peak, wings spread, breathing ethereal blue fire into a stormy sky, hyper-realistic, 8k, cinematic lighting, volumetric fog, intricate scales",
lines=5,
)
with gr.Accordion("🎭 Style Presets", open=False):
style_dropdown = gr.Dropdown(
choices=["None"] + STYLE_PRESETS,
value="hyper-realistic, 8k resolution, professional photography, ultra detailed, sharp focus, cinematic lighting, masterpiece, award-winning",
label="Style Template",
)
neg_prompt = gr.Textbox(
label="🚫 Negative Prompt",
value=NEGATIVE_PROMPT,
lines=2,
)
with gr.Row():
quality_preset = gr.Radio(
choices=list(QUALITY_PRESETS.keys()),
value="⚡ Speed (4 steps)",
label="⚡ Quality Preset",
)
with gr.Row():
width = gr.Slider(256, 1280, value=1024, step=64, label="Width")
height = gr.Slider(256, 1280, value=1024, step=64, label="Height")
with gr.Row():
seed = gr.Number(value=-1, label="🎲 Seed (-1 = random)", precision=0)
num_images = gr.Slider(1, 4, value=1, step=1, label="📸 Images")
with gr.Row():
enhance_cb = gr.Checkbox(value=True, label="✨ Auto-enhance quality")
upscale_dd = gr.Dropdown(
choices=["Original", "2K (2048px)", "4K (3840px)", "8K (7680px)"],
value="Original",
label="🔍 Upscale output",
)
generate_btn = gr.Button("🎨 GENERATE", variant="primary", size="lg")
with gr.Column(scale=1):
output_gallery = gr.Gallery(
label="Generated Images",
columns=2,
rows=2,
height=600,
object_fit="contain",
)
status_t2i = gr.Textbox(label="Status", interactive=False)
generate_btn.click(
fn=generate_text2img,
inputs=[
prompt_input, neg_prompt, style_dropdown, quality_preset,
width, height, seed, num_images, enhance_cb, upscale_dd,
],
outputs=[output_gallery, status_t2i],
)
# ═══════════════════════════════════════════════════════
# TAB 2: IMAGE-TO-IMAGE / PROMPT EDITING
# ═══════════════════════════════════════════════════════
with gr.TabItem("🖼️ Prompt Edit (Img2Img)", id="img2img"):
with gr.Row():
with gr.Column(scale=1):
img2img_input = gr.Image(label="📤 Upload Image", type="pil", height=400)
img2img_prompt = gr.Textbox(
label="✏️ Edit Prompt",
placeholder="Describe how you want to transform this image...\n\nExample: turn this into a neon cyberpunk scene, add glowing holograms, futuristic city background",
lines=3,
)
with gr.Accordion("🎭 Style Presets", open=False):
img2img_style = gr.Dropdown(
choices=["None"] + STYLE_PRESETS,
value="None",
label="Style Template",
)
img2img_neg = gr.Textbox(label="🚫 Negative Prompt", value=NEGATIVE_PROMPT, lines=2)
img2img_strength = gr.Slider(0.1, 1.0, value=0.75, step=0.05, label="🔥 Transformation Strength")
img2img_quality = gr.Radio(
choices=list(QUALITY_PRESETS.keys()),
value="💎 Quality (15 steps)",
label="⚡ Quality Preset",
)
with gr.Row():
img2img_seed = gr.Number(value=-1, label="🎲 Seed")
img2img_enhance = gr.Checkbox(value=True, label="✨ Enhance")
img2img_upscale = gr.Dropdown(
choices=["Original", "2K (2048px)", "4K (3840px)", "8K (7680px)"],
value="Original",
label="🔍 Upscale",
)
img2img_btn = gr.Button("🖼️ TRANSFORM IMAGE", variant="primary", size="lg")
with gr.Column(scale=1):
img2img_output = gr.Image(label="✨ Edited Image", type="pil", height=500)
img2img_status = gr.Textbox(label="Status", interactive=False)
img2img_btn.click(
fn=edit_image_img2img,
inputs=[
img2img_input, img2img_prompt, img2img_neg, img2img_style,
img2img_strength, img2img_quality, img2img_seed,
img2img_enhance, img2img_upscale,
],
outputs=[img2img_output, img2img_status],
)
# ═══════════════════════════════════════════════════════
# TAB 3: INSTRUCTION-BASED EDITING
# ═══════════════════════════════════════════════════════
with gr.TabItem("📝 Instruct Edit (AI-Powered)", id="instruct"):
with gr.Row():
with gr.Column(scale=1):
instruct_input = gr.Image(label="📤 Upload Image", type="pil", height=400)
instruct_prompt = gr.Textbox(
label="🗣️ Natural Language Instruction",
placeholder="Tell the AI what to change in plain English...\n\nExamples:\n• 'Make the sky sunset orange'\n• 'Turn this into a watercolor painting'\n• 'Add snow on the mountains'\n• 'Make the person smile'\n• 'Change the background to a beach'",
lines=3,
)
with gr.Row():
instruct_img_cfg = gr.Slider(1.0, 3.0, value=1.5, step=0.1, label="Image Faithfulness")
instruct_text_cfg = gr.Slider(1.0, 15.0, value=7.5, step=0.5, label="Instruction Strength")
with gr.Row():
instruct_steps = gr.Slider(10, 100, value=50, step=5, label="Quality Steps")
instruct_seed = gr.Number(value=-1, label="🎲 Seed")
with gr.Row():
instruct_enhance = gr.Checkbox(value=True, label="✨ Enhance")
instruct_upscale = gr.Dropdown(
choices=["Original", "2K (2048px)", "4K (3840px)", "8K (7680px)"],
value="Original",
label="🔍 Upscale",
)
instruct_btn = gr.Button("🤖 APPLY INSTRUCTION", variant="primary", size="lg")
with gr.Column(scale=1):
instruct_output = gr.Image(label="✨ Edited Image", type="pil", height=500)
instruct_status = gr.Textbox(label="Status", interactive=False)
instruct_btn.click(
fn=edit_image_instruct,
inputs=[
instruct_input, instruct_prompt, instruct_img_cfg,
instruct_text_cfg, instruct_steps, instruct_seed,
instruct_enhance, instruct_upscale,
],
outputs=[instruct_output, instruct_status],
)
# ═══════════════════════════════════════════════════════
# TAB 4: INPAINTING
# ═══════════════════════════════════════════════════════
with gr.TabItem("🖌️ Inpaint (Draw & Fill)", id="inpaint"):
with gr.Row():
with gr.Column(scale=1):
inpaint_sketch = gr.Image(
label="📤 Upload Image & Draw Mask",
type="pil",
tool="sketch",
height=400,
)
gr.HTML("<p style='color:#94a3b8;font-size:0.85rem;margin-top:-10px;'>✏️ <b>Draw</b> on the image to create a mask, then describe what to fill</p>")
inpaint_prompt = gr.Textbox(
label="🎨 What to generate in the masked area",
placeholder="Describe what should appear inside the drawn mask...",
lines=2,
)
with gr.Accordion("🎭 Style Presets", open=False):
inpaint_style = gr.Dropdown(
choices=["None"] + STYLE_PRESETS,
value="None",
label="Style",
)
inpaint_quality = gr.Radio(
choices=list(QUALITY_PRESETS.keys()),
value="💎 Quality (15 steps)",
label="⚡ Quality Preset",
)
with gr.Row():
inpaint_seed = gr.Number(value=-1, label="🎲 Seed")
inpaint_enhance = gr.Checkbox(value=True, label="✨ Enhance")
inpaint_upscale = gr.Dropdown(
choices=["Original", "2K (2048px)", "4K (3840px)", "8K (7680px)"],
value="Original",
label="🔍 Upscale",
)
inpaint_btn = gr.Button("🖌️ INPAINT", variant="primary", size="lg")
with gr.Column(scale=1):
inpaint_output = gr.Image(label="✨ Inpainted Image", type="pil", height=500)
inpaint_status = gr.Textbox(label="Status", interactive=False)
inpaint_btn.click(
fn=handle_inpaint,
inputs=[
inpaint_sketch, inpaint_prompt, inpaint_style,
inpaint_quality, inpaint_seed, inpaint_enhance, inpaint_upscale,
],
outputs=[inpaint_output, inpaint_status],
)
# ═══════════════════════════════════════════════════════
# TAB 5: UPSCALER
# ═══════════════════════════════════════════════════════
with gr.TabItem("🔍 Upscaler (8K)", id="upscaler"):
with gr.Row():
with gr.Column(scale=1):
upscale_input = gr.Image(label="📤 Upload Image", type="pil", height=400)
upscale_target = gr.Radio(
choices=["2K (2048px)", "4K (3840px)", "8K (7680px)"],
value="4K (3840px)",
label="📐 Target Resolution",
)
upscale_enhance = gr.Checkbox(value=True, label="✨ Auto-enhance sharpness & contrast")
upscale_btn = gr.Button("🔍 UPSCALE", variant="primary", size="lg")
with gr.Column(scale=1):
upscale_output = gr.Image(label="✨ Upscaled Image", type="pil", height=500)
upscale_status = gr.Textbox(label="Status", interactive=False)
upscale_btn.click(
fn=upscale_standalone,
inputs=[upscale_input, upscale_target, upscale_enhance],
outputs=[upscale_output, upscale_status],
)
# Footer
gr.HTML(
"""
<div style="text-align:center; padding:2rem; color:#64748b; font-size:0.85rem;">
<p>⚡ <b>The-X</b> — Powered by FLUX.1 • Uncensored • No content filters • No safety checkers</p>
<p style="margin-top:0.5rem;">All generated content is your responsibility. Use wisely. 🎨</p>
</div>
"""
)
# ── Launch ────────────────────────────────────────────────────
if __name__ == "__main__":
demo.queue(max_size=10).launch(server_name="0.0.0.0", server_port=7860)