scmlewis commited on
Commit
e55ab8a
·
verified ·
1 Parent(s): 8aa68a4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +20 -28
app.py CHANGED
@@ -15,6 +15,7 @@ def generate_edit(prompt, pil_image, api_key, model="gemini-2.0-flash-exp"):
15
  with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp_img:
16
  image_path = tmp_img.name
17
  pil_image.save(image_path)
 
18
  files = [client.files.upload(file=image_path)]
19
  contents = [
20
  types.Content(
@@ -33,8 +34,10 @@ def generate_edit(prompt, pil_image, api_key, model="gemini-2.0-flash-exp"):
33
  response_modalities=["image", "text"],
34
  response_mime_type="text/plain",
35
  )
 
36
  text_response = ""
37
  image_out_path = None
 
38
  with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp_out:
39
  out_path = tmp_out.name
40
  for chunk in client.models.generate_content_stream(
@@ -54,29 +57,24 @@ def generate_edit(prompt, pil_image, api_key, model="gemini-2.0-flash-exp"):
54
  del files
55
  return image_out_path, text_response
56
 
57
- def process_image_and_prompt(pil_image, prompt, api_key, progress_callback=None):
58
  try:
59
- if progress_callback:
60
- progress_callback("Generating…")
61
  image_path, text_out = generate_edit(prompt, pil_image, api_key)
62
  if image_path:
63
  img = Image.open(image_path)
64
  if img.mode == "RGBA":
65
  img = img.convert("RGB")
66
- if progress_callback:
67
- progress_callback("Done ✓")
68
- return img, "Image generated successfully!", None
69
  else:
70
- if progress_callback:
71
- progress_callback("Failed to generate image")
72
- return None, f"⚠️ {text_out.strip()}", None
73
  except Exception as e:
74
- if progress_callback:
75
- progress_callback("Error")
76
- return None, f"❌ Generation failed: {str(e)}", None
77
 
78
  def reset_inputs(api_key_value=None):
79
- return None, "", api_key_value or "", ""
 
80
 
81
  # Styles
82
  css_style = """
@@ -106,10 +104,6 @@ body, .app-container { background: var(--bg); color: var(--text); }
106
  @media (max-width: 1100px) {
107
  .layout-two-col { grid-template-columns: 1fr; }
108
  }
109
- .input-area, .output-area { background: #202533; border-radius: 12px; padding: 12px; }
110
- #status-container { display: flex; flex-direction: column; gap: 6px; padding: 6px; background: #1b1f2b; border-radius: 8px; }
111
- #status-label { font-weight: 700; color: #a6d1ff; }
112
- #status-text { height: 6em; max-height: 8em; overflow: auto; white-space: pre-wrap; word-break: break-word; padding: 6px 8px; border: none; background: transparent; color: #cbd5e1; font-weight: 600; }
113
 
114
  #output-viewport { display: flex; justify-content: center; align-items: center; min-height: 260px; }
115
  #output-image { display: flex; justify-content: center; align-items: center; }
@@ -122,10 +116,11 @@ with gr.Blocks(css=css_style) as app:
122
  <div class='header-block'>
123
  <div class='header-gradient'>
124
  <h1 class='header-title'>🖼️ Image Editor <span style="font-size:1.1em;">(Powered by Gemini)</span> 🔮</h1>
125
- <div class='header-subtitle'>Step-by-step prompts with a persistent status banner and progress feedback</div>
126
  </div>
127
  </div>
128
  """)
 
129
  with gr.Row():
130
  with gr.Column(scale=3, elem_classes="sidebar"):
131
  gr.Markdown(
@@ -158,28 +153,25 @@ with gr.Blocks(css=css_style) as app:
158
  with gr.Row():
159
  submit_btn = gr.Button("Generate Edit", elem_classes="gradient-button")
160
  reset_btn = gr.Button("Reset Inputs")
 
 
161
 
162
- # Status area (enhanced)
163
- with gr.Column():
164
- gr.HTML("<div id='status-container'><div id='status-label'>Status</div></div>")
165
- status_bar = gr.Textbox(label="", interactive=False, lines=6, elem_id="status-text")
166
-
167
- def on_submit(pil_img, prompt, key, progress=None):
168
  if not key or key.strip() == "":
169
  raise gr.Error("Gemini API Key is required!")
170
- img, stat, _ = process_image_and_prompt(pil_img, prompt, key, progress)
171
- return img, stat
172
 
173
  submit_btn.click(
174
  fn=on_submit,
175
  inputs=[image_input, prompt_input, api_key_input],
176
- outputs=[output_image, status_bar]
177
  )
178
 
179
  reset_btn.click(
180
  fn=reset_inputs,
181
  inputs=[api_key_input],
182
- outputs=[image_input, prompt_input, api_key_input, status_bar]
183
  )
184
 
185
  app.launch()
 
15
  with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp_img:
16
  image_path = tmp_img.name
17
  pil_image.save(image_path)
18
+
19
  files = [client.files.upload(file=image_path)]
20
  contents = [
21
  types.Content(
 
34
  response_modalities=["image", "text"],
35
  response_mime_type="text/plain",
36
  )
37
+
38
  text_response = ""
39
  image_out_path = None
40
+
41
  with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp_out:
42
  out_path = tmp_out.name
43
  for chunk in client.models.generate_content_stream(
 
57
  del files
58
  return image_out_path, text_response
59
 
60
+ def process_image_and_prompt(pil_image, prompt, api_key):
61
  try:
 
 
62
  image_path, text_out = generate_edit(prompt, pil_image, api_key)
63
  if image_path:
64
  img = Image.open(image_path)
65
  if img.mode == "RGBA":
66
  img = img.convert("RGB")
67
+ return img # Return only the image on success
 
 
68
  else:
69
+ # If no image generated, raise an error for Gradio popup
70
+ raise gr.Error(f"⚠️ Image generation failed: {text_out.strip() if text_out.strip() else 'No specific error message.'}")
 
71
  except Exception as e:
72
+ # Catch any other exceptions and re-raise as Gradio error
73
+ raise gr.Error(f"❌ Generation failed: {str(e)}")
 
74
 
75
  def reset_inputs(api_key_value=None):
76
+ # Reset all inputs, keeping API key unchanged
77
+ return None, "", api_key_value or ""
78
 
79
  # Styles
80
  css_style = """
 
104
  @media (max-width: 1100px) {
105
  .layout-two-col { grid-template-columns: 1fr; }
106
  }
 
 
 
 
107
 
108
  #output-viewport { display: flex; justify-content: center; align-items: center; min-height: 260px; }
109
  #output-image { display: flex; justify-content: center; align-items: center; }
 
116
  <div class='header-block'>
117
  <div class='header-gradient'>
118
  <h1 class='header-title'>🖼️ Image Editor <span style="font-size:1.1em;">(Powered by Gemini)</span> 🔮</h1>
119
+ <div class='header-subtitle'>Step-by-step prompts for image editing</div>
120
  </div>
121
  </div>
122
  """)
123
+
124
  with gr.Row():
125
  with gr.Column(scale=3, elem_classes="sidebar"):
126
  gr.Markdown(
 
153
  with gr.Row():
154
  submit_btn = gr.Button("Generate Edit", elem_classes="gradient-button")
155
  reset_btn = gr.Button("Reset Inputs")
156
+
157
+ # Note: Status bar elements removed as requested. Errors will now show as Gradio popups.
158
 
159
+ def on_submit(pil_img, prompt, key):
 
 
 
 
 
160
  if not key or key.strip() == "":
161
  raise gr.Error("Gemini API Key is required!")
162
+ # process_image_and_prompt now raises gr.Error directly for failures
163
+ return process_image_and_prompt(pil_img, prompt, key)
164
 
165
  submit_btn.click(
166
  fn=on_submit,
167
  inputs=[image_input, prompt_input, api_key_input],
168
+ outputs=[output_image] # Only output the image
169
  )
170
 
171
  reset_btn.click(
172
  fn=reset_inputs,
173
  inputs=[api_key_input],
174
+ outputs=[image_input, prompt_input, api_key_input] # Remove status_bar from outputs
175
  )
176
 
177
  app.launch()