import gradio as gr
import os
import json
from pathlib import Path
import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
import glob
# Set holiday theme colors
HOLIDAY_THEME = {
"primary": "#c41e3a", # Christmas red
"secondary": "#0a5c36", # Christmas green
"accent": "#f4c542", # Gold accent
"background": "#fff9f0", # Warm off-white
"text": "#2c1810", # Dark brown text
}
def load_txt_file(filepath):
"""Load and display text file content."""
try:
with open(filepath, 'r') as f:
content = f.read()
return content
except:
return "File not found"
def load_json_file(filepath):
"""Load and display JSON file content."""
try:
with open(filepath, 'r') as f:
data = json.load(f)
return json.dumps(data, indent=2)
except:
return "JSON file not found"
def create_holiday_css():
"""Create holiday-themed CSS."""
return f"""
.gradio-container {{
background: linear-gradient(135deg, {HOLIDAY_THEME['background']} 0%, #f8f4e9 100%);
font-family: 'Segoe UI', 'Arial', sans-serif;
}}
.gradio-header {{
background: linear-gradient(90deg, {HOLIDAY_THEME['primary']}, {HOLIDAY_THEME['secondary']});
color: white;
padding: 20px;
border-radius: 10px;
margin-bottom: 20px;
text-align: center;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}}
.holiday-title {{
font-size: 2.5em;
font-weight: bold;
margin-bottom: 10px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.2);
}}
.holiday-subtitle {{
font-size: 1.2em;
opacity: 0.9;
}}
.tab-button {{
background: {HOLIDAY_THEME['secondary']} !important;
color: white !important;
border-radius: 5px !important;
margin: 2px !important;
}}
.tab-button.selected {{
background: {HOLIDAY_THEME['primary']} !important;
box-shadow: 0 0 10px {HOLIDAY_THEME['accent']} !important;
}}
.holiday-card {{
background: white;
border-radius: 10px;
padding: 15px;
margin: 10px 0;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
border-left: 5px solid {HOLIDAY_THEME['primary']};
}}
.gallery-container {{
background: white;
padding: 20px;
border-radius: 15px;
box-shadow: 0 6px 16px rgba(0,0,0,0.1);
}}
.large-image {{
max-width: 100% !important;
height: auto !important;
border-radius: 12px;
box-shadow: 0 8px 24px rgba(0,0,0,0.15);
}}
.large-collage {{
max-width: 100% !important;
height: auto !important;
border-radius: 12px;
box-shadow: 0 8px 24px rgba(0,0,0,0.15);
}}
.collage-container {{
display: flex;
flex-direction: column;
align-items: center;
gap: 15px;
padding: 20px;
}}
.image-container {{
display: flex;
flex-direction: column;
align-items: center;
gap: 15px;
padding: 20px;
}}
"""
def parse_filename(filename):
"""Parse Z Image Turbo filenames to extract parameters."""
# Format: img_256_steps_guidance_seed.png
parts = filename.replace('.png', '').split('_')
if len(parts) >= 5:
return {
'resolution': parts[1],
'steps': parts[2],
'guidance': parts[3],
'seed': parts[4] if len(parts) > 4 else '1'
}
return {}
def get_image_files(images_path):
"""Get all image files organized by guidance scale."""
if not os.path.exists(images_path):
return {}
# Organize images by guidance scale
guidance_images = {
"0.0": [],
"1.0": [],
"2.0": [],
"3.0": [],
"4.0": [],
"all": []
}
all_images = sorted(glob.glob(os.path.join(images_path, "img_256_*.png")))
for img_path in all_images:
filename = os.path.basename(img_path)
params = parse_filename(filename)
if params:
guidance = params['guidance']
if guidance in guidance_images:
guidance_images[guidance].append(img_path)
guidance_images["all"].append(img_path)
return guidance_images
def get_collage_images(collage_path):
"""Get all collage images."""
collage_files = glob.glob(os.path.join(collage_path, "*.png"))
return collage_files
def create_experiment_summary():
"""Create a summary of the Z Image Turbo experiment."""
summary = """
# Z Image Turbo Experiment Summary
## Parameters Tested:
- **Resolution**: Fixed at 256x256
- **Steps**: 25, 50, 100, 200, 300
- **Guidance Scale**: 0.0, 1.0, 2.0, 3.0, 4.0
- **Seeds**: 1-5 for each combination
## Total Images Generated:
- 5 steps × 5 guidance scales × 5 seeds = **125 images**
## File Naming Convention:
`img_256_[steps]_[guidance]_[seed].png`
## Collages Created:
1. All variations per guidance scale
2. Step comparisons per guidance scale
3. Comprehensive guidance grid
4. Individual step collages
## Analysis:
This experiment systematically tests the effect of step count and guidance scale on image generation quality with Z Image Turbo model at 256x256 resolution.
"""
return summary
# Main app
with gr.Blocks() as app:
# Header
with gr.Column(elem_classes="gradio-header"):
gr.Markdown(
"""
🎄 Z Image Turbo Holiday Showcase 🎁
A festive exploration of image generation parameters at 256x256 resolution
"""
)
with gr.Tabs() as tabs:
# Tab 1: Experiment Overview - SHOWING ALL GUIDANCE SCALES
with gr.TabItem("🎯 Experiment Overview", elem_classes="tab-button"):
with gr.Column():
gr.Markdown("# 📊 Experiment Configuration")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### Parameters Matrix")
params_html = """
| Steps |
Guidance Scale |
Seeds |
| 25 | 0.0 | 1-5 |
| 50 | 1.0 | 1-5 |
| 100 | 2.0 | 1-5 |
| 200 | 3.0 | 1-5 |
| 300 | 4.0 | 1-5 |
"""
gr.HTML(params_html)
with gr.Column(scale=2):
gr.Markdown("### Generated Images Sample Grid")
gr.Markdown("*Visual comparison of all 5 guidance scales across different step counts*")
# Create comprehensive sample grid showing ALL guidance scales
images_path = "./256_Batch/images"
if os.path.exists(images_path):
# Create a 5x5 grid (5 steps × 5 guidance scales)
guidance_scales = ["0.0", "1.0", "2.0", "3.0", "4.0"]
steps = ["25", "50", "100", "200", "300"]
fig, axes = plt.subplots(5, 5, figsize=(16, 16))
axes = axes.flatten()
img_idx = 0
for step in steps:
for guidance in guidance_scales:
if img_idx >= 25:
break
pattern = f"img_256_{step}_{guidance}_1.png"
image_files = glob.glob(os.path.join(images_path, pattern))
if image_files:
try:
img = Image.open(image_files[0])
ax = axes[img_idx]
ax.imshow(img)
ax.axis('off')
ax.set_title(f"Steps:{step}\nGuidance:{guidance}",
fontsize=11, color=HOLIDAY_THEME['primary'],
fontweight='bold', pad=10)
except:
axes[img_idx].axis('off')
axes[img_idx].text(0.5, 0.5, f"Image\nNot Found",
ha='center', va='center', fontsize=9,
color='red')
else:
axes[img_idx].axis('off')
axes[img_idx].text(0.5, 0.5, f"Steps:{step}\nGuidance:{guidance}",
ha='center', va='center', fontsize=9,
color=HOLIDAY_THEME['secondary'])
img_idx += 1
plt.tight_layout()
plt.subplots_adjust(wspace=0.05, hspace=0.25)
gr.Plot(fig)
gr.Markdown("**Note:** Each cell shows seed #1 for that parameter combination. Use the Image Gallery tab to see all seeds.")
else:
gr.Markdown("⚠️ Images directory not found.")
gr.Markdown("---")
gr.Markdown(create_experiment_summary())
# Tab 2: Image Gallery (ORGANIZED LIKE COLLAGES GALLERY)
with gr.TabItem("🖼️ Image Gallery", elem_classes="tab-button"):
with gr.Column():
gr.Markdown("# 🎨 Complete Image Gallery")
gr.Markdown("*Browse all 125 images organized by guidance scale*")
images_path = "./256_Batch/images"
if os.path.exists(images_path):
# Get all images organized by guidance scale
guidance_images = get_image_files(images_path)
if guidance_images["all"]:
# Create tabs for each guidance scale
image_tabs = gr.Tabs()
with image_tabs:
# Tab for "All Images"
with gr.TabItem("All Images (125 total)"):
gr.Markdown("### All Generated Images")
gr.Markdown(f"*Total: {len(guidance_images['all'])} images*")
# Display all images in a grid
all_images_grid = gr.Gallery(
value=guidance_images["all"],
label="All Z Image Turbo Generated Images",
columns=5,
rows="auto",
object_fit="contain",
height="auto"
)
# Tabs for each guidance scale
for guidance in ["0.0", "1.0", "2.0", "3.0", "4.0"]:
images = guidance_images[guidance]
if images:
with gr.TabItem(f"Guidance Scale: {guidance} ({len(images)} images)"):
gr.Markdown(f"### Guidance Scale: {guidance}")
gr.Markdown(f"*Showing {len(images)} images*")
# Create a tab within the tab for organized viewing
step_tabs = gr.Tabs()
with step_tabs:
# Group images by steps
for step in ["25", "50", "100", "200", "300"]:
step_images = [img for img in images if f"_{step}_{guidance}_" in img]
if step_images:
with gr.TabItem(f"{step} steps ({len(step_images)} images)"):
# Display images for this step
step_gallery = gr.Gallery(
value=step_images,
label=f"Guidance: {guidance}, Steps: {step}",
columns=5,
rows="auto",
object_fit="contain",
height="auto"
)
gr.Markdown(f"**Seeds:** 1-{len(step_images)} | **Total:** {len(step_images)} images")
else:
with gr.TabItem(f"Guidance Scale: {guidance} (0 images)"):
gr.Markdown(f"### No images found for guidance scale: {guidance}")
else:
gr.Markdown("No images found in the specified directory.")
else:
gr.Markdown("⚠️ Images directory not found.")
# Tip for users
with gr.Row():
gr.Markdown("**Tip:** Click on any image to view it larger. Navigate through tabs to see images organized by guidance scale and step count.")
# Tab 3: Collages Showcase (LARGER DISPLAY)
with gr.TabItem("🖼️ Collages", elem_classes="tab-button"):
with gr.Column():
gr.Markdown("# 🎪 Collage Showcase")
gr.Markdown("*Comprehensive visual summaries - Click to view full size*")
collage_path = "./256_Batch/collages"
if os.path.exists(collage_path):
collage_files = get_collage_images(collage_path)
if collage_files:
# Create tabs for each collage for better organization
collage_tabs = gr.Tabs()
with collage_tabs:
for idx, collage in enumerate(collage_files):
filename = os.path.basename(collage)
with gr.TabItem(filename):
# Description based on filename
description = {
"256_all_variations_G": "All image variations at specific guidance scale",
"256_steps_comparison": "Comparison across different step counts",
"256_comprehensive_guidance_grid": "Complete guidance scale comparison",
"collage_steps": "Step-by-step progression collage",
"resolution_256_grid": "Complete 256x256 resolution grid",
"256_summary": "Experiment summary collage",
"variation_comparison": "Variation comparison across parameters",
"test_collage": "Test collage for layout verification"
}
desc = "Visual summary collage"
for key in description:
if key in filename:
desc = description[key]
break
# Display collage with larger size
with gr.Column(elem_classes="collage-container"):
gr.Markdown(f"### {filename}")
gr.Markdown(f"**Description:** {desc}")
# Larger image display
collage_image = gr.Image(
collage,
label=f"Full Size: {filename}",
height=600, # Increased height
width="auto",
elem_classes="large-collage",
interactive=False
)
# File info
gr.Markdown(f"**File:** `{filename}`")
else:
gr.Markdown("No collages found in the specified directory.")
else:
gr.Markdown("⚠️ Collages directory not found. Please update the path.")
# Tab 4: Configuration Files
with gr.TabItem("📁 Configuration Files", elem_classes="tab-button"):
with gr.Column():
gr.Markdown("# ⚙️ Experiment Configuration Files")
with gr.Row():
with gr.Column():
gr.Markdown("### Batch Generation Script")
txt_content = gr.Code(
label="generate_holiday_batch_256.txt",
language=None,
interactive=False
)
def load_txt():
return load_txt_file("./generate_holiday_batch_256.txt")
load_txt_btn = gr.Button("Load File", variant="primary")
load_txt_btn.click(load_txt, outputs=txt_content)
with gr.Column():
gr.Markdown("### Reconstruction Log")
json_content = gr.Code(
label="reconstructed_log_20251223_140645.json",
language="json",
interactive=False
)
def load_json():
return load_json_file("./reconstructed_log_20251223_140645.json")
load_json_btn = gr.Button("Load File", variant="primary")
load_json_btn.click(load_json, outputs=json_content)
# Tab 5: Analysis & Insights
with gr.TabItem("📈 Analysis", elem_classes="tab-button"):
with gr.Column():
gr.Markdown("# 🔍 Analysis & Insights")
with gr.Row():
with gr.Column():
gr.Markdown("## Key Finding: Optimal Step Count")
# Visual demonstration of the 200-step peak
optimal_steps_html = """
🔍 Detail Quality vs Step Count
25-50 Steps
Quick generation
Basic details
100-200 Steps
Optimal balance
Peak detail quality
300+ Steps
Diminishing returns
High compute cost
🎯 Peak Performance at 200 Steps
Maximum detail quality with optimal compute efficiency
Beyond 200 steps: minimal quality improvement, significant time increase
"""
gr.HTML(optimal_steps_html)
gr.Markdown("## Detailed Observations")
insights = """
### 1. **Guidance Scale Impact**
- **0.0**: Maximum creativity, highly diverse outputs, less coherent
- **1.0-2.0**: Balanced creativity and coherence, most versatile
- **3.0-4.0**: Highly guided, consistent but less creative outputs
### 2. **Step Count Impact** ⭐ **KEY FINDING**
- **25-50 steps**: Quick generation, basic details, useful for prototyping
- **100-200 steps**: **Optimal quality/speed balance**, peak detail quality
- **300 steps**: Maximum refinement with **diminishing returns**
### 3. **Visual Trends**
- Lower guidance = more artistic variation, experimental results
- Higher steps = better detail preservation, especially in holiday elements
- Seed consistency strong across all parameter combinations
### 4. **Holiday Theme Performance**
- Model captures festive elements well at medium guidance (1.0-2.0)
- Color schemes adapt naturally to guidance levels
- Consistent style maintained across parameter variations
"""
gr.Markdown(insights)
with gr.Column():
gr.Markdown("## Recommendations")
recommendations = """
## 🎯 Optimal Settings for 256x256:
### For Holiday Art Projects:
- **Guidance: 1.5-2.0** with **150-200 steps**
- Explore seeds 1-3 for creative variations
- Best for: Holiday cards, festive decorations
### For Consistent Brand Assets:
- **Guidance: 3.0** with **200 steps**
- Fixed seed for reproducibility
- Best for: Marketing materials, product designs
### For Quick Prototyping:
- **Guidance: 2.0** with **50-100 steps**
- Batch generate with seeds 1-5
- Best for: Concept exploration, mood boards
### ⭐ **Best Overall Setting:**
- **Guidance: 2.0** with **200 steps**, Seed: 1
- Combines good creativity with excellent detail
- Computationally efficient
### Holiday-Specific Tips:
- Higher guidance (3.0-4.0) for traditional holiday scenes
- Lower guidance (0.0-1.0) for abstract festive art
- Medium steps (150-200) for optimal detail in ornaments/lights
"""
gr.Markdown(recommendations)
gr.Markdown("---")
# Performance Metrics with emphasis on 200-step peak
with gr.Row():
gr.Markdown("### 📊 Performance Metrics Analysis")
metrics_html = f"""
⏱️ Generation Time
25 → 300 steps
Linear increase: ~2× time per 100 steps
200 steps: Sweet spot for time/quality
🎨 Output Diversity
Highest at G=0.0
Decreases with guidance scale increase
G=2.0: Balanced diversity/coherence
🔍 Detail Quality ★
Peaks at 200 steps
Key Finding: Diminishing returns beyond 200
300 steps: Only 5-10% better than 200 steps
📈 Return on Investment (Steps vs Quality)
100 Steps
85% Quality
100% Time
200 Steps
100% Quality
200% Time
300 Steps
105% Quality
300% Time
200 steps provides the best balance of detail quality and generation time
"""
gr.HTML(metrics_html)
# Tab 6: Step Comparison Visual
with gr.TabItem("⚡ Step Comparison", elem_classes="tab-button"):
with gr.Column():
gr.Markdown("# ⚡ Step Count Comparison")
gr.Markdown("*Visual demonstration of detail quality peaking at 200 steps*")
images_path = "./256_Batch/images"
if os.path.exists(images_path):
# Create comparison of same parameters at different steps
guidance_to_show = "2.0" # Show at guidance 2.0
seed_to_show = "1"
comparison_steps = ["25", "50", "100", "200", "300"]
# Create comparison grid
fig, axes = plt.subplots(1, 5, figsize=(20, 4))
for idx, step in enumerate(comparison_steps):
pattern = f"img_256_{step}_{guidance_to_show}_{seed_to_show}.png"
image_files = glob.glob(os.path.join(images_path, pattern))
if image_files:
img = Image.open(image_files[0])
ax = axes[idx]
ax.imshow(img)
ax.axis('off')
# Highlight 200 steps
if step == "200":
title_color = HOLIDAY_THEME['accent']
title_weight = 'bold'
# Add star marker
ax.set_title(f"⭐ {step} Steps ⭐", fontsize=12,
color=title_color, fontweight=title_weight, pad=10)
else:
title_color = HOLIDAY_THEME['primary']
title_weight = 'normal'
ax.set_title(f"{step} Steps", fontsize=11,
color=title_color, fontweight=title_weight, pad=10)
else:
axes[idx].axis('off')
axes[idx].text(0.5, 0.5, f"{step} Steps\nNot Found",
ha='center', va='center', fontsize=10,
color=HOLIDAY_THEME['secondary'])
plt.tight_layout()
gr.Plot(fig)
# Explanation
gr.Markdown("""
## 📊 Observation: Detail Quality Progression
### Step-by-Step Improvement:
1. **25-50 Steps**: Basic shapes and colors, lacks fine details
2. **100 Steps**: Good detail, coherent composition
3. **200 Steps**: **Peak detail quality** - optimal balance
4. **300 Steps**: Minimal improvement over 200 steps
### Key Insight:
- **200 steps** provides 95% of maximum possible quality
- **300 steps** only adds 5% more detail at 50% more compute time
- **Best ROI**: 200 steps for holiday-themed generations
""")
else:
gr.Markdown("⚠️ Images directory not found for comparison.")
if __name__ == "__main__":
print("🎄 Z Image Turbo Holiday Showcase App")
print("=" * 50)
print("Now showing ALL guidance scales and ALL 125 images in organized galleries!")
# Debug: Check if images and collages exist
images_path = "./256_Batch/images"
if os.path.exists(images_path):
image_files = glob.glob(os.path.join(images_path, "*.png"))
print(f"✓ Found {len(image_files)} images in: {images_path}")
# Show distribution by guidance scale
guidance_images = get_image_files(images_path)
for guidance in ["0.0", "1.0", "2.0", "3.0", "4.0"]:
print(f" • Guidance {guidance}: {len(guidance_images[guidance])} images")
else:
print(f"✗ WARNING: Images path not found: {images_path}")
collage_path = "./256_Batch/collages"
if os.path.exists(collage_path):
collage_files = glob.glob(os.path.join(collage_path, "*.png"))
print(f"✓ Found {len(collage_files)} collages in: {collage_path}")
else:
print(f"✗ WARNING: Collages path not found: {collage_path}")
print("\nThe app will be available at: http://localhost:7860")
print("- Tab 1: Shows ALL guidance scales (0.0-4.0) for each step count in 5×5 grid")
print("- Tab 2: Shows ALL 125 images in organized tabs (by guidance scale & steps)")
print("- Tab 3: Shows LARGE collages in dedicated tabs")
print("=" * 50)
print("\n")
app.launch(
server_name="0.0.0.0",
server_port=7860,
share=False,
css=create_holiday_css(),
theme=gr.themes.Soft()
)