MySafeCode commited on
Commit
7698cc1
·
verified ·
1 Parent(s): ef77e93

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +156 -329
  2. requirements.txt +1 -1
app.py CHANGED
@@ -80,28 +80,17 @@ def call_pixazo_api(prompt, num_steps=4, seed=None, height=512, width=512,
80
  if image.mode in ('RGBA', 'LA', 'P'):
81
  image = image.convert('RGB')
82
 
83
- # Create a simplified result
84
- simplified_result = {
85
  "success": True,
86
  "status_code": 200,
87
- "image_url": image_url,
88
  "image_size": f"{image.size[0]}x{image.size[1]}",
89
- "image_mode": image.mode,
90
  "timestamp": datetime.now().isoformat()
91
  }
92
-
93
- # Add original response keys (excluding potentially large data)
94
- for key, value in result.items():
95
- if key != "output" and not isinstance(value, (str, int, float, bool, type(None))) or len(str(value)) > 1000:
96
- simplified_result[f"original_{key}"] = type(value).__name__
97
- else:
98
- simplified_result[f"original_{key}"] = value
99
-
100
- return image, simplified_result
101
  else:
102
  return None, {
103
  "error": f"Failed to download image: HTTP {img_response.status_code}",
104
- "image_url": image_url,
105
  "download_status": img_response.status_code,
106
  "timestamp": datetime.now().isoformat()
107
  }
@@ -109,7 +98,7 @@ def call_pixazo_api(prompt, num_steps=4, seed=None, height=512, width=512,
109
  except Exception as e:
110
  return None, {
111
  "error": f"Error downloading image: {str(e)}",
112
- "image_url": image_url,
113
  "timestamp": datetime.now().isoformat()
114
  }
115
  else:
@@ -148,14 +137,14 @@ def call_pixazo_api(prompt, num_steps=4, seed=None, height=512, width=512,
148
  "timestamp": datetime.now().isoformat()
149
  }
150
 
151
- # Generate images with progress
152
  def generate_images(prompt, num_steps, seed, height, width, style_preset,
153
- num_images, guidance_scale, progress=gr.Progress()):
154
 
155
  images = []
156
  all_results = []
157
 
158
- for i in progress.tqdm(range(num_images), desc="Generating images"):
159
  try:
160
  current_seed = seed + i if seed > 0 else 0
161
 
@@ -171,12 +160,16 @@ def generate_images(prompt, num_steps, seed, height, width, style_preset,
171
 
172
  if image:
173
  images.append(image)
174
- progress((i + 1, num_images), desc=f"✅ Image {i+1}/{num_images} generated")
175
- else:
176
- progress((i + 1, num_images), desc=f"❌ Image {i+1}/{num_images} failed")
177
 
178
  all_results.append(result)
179
 
 
 
 
 
 
 
 
180
  # Small delay between requests
181
  if i < num_images - 1:
182
  time.sleep(1)
@@ -184,7 +177,11 @@ def generate_images(prompt, num_steps, seed, height, width, style_preset,
184
  except Exception as e:
185
  error_result = {"error": str(e), "image_index": i, "timestamp": datetime.now().isoformat()}
186
  all_results.append(error_result)
187
- progress((i + 1, num_images), desc=f"⚠️ Image {i+1}/{num_images} error")
 
 
 
 
188
  break
189
 
190
  # Prepare final output
@@ -192,13 +189,13 @@ def generate_images(prompt, num_steps, seed, height, width, style_preset,
192
 
193
  if success_count == 0:
194
  status = f"❌ No images generated ({success_count}/{num_images} successful)"
195
- gallery_visible = False
196
  elif success_count < num_images:
197
  status = f"⚠️ Partial success: {success_count}/{num_images} images"
198
- gallery_visible = True
199
  else:
200
  status = f"🎉 Success! All {success_count} images generated"
201
- gallery_visible = True
202
 
203
  summary = {
204
  "total_attempts": num_images,
@@ -214,330 +211,160 @@ def generate_images(prompt, num_steps, seed, height, width, style_preset,
214
  }
215
  }
216
 
217
- return (gr.update(value=images, visible=gallery_visible),
218
- status,
219
- summary)
220
 
221
- # Create enhanced interface with latest Gradio features
222
- def create_interface():
223
- with gr.Blocks(
224
- theme=gr.themes.Soft(
225
- primary_hue="purple",
226
- secondary_hue="pink"
227
- ),
228
- title="Pixazo AI Image Generator",
229
- css="""
230
- .success { color: #10b981; font-weight: bold; }
231
- .error { color: #ef4444; font-weight: bold; }
232
- .warning { color: #f59e0b; font-weight: bold; }
233
- .info-box {
234
- background: #f8fafc;
235
- padding: 15px;
236
- border-radius: 10px;
237
- border-left: 4px solid #8b5cf6;
238
- }
239
- """
240
- ) as demo:
241
-
242
- # Header
243
  gr.Markdown("""
244
- # 🎨 Pixazo AI Image Generator
245
 
246
- Generate stunning images with FLUX-1 Schnell model
 
 
 
247
  """)
248
-
249
- # API Status
250
- api_key = get_api_key()
251
- if api_key:
252
- status_html = """
253
- <div class="info-box">
254
- <h3>✅ API Status: Connected</h3>
255
- <p>Your API key is configured and ready to use.</p>
256
- </div>
257
- """
258
- else:
259
- status_html = """
260
- <div style="background: #fef2f2; padding: 15px; border-radius: 10px; border-left: 4px solid #ef4444;">
261
- <h3>❌ API Status: Not Configured</h3>
262
- <p><strong>Setup Required:</strong></p>
263
- <ol>
264
- <li>Go to Space Settings Repository secrets</li>
265
- <li>Add secret: <code>PIXAZO_API_KEY</code> = your API key</li>
266
- <li>Click "Restart this Space" at the bottom of settings</li>
267
- </ol>
268
- </div>
269
- """
270
-
271
- gr.HTML(status_html)
272
-
273
- with gr.Row():
274
- with gr.Column(scale=1, min_width=400):
275
- # Input Section
276
- with gr.Group():
277
- prompt = gr.Textbox(
278
- label="🎨 Prompt",
279
- placeholder="Describe the image you want to generate...",
280
- lines=3,
281
- max_lines=5,
282
- show_label=True,
283
- info="Be descriptive for better results"
284
- )
285
-
286
- with gr.Row():
287
- with gr.Column():
288
- style_preset = gr.Dropdown(
289
- label="🎭 Style",
290
- choices=[
291
- "none", "cyberpunk", "fantasy", "anime", "photographic",
292
- "digital-art", "comic", "3d-model", "pixel-art", "isometric",
293
- "minimalist", "watercolor", "oil-painting", "sketch"
294
- ],
295
- value="none",
296
- info="Optional style preset"
297
- )
298
-
299
- with gr.Column():
300
- guidance_scale = gr.Slider(
301
- label="🎯 Guidance Scale",
302
- minimum=1.0,
303
- maximum=20.0,
304
- value=7.5,
305
- step=0.5,
306
- info="Higher = more prompt adherence"
307
- )
308
-
309
- with gr.Row():
310
- with gr.Column():
311
- num_steps = gr.Slider(
312
- label="⚡ Steps",
313
- minimum=1,
314
- maximum=50,
315
- value=4,
316
- step=1,
317
- info="Quality vs speed trade-off"
318
- )
319
-
320
- with gr.Column():
321
- seed = gr.Number(
322
- label="🌱 Seed",
323
- value=42,
324
- info="0 = random, same seed = same result"
325
- )
326
-
327
- with gr.Row():
328
- with gr.Column():
329
- width = gr.Slider(
330
- label="📏 Width",
331
- minimum=256,
332
- maximum=1024,
333
- value=512,
334
- step=64
335
- )
336
-
337
- with gr.Column():
338
- height = gr.Slider(
339
- label="📐 Height",
340
- minimum=256,
341
- maximum=1024,
342
- value=512,
343
- step=64
344
- )
345
 
346
- num_images = gr.Slider(
347
- label="🖼️ Number of Images",
 
 
 
 
 
 
 
 
 
348
  minimum=1,
349
- maximum=8,
350
- value=1,
351
- step=1,
352
- info="Generate multiple variations"
353
  )
354
 
355
- with gr.Row():
356
- generate_btn = gr.Button("✨ Generate", variant="primary", scale=2)
357
- clear_btn = gr.Button("🗑️ Clear", variant="secondary")
358
-
359
- # Examples
360
- with gr.Accordion("📚 Example Prompts", open=False):
361
- examples = [
362
- ["A majestic dragon overlooking a fantasy kingdom at sunset, cinematic lighting", "fantasy"],
363
- ["Cyberpunk city street with neon signs and flying cars, rainy night", "cyberpunk"],
364
- ["Cute anime girl with magical powers in a cherry blossom garden", "anime"],
365
- ["Photorealistic portrait of an astronaut on Mars with detailed reflection in visor", "photographic"],
366
- ["Isometric view of a cozy cottage in a magical forest", "isometric"],
367
- ["Watercolor painting of a serene mountain lake at dawn", "watercolor"]
368
- ]
369
-
370
- for example_prompt, example_style in examples:
371
- with gr.Row():
372
- gr.Textbox(value=example_prompt, show_label=False, interactive=False)
373
- gr.Button("📋 Use", size="sm").click(
374
- fn=lambda p=example_prompt, s=example_style: [p, s],
375
- outputs=[prompt, style_preset]
376
- )
377
 
378
- with gr.Column(scale=2, min_width=600):
379
- # Output Section
380
- status_display = gr.HTML(
381
- value="<div class='info-box'><h3>Status: Ready</h3><p>Enter a prompt and click Generate</p></div>"
 
 
 
382
  )
383
 
384
- gallery = gr.Gallery(
385
- label="Generated Images",
386
- show_label=True,
387
- columns=2,
388
- height="auto",
389
- object_fit="cover",
390
- preview=True,
391
- visible=False
392
- )
393
-
394
- # Response and Info
395
- with gr.Tabs():
396
- with gr.TabItem("📊 Generation Summary"):
397
- summary_json = gr.JSON(
398
- label="Summary",
399
- container=True
400
- )
401
-
402
- with gr.TabItem("🔧 Parameters"):
403
- param_display = gr.JSON(
404
- label="Current Parameters",
405
- value={},
406
- container=True
407
- )
408
-
409
- with gr.TabItem("ℹ️ About"):
410
- gr.Markdown("""
411
- ### About This App
412
-
413
- This app uses the **Pixazo FLUX-1 Schnell** AI image generation model.
414
-
415
- **API Response Format:**
416
- ```json
417
- {
418
- "output": "https://image-url-here.png"
419
- }
420
- ```
421
-
422
- **How it works:**
423
- 1. Your prompt and settings are sent to Pixazo API
424
- 2. API returns a JSON with an image URL
425
- 3. App downloads and displays the image
426
-
427
- **Tips:**
428
- - Be descriptive in your prompts
429
- - Try different styles for varied results
430
- - Use seeds for reproducible results
431
- - Start with 4 steps for quick testing
432
- """)
433
-
434
- # Event handlers
435
- def update_param_display(prompt, num_steps, seed, height, width, style_preset, num_images, guidance_scale):
436
- return {
437
- "prompt": prompt[:100] + "..." if len(prompt) > 100 else prompt,
438
- "prompt_length": len(prompt),
439
- "steps": num_steps,
440
- "seed": seed if seed > 0 else "random",
441
- "resolution": f"{width}×{height}",
442
- "style": style_preset,
443
- "num_images": num_images,
444
- "guidance_scale": guidance_scale,
445
- "timestamp": datetime.now().strftime("%H:%M:%S")
446
- }
447
-
448
- # Update parameters on input change
449
- inputs = [prompt, num_steps, seed, height, width, style_preset, num_images, guidance_scale]
450
- for inp in inputs:
451
- inp.change(
452
- update_param_display,
453
- inputs=inputs,
454
- outputs=param_display
455
- )
456
-
457
- # Initialize param display
458
- demo.load(
459
- fn=lambda: update_param_display(*[i.value for i in inputs]),
460
- outputs=param_display
461
- )
462
-
463
- # Generate button click
464
- def on_generate(prompt, num_steps, seed, height, width, style_preset, num_images, guidance_scale):
465
- if not prompt.strip():
466
- return (
467
- gr.update(visible=False),
468
- "<div class='error'><h3>❌ Error</h3><p>Please enter a prompt</p></div>",
469
- {"error": "No prompt provided"}
470
  )
471
 
472
- gallery, status, summary = generate_images(
473
- prompt, num_steps, seed, height, width, style_preset, num_images, guidance_scale
 
 
 
 
474
  )
475
 
476
- # Format status HTML
477
- if "❌" in status:
478
- status_html = f"<div class='error'><h3>{status}</h3></div>"
479
- elif "⚠️" in status:
480
- status_html = f"<div class='warning'><h3>{status}</h3></div>"
481
- else:
482
- status_html = f"<div class='success'><h3>{status}</h3></div>"
483
 
484
- return gallery, status_html, summary
485
-
486
- generate_btn.click(
487
- fn=on_generate,
488
- inputs=inputs,
489
- outputs=[gallery, status_display, summary_json]
490
- )
491
-
492
- # Clear button
493
- clear_btn.click(
494
- fn=lambda: [
495
- gr.update(visible=False),
496
- "<div class='info-box'><h3>Status: Ready</h3><p>Enter a prompt and click Generate</p></div>",
497
- {"status": "cleared"}
498
- ],
499
- outputs=[gallery, status_display, summary_json]
500
- )
501
 
502
- # Footer
503
- gr.Markdown("""
504
- ---
505
- <div style="text-align: center; color: #666; font-size: 0.9em;">
506
- <p>Built with Gradio • Powered by Pixazo FLUX-1 Schnell</p>
507
- <p>API Response Format: <code>{"output": "IMAGE_URL"}</code></p>
508
- </div>
509
- """)
 
 
 
 
 
 
 
 
 
 
510
 
511
- return demo
512
-
513
- # Simple test function
514
- def test_connection():
515
- api_key = get_api_key()
516
- return {
517
- "api_key_present": bool(api_key),
518
- "api_key_length": len(api_key) if api_key else 0,
519
- "timestamp": datetime.now().isoformat(),
520
- "gradio_version": gr.__version__
521
- }
522
-
523
- # Main function
524
- def main():
525
- print("=" * 60)
526
- print(f"🚀 Pixazo Image Generator")
527
- print(f"📦 Gradio Version: {gr.__version__}")
528
- print(f"🔑 API Key: {'✅ Present' if get_api_key() else '❌ Missing'}")
529
- print("=" * 60)
530
 
531
- # Create and launch interface
532
- demo = create_interface()
533
 
534
- demo.launch(
535
- server_name="0.0.0.0",
536
- server_port=7860,
537
- share=False,
538
- show_error=True,
539
- debug=False
540
  )
541
 
 
542
  if __name__ == "__main__":
543
- main()
 
 
 
 
 
 
 
 
80
  if image.mode in ('RGBA', 'LA', 'P'):
81
  image = image.convert('RGB')
82
 
83
+ return image, {
 
84
  "success": True,
85
  "status_code": 200,
86
+ "image_url": image_url[:100] + "..." if len(image_url) > 100 else image_url,
87
  "image_size": f"{image.size[0]}x{image.size[1]}",
 
88
  "timestamp": datetime.now().isoformat()
89
  }
 
 
 
 
 
 
 
 
 
90
  else:
91
  return None, {
92
  "error": f"Failed to download image: HTTP {img_response.status_code}",
93
+ "image_url": image_url[:100] + "..." if len(image_url) > 100 else image_url,
94
  "download_status": img_response.status_code,
95
  "timestamp": datetime.now().isoformat()
96
  }
 
98
  except Exception as e:
99
  return None, {
100
  "error": f"Error downloading image: {str(e)}",
101
+ "image_url": image_url[:100] + "..." if len(image_url) > 100 else image_url,
102
  "timestamp": datetime.now().isoformat()
103
  }
104
  else:
 
137
  "timestamp": datetime.now().isoformat()
138
  }
139
 
140
+ # Generate images
141
  def generate_images(prompt, num_steps, seed, height, width, style_preset,
142
+ num_images, guidance_scale):
143
 
144
  images = []
145
  all_results = []
146
 
147
+ for i in range(num_images):
148
  try:
149
  current_seed = seed + i if seed > 0 else 0
150
 
 
160
 
161
  if image:
162
  images.append(image)
 
 
 
163
 
164
  all_results.append(result)
165
 
166
+ # Update status
167
+ yield [
168
+ images if images else None,
169
+ f"Progress: {i+1}/{num_images} images",
170
+ json.dumps(result, indent=2)
171
+ ]
172
+
173
  # Small delay between requests
174
  if i < num_images - 1:
175
  time.sleep(1)
 
177
  except Exception as e:
178
  error_result = {"error": str(e), "image_index": i, "timestamp": datetime.now().isoformat()}
179
  all_results.append(error_result)
180
+ yield [
181
+ images if images else None,
182
+ f"Error on image {i+1}: {str(e)[:50]}",
183
+ json.dumps(error_result, indent=2)
184
+ ]
185
  break
186
 
187
  # Prepare final output
 
189
 
190
  if success_count == 0:
191
  status = f"❌ No images generated ({success_count}/{num_images} successful)"
192
+ final_images = None
193
  elif success_count < num_images:
194
  status = f"⚠️ Partial success: {success_count}/{num_images} images"
195
+ final_images = images
196
  else:
197
  status = f"🎉 Success! All {success_count} images generated"
198
+ final_images = images
199
 
200
  summary = {
201
  "total_attempts": num_images,
 
211
  }
212
  }
213
 
214
+ yield [final_images, status, json.dumps(summary, indent=2)]
 
 
215
 
216
+ # Create Gradio interface
217
+ with gr.Blocks(
218
+ title="Pixazo Image Generator",
219
+ theme=gr.themes.Soft()
220
+ ) as demo:
221
+
222
+ # Header
223
+ gr.Markdown("""
224
+ # 🎨 Pixazo Image Generator
225
+
226
+ Generate images using Pixazo's FLUX-1 Schnell AI model
227
+ """)
228
+
229
+ # API Status
230
+ api_key = get_api_key()
231
+ if api_key:
232
+ gr.Markdown("### API Key: Configured")
233
+ else:
 
 
 
 
234
  gr.Markdown("""
235
+ ### API Key: Not Configured
236
 
237
+ **To set up:**
238
+ 1. Go to Space Settings → Repository secrets
239
+ 2. Add: `PIXAZO_API_KEY` = your API key
240
+ 3. Click "Restart this Space"
241
  """)
242
+
243
+ with gr.Row():
244
+ with gr.Column(scale=1):
245
+ # Input Section
246
+ with gr.Group():
247
+ prompt = gr.Textbox(
248
+ label="Prompt",
249
+ placeholder="Describe the image you want to generate...",
250
+ lines=3,
251
+ value="A beautiful sunset over mountains"
252
+ )
253
+
254
+ with gr.Row():
255
+ style_preset = gr.Dropdown(
256
+ label="Style Preset",
257
+ choices=[
258
+ "none", "cyberpunk", "fantasy", "anime", "photographic",
259
+ "digital-art", "comic", "3d-model", "pixel-art"
260
+ ],
261
+ value="none"
262
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
 
264
+ guidance_scale = gr.Slider(
265
+ label="Guidance Scale",
266
+ minimum=1.0,
267
+ maximum=20.0,
268
+ value=7.5,
269
+ step=0.5
270
+ )
271
+
272
+ with gr.Row():
273
+ num_steps = gr.Slider(
274
+ label="Number of Steps",
275
  minimum=1,
276
+ maximum=50,
277
+ value=4,
278
+ step=1
 
279
  )
280
 
281
+ seed = gr.Number(
282
+ label="Seed",
283
+ value=42,
284
+ minimum=0,
285
+ maximum=999999
286
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
287
 
288
+ with gr.Row():
289
+ width = gr.Slider(
290
+ label="Width",
291
+ minimum=256,
292
+ maximum=1024,
293
+ value=512,
294
+ step=64
295
  )
296
 
297
+ height = gr.Slider(
298
+ label="Height",
299
+ minimum=256,
300
+ maximum=1024,
301
+ value=512,
302
+ step=64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
303
  )
304
 
305
+ num_images = gr.Slider(
306
+ label="Number of Images",
307
+ minimum=1,
308
+ maximum=4,
309
+ value=1,
310
+ step=1
311
  )
312
 
313
+ generate_btn = gr.Button("Generate Images", variant="primary")
 
 
 
 
 
 
314
 
315
+ # Examples
316
+ gr.Examples(
317
+ examples=[
318
+ ["A cyberpunk cityscape with flying cars and neon lights at night", 4, 123, 512, 512, "cyberpunk", 1, 7.5],
319
+ ["A magical dragon in a fantasy landscape, cinematic lighting", 4, 456, 512, 512, "fantasy", 1, 7.5],
320
+ ["Cute anime character with magical powers", 4, 789, 512, 512, "anime", 1, 7.5],
321
+ ["Photorealistic portrait of an astronaut", 6, 999, 768, 512, "photographic", 1, 8.0]
322
+ ],
323
+ inputs=[prompt, num_steps, seed, height, width, style_preset, num_images, guidance_scale],
324
+ label="Try these examples:"
325
+ )
 
 
 
 
 
 
326
 
327
+ with gr.Column(scale=2):
328
+ # Output Section
329
+ status = gr.Textbox(
330
+ label="Status",
331
+ value="Ready to generate..."
332
+ )
333
+
334
+ gallery = gr.Gallery(
335
+ label="Generated Images",
336
+ columns=2,
337
+ height="auto"
338
+ )
339
+
340
+ # Response viewer
341
+ with gr.Accordion("API Response", open=False):
342
+ json_output = gr.JSON(
343
+ label="Response"
344
+ )
345
 
346
+ # Footer
347
+ gr.Markdown("""
348
+ ---
349
+ **Note:** The Pixazo API returns `{"output": "IMAGE_URL"}`, and the app downloads the image from that URL.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
350
 
351
+ Make sure to set `PIXAZO_API_KEY` in your Space secrets for the app to work.
352
+ """)
353
 
354
+ # Connect button to function
355
+ generate_btn.click(
356
+ fn=generate_images,
357
+ inputs=[prompt, num_steps, seed, height, width, style_preset, num_images, guidance_scale],
358
+ outputs=[gallery, status, json_output]
 
359
  )
360
 
361
+ # Launch the app
362
  if __name__ == "__main__":
363
+ print("Starting Pixazo Image Generator...")
364
+ print(f"API Key configured: {'Yes' if get_api_key() else 'No'}")
365
+
366
+ demo.launch(
367
+ server_name="0.0.0.0",
368
+ server_port=7860,
369
+ share=False
370
+ )
requirements.txt CHANGED
@@ -1,3 +1,3 @@
1
- gradio>=4.12.0
2
  pillow>=10.0.0
3
  requests>=2.31.0
 
1
+ gradio>=3.41.0,<4.0.0
2
  pillow>=10.0.0
3
  requests>=2.31.0