Files changed (2) hide show
  1. README.md +3 -1
  2. app-BACKUP.py +337 -0
README.md CHANGED
@@ -4,9 +4,11 @@ emoji: ๐Ÿš€
4
  colorFrom: green
5
  colorTo: gray
6
  sdk: gradio
7
- sdk_version: 5.44.1
8
  app_file: app.py
9
  pinned: false
10
  license: mit
11
  short_description: Free 'Nano Banana' Officail version
12
  ---
 
 
 
4
  colorFrom: green
5
  colorTo: gray
6
  sdk: gradio
7
+ sdk_version: 5.44.0
8
  app_file: app.py
9
  pinned: false
10
  license: mit
11
  short_description: Free 'Nano Banana' Officail version
12
  ---
13
+
14
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app-BACKUP.py ADDED
@@ -0,0 +1,337 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import replicate
3
+ import os
4
+ from PIL import Image
5
+ import requests
6
+ from io import BytesIO
7
+ import time
8
+ import tempfile
9
+ import base64
10
+
11
+ # Set up Replicate API key from environment variable
12
+ os.environ['REPLICATE_API_TOKEN'] = os.getenv('REPLICATE_API_TOKEN')
13
+
14
+ def upload_image_to_hosting(image):
15
+ """
16
+ Upload image to multiple hosting services with fallback
17
+ """
18
+ # Method 1: Try imgbb.com (most reliable)
19
+ try:
20
+ buffered = BytesIO()
21
+ image.save(buffered, format="PNG")
22
+ buffered.seek(0)
23
+ img_base64 = base64.b64encode(buffered.getvalue()).decode()
24
+
25
+ response = requests.post(
26
+ "https://api.imgbb.com/1/upload",
27
+ data={
28
+ 'key': '6d207e02198a847aa98d0a2a901485a5',
29
+ 'image': img_base64,
30
+ }
31
+ )
32
+
33
+ if response.status_code == 200:
34
+ data = response.json()
35
+ if data.get('success'):
36
+ return data['data']['url']
37
+ except:
38
+ pass
39
+
40
+ # Method 2: Try 0x0.st (simple and reliable)
41
+ try:
42
+ buffered = BytesIO()
43
+ image.save(buffered, format="PNG")
44
+ buffered.seek(0)
45
+
46
+ files = {'file': ('image.png', buffered, 'image/png')}
47
+ response = requests.post("https://0x0.st", files=files)
48
+
49
+ if response.status_code == 200:
50
+ return response.text.strip()
51
+ except:
52
+ pass
53
+
54
+ # Method 3: Fallback to base64
55
+ buffered = BytesIO()
56
+ image.save(buffered, format="PNG")
57
+ buffered.seek(0)
58
+ img_base64 = base64.b64encode(buffered.getvalue()).decode()
59
+ return f"data:image/png;base64,{img_base64}"
60
+
61
+ def process_images(prompt, image1, image2=None):
62
+ """
63
+ Process uploaded images with Replicate API
64
+ """
65
+ if not image1:
66
+ return None, "Please upload at least one image"
67
+
68
+ if not os.getenv('REPLICATE_API_TOKEN'):
69
+ return None, "Please set REPLICATE_API_TOKEN"
70
+
71
+ try:
72
+ image_urls = []
73
+
74
+ # Upload images
75
+ url1 = upload_image_to_hosting(image1)
76
+ image_urls.append(url1)
77
+
78
+ if image2:
79
+ url2 = upload_image_to_hosting(image2)
80
+ image_urls.append(url2)
81
+
82
+ # Run the model
83
+ output = replicate.run(
84
+ "google/nano-banana",
85
+ input={
86
+ "prompt": prompt,
87
+ "image_input": image_urls
88
+ }
89
+ )
90
+
91
+ if output is None:
92
+ return None, "No output received"
93
+
94
+ # Get the generated image
95
+ try:
96
+ if hasattr(output, 'read'):
97
+ img_data = output.read()
98
+ img = Image.open(BytesIO(img_data))
99
+ return img, "โœจ Generated successfully!"
100
+ except:
101
+ pass
102
+
103
+ try:
104
+ if hasattr(output, 'url'):
105
+ output_url = output.url()
106
+ response = requests.get(output_url, timeout=30)
107
+ if response.status_code == 200:
108
+ img = Image.open(BytesIO(response.content))
109
+ return img, "โœจ Generated successfully!"
110
+ except:
111
+ pass
112
+
113
+ output_url = None
114
+ if isinstance(output, str):
115
+ output_url = output
116
+ elif isinstance(output, list) and len(output) > 0:
117
+ output_url = output[0]
118
+
119
+ if output_url:
120
+ response = requests.get(output_url, timeout=30)
121
+ if response.status_code == 200:
122
+ img = Image.open(BytesIO(response.content))
123
+ return img, "โœจ Generated successfully!"
124
+
125
+ return None, "Could not process output"
126
+
127
+ except Exception as e:
128
+ return None, f"Error: {str(e)[:100]}"
129
+
130
+ # Enhanced CSS with modern, minimal design
131
+ css = """
132
+ .gradio-container {
133
+ background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
134
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
135
+ min-height: 100vh;
136
+ }
137
+ .header-container {
138
+ background: linear-gradient(135deg, #ffd93d 0%, #ffb347 100%);
139
+ padding: 2.5rem;
140
+ border-radius: 24px;
141
+ margin-bottom: 2.5rem;
142
+ box-shadow: 0 20px 60px rgba(255, 179, 71, 0.25);
143
+ }
144
+ .logo-text {
145
+ font-size: 3.5rem;
146
+ font-weight: 900;
147
+ color: #2d3436;
148
+ text-align: center;
149
+ margin: 0;
150
+ letter-spacing: -2px;
151
+ }
152
+ .subtitle {
153
+ color: #2d3436;
154
+ text-align: center;
155
+ font-size: 1rem;
156
+ margin-top: 0.5rem;
157
+ opacity: 0.8;
158
+ }
159
+ .main-content {
160
+ background: rgba(255, 255, 255, 0.95);
161
+ backdrop-filter: blur(20px);
162
+ border-radius: 24px;
163
+ padding: 2.5rem;
164
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.08);
165
+ }
166
+ .gr-button-primary {
167
+ background: linear-gradient(135deg, #ffd93d 0%, #ffb347 100%) !important;
168
+ border: none !important;
169
+ color: #2d3436 !important;
170
+ font-weight: 700 !important;
171
+ font-size: 1.1rem !important;
172
+ padding: 1.2rem 2rem !important;
173
+ border-radius: 14px !important;
174
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
175
+ text-transform: uppercase;
176
+ letter-spacing: 1px;
177
+ width: 100%;
178
+ margin-top: 1rem !important;
179
+ }
180
+ .gr-button-primary:hover {
181
+ transform: translateY(-3px) !important;
182
+ box-shadow: 0 15px 40px rgba(255, 179, 71, 0.35) !important;
183
+ }
184
+ .gr-input, .gr-textarea {
185
+ background: #ffffff !important;
186
+ border: 2px solid #e1e8ed !important;
187
+ border-radius: 14px !important;
188
+ color: #2d3436 !important;
189
+ font-size: 1rem !important;
190
+ padding: 0.8rem 1rem !important;
191
+ }
192
+ .gr-input:focus, .gr-textarea:focus {
193
+ border-color: #ffd93d !important;
194
+ box-shadow: 0 0 0 4px rgba(255, 217, 61, 0.15) !important;
195
+ }
196
+ .gr-form {
197
+ background: transparent !important;
198
+ border: none !important;
199
+ }
200
+ .gr-panel {
201
+ background: #ffffff !important;
202
+ border: 2px solid #e1e8ed !important;
203
+ border-radius: 16px !important;
204
+ padding: 1.5rem !important;
205
+ }
206
+ .gr-box {
207
+ border-radius: 14px !important;
208
+ border-color: #e1e8ed !important;
209
+ }
210
+ label {
211
+ color: #636e72 !important;
212
+ font-weight: 600 !important;
213
+ font-size: 0.85rem !important;
214
+ text-transform: uppercase;
215
+ letter-spacing: 0.5px;
216
+ margin-bottom: 0.5rem !important;
217
+ }
218
+ .status-text {
219
+ font-family: 'SF Mono', 'Monaco', monospace;
220
+ color: #00b894;
221
+ font-size: 0.9rem;
222
+ }
223
+ .image-container {
224
+ border-radius: 14px !important;
225
+ overflow: hidden;
226
+ border: 2px solid #e1e8ed !important;
227
+ background: #fafbfc !important;
228
+ }
229
+ footer {
230
+ display: none !important;
231
+ }
232
+ /* Equal sizing for all image containers */
233
+ .image-upload {
234
+ min-height: 200px !important;
235
+ max-height: 200px !important;
236
+ }
237
+ .output-image {
238
+ min-height: 420px !important;
239
+ max-height: 420px !important;
240
+ }
241
+ /* Ensure consistent spacing */
242
+ .gr-row {
243
+ gap: 1rem !important;
244
+ }
245
+ .gr-column {
246
+ gap: 1rem !important;
247
+ }
248
+ """
249
+
250
+ with gr.Blocks(css=css, theme=gr.themes.Base()) as demo:
251
+ with gr.Column(elem_classes="header-container"):
252
+ gr.HTML("""
253
+ <h1 class="logo-text">๐ŸŒ Free Nano Banana</h1>
254
+ <p class="subtitle">AI-Powered Image Style Transfer</p>
255
+ <div style="display: flex; justify-content: center; align-items: center; gap: 10px; margin-top: 20px;">
256
+
257
+ <a href="https://huggingface.co/spaces/ginigen/Nano-Banana-PRO" target="_blank">
258
+ <img src="https://img.shields.io/static/v1?label=NANO%20BANANA&message=PRO&color=%230000ff&labelColor=%23800080&logo=HUGGINGFACE&logoColor=white&style=for-the-badge" alt="badge">
259
+ </a>
260
+ <a href="https://huggingface.co/spaces/openfree/Nano-Banana-Upscale" target="_blank">
261
+ <img src="https://img.shields.io/static/v1?label=NANO%20BANANA&message=UPSCALE&color=%230000ff&labelColor=%23800080&logo=GOOGLE&logoColor=white&style=for-the-badge" alt="Nano Banana Upscale">
262
+ </a>
263
+ <a href="https://huggingface.co/spaces/aiqtech/Nano-Banana-API" target="_blank">
264
+ <img src="https://img.shields.io/static/v1?label=NANO%20BANANA&message=API&color=%230000ff&labelColor=%23800080&logo=GOOGLE&logoColor=white&style=for-the-badge" alt="Nano Banana API">
265
+ </a>
266
+ <a href="https://huggingface.co/spaces/ginigen/Nano-Banana-Video" target="_blank">
267
+ <img src="https://img.shields.io/static/v1?label=NANO%20BANANA&message=VIDEO&color=%230000ff&labelColor=%23800080&logo=GOOGLE&logoColor=white&style=for-the-badge" alt="Nano Banana VIDEO">
268
+ </a>
269
+ <a href="https://discord.gg/openfreeai" target="_blank">
270
+ <img src="https://img.shields.io/static/v1?label=Discord&message=Openfree%20AI&color=%230000ff&labelColor=%23800080&logo=discord&logoColor=white&style=for-the-badge" alt="Discord Openfree AI">
271
+ </a>
272
+ </div>
273
+ """)
274
+
275
+ with gr.Column(elem_classes="main-content"):
276
+ with gr.Row(equal_height=True):
277
+ # Left Column - Inputs
278
+ with gr.Column(scale=1):
279
+ prompt = gr.Textbox(
280
+ label="Style Description",
281
+ placeholder="Describe your style...",
282
+ lines=3,
283
+ value="Make the sheets in the style of the logo. Make the scene natural.",
284
+ elem_classes="prompt-input"
285
+ )
286
+
287
+ with gr.Row(equal_height=True):
288
+ image1 = gr.Image(
289
+ label="Primary Image",
290
+ type="pil",
291
+ height=200,
292
+ elem_classes="image-container image-upload"
293
+ )
294
+ image2 = gr.Image(
295
+ label="Secondary Image",
296
+ type="pil",
297
+ height=200,
298
+ elem_classes="image-container image-upload"
299
+ )
300
+
301
+ generate_btn = gr.Button(
302
+ "Generate Magic โœจ",
303
+ variant="primary",
304
+ size="lg"
305
+ )
306
+
307
+ # Right Column - Output
308
+ with gr.Column(scale=1):
309
+ output_image = gr.Image(
310
+ label="Generated Result",
311
+ type="pil",
312
+ height=420,
313
+ elem_classes="image-container output-image"
314
+ )
315
+
316
+ status = gr.Textbox(
317
+ label="Status",
318
+ interactive=False,
319
+ lines=1,
320
+ elem_classes="status-text",
321
+ value="Ready to generate..."
322
+ )
323
+
324
+ # Event handler
325
+ generate_btn.click(
326
+ fn=process_images,
327
+ inputs=[prompt, image1, image2],
328
+ outputs=[output_image, status]
329
+ )
330
+
331
+ # Launch
332
+ if __name__ == "__main__":
333
+ demo.launch(
334
+ share=True,
335
+ server_name="0.0.0.0",
336
+ server_port=7860
337
+ )