Spaces:
Sleeping
Sleeping
Refactor artistic examples to use gr.Gallery instead of manual grid
Browse filesReplaced 400+ lines of repetitive code (9 images + 9 buttons + 9 handlers)
with a clean data-driven gr.Gallery implementation.
Changes:
- Added ARTISTIC_EXAMPLES data structure (lines 2553-2689)
- Replaced manual 3x3 grid with gr.Gallery component (lines 3273-3282)
- Single click handler using gr.SelectData (lines 3285-3320)
- Users click images directly to load settings (no separate buttons)
Benefits:
- 75% less code (~90 lines vs ~400 lines)
- Easier to maintain (add examples by updating list)
- Better UX (native gallery with preview, cleaner interface)
- All example data organized in one place
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
app.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
| 1 |
import os
|
|
|
|
| 2 |
import sys
|
| 3 |
-
import time
|
| 4 |
import threading
|
| 5 |
-
import
|
| 6 |
|
| 7 |
# Force unbuffered output for real-time logging
|
| 8 |
sys.stdout.reconfigure(line_buffering=True)
|
|
@@ -587,10 +587,10 @@ def get_dynamic_duration(*args, **kwargs):
|
|
| 587 |
Artistic: 640+anim=23s, 832+anim=45s, 832+anim+upscale=57s, 1024+anim+upscale=124s
|
| 588 |
"""
|
| 589 |
# Extract only the parameters we need from kwargs
|
| 590 |
-
pipeline = kwargs.get(
|
| 591 |
-
image_size = kwargs.get(
|
| 592 |
-
enable_animation = kwargs.get(
|
| 593 |
-
enable_upscale = kwargs.get(
|
| 594 |
|
| 595 |
if pipeline == "standard":
|
| 596 |
# Standard pipeline benchmarks (with 20% safety margin)
|
|
@@ -739,11 +739,14 @@ def generate_qr_code_unified(
|
|
| 739 |
|
| 740 |
class AnimationHandler:
|
| 741 |
"""Handler for managing KSampler animation callbacks"""
|
|
|
|
| 742 |
def __init__(self, preview_size=512):
|
| 743 |
self.intermediate_images = []
|
| 744 |
self.image_queue = queue.Queue()
|
| 745 |
self.enabled = False
|
| 746 |
-
self.preview_size =
|
|
|
|
|
|
|
| 747 |
|
| 748 |
def create_callback(self, vae, interval=5):
|
| 749 |
"""Create a callback that stores intermediate decoded images"""
|
|
@@ -761,6 +764,7 @@ class AnimationHandler:
|
|
| 761 |
# Key insight: inference_mode tensors cannot be used in backward pass
|
| 762 |
# Source: https://pytorch.org/docs/stable/generated/torch.autograd.grad_mode.inference_mode.html
|
| 763 |
import torch
|
|
|
|
| 764 |
with torch.no_grad():
|
| 765 |
# Create a detached clone and ensure contiguous memory layout
|
| 766 |
# .contiguous() ensures proper memory layout for VAE decoder
|
|
@@ -777,13 +781,20 @@ class AnimationHandler:
|
|
| 777 |
image_tensor = get_value_at_index(decoded, 0)
|
| 778 |
|
| 779 |
# Convert EXACTLY like final images (lines 1915-1918) - no transpose, no mode
|
| 780 |
-
image_np = (image_tensor.detach().cpu().numpy() * 255).astype(
|
|
|
|
|
|
|
| 781 |
image_np = image_np[0]
|
| 782 |
pil_image = Image.fromarray(image_np)
|
| 783 |
|
| 784 |
# Resize to consistent preview size to avoid size inconsistencies in UI
|
| 785 |
-
if
|
| 786 |
-
pil_image.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 787 |
|
| 788 |
# Store with message (step is already the correct value at interval points)
|
| 789 |
msg = f"Sampling progress: step {step}/{total_steps}"
|
|
@@ -801,9 +812,20 @@ class AnimationHandler:
|
|
| 801 |
return images
|
| 802 |
|
| 803 |
|
| 804 |
-
def ksampler_with_animation(
|
| 805 |
-
|
| 806 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 807 |
"""
|
| 808 |
Custom KSampler that supports animation callbacks.
|
| 809 |
Based on ComfyUI's common_ksampler but with animation support.
|
|
@@ -837,12 +859,24 @@ def ksampler_with_animation(model, seed, steps, cfg, sampler_name, scheduler,
|
|
| 837 |
|
| 838 |
# Sample
|
| 839 |
samples = comfy.sample.sample(
|
| 840 |
-
model,
|
| 841 |
-
|
| 842 |
-
|
| 843 |
-
|
| 844 |
-
|
| 845 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 846 |
)
|
| 847 |
|
| 848 |
out = latent.copy()
|
|
@@ -1782,7 +1816,9 @@ def _pipeline_standard(
|
|
| 1782 |
gr_progress=None,
|
| 1783 |
):
|
| 1784 |
# Initialize animation handler if enabled
|
| 1785 |
-
animation_handler =
|
|
|
|
|
|
|
| 1786 |
if animation_handler:
|
| 1787 |
animation_handler.enabled = True
|
| 1788 |
|
|
@@ -1840,7 +1876,9 @@ def _pipeline_standard(
|
|
| 1840 |
return
|
| 1841 |
|
| 1842 |
# Calculate total steps based on enabled features
|
| 1843 |
-
total_steps =
|
|
|
|
|
|
|
| 1844 |
|
| 1845 |
# 1) Yield the base QR image as the first intermediate result
|
| 1846 |
base_qr_tensor = get_value_at_index(comfy_qr_by_module_size_15, 0)
|
|
@@ -1895,6 +1933,7 @@ def _pipeline_standard(
|
|
| 1895 |
if animation_handler and enable_animation:
|
| 1896 |
# Run ksampler in thread to allow real-time image yielding
|
| 1897 |
result_container = [None]
|
|
|
|
| 1898 |
def run_ksampler():
|
| 1899 |
result_container[0] = ksampler_with_animation(
|
| 1900 |
model=get_value_at_index(checkpointloadersimple_4, 0),
|
|
@@ -1915,7 +1954,9 @@ def _pipeline_standard(
|
|
| 1915 |
ksampler_thread.start()
|
| 1916 |
|
| 1917 |
# Yield intermediate images as they're captured
|
| 1918 |
-
while
|
|
|
|
|
|
|
| 1919 |
try:
|
| 1920 |
img, msg = animation_handler.image_queue.get(timeout=0.1)
|
| 1921 |
yield img, msg
|
|
@@ -1957,7 +1998,9 @@ def _pipeline_standard(
|
|
| 1957 |
mid_np = (mid_tensor.detach().cpu().numpy() * 255).astype(np.uint8)
|
| 1958 |
mid_np = mid_np[0]
|
| 1959 |
mid_pil = Image.fromarray(mid_np)
|
| 1960 |
-
msg =
|
|
|
|
|
|
|
| 1961 |
log_progress(msg, gr_progress, 0.5)
|
| 1962 |
yield mid_pil, msg
|
| 1963 |
|
|
@@ -1982,6 +2025,7 @@ def _pipeline_standard(
|
|
| 1982 |
if animation_handler and enable_animation:
|
| 1983 |
# Run ksampler in thread to allow real-time image yielding
|
| 1984 |
result_container = [None]
|
|
|
|
| 1985 |
def run_ksampler():
|
| 1986 |
result_container[0] = ksampler_with_animation(
|
| 1987 |
model=get_value_at_index(checkpointloadersimple_4, 0),
|
|
@@ -2002,7 +2046,9 @@ def _pipeline_standard(
|
|
| 2002 |
ksampler_thread.start()
|
| 2003 |
|
| 2004 |
# Yield intermediate images as they're captured
|
| 2005 |
-
while
|
|
|
|
|
|
|
| 2006 |
try:
|
| 2007 |
img, msg = animation_handler.image_queue.get(timeout=0.1)
|
| 2008 |
yield img, msg
|
|
@@ -2157,7 +2203,9 @@ def _pipeline_artistic(
|
|
| 2157 |
gr_progress=None,
|
| 2158 |
):
|
| 2159 |
# Initialize animation handler if enabled
|
| 2160 |
-
animation_handler =
|
|
|
|
|
|
|
| 2161 |
if animation_handler:
|
| 2162 |
animation_handler.enabled = True
|
| 2163 |
|
|
@@ -2320,6 +2368,7 @@ def _pipeline_artistic(
|
|
| 2320 |
if animation_handler and enable_animation:
|
| 2321 |
# Run ksampler in thread to allow real-time image yielding
|
| 2322 |
result_container = [None]
|
|
|
|
| 2323 |
def run_ksampler():
|
| 2324 |
result_container[0] = ksampler_with_animation(
|
| 2325 |
model=enhanced_model, # Using FreeU + SAG enhanced model
|
|
@@ -2415,6 +2464,7 @@ def _pipeline_artistic(
|
|
| 2415 |
if animation_handler and enable_animation:
|
| 2416 |
# Run ksampler in thread to allow real-time image yielding
|
| 2417 |
result_container = [None]
|
|
|
|
| 2418 |
def run_ksampler():
|
| 2419 |
result_container[0] = ksampler_with_animation(
|
| 2420 |
model=enhanced_model, # Using FreeU + SAG enhanced model
|
|
@@ -2553,6 +2603,145 @@ if __name__ == "__main__" and not os.environ.get("QR_TESTING_MODE"):
|
|
| 2553 |
else:
|
| 2554 |
print("ℹ️ AOT compilation skipped on MPS (MacBook) - using eager mode\n")
|
| 2555 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2556 |
# Start your Gradio app with automatic cache cleanup
|
| 2557 |
# delete_cache=(3600, 3600) means: check every hour and delete files older than 1 hour
|
| 2558 |
with gr.Blocks(delete_cache=(3600, 3600)) as app:
|
|
@@ -2647,7 +2836,9 @@ if __name__ == "__main__" and not os.environ.get("QR_TESTING_MODE"):
|
|
| 2647 |
|
| 2648 |
# Change Settings Manually - separate accordion
|
| 2649 |
with gr.Accordion("Change Settings Manually", open=False):
|
| 2650 |
-
gr.Markdown(
|
|
|
|
|
|
|
| 2651 |
# Negative Prompt
|
| 2652 |
negative_prompt_artistic = gr.Textbox(
|
| 2653 |
label="Negative Prompt",
|
|
@@ -2788,7 +2979,9 @@ if __name__ == "__main__" and not os.environ.get("QR_TESTING_MODE"):
|
|
| 2788 |
|
| 2789 |
# Color Quantization Section
|
| 2790 |
gr.Markdown("### Color Quantization (Optional)")
|
| 2791 |
-
gr.Markdown(
|
|
|
|
|
|
|
| 2792 |
artistic_enable_color_quantization = gr.Checkbox(
|
| 2793 |
label="Enable Color Quantization",
|
| 2794 |
value=False,
|
|
@@ -3124,392 +3317,44 @@ if __name__ == "__main__" and not os.environ.get("QR_TESTING_MODE"):
|
|
| 3124 |
outputs=[artistic_seed],
|
| 3125 |
)
|
| 3126 |
|
| 3127 |
-
#
|
| 3128 |
gr.Markdown("### Featured Examples")
|
| 3129 |
-
gr.Markdown(
|
| 3130 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3131 |
)
|
| 3132 |
|
| 3133 |
-
#
|
| 3134 |
-
|
| 3135 |
-
|
| 3136 |
-
|
| 3137 |
-
|
| 3138 |
-
|
| 3139 |
-
|
| 3140 |
-
|
| 3141 |
-
|
| 3142 |
-
|
| 3143 |
-
|
| 3144 |
-
|
| 3145 |
-
|
| 3146 |
-
|
| 3147 |
-
|
| 3148 |
-
|
| 3149 |
-
|
| 3150 |
-
|
| 3151 |
-
|
| 3152 |
-
|
| 3153 |
-
|
| 3154 |
-
|
| 3155 |
-
interactive=False,
|
| 3156 |
-
show_download_button=False,
|
| 3157 |
-
height=280,
|
| 3158 |
-
)
|
| 3159 |
-
ex2_btn = gr.Button(
|
| 3160 |
-
"Load Settings", size="sm", variant="secondary"
|
| 3161 |
-
)
|
| 3162 |
-
|
| 3163 |
-
# Example 3: Roman City
|
| 3164 |
-
with gr.Column(scale=1):
|
| 3165 |
-
ex3_img = gr.Image(
|
| 3166 |
-
"examples/artistic/roman_city.jpg",
|
| 3167 |
-
label="Roman City",
|
| 3168 |
-
show_label=True,
|
| 3169 |
-
interactive=False,
|
| 3170 |
-
show_download_button=False,
|
| 3171 |
-
height=280,
|
| 3172 |
-
)
|
| 3173 |
-
ex3_btn = gr.Button(
|
| 3174 |
-
"Load Settings", size="sm", variant="secondary"
|
| 3175 |
-
)
|
| 3176 |
-
|
| 3177 |
-
# Second row (3 images)
|
| 3178 |
-
with gr.Row():
|
| 3179 |
-
# Example 4: Neapolitan Pizza
|
| 3180 |
-
with gr.Column(scale=1):
|
| 3181 |
-
ex4_img = gr.Image(
|
| 3182 |
-
"examples/artistic/neapolitan_pizza.webp",
|
| 3183 |
-
label="Neapolitan Pizza",
|
| 3184 |
-
show_label=True,
|
| 3185 |
-
interactive=False,
|
| 3186 |
-
show_download_button=False,
|
| 3187 |
-
height=280,
|
| 3188 |
-
)
|
| 3189 |
-
ex4_btn = gr.Button(
|
| 3190 |
-
"Load Settings", size="sm", variant="secondary"
|
| 3191 |
-
)
|
| 3192 |
-
|
| 3193 |
-
# Example 5: Poker Chips
|
| 3194 |
-
with gr.Column(scale=1):
|
| 3195 |
-
ex5_img = gr.Image(
|
| 3196 |
-
"examples/artistic/poker_chips.webp",
|
| 3197 |
-
label="Poker Chips",
|
| 3198 |
-
show_label=True,
|
| 3199 |
-
interactive=False,
|
| 3200 |
-
show_download_button=False,
|
| 3201 |
-
height=280,
|
| 3202 |
-
)
|
| 3203 |
-
ex5_btn = gr.Button(
|
| 3204 |
-
"Load Settings", size="sm", variant="secondary"
|
| 3205 |
-
)
|
| 3206 |
-
|
| 3207 |
-
# Example 6: Underwater Fish
|
| 3208 |
-
with gr.Column(scale=1):
|
| 3209 |
-
ex6_img = gr.Image(
|
| 3210 |
-
"examples/artistic/underwater_fish.webp",
|
| 3211 |
-
label="Underwater Fish",
|
| 3212 |
-
show_label=True,
|
| 3213 |
-
interactive=False,
|
| 3214 |
-
show_download_button=False,
|
| 3215 |
-
height=280,
|
| 3216 |
-
)
|
| 3217 |
-
ex6_btn = gr.Button(
|
| 3218 |
-
"Load Settings", size="sm", variant="secondary"
|
| 3219 |
-
)
|
| 3220 |
-
|
| 3221 |
-
# Third row (3 images)
|
| 3222 |
-
with gr.Row():
|
| 3223 |
-
# Example 7: Mediterranean Garden
|
| 3224 |
-
with gr.Column(scale=1):
|
| 3225 |
-
ex7_img = gr.Image(
|
| 3226 |
-
"examples/artistic/mediterranean_garden.jpg",
|
| 3227 |
-
label="Mediterranean Garden",
|
| 3228 |
-
show_label=True,
|
| 3229 |
-
interactive=False,
|
| 3230 |
-
show_download_button=False,
|
| 3231 |
-
height=280,
|
| 3232 |
-
)
|
| 3233 |
-
ex7_btn = gr.Button(
|
| 3234 |
-
"Load Settings", size="sm", variant="secondary"
|
| 3235 |
-
)
|
| 3236 |
-
|
| 3237 |
-
# Example 8: Rice Fields
|
| 3238 |
-
with gr.Column(scale=1):
|
| 3239 |
-
ex8_img = gr.Image(
|
| 3240 |
-
"examples/artistic/rice_fields.jpg",
|
| 3241 |
-
label="Rice Fields",
|
| 3242 |
-
show_label=True,
|
| 3243 |
-
interactive=False,
|
| 3244 |
-
show_download_button=False,
|
| 3245 |
-
height=280,
|
| 3246 |
-
)
|
| 3247 |
-
ex8_btn = gr.Button(
|
| 3248 |
-
"Load Settings", size="sm", variant="secondary"
|
| 3249 |
-
)
|
| 3250 |
-
|
| 3251 |
-
# Example 9: Cyberpunk City
|
| 3252 |
-
with gr.Column(scale=1):
|
| 3253 |
-
ex9_img = gr.Image(
|
| 3254 |
-
"examples/artistic/cyberpunk_city.webp",
|
| 3255 |
-
label="Cyberpunk City",
|
| 3256 |
-
show_label=True,
|
| 3257 |
-
interactive=False,
|
| 3258 |
-
show_download_button=False,
|
| 3259 |
-
height=280,
|
| 3260 |
-
)
|
| 3261 |
-
ex9_btn = gr.Button(
|
| 3262 |
-
"Load Settings", size="sm", variant="secondary"
|
| 3263 |
-
)
|
| 3264 |
-
|
| 3265 |
-
# Load settings button handlers
|
| 3266 |
-
# Ex1: Japanese Temple
|
| 3267 |
-
ex1_btn.click(
|
| 3268 |
-
fn=lambda: (
|
| 3269 |
-
"some clothes spread on ropes, Japanese girl sits inside in the middle of the image, few sakura flowers, realistic, great details, out in the open air sunny day realistic, great details, absence of people, Detailed and Intricate, CGI, Photoshoot, rim light, 8k, 16k, ultra detail",
|
| 3270 |
-
"https://www.google.com",
|
| 3271 |
-
"URL",
|
| 3272 |
-
640,
|
| 3273 |
-
6,
|
| 3274 |
-
"Medium (15%)",
|
| 3275 |
-
14,
|
| 3276 |
-
"Square",
|
| 3277 |
-
True,
|
| 3278 |
-
718313,
|
| 3279 |
-
0.5,
|
| 3280 |
-
),
|
| 3281 |
-
outputs=[
|
| 3282 |
-
artistic_prompt_input,
|
| 3283 |
-
artistic_text_input,
|
| 3284 |
-
artistic_input_type,
|
| 3285 |
-
artistic_image_size,
|
| 3286 |
-
artistic_border_size,
|
| 3287 |
-
artistic_error_correction,
|
| 3288 |
-
artistic_module_size,
|
| 3289 |
-
artistic_module_drawer,
|
| 3290 |
-
artistic_use_custom_seed,
|
| 3291 |
-
artistic_seed,
|
| 3292 |
-
sag_blur_sigma,
|
| 3293 |
-
],
|
| 3294 |
-
)
|
| 3295 |
-
# Ex2: Sunset Mountains
|
| 3296 |
-
ex2_btn.click(
|
| 3297 |
-
fn=lambda: (
|
| 3298 |
-
"a beautiful sunset over mountains, photorealistic, detailed landscape, golden hour, dramatic lighting, 8k, ultra detailed",
|
| 3299 |
-
"https://github.com",
|
| 3300 |
-
"URL",
|
| 3301 |
-
704,
|
| 3302 |
-
6,
|
| 3303 |
-
"High (30%)",
|
| 3304 |
-
16,
|
| 3305 |
-
"Square",
|
| 3306 |
-
True,
|
| 3307 |
-
718313,
|
| 3308 |
-
0.5,
|
| 3309 |
-
),
|
| 3310 |
-
outputs=[
|
| 3311 |
-
artistic_prompt_input,
|
| 3312 |
-
artistic_text_input,
|
| 3313 |
-
artistic_input_type,
|
| 3314 |
-
artistic_image_size,
|
| 3315 |
-
artistic_border_size,
|
| 3316 |
-
artistic_error_correction,
|
| 3317 |
-
artistic_module_size,
|
| 3318 |
-
artistic_module_drawer,
|
| 3319 |
-
artistic_use_custom_seed,
|
| 3320 |
-
artistic_seed,
|
| 3321 |
-
sag_blur_sigma,
|
| 3322 |
-
],
|
| 3323 |
-
)
|
| 3324 |
-
# Ex3: Roman City
|
| 3325 |
-
ex3_btn.click(
|
| 3326 |
-
fn=lambda: (
|
| 3327 |
-
"aerial bird view of ancient Roman city, cobblestone streets and pathways forming intricate patterns, vintage illustration style, sepia tones, aged parchment look, detailed architecture, 8k, ultra detailed",
|
| 3328 |
-
"WIFI:T:WPA;S:MyNetwork;P:MyPassword123;;",
|
| 3329 |
-
"Plain Text",
|
| 3330 |
-
832,
|
| 3331 |
-
6,
|
| 3332 |
-
"High (30%)",
|
| 3333 |
-
16,
|
| 3334 |
-
"Square",
|
| 3335 |
-
True,
|
| 3336 |
-
718313,
|
| 3337 |
-
0.5,
|
| 3338 |
-
),
|
| 3339 |
-
outputs=[
|
| 3340 |
-
artistic_prompt_input,
|
| 3341 |
-
artistic_text_input,
|
| 3342 |
-
artistic_input_type,
|
| 3343 |
-
artistic_image_size,
|
| 3344 |
-
artistic_border_size,
|
| 3345 |
-
artistic_error_correction,
|
| 3346 |
-
artistic_module_size,
|
| 3347 |
-
artistic_module_drawer,
|
| 3348 |
-
artistic_use_custom_seed,
|
| 3349 |
-
artistic_seed,
|
| 3350 |
-
sag_blur_sigma,
|
| 3351 |
-
],
|
| 3352 |
-
)
|
| 3353 |
-
# Ex4: Neapolitan Pizza
|
| 3354 |
-
ex4_btn.click(
|
| 3355 |
-
fn=lambda: (
|
| 3356 |
-
"artisan Neapolitan pizza on rustic wooden board, fresh basil leaves scattered on top and around, oregano sprinkled, flour dust particles floating in air, melted mozzarella with char marks, traditional Italian pizzeria ambiance, warm brick oven glow in background, detailed food photography, photorealistic, 8k, ultra detailed",
|
| 3357 |
-
"https://www.pizzamaking.com",
|
| 3358 |
-
"URL",
|
| 3359 |
-
704,
|
| 3360 |
-
5,
|
| 3361 |
-
"High (30%)",
|
| 3362 |
-
16,
|
| 3363 |
-
"Square",
|
| 3364 |
-
True,
|
| 3365 |
-
856749,
|
| 3366 |
-
2.0,
|
| 3367 |
-
),
|
| 3368 |
-
outputs=[
|
| 3369 |
-
artistic_prompt_input,
|
| 3370 |
-
artistic_text_input,
|
| 3371 |
-
artistic_input_type,
|
| 3372 |
-
artistic_image_size,
|
| 3373 |
-
artistic_border_size,
|
| 3374 |
-
artistic_error_correction,
|
| 3375 |
-
artistic_module_size,
|
| 3376 |
-
artistic_module_drawer,
|
| 3377 |
-
artistic_use_custom_seed,
|
| 3378 |
-
artistic_seed,
|
| 3379 |
-
sag_blur_sigma,
|
| 3380 |
-
],
|
| 3381 |
-
)
|
| 3382 |
-
# Ex5: Poker Chips
|
| 3383 |
-
ex5_btn.click(
|
| 3384 |
-
fn=lambda: (
|
| 3385 |
-
"some cards on poker tale, realistic, great details, realistic, great details,absence of people, Detailed and Intricate, CGI, Photoshoot,rim light, 8k, 16k, ultra detail",
|
| 3386 |
-
"https://store.steampowered.com",
|
| 3387 |
-
"URL",
|
| 3388 |
-
768,
|
| 3389 |
-
6,
|
| 3390 |
-
"High (30%)",
|
| 3391 |
-
16,
|
| 3392 |
-
"Square",
|
| 3393 |
-
True,
|
| 3394 |
-
718313,
|
| 3395 |
-
2.5,
|
| 3396 |
-
),
|
| 3397 |
-
outputs=[
|
| 3398 |
-
artistic_prompt_input,
|
| 3399 |
-
artistic_text_input,
|
| 3400 |
-
artistic_input_type,
|
| 3401 |
-
artistic_image_size,
|
| 3402 |
-
artistic_border_size,
|
| 3403 |
-
artistic_error_correction,
|
| 3404 |
-
artistic_module_size,
|
| 3405 |
-
artistic_module_drawer,
|
| 3406 |
-
artistic_use_custom_seed,
|
| 3407 |
-
artistic_seed,
|
| 3408 |
-
sag_blur_sigma,
|
| 3409 |
-
],
|
| 3410 |
-
)
|
| 3411 |
-
# Ex6: Underwater Fish
|
| 3412 |
-
ex6_btn.click(
|
| 3413 |
-
fn=lambda: (
|
| 3414 |
-
"underwater scene with tropical fish, coral reef, rays of sunlight penetrating water, vibrant colors, detailed marine life, photorealistic, 8k, ultra detailed",
|
| 3415 |
-
"https://www.reddit.com",
|
| 3416 |
-
"URL",
|
| 3417 |
-
704,
|
| 3418 |
-
6,
|
| 3419 |
-
"High (30%)",
|
| 3420 |
-
16,
|
| 3421 |
-
"Square",
|
| 3422 |
-
True,
|
| 3423 |
-
718313,
|
| 3424 |
-
0.5,
|
| 3425 |
-
),
|
| 3426 |
-
outputs=[
|
| 3427 |
-
artistic_prompt_input,
|
| 3428 |
-
artistic_text_input,
|
| 3429 |
-
artistic_input_type,
|
| 3430 |
-
artistic_image_size,
|
| 3431 |
-
artistic_border_size,
|
| 3432 |
-
artistic_error_correction,
|
| 3433 |
-
artistic_module_size,
|
| 3434 |
-
artistic_module_drawer,
|
| 3435 |
-
artistic_use_custom_seed,
|
| 3436 |
-
artistic_seed,
|
| 3437 |
-
sag_blur_sigma,
|
| 3438 |
-
],
|
| 3439 |
-
)
|
| 3440 |
-
# Ex7: Mediterranean Garden
|
| 3441 |
-
ex7_btn.click(
|
| 3442 |
-
fn=lambda: (
|
| 3443 |
-
"ancient stone sundial in Mediterranean garden, olive trees, dappled sunlight through leaves, weathered stone texture, peaceful afternoon scene, photorealistic, detailed, 8k, ultra detailed",
|
| 3444 |
-
"BEGIN:VEVENT\\nSUMMARY:Team Meeting\\nDTSTART:20251115T140000Z\\nDTEND:20251115T150000Z\\nLOCATION:Conference Room A\\nEND:VEVENT",
|
| 3445 |
-
"Plain Text",
|
| 3446 |
-
1024,
|
| 3447 |
-
6,
|
| 3448 |
-
"High (30%)",
|
| 3449 |
-
14,
|
| 3450 |
-
"Square",
|
| 3451 |
-
True,
|
| 3452 |
-
413468,
|
| 3453 |
-
0.5,
|
| 3454 |
-
),
|
| 3455 |
-
outputs=[
|
| 3456 |
-
artistic_prompt_input,
|
| 3457 |
-
artistic_text_input,
|
| 3458 |
-
artistic_input_type,
|
| 3459 |
-
artistic_image_size,
|
| 3460 |
-
artistic_border_size,
|
| 3461 |
-
artistic_error_correction,
|
| 3462 |
-
artistic_module_size,
|
| 3463 |
-
artistic_module_drawer,
|
| 3464 |
-
artistic_use_custom_seed,
|
| 3465 |
-
artistic_seed,
|
| 3466 |
-
sag_blur_sigma,
|
| 3467 |
-
],
|
| 3468 |
-
)
|
| 3469 |
-
# Ex8: Rice Fields
|
| 3470 |
-
ex8_btn.click(
|
| 3471 |
-
fn=lambda: (
|
| 3472 |
-
"aerial view of terraced rice fields on mountainside, winding pathways between green paddies, Asian countryside, bird's eye perspective, detailed landscape, golden hour lighting, photorealistic, 8k, ultra detailed",
|
| 3473 |
-
"geo:37.7749,-122.4194",
|
| 3474 |
-
"Plain Text",
|
| 3475 |
-
704,
|
| 3476 |
-
6,
|
| 3477 |
-
"High (30%)",
|
| 3478 |
-
16,
|
| 3479 |
-
"Square",
|
| 3480 |
-
True,
|
| 3481 |
-
962359,
|
| 3482 |
-
0.5,
|
| 3483 |
-
),
|
| 3484 |
-
outputs=[
|
| 3485 |
-
artistic_prompt_input,
|
| 3486 |
-
artistic_text_input,
|
| 3487 |
-
artistic_input_type,
|
| 3488 |
-
artistic_image_size,
|
| 3489 |
-
artistic_border_size,
|
| 3490 |
-
artistic_error_correction,
|
| 3491 |
-
artistic_module_size,
|
| 3492 |
-
artistic_module_drawer,
|
| 3493 |
-
artistic_use_custom_seed,
|
| 3494 |
-
artistic_seed,
|
| 3495 |
-
sag_blur_sigma,
|
| 3496 |
-
],
|
| 3497 |
-
)
|
| 3498 |
-
# Ex9: Cyberpunk City
|
| 3499 |
-
ex9_btn.click(
|
| 3500 |
-
fn=lambda: (
|
| 3501 |
-
"futuristic cityscape with flying cars and neon lights, cyberpunk style, detailed architecture, night scene, 8k, ultra detailed",
|
| 3502 |
-
"https://linkedin.com",
|
| 3503 |
-
"URL",
|
| 3504 |
-
704,
|
| 3505 |
-
6,
|
| 3506 |
-
"High (30%)",
|
| 3507 |
-
16,
|
| 3508 |
-
"Square",
|
| 3509 |
-
True,
|
| 3510 |
-
718313,
|
| 3511 |
-
1.5,
|
| 3512 |
-
),
|
| 3513 |
outputs=[
|
| 3514 |
artistic_prompt_input,
|
| 3515 |
artistic_text_input,
|
|
@@ -3577,7 +3422,9 @@ if __name__ == "__main__" and not os.environ.get("QR_TESTING_MODE"):
|
|
| 3577 |
|
| 3578 |
# Change Settings Manually - separate accordion
|
| 3579 |
with gr.Accordion("Change Settings Manually", open=False):
|
| 3580 |
-
gr.Markdown(
|
|
|
|
|
|
|
| 3581 |
# Negative Prompt
|
| 3582 |
negative_prompt_standard = gr.Textbox(
|
| 3583 |
label="Negative Prompt",
|
|
@@ -3718,7 +3565,9 @@ if __name__ == "__main__" and not os.environ.get("QR_TESTING_MODE"):
|
|
| 3718 |
|
| 3719 |
# Color Quantization Section
|
| 3720 |
gr.Markdown("### Color Quantization (Optional)")
|
| 3721 |
-
gr.Markdown(
|
|
|
|
|
|
|
| 3722 |
enable_color_quantization = gr.Checkbox(
|
| 3723 |
label="Enable Color Quantization",
|
| 3724 |
value=False,
|
|
@@ -4092,6 +3941,6 @@ if __name__ == "__main__" and not os.environ.get("QR_TESTING_MODE"):
|
|
| 4092 |
|
| 4093 |
# ARTISTIC QR TAB
|
| 4094 |
app.queue() # Required for gr.Progress() to work!
|
| 4095 |
-
app.launch(share=
|
| 4096 |
# Note: Automatic file cleanup via delete_cache not available in Gradio 5.49.1
|
| 4097 |
# Files will be cleaned up when the server is restarted
|
|
|
|
| 1 |
import os
|
| 2 |
+
import queue
|
| 3 |
import sys
|
|
|
|
| 4 |
import threading
|
| 5 |
+
import time
|
| 6 |
|
| 7 |
# Force unbuffered output for real-time logging
|
| 8 |
sys.stdout.reconfigure(line_buffering=True)
|
|
|
|
| 587 |
Artistic: 640+anim=23s, 832+anim=45s, 832+anim+upscale=57s, 1024+anim+upscale=124s
|
| 588 |
"""
|
| 589 |
# Extract only the parameters we need from kwargs
|
| 590 |
+
pipeline = kwargs.get("pipeline", "standard")
|
| 591 |
+
image_size = kwargs.get("image_size", 512)
|
| 592 |
+
enable_animation = kwargs.get("enable_animation", True)
|
| 593 |
+
enable_upscale = kwargs.get("enable_upscale", False)
|
| 594 |
|
| 595 |
if pipeline == "standard":
|
| 596 |
# Standard pipeline benchmarks (with 20% safety margin)
|
|
|
|
| 739 |
|
| 740 |
class AnimationHandler:
|
| 741 |
"""Handler for managing KSampler animation callbacks"""
|
| 742 |
+
|
| 743 |
def __init__(self, preview_size=512):
|
| 744 |
self.intermediate_images = []
|
| 745 |
self.image_queue = queue.Queue()
|
| 746 |
self.enabled = False
|
| 747 |
+
self.preview_size = (
|
| 748 |
+
preview_size # Consistent preview size for all intermediate images
|
| 749 |
+
)
|
| 750 |
|
| 751 |
def create_callback(self, vae, interval=5):
|
| 752 |
"""Create a callback that stores intermediate decoded images"""
|
|
|
|
| 764 |
# Key insight: inference_mode tensors cannot be used in backward pass
|
| 765 |
# Source: https://pytorch.org/docs/stable/generated/torch.autograd.grad_mode.inference_mode.html
|
| 766 |
import torch
|
| 767 |
+
|
| 768 |
with torch.no_grad():
|
| 769 |
# Create a detached clone and ensure contiguous memory layout
|
| 770 |
# .contiguous() ensures proper memory layout for VAE decoder
|
|
|
|
| 781 |
image_tensor = get_value_at_index(decoded, 0)
|
| 782 |
|
| 783 |
# Convert EXACTLY like final images (lines 1915-1918) - no transpose, no mode
|
| 784 |
+
image_np = (image_tensor.detach().cpu().numpy() * 255).astype(
|
| 785 |
+
np.uint8
|
| 786 |
+
)
|
| 787 |
image_np = image_np[0]
|
| 788 |
pil_image = Image.fromarray(image_np)
|
| 789 |
|
| 790 |
# Resize to consistent preview size to avoid size inconsistencies in UI
|
| 791 |
+
if (
|
| 792 |
+
pil_image.size[0] > self.preview_size
|
| 793 |
+
or pil_image.size[1] > self.preview_size
|
| 794 |
+
):
|
| 795 |
+
pil_image.thumbnail(
|
| 796 |
+
(self.preview_size, self.preview_size), Image.LANCZOS
|
| 797 |
+
)
|
| 798 |
|
| 799 |
# Store with message (step is already the correct value at interval points)
|
| 800 |
msg = f"Sampling progress: step {step}/{total_steps}"
|
|
|
|
| 812 |
return images
|
| 813 |
|
| 814 |
|
| 815 |
+
def ksampler_with_animation(
|
| 816 |
+
model,
|
| 817 |
+
seed,
|
| 818 |
+
steps,
|
| 819 |
+
cfg,
|
| 820 |
+
sampler_name,
|
| 821 |
+
scheduler,
|
| 822 |
+
positive,
|
| 823 |
+
negative,
|
| 824 |
+
latent_image,
|
| 825 |
+
denoise=1.0,
|
| 826 |
+
animation_handler=None,
|
| 827 |
+
vae=None,
|
| 828 |
+
):
|
| 829 |
"""
|
| 830 |
Custom KSampler that supports animation callbacks.
|
| 831 |
Based on ComfyUI's common_ksampler but with animation support.
|
|
|
|
| 859 |
|
| 860 |
# Sample
|
| 861 |
samples = comfy.sample.sample(
|
| 862 |
+
model,
|
| 863 |
+
noise,
|
| 864 |
+
steps,
|
| 865 |
+
cfg,
|
| 866 |
+
sampler_name,
|
| 867 |
+
scheduler,
|
| 868 |
+
positive,
|
| 869 |
+
negative,
|
| 870 |
+
latent_image_data,
|
| 871 |
+
denoise=denoise,
|
| 872 |
+
disable_noise=False,
|
| 873 |
+
start_step=None,
|
| 874 |
+
last_step=None,
|
| 875 |
+
force_full_denoise=False,
|
| 876 |
+
noise_mask=noise_mask,
|
| 877 |
+
callback=animation_callback,
|
| 878 |
+
disable_pbar=disable_pbar,
|
| 879 |
+
seed=seed,
|
| 880 |
)
|
| 881 |
|
| 882 |
out = latent.copy()
|
|
|
|
| 1816 |
gr_progress=None,
|
| 1817 |
):
|
| 1818 |
# Initialize animation handler if enabled
|
| 1819 |
+
animation_handler = (
|
| 1820 |
+
AnimationHandler(preview_size=image_size) if enable_animation else None
|
| 1821 |
+
)
|
| 1822 |
if animation_handler:
|
| 1823 |
animation_handler.enabled = True
|
| 1824 |
|
|
|
|
| 1876 |
return
|
| 1877 |
|
| 1878 |
# Calculate total steps based on enabled features
|
| 1879 |
+
total_steps = (
|
| 1880 |
+
3 + (1 if enable_upscale else 0) + (1 if enable_color_quantization else 0)
|
| 1881 |
+
)
|
| 1882 |
|
| 1883 |
# 1) Yield the base QR image as the first intermediate result
|
| 1884 |
base_qr_tensor = get_value_at_index(comfy_qr_by_module_size_15, 0)
|
|
|
|
| 1933 |
if animation_handler and enable_animation:
|
| 1934 |
# Run ksampler in thread to allow real-time image yielding
|
| 1935 |
result_container = [None]
|
| 1936 |
+
|
| 1937 |
def run_ksampler():
|
| 1938 |
result_container[0] = ksampler_with_animation(
|
| 1939 |
model=get_value_at_index(checkpointloadersimple_4, 0),
|
|
|
|
| 1954 |
ksampler_thread.start()
|
| 1955 |
|
| 1956 |
# Yield intermediate images as they're captured
|
| 1957 |
+
while (
|
| 1958 |
+
ksampler_thread.is_alive() or not animation_handler.image_queue.empty()
|
| 1959 |
+
):
|
| 1960 |
try:
|
| 1961 |
img, msg = animation_handler.image_queue.get(timeout=0.1)
|
| 1962 |
yield img, msg
|
|
|
|
| 1998 |
mid_np = (mid_tensor.detach().cpu().numpy() * 255).astype(np.uint8)
|
| 1999 |
mid_np = mid_np[0]
|
| 2000 |
mid_pil = Image.fromarray(mid_np)
|
| 2001 |
+
msg = (
|
| 2002 |
+
f"First enhancement pass complete (step 2/{total_steps})… refining details"
|
| 2003 |
+
)
|
| 2004 |
log_progress(msg, gr_progress, 0.5)
|
| 2005 |
yield mid_pil, msg
|
| 2006 |
|
|
|
|
| 2025 |
if animation_handler and enable_animation:
|
| 2026 |
# Run ksampler in thread to allow real-time image yielding
|
| 2027 |
result_container = [None]
|
| 2028 |
+
|
| 2029 |
def run_ksampler():
|
| 2030 |
result_container[0] = ksampler_with_animation(
|
| 2031 |
model=get_value_at_index(checkpointloadersimple_4, 0),
|
|
|
|
| 2046 |
ksampler_thread.start()
|
| 2047 |
|
| 2048 |
# Yield intermediate images as they're captured
|
| 2049 |
+
while (
|
| 2050 |
+
ksampler_thread.is_alive() or not animation_handler.image_queue.empty()
|
| 2051 |
+
):
|
| 2052 |
try:
|
| 2053 |
img, msg = animation_handler.image_queue.get(timeout=0.1)
|
| 2054 |
yield img, msg
|
|
|
|
| 2203 |
gr_progress=None,
|
| 2204 |
):
|
| 2205 |
# Initialize animation handler if enabled
|
| 2206 |
+
animation_handler = (
|
| 2207 |
+
AnimationHandler(preview_size=image_size) if enable_animation else None
|
| 2208 |
+
)
|
| 2209 |
if animation_handler:
|
| 2210 |
animation_handler.enabled = True
|
| 2211 |
|
|
|
|
| 2368 |
if animation_handler and enable_animation:
|
| 2369 |
# Run ksampler in thread to allow real-time image yielding
|
| 2370 |
result_container = [None]
|
| 2371 |
+
|
| 2372 |
def run_ksampler():
|
| 2373 |
result_container[0] = ksampler_with_animation(
|
| 2374 |
model=enhanced_model, # Using FreeU + SAG enhanced model
|
|
|
|
| 2464 |
if animation_handler and enable_animation:
|
| 2465 |
# Run ksampler in thread to allow real-time image yielding
|
| 2466 |
result_container = [None]
|
| 2467 |
+
|
| 2468 |
def run_ksampler():
|
| 2469 |
result_container[0] = ksampler_with_animation(
|
| 2470 |
model=enhanced_model, # Using FreeU + SAG enhanced model
|
|
|
|
| 2603 |
else:
|
| 2604 |
print("ℹ️ AOT compilation skipped on MPS (MacBook) - using eager mode\n")
|
| 2605 |
|
| 2606 |
+
# Define artistic examples data
|
| 2607 |
+
ARTISTIC_EXAMPLES = [
|
| 2608 |
+
{
|
| 2609 |
+
"image": "examples/artistic/japanese_temple.jpg",
|
| 2610 |
+
"label": "Japanese Temple",
|
| 2611 |
+
"prompt": "some clothes spread on ropes, Japanese girl sits inside in the middle of the image, few sakura flowers, realistic, great details, out in the open air sunny day realistic, great details, absence of people, Detailed and Intricate, CGI, Photoshoot, rim light, 8k, 16k, ultra detail",
|
| 2612 |
+
"text_input": "https://www.google.com",
|
| 2613 |
+
"input_type": "URL",
|
| 2614 |
+
"image_size": 640,
|
| 2615 |
+
"border_size": 6,
|
| 2616 |
+
"error_correction": "Medium (15%)",
|
| 2617 |
+
"module_size": 14,
|
| 2618 |
+
"module_drawer": "Square",
|
| 2619 |
+
"use_custom_seed": True,
|
| 2620 |
+
"seed": 718313,
|
| 2621 |
+
"sag_blur_sigma": 0.5,
|
| 2622 |
+
},
|
| 2623 |
+
{
|
| 2624 |
+
"image": "examples/artistic/sunset_mountains.jpg",
|
| 2625 |
+
"label": "Sunset Mountains",
|
| 2626 |
+
"prompt": "a beautiful sunset over mountains, photorealistic, detailed landscape, golden hour, dramatic lighting, 8k, ultra detailed",
|
| 2627 |
+
"text_input": "https://github.com",
|
| 2628 |
+
"input_type": "URL",
|
| 2629 |
+
"image_size": 704,
|
| 2630 |
+
"border_size": 6,
|
| 2631 |
+
"error_correction": "High (30%)",
|
| 2632 |
+
"module_size": 16,
|
| 2633 |
+
"module_drawer": "Square",
|
| 2634 |
+
"use_custom_seed": True,
|
| 2635 |
+
"seed": 718313,
|
| 2636 |
+
"sag_blur_sigma": 0.5,
|
| 2637 |
+
},
|
| 2638 |
+
{
|
| 2639 |
+
"image": "examples/artistic/roman_city.jpg",
|
| 2640 |
+
"label": "Roman City",
|
| 2641 |
+
"prompt": "aerial bird view of ancient Roman city, cobblestone streets and pathways forming intricate patterns, vintage illustration style, sepia tones, aged parchment look, detailed architecture, 8k, ultra detailed",
|
| 2642 |
+
"text_input": "WIFI:T:WPA;S:MyNetwork;P:MyPassword123;;",
|
| 2643 |
+
"input_type": "Plain Text",
|
| 2644 |
+
"image_size": 832,
|
| 2645 |
+
"border_size": 6,
|
| 2646 |
+
"error_correction": "High (30%)",
|
| 2647 |
+
"module_size": 16,
|
| 2648 |
+
"module_drawer": "Square",
|
| 2649 |
+
"use_custom_seed": True,
|
| 2650 |
+
"seed": 718313,
|
| 2651 |
+
"sag_blur_sigma": 0.5,
|
| 2652 |
+
},
|
| 2653 |
+
{
|
| 2654 |
+
"image": "examples/artistic/neapolitan_pizza.webp",
|
| 2655 |
+
"label": "Neapolitan Pizza",
|
| 2656 |
+
"prompt": "artisan Neapolitan pizza on rustic wooden board, fresh basil leaves scattered on top and around, oregano sprinkled, flour dust particles floating in air, melted mozzarella with char marks, traditional Italian pizzeria ambiance, warm brick oven glow in background, detailed food photography, photorealistic, 8k, ultra detailed",
|
| 2657 |
+
"text_input": "https://www.pizzamaking.com",
|
| 2658 |
+
"input_type": "URL",
|
| 2659 |
+
"image_size": 704,
|
| 2660 |
+
"border_size": 5,
|
| 2661 |
+
"error_correction": "High (30%)",
|
| 2662 |
+
"module_size": 16,
|
| 2663 |
+
"module_drawer": "Square",
|
| 2664 |
+
"use_custom_seed": True,
|
| 2665 |
+
"seed": 856749,
|
| 2666 |
+
"sag_blur_sigma": 2.0,
|
| 2667 |
+
},
|
| 2668 |
+
{
|
| 2669 |
+
"image": "examples/artistic/poker_chips.webp",
|
| 2670 |
+
"label": "Poker Chips",
|
| 2671 |
+
"prompt": "some cards on poker tale, realistic, great details, realistic, great details,absence of people, Detailed and Intricate, CGI, Photoshoot,rim light, 8k, 16k, ultra detail",
|
| 2672 |
+
"text_input": "https://store.steampowered.com",
|
| 2673 |
+
"input_type": "URL",
|
| 2674 |
+
"image_size": 768,
|
| 2675 |
+
"border_size": 6,
|
| 2676 |
+
"error_correction": "High (30%)",
|
| 2677 |
+
"module_size": 16,
|
| 2678 |
+
"module_drawer": "Square",
|
| 2679 |
+
"use_custom_seed": True,
|
| 2680 |
+
"seed": 718313,
|
| 2681 |
+
"sag_blur_sigma": 2.5,
|
| 2682 |
+
},
|
| 2683 |
+
{
|
| 2684 |
+
"image": "examples/artistic/underwater_fish.webp",
|
| 2685 |
+
"label": "Underwater Fish",
|
| 2686 |
+
"prompt": "underwater scene with tropical fish, coral reef, rays of sunlight penetrating water, vibrant colors, detailed marine life, photorealistic, 8k, ultra detailed",
|
| 2687 |
+
"text_input": "https://www.reddit.com",
|
| 2688 |
+
"input_type": "URL",
|
| 2689 |
+
"image_size": 704,
|
| 2690 |
+
"border_size": 6,
|
| 2691 |
+
"error_correction": "High (30%)",
|
| 2692 |
+
"module_size": 16,
|
| 2693 |
+
"module_drawer": "Square",
|
| 2694 |
+
"use_custom_seed": True,
|
| 2695 |
+
"seed": 718313,
|
| 2696 |
+
"sag_blur_sigma": 0.5,
|
| 2697 |
+
},
|
| 2698 |
+
{
|
| 2699 |
+
"image": "examples/artistic/mediterranean_garden.jpg",
|
| 2700 |
+
"label": "Mediterranean Garden",
|
| 2701 |
+
"prompt": "ancient stone sundial in Mediterranean garden, olive trees, dappled sunlight through leaves, weathered stone texture, peaceful afternoon scene, photorealistic, detailed, 8k, ultra detailed",
|
| 2702 |
+
"text_input": "BEGIN:VEVENT\\nSUMMARY:Team Meeting\\nDTSTART:20251115T140000Z\\nDTEND:20251115T150000Z\\nLOCATION:Conference Room A\\nEND:VEVENT",
|
| 2703 |
+
"input_type": "Plain Text",
|
| 2704 |
+
"image_size": 1024,
|
| 2705 |
+
"border_size": 6,
|
| 2706 |
+
"error_correction": "High (30%)",
|
| 2707 |
+
"module_size": 14,
|
| 2708 |
+
"module_drawer": "Square",
|
| 2709 |
+
"use_custom_seed": True,
|
| 2710 |
+
"seed": 413468,
|
| 2711 |
+
"sag_blur_sigma": 0.5,
|
| 2712 |
+
},
|
| 2713 |
+
{
|
| 2714 |
+
"image": "examples/artistic/rice_fields.jpg",
|
| 2715 |
+
"label": "Rice Fields",
|
| 2716 |
+
"prompt": "aerial view of terraced rice fields on mountainside, winding pathways between green paddies, Asian countryside, bird's eye perspective, detailed landscape, golden hour lighting, photorealistic, 8k, ultra detailed",
|
| 2717 |
+
"text_input": "geo:37.7749,-122.4194",
|
| 2718 |
+
"input_type": "Plain Text",
|
| 2719 |
+
"image_size": 704,
|
| 2720 |
+
"border_size": 6,
|
| 2721 |
+
"error_correction": "High (30%)",
|
| 2722 |
+
"module_size": 16,
|
| 2723 |
+
"module_drawer": "Square",
|
| 2724 |
+
"use_custom_seed": True,
|
| 2725 |
+
"seed": 962359,
|
| 2726 |
+
"sag_blur_sigma": 0.5,
|
| 2727 |
+
},
|
| 2728 |
+
{
|
| 2729 |
+
"image": "examples/artistic/cyberpunk_city.webp",
|
| 2730 |
+
"label": "Cyberpunk City",
|
| 2731 |
+
"prompt": "futuristic cityscape with flying cars and neon lights, cyberpunk style, detailed architecture, night scene, 8k, ultra detailed",
|
| 2732 |
+
"text_input": "https://linkedin.com",
|
| 2733 |
+
"input_type": "URL",
|
| 2734 |
+
"image_size": 704,
|
| 2735 |
+
"border_size": 6,
|
| 2736 |
+
"error_correction": "High (30%)",
|
| 2737 |
+
"module_size": 16,
|
| 2738 |
+
"module_drawer": "Square",
|
| 2739 |
+
"use_custom_seed": True,
|
| 2740 |
+
"seed": 718313,
|
| 2741 |
+
"sag_blur_sigma": 1.5,
|
| 2742 |
+
},
|
| 2743 |
+
]
|
| 2744 |
+
|
| 2745 |
# Start your Gradio app with automatic cache cleanup
|
| 2746 |
# delete_cache=(3600, 3600) means: check every hour and delete files older than 1 hour
|
| 2747 |
with gr.Blocks(delete_cache=(3600, 3600)) as app:
|
|
|
|
| 2836 |
|
| 2837 |
# Change Settings Manually - separate accordion
|
| 2838 |
with gr.Accordion("Change Settings Manually", open=False):
|
| 2839 |
+
gr.Markdown(
|
| 2840 |
+
"**Advanced controls including:** Animation toggle, Color Quantization, FreeU/SAG parameters, ControlNet strength, QR settings, and more."
|
| 2841 |
+
)
|
| 2842 |
# Negative Prompt
|
| 2843 |
negative_prompt_artistic = gr.Textbox(
|
| 2844 |
label="Negative Prompt",
|
|
|
|
| 2979 |
|
| 2980 |
# Color Quantization Section
|
| 2981 |
gr.Markdown("### Color Quantization (Optional)")
|
| 2982 |
+
gr.Markdown(
|
| 2983 |
+
"Use this option to specify a custom color scheme for your QR code. Perfect for matching brand colors or creating themed designs."
|
| 2984 |
+
)
|
| 2985 |
artistic_enable_color_quantization = gr.Checkbox(
|
| 2986 |
label="Enable Color Quantization",
|
| 2987 |
value=False,
|
|
|
|
| 3317 |
outputs=[artistic_seed],
|
| 3318 |
)
|
| 3319 |
|
| 3320 |
+
# Examples Gallery
|
| 3321 |
gr.Markdown("### Featured Examples")
|
| 3322 |
+
gr.Markdown("Click any image to load its settings")
|
| 3323 |
+
|
| 3324 |
+
# Create gallery from examples data
|
| 3325 |
+
example_gallery = gr.Gallery(
|
| 3326 |
+
value=[(ex["image"], ex["label"]) for ex in ARTISTIC_EXAMPLES],
|
| 3327 |
+
label="Example Gallery",
|
| 3328 |
+
columns=3,
|
| 3329 |
+
rows=3,
|
| 3330 |
+
height="auto",
|
| 3331 |
+
object_fit="cover",
|
| 3332 |
+
allow_preview=True,
|
| 3333 |
+
show_download_button=False,
|
| 3334 |
)
|
| 3335 |
|
| 3336 |
+
# Event handler to load settings when user clicks an example
|
| 3337 |
+
def load_example_settings(evt: gr.SelectData):
|
| 3338 |
+
"""Load settings when user clicks an example image"""
|
| 3339 |
+
example = ARTISTIC_EXAMPLES[evt.index]
|
| 3340 |
+
return (
|
| 3341 |
+
example["prompt"],
|
| 3342 |
+
example["text_input"],
|
| 3343 |
+
example["input_type"],
|
| 3344 |
+
example["image_size"],
|
| 3345 |
+
example["border_size"],
|
| 3346 |
+
example["error_correction"],
|
| 3347 |
+
example["module_size"],
|
| 3348 |
+
example["module_drawer"],
|
| 3349 |
+
example["use_custom_seed"],
|
| 3350 |
+
example["seed"],
|
| 3351 |
+
example["sag_blur_sigma"],
|
| 3352 |
+
)
|
| 3353 |
+
|
| 3354 |
+
# Attach the event handler
|
| 3355 |
+
example_gallery.select(
|
| 3356 |
+
fn=load_example_settings,
|
| 3357 |
+
inputs=None,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3358 |
outputs=[
|
| 3359 |
artistic_prompt_input,
|
| 3360 |
artistic_text_input,
|
|
|
|
| 3422 |
|
| 3423 |
# Change Settings Manually - separate accordion
|
| 3424 |
with gr.Accordion("Change Settings Manually", open=False):
|
| 3425 |
+
gr.Markdown(
|
| 3426 |
+
"**Advanced controls including:** Animation toggle, Color Quantization, ControlNet strength, QR settings, and more."
|
| 3427 |
+
)
|
| 3428 |
# Negative Prompt
|
| 3429 |
negative_prompt_standard = gr.Textbox(
|
| 3430 |
label="Negative Prompt",
|
|
|
|
| 3565 |
|
| 3566 |
# Color Quantization Section
|
| 3567 |
gr.Markdown("### Color Quantization (Optional)")
|
| 3568 |
+
gr.Markdown(
|
| 3569 |
+
"Use this option to specify a custom color scheme for your QR code. Perfect for matching brand colors or creating themed designs."
|
| 3570 |
+
)
|
| 3571 |
enable_color_quantization = gr.Checkbox(
|
| 3572 |
label="Enable Color Quantization",
|
| 3573 |
value=False,
|
|
|
|
| 3941 |
|
| 3942 |
# ARTISTIC QR TAB
|
| 3943 |
app.queue() # Required for gr.Progress() to work!
|
| 3944 |
+
app.launch(share=True, mcp_server=True)
|
| 3945 |
# Note: Automatic file cleanup via delete_cache not available in Gradio 5.49.1
|
| 3946 |
# Files will be cleaned up when the server is restarted
|