Spaces:
Running
on
Zero
Running
on
Zero
Julian Bilcke
commited on
Commit
·
3678ee4
1
Parent(s):
4cf61fa
wip
Browse files
app.py
CHANGED
|
@@ -520,26 +520,31 @@ def create_single_page_pdf(images: List[Image.Image], layout_id: str, num_images
|
|
| 520 |
layout = next((l for l in layouts if l["id"] == layout_id), None)
|
| 521 |
|
| 522 |
if not layout:
|
| 523 |
-
# Fallback to default grid layout
|
| 524 |
if num_images == 1:
|
| 525 |
-
positions = [[0.
|
| 526 |
elif num_images == 2:
|
| 527 |
-
|
|
|
|
| 528 |
elif num_images == 3:
|
| 529 |
-
|
|
|
|
| 530 |
elif num_images == 4:
|
| 531 |
-
|
| 532 |
-
|
|
|
|
| 533 |
elif num_images == 5:
|
| 534 |
-
|
| 535 |
-
|
|
|
|
| 536 |
elif num_images == 6:
|
| 537 |
-
|
| 538 |
-
|
| 539 |
-
[0.
|
|
|
|
| 540 |
else:
|
| 541 |
# For more than 6, create a simple grid
|
| 542 |
-
positions = [[0.
|
| 543 |
else:
|
| 544 |
positions = layout["positions"]
|
| 545 |
|
|
@@ -550,27 +555,13 @@ def create_single_page_pdf(images: List[Image.Image], layout_id: str, num_images
|
|
| 550 |
|
| 551 |
x_rel, y_rel, w_rel, h_rel = pos
|
| 552 |
|
| 553 |
-
#
|
| 554 |
-
|
| 555 |
-
padding = 0.005
|
| 556 |
|
| 557 |
-
#
|
| 558 |
-
# This
|
| 559 |
-
scale_factor = 1.15 # Increase overall scale by 15%
|
| 560 |
|
| 561 |
-
#
|
| 562 |
-
center_x = 0.5
|
| 563 |
-
center_y = 0.5
|
| 564 |
-
|
| 565 |
-
# Scale positions relative to center
|
| 566 |
-
x_rel = center_x + (x_rel - center_x) * scale_factor
|
| 567 |
-
y_rel = center_y + (y_rel - center_y) * scale_factor
|
| 568 |
-
|
| 569 |
-
# Scale sizes
|
| 570 |
-
w_rel = w_rel * scale_factor
|
| 571 |
-
h_rel = h_rel * scale_factor
|
| 572 |
-
|
| 573 |
-
# Apply bounds checking to prevent overflow
|
| 574 |
if x_rel < padding:
|
| 575 |
x_rel = padding
|
| 576 |
if y_rel < padding:
|
|
@@ -862,21 +853,40 @@ with gr.Blocks(css=css) as demo:
|
|
| 862 |
</div>
|
| 863 |
""")
|
| 864 |
gr.Markdown("This demo uses [Qwen-Image-Lightning](https://huggingface.co/lightx2v/Qwen-Image-Lightning). Hugigng Face PRO users can perform more generations.")
|
|
|
|
|
|
|
| 865 |
with gr.Row():
|
| 866 |
prompt = gr.Text(
|
| 867 |
label="Prompt",
|
| 868 |
show_label=False,
|
| 869 |
placeholder="Enter your prompt",
|
| 870 |
container=False,
|
|
|
|
| 871 |
)
|
| 872 |
-
|
| 873 |
-
|
| 874 |
-
reset_button = gr.Button("Reset", variant="secondary")
|
| 875 |
|
| 876 |
-
#
|
| 877 |
with gr.Row():
|
|
|
|
| 878 |
with gr.Column(scale=1):
|
| 879 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 880 |
num_images_slider = gr.Slider(
|
| 881 |
label="Images per page",
|
| 882 |
minimum=1,
|
|
@@ -886,7 +896,7 @@ with gr.Blocks(css=css) as demo:
|
|
| 886 |
info="Number of images to generate for the PDF (1-6)"
|
| 887 |
)
|
| 888 |
|
| 889 |
-
|
| 890 |
layout_dropdown = gr.Dropdown(
|
| 891 |
label="Page Layout",
|
| 892 |
choices=[("Full Page", "full_page")],
|
|
@@ -895,48 +905,52 @@ with gr.Blocks(css=css) as demo:
|
|
| 895 |
info="How images are arranged on the page"
|
| 896 |
)
|
| 897 |
|
| 898 |
-
|
| 899 |
-
|
| 900 |
-
|
| 901 |
-
|
| 902 |
-
|
| 903 |
-
|
| 904 |
-
|
| 905 |
-
|
| 906 |
-
|
| 907 |
-
|
| 908 |
-
|
| 909 |
-
|
| 910 |
-
|
| 911 |
-
|
| 912 |
-
|
| 913 |
-
|
| 914 |
-
|
| 915 |
-
|
| 916 |
-
|
| 917 |
-
with gr.Column():
|
| 918 |
-
pdf_preview = PDF(label="PDF Preview", show_label=True, height=600, elem_id="pdf-preview")
|
| 919 |
pdf_output = gr.File(label="Download PDF", show_label=True, elem_id="pdf-download")
|
|
|
|
| 920 |
gr.Markdown("""**Note:** Your images and PDF are saved for up to 24 hours.
|
| 921 |
You can continue adding pages (up to 128) by clicking the generate button.""")
|
| 922 |
|
| 923 |
-
|
| 924 |
-
|
| 925 |
-
|
| 926 |
-
|
| 927 |
-
|
| 928 |
-
|
| 929 |
-
|
| 930 |
-
|
| 931 |
-
|
| 932 |
-
|
| 933 |
-
|
| 934 |
-
|
| 935 |
-
|
| 936 |
-
|
| 937 |
-
|
| 938 |
-
|
| 939 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 940 |
|
| 941 |
# Add interaction to show/hide custom style text field
|
| 942 |
def toggle_custom_style(style_value):
|
|
@@ -959,24 +973,6 @@ with gr.Blocks(css=css) as demo:
|
|
| 959 |
outputs=[layout_dropdown]
|
| 960 |
)
|
| 961 |
|
| 962 |
-
# Update examples to show some with different styles and image counts
|
| 963 |
-
styled_examples = [
|
| 964 |
-
["A capybara wearing a suit holding a sign that reads Hello World", "no_style", "", 1],
|
| 965 |
-
["sharks raining down on san francisco", "anime", "", 2],
|
| 966 |
-
["A beautiful landscape with mountains and a lake", "watercolor", "", 3],
|
| 967 |
-
["A knight fighting a dragon", "medieval", "", 4],
|
| 968 |
-
["Space battle with laser beams", "sci-fi", "", 5],
|
| 969 |
-
["Detective investigating a mystery", "noir", "", 6],
|
| 970 |
-
]
|
| 971 |
-
|
| 972 |
-
gr.Examples(
|
| 973 |
-
examples=styled_examples,
|
| 974 |
-
inputs=[prompt, style_preset, custom_style_text, num_images_slider],
|
| 975 |
-
outputs=None, # Don't show outputs for examples
|
| 976 |
-
fn=None,
|
| 977 |
-
cache_examples=False
|
| 978 |
-
)
|
| 979 |
-
|
| 980 |
# Define the main generation event
|
| 981 |
generation_event = gr.on(
|
| 982 |
triggers=[run_button.click, prompt.submit],
|
|
|
|
| 520 |
layout = next((l for l in layouts if l["id"] == layout_id), None)
|
| 521 |
|
| 522 |
if not layout:
|
| 523 |
+
# Fallback to default grid layout with proper spacing
|
| 524 |
if num_images == 1:
|
| 525 |
+
positions = [[0.02, 0.02, 0.96, 0.96]]
|
| 526 |
elif num_images == 2:
|
| 527 |
+
# Horizontal split with gap
|
| 528 |
+
positions = [[0.02, 0.02, 0.47, 0.96], [0.51, 0.02, 0.47, 0.96]]
|
| 529 |
elif num_images == 3:
|
| 530 |
+
# Three horizontal panels with gaps
|
| 531 |
+
positions = [[0.02, 0.2, 0.31, 0.6], [0.345, 0.2, 0.31, 0.6], [0.67, 0.2, 0.31, 0.6]]
|
| 532 |
elif num_images == 4:
|
| 533 |
+
# 2x2 grid with gaps
|
| 534 |
+
positions = [[0.02, 0.02, 0.47, 0.47], [0.51, 0.02, 0.47, 0.47],
|
| 535 |
+
[0.02, 0.51, 0.47, 0.47], [0.51, 0.51, 0.47, 0.47]]
|
| 536 |
elif num_images == 5:
|
| 537 |
+
# Hero top with 4 small panels below
|
| 538 |
+
positions = [[0.02, 0.02, 0.96, 0.44], [0.02, 0.48, 0.31, 0.5], [0.345, 0.48, 0.31, 0.5],
|
| 539 |
+
[0.67, 0.48, 0.31, 0.24], [0.67, 0.74, 0.31, 0.24]]
|
| 540 |
elif num_images == 6:
|
| 541 |
+
# 2x3 grid with gaps
|
| 542 |
+
positions = [[0.02, 0.02, 0.47, 0.31], [0.51, 0.02, 0.47, 0.31],
|
| 543 |
+
[0.02, 0.345, 0.47, 0.31], [0.51, 0.345, 0.47, 0.31],
|
| 544 |
+
[0.02, 0.67, 0.47, 0.31], [0.51, 0.67, 0.47, 0.31]]
|
| 545 |
else:
|
| 546 |
# For more than 6, create a simple grid
|
| 547 |
+
positions = [[0.02, 0.02, 0.96, 0.96]]
|
| 548 |
else:
|
| 549 |
positions = layout["positions"]
|
| 550 |
|
|
|
|
| 555 |
|
| 556 |
x_rel, y_rel, w_rel, h_rel = pos
|
| 557 |
|
| 558 |
+
# Add small padding between panels (1% of page dimensions)
|
| 559 |
+
padding = 0.01
|
|
|
|
| 560 |
|
| 561 |
+
# Don't scale up - use the positions as defined in the layout
|
| 562 |
+
# This prevents overlapping when there are multiple images
|
|
|
|
| 563 |
|
| 564 |
+
# Apply padding to prevent images from touching edges
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 565 |
if x_rel < padding:
|
| 566 |
x_rel = padding
|
| 567 |
if y_rel < padding:
|
|
|
|
| 853 |
</div>
|
| 854 |
""")
|
| 855 |
gr.Markdown("This demo uses [Qwen-Image-Lightning](https://huggingface.co/lightx2v/Qwen-Image-Lightning). Hugigng Face PRO users can perform more generations.")
|
| 856 |
+
|
| 857 |
+
# First row: prompt input, generate button, reset button
|
| 858 |
with gr.Row():
|
| 859 |
prompt = gr.Text(
|
| 860 |
label="Prompt",
|
| 861 |
show_label=False,
|
| 862 |
placeholder="Enter your prompt",
|
| 863 |
container=False,
|
| 864 |
+
scale=4
|
| 865 |
)
|
| 866 |
+
run_button = gr.Button("Generate page 1", variant="primary", scale=1)
|
| 867 |
+
reset_button = gr.Button("Reset", variant="secondary", scale=1)
|
|
|
|
| 868 |
|
| 869 |
+
# Second row: 1/3 controls on left, 2/3 PDF preview on right
|
| 870 |
with gr.Row():
|
| 871 |
+
# Left column (1/3) - Controls
|
| 872 |
with gr.Column(scale=1):
|
| 873 |
+
# Create dropdown choices from loaded presets
|
| 874 |
+
style_choices = [(preset["label"], key) for key, preset in STYLE_PRESETS.items()]
|
| 875 |
+
style_preset = gr.Dropdown(
|
| 876 |
+
label="Style Preset",
|
| 877 |
+
choices=style_choices,
|
| 878 |
+
value="no_style",
|
| 879 |
+
interactive=True
|
| 880 |
+
)
|
| 881 |
+
|
| 882 |
+
custom_style_text = gr.Textbox(
|
| 883 |
+
label="Custom Style Text",
|
| 884 |
+
placeholder="Enter custom style (e.g., 'oil painting')",
|
| 885 |
+
visible=False,
|
| 886 |
+
lines=1
|
| 887 |
+
)
|
| 888 |
+
|
| 889 |
+
# Number of images slider
|
| 890 |
num_images_slider = gr.Slider(
|
| 891 |
label="Images per page",
|
| 892 |
minimum=1,
|
|
|
|
| 896 |
info="Number of images to generate for the PDF (1-6)"
|
| 897 |
)
|
| 898 |
|
| 899 |
+
# Page layout dropdown
|
| 900 |
layout_dropdown = gr.Dropdown(
|
| 901 |
label="Page Layout",
|
| 902 |
choices=[("Full Page", "full_page")],
|
|
|
|
| 905 |
info="How images are arranged on the page"
|
| 906 |
)
|
| 907 |
|
| 908 |
+
# Advanced settings accordion
|
| 909 |
+
with gr.Accordion("Advanced Settings", open=False):
|
| 910 |
+
guidance_scale = gr.Slider(
|
| 911 |
+
label="Guidance scale (True CFG Scale)",
|
| 912 |
+
minimum=1.0,
|
| 913 |
+
maximum=5.0,
|
| 914 |
+
step=0.1,
|
| 915 |
+
value=1.0,
|
| 916 |
+
)
|
| 917 |
+
|
| 918 |
+
num_inference_steps = gr.Slider(
|
| 919 |
+
label="Number of inference steps",
|
| 920 |
+
minimum=4,
|
| 921 |
+
maximum=28,
|
| 922 |
+
step=1,
|
| 923 |
+
value=8,
|
| 924 |
+
)
|
| 925 |
+
|
| 926 |
+
# Download link
|
|
|
|
|
|
|
| 927 |
pdf_output = gr.File(label="Download PDF", show_label=True, elem_id="pdf-download")
|
| 928 |
+
|
| 929 |
gr.Markdown("""**Note:** Your images and PDF are saved for up to 24 hours.
|
| 930 |
You can continue adding pages (up to 128) by clicking the generate button.""")
|
| 931 |
|
| 932 |
+
# Examples section in the left column
|
| 933 |
+
with gr.Accordion("Examples", open=True):
|
| 934 |
+
styled_examples = [
|
| 935 |
+
["A capybara wearing a suit holding a sign that reads Hello World", "no_style", "", 1],
|
| 936 |
+
["sharks raining down on san francisco", "anime", "", 2],
|
| 937 |
+
["A beautiful landscape with mountains and a lake", "watercolor", "", 3],
|
| 938 |
+
["A knight fighting a dragon", "medieval", "", 4],
|
| 939 |
+
["Space battle with laser beams", "sci-fi", "", 5],
|
| 940 |
+
["Detective investigating a mystery", "noir", "", 6],
|
| 941 |
+
]
|
| 942 |
+
|
| 943 |
+
gr.Examples(
|
| 944 |
+
examples=styled_examples,
|
| 945 |
+
inputs=[prompt, style_preset, custom_style_text, num_images_slider],
|
| 946 |
+
outputs=None, # Don't show outputs for examples
|
| 947 |
+
fn=None,
|
| 948 |
+
cache_examples=False
|
| 949 |
+
)
|
| 950 |
+
|
| 951 |
+
# Right column (2/3) - PDF Preview
|
| 952 |
+
with gr.Column(scale=2):
|
| 953 |
+
pdf_preview = PDF(label="PDF Preview", show_label=True, height=700, elem_id="pdf-preview")
|
| 954 |
|
| 955 |
# Add interaction to show/hide custom style text field
|
| 956 |
def toggle_custom_style(style_value):
|
|
|
|
| 973 |
outputs=[layout_dropdown]
|
| 974 |
)
|
| 975 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 976 |
# Define the main generation event
|
| 977 |
generation_event = gr.on(
|
| 978 |
triggers=[run_button.click, prompt.submit],
|