Vineet Agarwal commited on
Commit
7dafaa0
Β·
1 Parent(s): 232d93f

Add application file

Browse files
Files changed (2) hide show
  1. app.py +224 -0
  2. requirements.txt +3 -0
app.py ADDED
@@ -0,0 +1,224 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import requests
3
+ from PIL import Image
4
+ import io
5
+
6
+ BASE_URL = "https://api.jigsawstack.com/v1"
7
+ headers = {"x-api-key": ""}
8
+
9
+ # ----------------- JigsawStack API Wrappers ------------------
10
+
11
+ def generate_image(prompt, aspect_ratio, width, height, steps, negative_prompt, guidance, seed):
12
+ # Validate required inputs
13
+ if not prompt or not prompt.strip():
14
+ return None, {"error": "Prompt is required"}
15
+
16
+ if len(prompt.strip()) > 5000:
17
+ return None, {"error": "Prompt must be between 1-5000 characters"}
18
+
19
+ # Build payload with required and optional parameters
20
+ payload = {
21
+ "prompt": prompt.strip()
22
+ }
23
+
24
+ # Add optional parameters if provided
25
+ if aspect_ratio and aspect_ratio.strip():
26
+ payload["aspect_ratio"] = aspect_ratio.strip()
27
+
28
+ if width:
29
+ try:
30
+ width_int = int(width)
31
+ if 256 <= width_int <= 1920:
32
+ payload["width"] = width_int
33
+ else:
34
+ return None, {"error": "Width must be between 256-1920 pixels"}
35
+ except ValueError:
36
+ return None, {"error": "Width must be a valid number"}
37
+
38
+ if height:
39
+ try:
40
+ height_int = int(height)
41
+ if 256 <= height_int <= 1920:
42
+ payload["height"] = height_int
43
+ else:
44
+ return None, {"error": "Height must be between 256-1920 pixels"}
45
+ except ValueError:
46
+ return None, {"error": "Height must be a valid number"}
47
+
48
+ if steps:
49
+ try:
50
+ steps_int = int(steps)
51
+ if 1 <= steps_int <= 90:
52
+ payload["steps"] = steps_int
53
+ else:
54
+ return None, {"error": "Steps must be between 1-90"}
55
+ except ValueError:
56
+ return None, {"error": "Steps must be a valid number"}
57
+
58
+ if negative_prompt and negative_prompt.strip():
59
+ payload["negative_prompt"] = negative_prompt.strip()
60
+
61
+ if guidance:
62
+ try:
63
+ guidance_float = float(guidance)
64
+ if 1 <= guidance_float <= 28:
65
+ payload["guidance"] = guidance_float
66
+ else:
67
+ return None, {"error": "Guidance must be between 1-28"}
68
+ except ValueError:
69
+ return None, {"error": "Guidance must be a valid number"}
70
+
71
+ if seed:
72
+ try:
73
+ seed_int = int(seed)
74
+ payload["seed"] = seed_int
75
+ except ValueError:
76
+ return None, {"error": "Seed must be a valid number"}
77
+
78
+ try:
79
+ r = requests.post(f"{BASE_URL}/ai/image_generation", headers=headers, json=payload)
80
+ r.raise_for_status()
81
+
82
+ # The API returns the image directly as binary data
83
+ if r.headers.get('content-type', '').startswith('image/'):
84
+ # Convert bytes to PIL Image for Gradio
85
+
86
+ # Create PIL Image from bytes
87
+ image = Image.open(io.BytesIO(r.content))
88
+
89
+ return image, {"success": True, "message": "Image generated successfully!"}
90
+ else:
91
+ # If not an image, try to parse as JSON for error
92
+ try:
93
+ error_data = r.json()
94
+ return None, {"error": "Image generation failed", "details": error_data}
95
+ except:
96
+ return None, {"error": "Unexpected response format"}
97
+
98
+ except requests.exceptions.RequestException as req_err:
99
+ return None, {"error": "Request failed", "message": str(req_err)}
100
+ except Exception as e:
101
+ return None, {"error": "Unexpected error", "message": str(e)}
102
+
103
+ # ----------------- Gradio UI ------------------
104
+
105
+ with gr.Blocks() as demo:
106
+ gr.Markdown("""
107
+ <div style='text-align: center; margin-bottom: 24px;'>
108
+ <h1 style='font-size:2.2em; margin-bottom: 0.2em;'>🧩 JigsawStack Image Generation Demo</h1>
109
+ <p style='font-size:1.2em; margin-top: 0;'>Generate high-quality images from text prompts using advanced AI models.</p>
110
+ <p style='font-size:1em; margin-top: 0.5em;'>For more details and API usage, see the <a href='https://jigsawstack.com/docs/api-reference/ai/image-generation' target='_blank'>documentation</a>.</p>
111
+ </div>
112
+ """)
113
+
114
+ with gr.Row():
115
+ with gr.Column():
116
+ gr.Markdown("#### Input")
117
+ prompt = gr.Textbox(
118
+ label="Text Prompt",
119
+ lines=4,
120
+ placeholder="Enter text to describe the image"
121
+ )
122
+
123
+ gr.Markdown("#### Quick Examples")
124
+ gr.Markdown("Click any example below to auto-fill the prompt:")
125
+
126
+ with gr.Row():
127
+ img_example_btn1 = gr.Button("πŸ”οΈ Mountain Landscape", size="sm")
128
+ img_example_btn2 = gr.Button("🐱 Cute Cat Portrait", size="sm")
129
+ img_example_btn3 = gr.Button("πŸ™οΈ Cyberpunk City", size="sm")
130
+
131
+ with gr.Row():
132
+ img_example_btn4 = gr.Button("🌊 Ocean Sunset", size="sm")
133
+ img_example_btn5 = gr.Button("πŸš€ Space Station", size="sm")
134
+ img_example_btn6 = gr.Button("🏰 Medieval Castle", size="sm")
135
+
136
+ with gr.Row():
137
+ img_example_btn7 = gr.Button("🎨 Abstract Art", size="sm")
138
+ img_example_btn8 = gr.Button("πŸ• Delicious Pizza", size="sm")
139
+
140
+ gr.Markdown("#### Image Options")
141
+ aspect_ratio = gr.Textbox(
142
+ label="Aspect Ratio (optional, e.g., 16:9, 4:3)",
143
+ placeholder="16:9, 4:3, etc.",
144
+ info="Common ratios: 16:9, 4:3, 1:1"
145
+ )
146
+ width = gr.Textbox(
147
+ label="Width (optional, pixels)",
148
+ placeholder="1024",
149
+ info="Minimum: 256, Maximum: 1920"
150
+ )
151
+ height = gr.Textbox(
152
+ label="Height (optional, pixels)",
153
+ placeholder="768",
154
+ info="Minimum: 256, Maximum: 1920"
155
+ )
156
+ steps = gr.Textbox(
157
+ label="Steps (optional, 1-90)",
158
+ placeholder="50",
159
+ info="Minimum: 1, Maximum: 90"
160
+ )
161
+ negative_prompt = gr.Textbox(
162
+ label="Negative Prompt (optional)",
163
+ placeholder="A bad image",
164
+ info="Optional: describe what you don't want in the image"
165
+ )
166
+ guidance = gr.Textbox(
167
+ label="Guidance (optional, 1-28)",
168
+ placeholder="7.5",
169
+ info="Minimum: 1, Maximum: 28"
170
+ )
171
+ seed = gr.Textbox(
172
+ label="Seed (optional)",
173
+ placeholder="Random",
174
+ info="Optional: randomize image generation"
175
+ )
176
+
177
+ with gr.Column():
178
+ gr.Markdown("#### Preview")
179
+ image_preview = gr.Image(label="Generated Image")
180
+ generate_image_btn = gr.Button("Generate Image", variant="primary")
181
+ generate_image_result = gr.JSON(label="Image Generation Result")
182
+
183
+ # Example functions to auto-fill prompt field
184
+ def fill_img_example_1():
185
+ return "A majestic mountain landscape with snow-capped peaks, crystal clear lake in the foreground, golden hour lighting, photorealistic, 8K resolution"
186
+
187
+ def fill_img_example_2():
188
+ return "A cute fluffy cat sitting on a windowsill, looking directly at camera with big green eyes, soft natural lighting, high quality, detailed fur"
189
+
190
+ def fill_img_example_3():
191
+ return "A futuristic cyberpunk cityscape at night, neon lights, flying cars, tall skyscrapers, rain-slicked streets, cinematic lighting"
192
+
193
+ def fill_img_example_4():
194
+ return "A breathtaking ocean sunset over calm waters, orange and pink sky, silhouettes of palm trees, peaceful atmosphere, high resolution"
195
+
196
+ def fill_img_example_5():
197
+ return "A massive space station orbiting Earth, detailed engineering, solar panels, astronauts in space suits, stars and nebula background"
198
+
199
+ def fill_img_example_6():
200
+ return "An ancient medieval castle on a hilltop, stone walls and towers, flags waving, dramatic clouds, fantasy atmosphere, detailed architecture"
201
+
202
+ def fill_img_example_7():
203
+ return "Abstract digital art with flowing colors, geometric shapes, vibrant gradients, modern aesthetic, artistic composition"
204
+
205
+ def fill_img_example_8():
206
+ return "A delicious pizza with melted cheese, pepperoni, fresh basil, wood-fired oven, appetizing, high quality food photography"
207
+
208
+ # Connect example buttons to auto-fill functions
209
+ img_example_btn1.click(fill_img_example_1, outputs=[prompt])
210
+ img_example_btn2.click(fill_img_example_2, outputs=[prompt])
211
+ img_example_btn3.click(fill_img_example_3, outputs=[prompt])
212
+ img_example_btn4.click(fill_img_example_4, outputs=[prompt])
213
+ img_example_btn5.click(fill_img_example_5, outputs=[prompt])
214
+ img_example_btn6.click(fill_img_example_6, outputs=[prompt])
215
+ img_example_btn7.click(fill_img_example_7, outputs=[prompt])
216
+ img_example_btn8.click(fill_img_example_8, outputs=[prompt])
217
+
218
+ generate_image_btn.click(
219
+ generate_image,
220
+ inputs=[prompt, aspect_ratio, width, height, steps, negative_prompt, guidance, seed],
221
+ outputs=[image_preview, generate_image_result]
222
+ )
223
+
224
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ gradio
2
+ requests
3
+ Pillow