AkashKumarave commited on
Commit
3380cf2
Β·
verified Β·
1 Parent(s): 45d31c6

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +197 -165
app.py CHANGED
@@ -1,165 +1,197 @@
1
- import os
2
- import tempfile
3
- from PIL import Image
4
- import gradio as gr
5
- import google.generativeai as genai
6
- from io import BytesIO
7
-
8
- # Hardcode the Gemini API key
9
- GEMINI_API_KEY = "AIzaSyDL5Rilo7ptJpUOZdY6wy8PJYUcVcnDADs"
10
-
11
- def configure_api_key():
12
- """Configure the Gemini API key."""
13
- if not GEMINI_API_KEY:
14
- raise gr.Error("Gemini API key is not set.")
15
- genai.configure(api_key=GEMINI_API_KEY)
16
-
17
- def generate(text, images, model="gemini-2.5-flash"):
18
- """Generate content using the Gemini model."""
19
- configure_api_key()
20
-
21
- # Convert images to Gemini-compatible format
22
- contents = []
23
- for img in images:
24
- if img.mode == "RGBA":
25
- img = img.convert("RGB")
26
- contents.append(img)
27
- contents.append(text)
28
-
29
- try:
30
- response = genai.GenerativeModel(model).generate_content(contents)
31
-
32
- text_response = ""
33
- image_path = None
34
-
35
- for part in response.candidates[0].content.parts:
36
- if hasattr(part, 'text') and part.text:
37
- text_response += part.text + "\n"
38
- elif hasattr(part, 'inline_data') and part.inline_data:
39
- # Save generated image to a temporary file
40
- with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
41
- image_path = tmp.name
42
- generated_image = Image.open(BytesIO(part.inline_data.data))
43
- generated_image.save(image_path)
44
- print(f"Generated image saved to: {image_path} with prompt: {text}")
45
-
46
- return image_path, text_response
47
- except Exception as e:
48
- raise gr.Error(f"Error generating content: {str(e)}")
49
-
50
- def load_uploaded_images(uploaded_files):
51
- """Load and display uploaded images immediately."""
52
- uploaded_images = []
53
- if uploaded_files:
54
- for file in uploaded_files:
55
- if file.name.lower().endswith(('.png', '.jpg', '.jpeg', '.webp')):
56
- img = Image.open(file.name)
57
- uploaded_images.append(img)
58
- return uploaded_images
59
-
60
- def process_image_and_prompt(uploaded_files, prompt):
61
- """Process uploaded images and prompt to generate output."""
62
- try:
63
- if not uploaded_files:
64
- raise gr.Error("Please upload at least one image.")
65
- if not prompt:
66
- raise gr.Error("Please provide a prompt.")
67
-
68
- # Load images
69
- images = load_uploaded_images(uploaded_files)
70
-
71
- # Generate content
72
- image_path, text_response = generate(
73
- text=prompt,
74
- images=images
75
- )
76
-
77
- # Prepare outputs
78
- output_images = [Image.open(image_path)] if image_path else None
79
- return images, output_images, text_response
80
- except Exception as e:
81
- raise gr.Error(f"Error: {str(e)}")
82
-
83
- # Gradio interface
84
- with gr.Blocks(css="style.css") as demo:
85
- gr.HTML("""
86
- <div class="header-container">
87
- <div>
88
- <img src="https://www.gstatic.com/lamda/images/gemini_favicon_f069958c85030456e93de685481c559f160ea06b.png" alt="Gemini logo">
89
- </div>
90
- <div>
91
- <h1>Gemini for Image Editing</h1>
92
- <p>Powered by <a href="https://gradio.app/">Gradio</a>⚑️ |
93
- <a href="https://huggingface.co/spaces">Duplicate this Space</a> |
94
- <a href="https://aistudio.google.com/apikey">Learn about Gemini API</a></p>
95
- </div>
96
- </div>
97
- """)
98
-
99
- with gr.Accordion("⚠️ API Configuration ⚠️", open=False):
100
- gr.Markdown("""
101
- - **Note:** The Gemini API is pre-configured for this Space.
102
- - **Issue:** ❗ Sometimes the model returns text instead of an image.
103
- ### πŸ”§ Steps to Address:
104
- 1. **πŸ› οΈ Duplicate the Space**
105
- - Create a copy on Hugging Face Spaces for modifications.
106
- 2. **πŸ”‘ API Key Info**
107
- - The API key is already set up for this demo. For custom deployments, get your own key from Google AI Studio.
108
- """)
109
-
110
- with gr.Accordion("πŸ“Œ Usage Instructions", open=False):
111
- gr.Markdown("""
112
- ### πŸ“Œ Usage
113
- - Upload an image and enter a prompt to generate outputs.
114
- - If text is returned instead of an image, it will appear in the text output.
115
- - Supported formats: PNG, JPG, JPEG, WEBP
116
- - ❌ **Do not use NSFW images!**
117
- """)
118
-
119
- with gr.Row():
120
- with gr.Column():
121
- image_input = gr.File(
122
- file_types=["image"],
123
- file_count="multiple",
124
- label="Upload Images"
125
- )
126
- prompt_input = gr.Textbox(
127
- lines=2,
128
- placeholder="Enter prompt here...",
129
- label="Prompt"
130
- )
131
- submit_btn = gr.Button("Generate")
132
-
133
- with gr.Column():
134
- uploaded_gallery = gr.Gallery(label="Uploaded Images")
135
- output_gallery = gr.Gallery(label="Generated Outputs")
136
- output_text = gr.Textbox(
137
- label="Gemini Output",
138
- placeholder="Text response will appear here if no image is generated."
139
- )
140
-
141
- submit_btn.click(
142
- fn=process_image_and_prompt,
143
- inputs=[image_input, prompt_input],
144
- outputs=[uploaded_gallery, output_gallery, output_text]
145
- )
146
-
147
- image_input.upload(
148
- fn=load_uploaded_images,
149
- inputs=[image_input],
150
- outputs=[uploaded_gallery]
151
- )
152
-
153
- gr.Markdown("## Try these examples")
154
- examples = [
155
- ["data/1.webp", "change text to 'HUGGINGFACE'"],
156
- ["data/2.webp", "remove the spoon from hand only"],
157
- ["data/3.webp", "change text to 'AI POWERED'"],
158
- ["data/1.jpg", "add futuristic style to background"],
159
- ]
160
- gr.Examples(
161
- examples=examples,
162
- inputs=[image_input, prompt_input]
163
- )
164
-
165
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+ import time
4
+ import uuid
5
+ import tempfile
6
+ from PIL import Image, ImageDraw, ImageFont
7
+ import gradio as gr
8
+ import base64
9
+ import mimetypes
10
+ from io import BytesIO
11
+
12
+ from google import genai
13
+ from google.genai import types
14
+
15
+ def generate(text, images, api_key, model="gemini-2.5-flash-image-preview"):
16
+ # Initialize client using provided api_key (or fallback to env variable)
17
+ client = genai.Client(api_key=(api_key.strip() if api_key and api_key.strip() != ""
18
+ else os.environ.get("GEMINI_API_KEY")))
19
+
20
+ # Prepare contents with images first, then text
21
+ contents = images + [text]
22
+
23
+ response = client.models.generate_content(
24
+ model=model,
25
+ contents=contents,
26
+ )
27
+
28
+ text_response = ""
29
+ image_path = None
30
+
31
+ for part in response.candidates[0].content.parts:
32
+ if part.text is not None:
33
+ text_response += part.text + "\n"
34
+ elif part.inline_data is not None:
35
+ # Create a temporary file to store the generated image
36
+ with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
37
+ temp_path = tmp.name
38
+ generated_image = Image.open(BytesIO(part.inline_data.data))
39
+ generated_image.save(temp_path)
40
+ image_path = temp_path
41
+ print(f"Generated image saved to: {temp_path} with prompt: {text}")
42
+
43
+ return image_path, text_response
44
+
45
+ def load_uploaded_images(uploaded_files):
46
+ """Load and display uploaded images immediately"""
47
+ uploaded_images = []
48
+ if uploaded_files:
49
+ for file in uploaded_files:
50
+ if file.name.lower().endswith(('.png', '.jpg', '.jpeg', '.webp')):
51
+ img = Image.open(file.name)
52
+ if img.mode == "RGBA":
53
+ img = img.convert("RGBA")
54
+ uploaded_images.append(img)
55
+ return uploaded_images
56
+
57
+ def process_image_and_prompt(uploaded_files, prompt, gemini_api_key):
58
+ try:
59
+ input_text = prompt
60
+ model = "gemini-2.5-flash-image-preview"
61
+
62
+ # Load images from uploaded files
63
+ images = []
64
+ uploaded_images = []
65
+ if uploaded_files:
66
+ for file in uploaded_files:
67
+ if file.name.lower().endswith(('.png', '.jpg', '.jpeg', '.webp')):
68
+ img = Image.open(file.name)
69
+ if img.mode == "RGBA":
70
+ img = img.convert("RGBA")
71
+ images.append(img)
72
+ uploaded_images.append(img)
73
+
74
+ if not images:
75
+ raise gr.Error("Please upload at least one image", duration=5)
76
+
77
+ # Format: [dress_image, model_image, text_input] or [image1, image2, ..., text_input]
78
+ image_path, text_response = generate(text=input_text, images=images, api_key=gemini_api_key, model=model)
79
+
80
+ if image_path:
81
+ # Load and convert the image if needed.
82
+ result_img = Image.open(image_path)
83
+ if result_img.mode == "RGBA":
84
+ result_img = result_img.convert("RGBA")
85
+ return uploaded_images, [result_img], "" # Return uploaded images, generated image, and empty text output.
86
+ else:
87
+ # Return uploaded images, no generated image, and the text response.
88
+ return uploaded_images, None, text_response
89
+ except Exception as e:
90
+ raise gr.Error(f"Error Getting {e}", duration=5)
91
+
92
+
93
+ # Build a Blocks-based interface with a custom HTML header and CSS
94
+ with gr.Blocks(css_paths="style.css",) as demo:
95
+ # Custom HTML header with proper class for styling
96
+ gr.HTML(
97
+ """
98
+ <div class="header-container">
99
+ <div>
100
+ <img src="https://www.gstatic.com/lamda/images/gemini_favicon_f069958c85030456e93de685481c559f160ea06b.png" alt="Gemini logo">
101
+ </div>
102
+ <div>
103
+ <h1>Gemini for Image Editing</h1>
104
+ <p>Powered by <a href="https://gradio.app/">Gradio</a>⚑️|
105
+ <a href="https://huggingface.co/spaces/ameerazam08/Gemini-Image-Edit?duplicate=true">Duplicate</a> this Repo |
106
+ <a href="https://aistudio.google.com/apikey">Get an API Key</a> |
107
+ Follow me on Twitter: <a href="https://x.com/Ameerazam18">Ameerazam18</a></p>
108
+ </div>
109
+ </div>
110
+ """
111
+ )
112
+
113
+ with gr.Accordion("⚠️ API Configuration ⚠️", open=False, elem_classes="config-accordion"):
114
+ gr.Markdown("""
115
+ - **Issue:** ❗ Sometimes the model returns text instead of an image.
116
+ ### πŸ”§ Steps to Address:
117
+ 1. **πŸ› οΈ Duplicate the Repository**
118
+ - Create a separate copy for modifications.
119
+ 2. **πŸ”‘ Use Your Own Gemini API Key**
120
+ - You **must** configure your own Gemini key for generation!
121
+ """)
122
+
123
+ with gr.Accordion("πŸ“Œ Usage Instructions", open=False, elem_classes="instructions-accordion"):
124
+ gr.Markdown("""
125
+ ### πŸ“Œ Usage
126
+ - Upload an image and enter a prompt to generate outputs.
127
+ - If text is returned instead of an image, it will appear in the text output.
128
+ - Upload Only PNG Image
129
+ - ❌ **Do not use NSFW images!**
130
+ """)
131
+
132
+ with gr.Row(elem_classes="main-content"):
133
+ with gr.Column(elem_classes="input-column"):
134
+ image_input = gr.File(
135
+ file_types=["image"],
136
+ file_count="multiple",
137
+ label="Upload Images ",
138
+ elem_id="image-input",
139
+ elem_classes="upload-box"
140
+ )
141
+ gemini_api_key = gr.Textbox(
142
+ lines=1,
143
+ placeholder="Enter Gemini API Key (optional)",
144
+ label="Gemini API Key (optional)",
145
+ elem_classes="api-key-input"
146
+ )
147
+ prompt_input = gr.Textbox(
148
+ lines=2,
149
+ placeholder="Enter prompt here...",
150
+ label="Prompt",
151
+ elem_classes="prompt-input"
152
+ )
153
+ submit_btn = gr.Button("Generate", elem_classes="generate-btn")
154
+
155
+ with gr.Column(elem_classes="output-column"):
156
+ uploaded_gallery = gr.Gallery(label="Uploaded Images", elem_classes="uploaded-gallery")
157
+ output_gallery = gr.Gallery(label="Generated Outputs", elem_classes="output-gallery")
158
+ output_text = gr.Textbox(
159
+ label="Gemini Output",
160
+ placeholder="Text response will appear here if no image is generated.",
161
+ elem_classes="output-text"
162
+ )
163
+
164
+ # Set up the interaction with three outputs.
165
+ submit_btn.click(
166
+ fn=process_image_and_prompt,
167
+ inputs=[image_input, prompt_input, gemini_api_key],
168
+ outputs=[uploaded_gallery, output_gallery, output_text],
169
+ )
170
+
171
+ # Update uploaded gallery immediately when files are uploaded
172
+ image_input.upload(
173
+ fn=load_uploaded_images,
174
+ inputs=[image_input],
175
+ outputs=[uploaded_gallery],
176
+ )
177
+
178
+ gr.Markdown("## Try these examples", elem_classes="gr-examples-header")
179
+
180
+ examples = [
181
+ ["data/1.webp", 'change text to "AMEER"'],
182
+ ["data/2.webp", "remove the spoon from hand only"],
183
+ ["data/3.webp", 'change text to "Make it "'],
184
+ ["data/1.jpg", "add joker style only on face"],
185
+ ["data/1777043.jpg", "add joker style only on face"],
186
+ ["data/2807615.jpg", "add lipstick on lip only"],
187
+ ["data/76860.jpg", "add lipstick on lip only"],
188
+ ["data/2807615.jpg", "make it happy looking face only"],
189
+ ]
190
+
191
+ gr.Examples(
192
+ examples=examples,
193
+ inputs=[image_input, prompt_input,],
194
+ elem_id="examples-grid"
195
+ )
196
+
197
+ demo.queue(max_size=50).launch(mcp_server=True, share=True)