nemoooooooooo commited on
Commit
30d2e0f
Β·
1 Parent(s): 9ee643a
.gitattributes CHANGED
@@ -33,3 +33,6 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ *.jpg filter=lfs diff=lfs merge=lfs -text
37
+ *.png filter=lfs diff=lfs merge=lfs -text
38
+ *.jpeg filter=lfs diff=lfs merge=lfs -text
Assets/examples/1_print.jpg ADDED

Git LFS Details

  • SHA256: d050b0d484acc4d41a338e1bd715b82517e37286d77ca93d1458a8635c2e63a9
  • Pointer size: 131 Bytes
  • Size of remote file: 439 kB
Assets/examples/1_product.jpg ADDED

Git LFS Details

  • SHA256: 3f6d5d9ffe9b46cff61536d79ccba5f867d8baad12bd9db0c5d6daaddabec6c0
  • Pointer size: 130 Bytes
  • Size of remote file: 66.5 kB
Assets/examples/1_result.jpg ADDED

Git LFS Details

  • SHA256: cb94c749eb1746fb28580869853095b09d0c90c71f260e159a07d1f4422acf53
  • Pointer size: 131 Bytes
  • Size of remote file: 410 kB
Assets/examples/2_print.jpg ADDED

Git LFS Details

  • SHA256: cb9e46b56f34d30c02df079703b29479d6b6472342798ad0ff15ff742a7c57b8
  • Pointer size: 130 Bytes
  • Size of remote file: 24.3 kB
Assets/examples/2_product.jpg ADDED

Git LFS Details

  • SHA256: 710374e761ccbe71e9ed45875b45ce0d6b42a9ece16d9562c4a824c35bbd83c8
  • Pointer size: 130 Bytes
  • Size of remote file: 33.9 kB
Assets/examples/2_result.jpg ADDED

Git LFS Details

  • SHA256: 7504900165d688e88e49397c05783853aed3201e9f9f145033651db985113b26
  • Pointer size: 131 Bytes
  • Size of remote file: 204 kB
Assets/examples/3_print.jpg ADDED

Git LFS Details

  • SHA256: 4f4c745ac65e5c1e97dd3a9788ee2e09b26f76db46f685d10a54cccb4957258f
  • Pointer size: 131 Bytes
  • Size of remote file: 187 kB
Assets/examples/3_product.jpg ADDED

Git LFS Details

  • SHA256: 2d9c3b7082832f6129b92f9a1d82e6141af0b2adfb3dca52de15e7ec08e1dde1
  • Pointer size: 131 Bytes
  • Size of remote file: 133 kB
Assets/examples/3_result.jpg ADDED

Git LFS Details

  • SHA256: 73d1ade2d37a4b84d01f62db766a4b3b6712110da12dc334c3f25f13438af79e
  • Pointer size: 131 Bytes
  • Size of remote file: 904 kB
Assets/examples/4_print.jpg ADDED

Git LFS Details

  • SHA256: 3165871a3a54f6d7231c46715ef9bdd6703d63be1acfe4759102806092eeec5f
  • Pointer size: 131 Bytes
  • Size of remote file: 106 kB
Assets/examples/4_product.jpg ADDED

Git LFS Details

  • SHA256: fd08af362d0e2dc5e072d51573567194b3a03ef0263a9b6fcd572d11a95587e8
  • Pointer size: 130 Bytes
  • Size of remote file: 85 kB
Assets/examples/4_result.jpg ADDED

Git LFS Details

  • SHA256: e11374662652bacf89297939dee1607a47c1c4c10d22880981f31e5f85839488
  • Pointer size: 130 Bytes
  • Size of remote file: 79.7 kB
Assets/examples/color/1_print.jpg ADDED

Git LFS Details

  • SHA256: 2725b0d75b729348dce0b314d63039e13e85cb2d35f5bd09538663c79b333b4f
  • Pointer size: 130 Bytes
  • Size of remote file: 12.9 kB
Assets/examples/color/1_product.jpg ADDED

Git LFS Details

  • SHA256: bfcfcad894e89ad6dd11527a02a0bfbcb020718ff67c584ce594707c51b38645
  • Pointer size: 130 Bytes
  • Size of remote file: 52.9 kB
Assets/examples/color/1_result.jpg ADDED

Git LFS Details

  • SHA256: 56ff69b49b40459d49491a8f287db27017574934c8849bde8a32ad617a1445dc
  • Pointer size: 131 Bytes
  • Size of remote file: 209 kB
Assets/examples/color/2_print.jpg ADDED

Git LFS Details

  • SHA256: 124c9708e1e70dd5c73bc268190c2b96630c7d1ace45c5e9aa04da12de62424b
  • Pointer size: 130 Bytes
  • Size of remote file: 12.9 kB
Assets/examples/color/2_product.jpg ADDED

Git LFS Details

  • SHA256: 73c3dd496959ec310a4aa0fcef19c003fdce1e185b6e985c9b0d0f3880294ee4
  • Pointer size: 130 Bytes
  • Size of remote file: 72.8 kB
Assets/examples/color/2_result.jpg ADDED

Git LFS Details

  • SHA256: 43661a7285833361c1da74d00fb11d444795ed0644e3a4d6c39b398e7e275ded
  • Pointer size: 131 Bytes
  • Size of remote file: 210 kB
Assets/examples/color/3_print.jpg ADDED

Git LFS Details

  • SHA256: d0b4c94ceddf870710a5db816fb748a921ae67a93e20b7c88476c92895ea1118
  • Pointer size: 130 Bytes
  • Size of remote file: 10.9 kB
Assets/examples/color/3_product.jpg ADDED

Git LFS Details

  • SHA256: fd08af362d0e2dc5e072d51573567194b3a03ef0263a9b6fcd572d11a95587e8
  • Pointer size: 130 Bytes
  • Size of remote file: 85 kB
Assets/examples/color/3_result.jpg ADDED

Git LFS Details

  • SHA256: ed5ad63f0f16103fd2660862fa048c275bd14edf41808db1854e23909cea9d71
  • Pointer size: 131 Bytes
  • Size of remote file: 274 kB
Assets/print/1.1.jpg ADDED

Git LFS Details

  • SHA256: 60388d6364ebb85044fb4a21f7d4a1b78eb4ee5f37be40868678679ae7693c38
  • Pointer size: 131 Bytes
  • Size of remote file: 554 kB
Assets/print/10.1.jpg ADDED

Git LFS Details

  • SHA256: 2725b0d75b729348dce0b314d63039e13e85cb2d35f5bd09538663c79b333b4f
  • Pointer size: 130 Bytes
  • Size of remote file: 12.9 kB
Assets/print/2.1.jpg ADDED

Git LFS Details

  • SHA256: 35ce4960e120adacdbceafa0b0a25087923cf3c13ee7dee7632a78b9663fe631
  • Pointer size: 130 Bytes
  • Size of remote file: 81.7 kB
Assets/print/3.1.jpg ADDED

Git LFS Details

  • SHA256: cb9e46b56f34d30c02df079703b29479d6b6472342798ad0ff15ff742a7c57b8
  • Pointer size: 130 Bytes
  • Size of remote file: 24.3 kB
Assets/print/4.1.jpg ADDED

Git LFS Details

  • SHA256: de25637d6823ed4e443021c3c3b4722a745e7f09dc6a17d1ba0b0bb73b07b7f5
  • Pointer size: 131 Bytes
  • Size of remote file: 302 kB
Assets/print/5.1.jpg ADDED

Git LFS Details

  • SHA256: 20c8aadc7d323c7ef4110cbb0f3ba764814483b0dda67895595102301f23b1f0
  • Pointer size: 131 Bytes
  • Size of remote file: 171 kB
Assets/print/6.1.jpg ADDED

Git LFS Details

  • SHA256: e140bc40bade47d4316bd97fee8302615f6eff069d05b14e1b395acbb439dcef
  • Pointer size: 130 Bytes
  • Size of remote file: 12.9 kB
Assets/print/7.1.jpg ADDED

Git LFS Details

  • SHA256: 6a3d3e983555bafeb5aa54a4ef2ae9dcb35c082dd0c23ba0898d79b5f47034bf
  • Pointer size: 131 Bytes
  • Size of remote file: 201 kB
Assets/print/8.1.jpg ADDED

Git LFS Details

  • SHA256: 58448301f60c4a5cdfba371757fffa76f6f6bc81b1c0bab09d4a29212a1d3315
  • Pointer size: 131 Bytes
  • Size of remote file: 196 kB
Assets/print/9.1.jpg ADDED

Git LFS Details

  • SHA256: 124c9708e1e70dd5c73bc268190c2b96630c7d1ace45c5e9aa04da12de62424b
  • Pointer size: 130 Bytes
  • Size of remote file: 12.9 kB
Assets/product/1.jpg ADDED

Git LFS Details

  • SHA256: 710374e761ccbe71e9ed45875b45ce0d6b42a9ece16d9562c4a824c35bbd83c8
  • Pointer size: 130 Bytes
  • Size of remote file: 33.9 kB
Assets/product/10.jpg ADDED

Git LFS Details

  • SHA256: 73c3dd496959ec310a4aa0fcef19c003fdce1e185b6e985c9b0d0f3880294ee4
  • Pointer size: 130 Bytes
  • Size of remote file: 72.8 kB
Assets/product/11.jpg ADDED

Git LFS Details

  • SHA256: bfcfcad894e89ad6dd11527a02a0bfbcb020718ff67c584ce594707c51b38645
  • Pointer size: 130 Bytes
  • Size of remote file: 52.9 kB
Assets/product/12.jpg ADDED

Git LFS Details

  • SHA256: 3f6d5d9ffe9b46cff61536d79ccba5f867d8baad12bd9db0c5d6daaddabec6c0
  • Pointer size: 130 Bytes
  • Size of remote file: 66.5 kB
Assets/product/2.jpg ADDED

Git LFS Details

  • SHA256: 7941af55b38218e50ed3be5971618064d99594bfae0a980b3a5ea1f76a1c0d2f
  • Pointer size: 130 Bytes
  • Size of remote file: 44.7 kB
Assets/product/3.jpg ADDED

Git LFS Details

  • SHA256: 6b9dc1bb2f09e0808480ca5be2eb3bbdb437523c264192c234550b4bafd7aa14
  • Pointer size: 130 Bytes
  • Size of remote file: 29.8 kB
Assets/product/4.jpg ADDED

Git LFS Details

  • SHA256: 53d6bac5460227627940261ab8e86c686e13b73656348a3e518419869c4a5147
  • Pointer size: 130 Bytes
  • Size of remote file: 51.5 kB
Assets/product/6.jpg ADDED

Git LFS Details

  • SHA256: b85ff0c753eee9c762590c8e0fd9b948b1f47e544ee9a4e3100c9308ea887900
  • Pointer size: 131 Bytes
  • Size of remote file: 505 kB
Assets/product/8.jpg ADDED

Git LFS Details

  • SHA256: c77b22f3d17fae40bb56ba89905d313af46dd6f717937552a762b2e2bff8603f
  • Pointer size: 130 Bytes
  • Size of remote file: 95.5 kB
Assets/product/9.jpg ADDED

Git LFS Details

  • SHA256: 5d05fce5be8340256ccd9f502ea2e61bd441b12d803fb1838468f54742d94df6
  • Pointer size: 130 Bytes
  • Size of remote file: 96 kB
README.md CHANGED
@@ -1,8 +1,8 @@
1
  ---
2
  title: Snapwear Texture Transfer
3
- emoji: 😻
4
- colorFrom: green
5
- colorTo: green
6
  sdk: gradio
7
  sdk_version: 5.31.0
8
  app_file: app.py
 
1
  ---
2
  title: Snapwear Texture Transfer
3
+ emoji: 🎨✨
4
+ colorFrom: red
5
+ colorTo: yellow
6
  sdk: gradio
7
  sdk_version: 5.31.0
8
  app_file: app.py
app.py ADDED
@@ -0,0 +1,532 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import io
3
+ import base64
4
+ import time
5
+ import gradio as gr
6
+ from PIL import Image
7
+ import logging
8
+ import numpy as np
9
+ from gradio_client import Client
10
+ import json
11
+
12
+ # Setup logging
13
+ logging.basicConfig(level=logging.INFO)
14
+ logger = logging.getLogger(__name__)
15
+
16
+ # ───────── Backend connection ─────────
17
+ HF_TOKEN = os.getenv("HF_TOKEN")
18
+ if not HF_TOKEN:
19
+ raise ValueError("HF_TOKEN environment variable is required")
20
+
21
+ # Try to connect to backend
22
+ try:
23
+ client = Client("SnapwearAI/Pattern-Transfer-Backend", hf_token=HF_TOKEN)
24
+ logger.info("βœ… Backend client established")
25
+ backend_connected = True
26
+ except Exception as e:
27
+ logger.warning(f"⚠️ Backend connection failed: {e}")
28
+ client = None
29
+ backend_connected = False
30
+
31
+ # ───────── Styling ─────────
32
+ css = """
33
+ body, .gradio-container {
34
+ font-family: 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;
35
+ }
36
+ #col-left, #col-mid, #col-right {
37
+ margin: 0 auto;
38
+ max-width: 400px;
39
+ }
40
+ #col-showcase {
41
+ margin: 0 auto;
42
+ max-width: 1200px;
43
+ }
44
+ #button {
45
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
46
+ color: #ffffff;
47
+ font-weight: 600;
48
+ font-size: 16px;
49
+ border: none;
50
+ border-radius: 12px;
51
+ padding: 12px 24px;
52
+ transition: all 0.3s ease;
53
+ }
54
+ #button:hover {
55
+ transform: translateY(-2px);
56
+ box-shadow: 0 8px 25px rgba(102,126,234,0.3);
57
+ }
58
+ #button:disabled {
59
+ background: #ccc !important;
60
+ cursor: not-allowed;
61
+ transform: none;
62
+ box-shadow: none;
63
+ }
64
+ .hero-section {
65
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
66
+ color: white;
67
+ padding: 40px 20px;
68
+ border-radius: 20px;
69
+ margin: 20px 0;
70
+ text-align: center;
71
+ }
72
+ .feature-box {
73
+ background: #f8fafc;
74
+ border: 1px solid #e2e8f0;
75
+ padding: 20px;
76
+ border-radius: 12px;
77
+ margin: 10px 0;
78
+ border-left: 4px solid #667eea;
79
+ }
80
+ .showcase-section {
81
+ background: #ffffff;
82
+ border: 1px solid #e2e8f0;
83
+ padding: 30px;
84
+ border-radius: 16px;
85
+ box-shadow: 0 4px 20px rgba(0,0,0,0.1);
86
+ margin: 20px 0;
87
+ }
88
+ .step-header {
89
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
90
+ color: white;
91
+ padding: 15px;
92
+ border-radius: 12px;
93
+ text-align: center;
94
+ font-weight: 600;
95
+ margin: 10px 0;
96
+ }
97
+ .social-links {
98
+ text-align: center;
99
+ margin: 20px 0;
100
+ }
101
+ .social-links a {
102
+ margin: 0 10px;
103
+ padding: 8px 16px;
104
+ background: #667eea;
105
+ color: white;
106
+ text-decoration: none;
107
+ border-radius: 8px;
108
+ transition: all 0.3s ease;
109
+ }
110
+ .social-links a:hover {
111
+ background: #764ba2;
112
+ transform: translateY(-2px);
113
+ }
114
+ .status-banner {
115
+ padding: 15px;
116
+ border-radius: 12px;
117
+ margin: 10px 0;
118
+ text-align: center;
119
+ font-weight: 600;
120
+ }
121
+ .status-ready {
122
+ background: #d4edda;
123
+ border: 1px solid #c3e6cb;
124
+ color: #155724;
125
+ }
126
+ .status-starting {
127
+ background: #fff3cd;
128
+ border: 1px solid #ffeaa7;
129
+ color: #856404;
130
+ }
131
+ .status-error {
132
+ background: #f8d7da;
133
+ border: 1px solid #f5c6cb;
134
+ color: #721c24;
135
+ }
136
+ """
137
+
138
+ def image_to_base64(image):
139
+ """Convert PIL Image to base64 string."""
140
+ if image is None:
141
+ return ""
142
+
143
+ if hasattr(image, 'mode') and image.mode != 'RGB':
144
+ image = image.convert('RGB')
145
+
146
+ buffer = io.BytesIO()
147
+ image.save(buffer, format="PNG")
148
+ buffer.seek(0)
149
+ return base64.b64encode(buffer.getvalue()).decode('utf-8')
150
+
151
+ def base64_to_image(b64_string):
152
+ """Convert base64 string to PIL Image."""
153
+ if not b64_string:
154
+ return None
155
+
156
+ try:
157
+ image_data = base64.b64decode(b64_string)
158
+ return Image.open(io.BytesIO(image_data))
159
+ except Exception as e:
160
+ logger.error(f"Failed to decode base64 image: {e}")
161
+ return None
162
+
163
+ def try_connect_backend():
164
+ """Try to connect to backend and return status"""
165
+ global client, backend_connected
166
+
167
+ try:
168
+ test_client = Client("SnapwearAI/Pattern-Transfer-Backend", hf_token=HF_TOKEN)
169
+ client = test_client
170
+ backend_connected = True
171
+ return "🟒 Model is ready!", True
172
+ except Exception as e:
173
+ client = None
174
+ backend_connected = False
175
+ error_str = str(e).lower()
176
+ if "timeout" in error_str or "read operation timed out" in error_str:
177
+ return "🟑 Model is starting up (this takes 5-6 minutes on first load). Please wait and try again.", False
178
+ else:
179
+ return f"πŸ”΄ Backend error: {str(e)}", False
180
+
181
+ def call_backend_with_retry(print_image, product_image, max_retries=3):
182
+ """Call the backend with proper error handling."""
183
+ global client, backend_connected
184
+
185
+ # Validate inputs
186
+ if not print_image:
187
+ return None, "❌ Please upload a print/pattern image"
188
+
189
+ if not product_image:
190
+ return None, "❌ Please upload a product image"
191
+
192
+ # Check if we have a client
193
+ if not client or not backend_connected:
194
+ # Try to reconnect
195
+ status_msg, is_ready = try_connect_backend()
196
+ if not is_ready:
197
+ return None, status_msg
198
+
199
+ # Use fixed default values
200
+ guidance_scale = 50.0
201
+ num_steps = 50
202
+
203
+ for attempt in range(max_retries):
204
+ try:
205
+ logger.info(f"Calling backend (attempt {attempt + 1}/{max_retries})")
206
+
207
+ # Convert images to base64
208
+ print_b64 = image_to_base64(print_image)
209
+ product_b64 = image_to_base64(product_image)
210
+
211
+ logger.info("Images converted to base64")
212
+
213
+ # Make the backend call
214
+ start_time = time.time()
215
+ result = client.predict(
216
+ print_b64,
217
+ product_b64,
218
+ guidance_scale,
219
+ num_steps,
220
+ api_name="/predict"
221
+ )
222
+
223
+ processing_time = time.time() - start_time
224
+ logger.info(f"Backend call completed in {processing_time:.2f}s")
225
+
226
+ # Process the result
227
+ if result and len(result) >= 2:
228
+ result_b64, status = result[0], result[1]
229
+
230
+ if result_b64:
231
+ result_image = base64_to_image(result_b64)
232
+ if result_image:
233
+ logger.info("Successfully received and decoded result image")
234
+ return result_image, status
235
+ else:
236
+ return None, "❌ Failed to decode result image"
237
+ else:
238
+ return None, status or "❌ No image returned"
239
+ else:
240
+ return None, "❌ Invalid response from backend"
241
+
242
+ except Exception as e:
243
+ error_str = str(e).lower()
244
+ if "timeout" in error_str:
245
+ # Backend might be starting up again
246
+ backend_connected = False
247
+ client = None
248
+ return None, "🟑 Model timed out. It may be starting up again. Please wait 5-6 minutes and try the 'Check Status' button."
249
+
250
+ logger.error(f"Backend call attempt {attempt + 1} failed: {e}")
251
+ if attempt == max_retries - 1:
252
+ return None, f"❌ Backend error: {str(e)}"
253
+ time.sleep(2) # Wait before retry
254
+
255
+ return None, "❌ All attempts failed"
256
+
257
+ # ───────── Main UI ─────────
258
+ with gr.Blocks(css=css, title="Pattern & Color Transfer Studio") as demo:
259
+
260
+ # ──────── Hero Section ────────
261
+ gr.HTML("""
262
+ <div class="hero-section">
263
+ <h1 style="font-size:48px;margin:0;background:linear-gradient(45deg,#fff,#f0f8ff);-webkit-background-clip:text;-webkit-text-fill-color:transparent;">
264
+ 🎨 Snapwear Texture Transfer Studio
265
+ </h1>
266
+ <h2 style="font-size:24px;margin:10px 0;opacity:0.9;">
267
+ Transfer Any Pattern onto Any Product Instantly
268
+ </h2>
269
+ <p style="font-size:18px;margin:15px 0;opacity:0.8;">
270
+ β€’ Instant results β€’ Perfect for designers, brands & creators
271
+ </p>
272
+ <div class="social-links">
273
+ <a href="https://snapwear.io" target="_blank">🌐 Official Website</a>
274
+ <a href="https://www.instagram.com/snapwearai/" target="_blank">πŸ“Έ Instagram</a>
275
+ <a href="https://huggingface.co/spaces/SnapwearAI/Snapwear-Virtual-Try-On" target="_blank">πŸ‘— Try Virtual Try-On</a>
276
+ </div>
277
+ </div>
278
+ """)
279
+
280
+ # ──────── Status Check Section ────────
281
+ with gr.Row():
282
+ with gr.Column():
283
+ # Initial status message
284
+ if backend_connected:
285
+ initial_status = '<div class="status-banner status-ready">🟒 Model is ready! You can generate pattern transfers.</div>'
286
+ else:
287
+ initial_status = '<div class="status-banner status-starting">🟑 Model may be starting up. Click "Check Status" to verify.</div>'
288
+
289
+ status_display = gr.HTML(value=initial_status)
290
+
291
+ # Status check button
292
+ check_status_btn = gr.Button("πŸ”„ Check Status", size="sm")
293
+
294
+ # ──────── Info Box ────────
295
+ gr.HTML("""
296
+ <div style="background:#e8f4fd;border:1px solid #bee5eb;border-radius:12px;padding:20px;margin:20px 0;">
297
+ <h3 style="color:#0c5460;margin:0 0 10px 0;">ℹ️ First Time Here?</h3>
298
+ <p style="color:#0c5460;margin:0;">
299
+ Our AI model takes 5-6 minutes to start up on first visit after being idle.
300
+ Use the "Check Status" button above to see when the system is ready.
301
+ Once ready, pattern transfers complete in 30-60 seconds!
302
+ </p>
303
+ </div>
304
+ """)
305
+
306
+ # ──────── Key Features ────────
307
+ gr.HTML("""
308
+ <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:20px;margin:30px 0;">
309
+ <div class="feature-box">
310
+ <h3>πŸš€ Instant Transfer</h3>
311
+ <p>Apply any pattern to any product in 30-60 seconds with professional results</p>
312
+ </div>
313
+ <div class="feature-box">
314
+ <h3>🎯 Perfect Mapping</h3>
315
+ <p>Preserve product shape, lighting, and texture for realistic results</p>
316
+ </div>
317
+ <div class="feature-box">
318
+ <h3>🎨 Endless Possibilities</h3>
319
+ <p>Transfer prints, patterns, textures, and colors across any product type</p>
320
+ </div>
321
+ </div>
322
+ """)
323
+
324
+ # ──────── Step Headers ────────
325
+ with gr.Row():
326
+ with gr.Column(elem_id="col-left"):
327
+ gr.HTML('<div class="step-header">Step 1: Upload Pattern/Print 🎨</div>')
328
+ with gr.Column(elem_id="col-mid"):
329
+ gr.HTML('<div class="step-header">Step 2: Upload Product πŸ“¦</div>')
330
+ with gr.Column(elem_id="col-right"):
331
+ gr.HTML('<div class="step-header">Step 3: Generate Magic ✨</div>')
332
+
333
+ # ──────── Main Interface ────────
334
+ with gr.Row():
335
+ # β‘  Pattern/Print Upload
336
+ with gr.Column(elem_id="col-left"):
337
+ print_image = gr.Image(
338
+ label="Pattern/Print Image",
339
+ type="pil",
340
+ height=400,
341
+ )
342
+ gr.HTML('<p style="text-align:center;color:#666;font-size:14px;">Upload any color, print, or design you want to transfer</p>')
343
+
344
+ # Print examples
345
+ if os.path.exists("Assets/print"):
346
+ print_examples = [os.path.join("Assets/print", f) for f in os.listdir("Assets/print")][:10]
347
+ if print_examples:
348
+ gr.Examples(
349
+ label="✨ Example Patterns",
350
+ inputs=print_image,
351
+ examples_per_page=10,
352
+ examples=print_examples,
353
+ )
354
+
355
+ # β‘‘ Product Upload
356
+ with gr.Column(elem_id="col-mid"):
357
+ product_image = gr.Image(
358
+ label="Product Image",
359
+ type="pil",
360
+ height=400,
361
+ )
362
+ gr.HTML('<p style="text-align:center;color:#666;font-size:14px;">Upload the product you want to apply the pattern to</p>')
363
+
364
+ # Product examples
365
+ if os.path.exists("Assets/product"):
366
+ product_examples = [os.path.join("Assets/product", f) for f in os.listdir("Assets/product")][:12]
367
+ if product_examples:
368
+ gr.Examples(
369
+ label="πŸ“¦ Example Products",
370
+ inputs=product_image,
371
+ examples_per_page=12,
372
+ examples=product_examples,
373
+ )
374
+
375
+ # β‘’ Result + Controls
376
+ with gr.Column(elem_id="col-right"):
377
+ result_img = gr.Image(
378
+ label="✨ Transformed Result",
379
+ show_share_button=True,
380
+ height=400
381
+ )
382
+
383
+ # Status display
384
+ status_text = gr.Text(
385
+ label="Generation Status",
386
+ interactive=False,
387
+ placeholder="Upload images and click generate..."
388
+ )
389
+
390
+ # Generate button
391
+ generate_btn = gr.Button(
392
+ "πŸš€ Transform Pattern",
393
+ elem_id="button",
394
+ size="lg",
395
+ variant="primary"
396
+ )
397
+
398
+ # ──────── Showcase Examples ────────
399
+ gr.HTML("""
400
+ <div class="showcase-section">
401
+ <h2 style="text-align:center;color:#333;margin-bottom:30px;">
402
+ 🌟 Showcase: Pattern & Color Transfer Examples
403
+ </h2>
404
+ </div>
405
+ """)
406
+
407
+ # Pattern Transfer Showcase
408
+ with gr.Row():
409
+ gr.HTML('<h3 style="text-align:center;color:#667eea;margin:20px 0;">🎨 Pattern Transfer Showcase</h3>')
410
+
411
+ try:
412
+ if os.path.exists("Assets/examples"):
413
+ showcase_examples = [
414
+ [os.path.join("Assets/examples", "1_product.jpg"), os.path.join("Assets/examples", "1_print.jpg"), os.path.join("Assets/examples", "1_result.jpg")],
415
+ [os.path.join("Assets/examples", "2_product.jpg"), os.path.join("Assets/examples", "2_print.jpg"), os.path.join("Assets/examples", "2_result.jpg")],
416
+ [os.path.join("Assets/examples", "3_product.jpg"), os.path.join("Assets/examples", "3_print.jpg"), os.path.join("Assets/examples", "3_result.jpg")],
417
+ [os.path.join("Assets/examples", "4_product.jpg"), os.path.join("Assets/examples", "4_print.jpg"), os.path.join("Assets/examples", "4_result.jpg")],
418
+ ]
419
+ pattern_showcase = gr.Examples(
420
+ examples=showcase_examples,
421
+ inputs=[product_image, print_image, result_img],
422
+ label="Pattern Transfer Examples - Click any example to try it yourself!",
423
+ examples_per_page=4,
424
+ )
425
+ except:
426
+ gr.HTML("<p style='text-align:center;color:#666;'>Pattern transfer examples will appear here once example files are added to Assets/examples/</p>")
427
+
428
+ # Color Transfer Showcase
429
+ with gr.Row():
430
+ gr.HTML('<h3 style="text-align:center;color:#764ba2;margin:20px 0;">🌈 Color Transfer Showcase</h3>')
431
+
432
+ try:
433
+ if os.path.exists("Assets/examples/color"):
434
+ color_examples = [
435
+ [os.path.join("Assets/examples/color", "1_product.jpg"), os.path.join("Assets/examples/color", "1_print.jpg"), os.path.join("Assets/examples/color", "1_result.jpg")],
436
+ [os.path.join("Assets/examples/color", "2_product.jpg"), os.path.join("Assets/examples/color", "2_print.jpg"), os.path.join("Assets/examples/color", "2_result.jpg")],
437
+ [os.path.join("Assets/examples/color", "3_product.jpg"), os.path.join("Assets/examples/color", "3_print.jpg"), os.path.join("Assets/examples/color", "3_result.jpg")],
438
+ ]
439
+ color_showcase = gr.Examples(
440
+ examples=color_examples,
441
+ inputs=[product_image, print_image, result_img],
442
+ label="Color Transfer Examples - Perfect for recoloring products!",
443
+ examples_per_page=3,
444
+ )
445
+ except:
446
+ gr.HTML("<p style='text-align:center;color:#666;'>Color transfer examples will appear here once example files are added to Assets/examples/color/</p>")
447
+
448
+ # ──────── Use Cases ────────
449
+ gr.HTML("""
450
+ <div style="background:#f8fafc;border:1px solid #e2e8f0;padding:30px;border-radius:16px;margin:30px 0;">
451
+ <h2 style="text-align:center;color:#333;margin-bottom:25px;">🎯 Perfect For</h2>
452
+ <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:20px;">
453
+ <div style="text-align:center;padding:15px;">
454
+ <h3 style="color:#667eea;">πŸ‘— Fashion Designers</h3>
455
+ <p style="color:#666;">Visualize patterns on garments before production</p>
456
+ </div>
457
+ <div style="text-align:center;padding:15px;">
458
+ <h3 style="color:#667eea;">πŸ›οΈ E-commerce Brands</h3>
459
+ <p style="color:#666;">Show product variations without inventory</p>
460
+ </div>
461
+ <div style="text-align:center;padding:15px;">
462
+ <h3 style="color:#667eea;">🎨 Print-on-Demand</h3>
463
+ <p style="color:#666;">Preview designs on products instantly</p>
464
+ </div>
465
+ <div style="text-align:center;padding:15px;">
466
+ <h3 style="color:#667eea;">πŸ“± Content Creators</h3>
467
+ <p style="color:#666;">Create unique visuals for social media</p>
468
+ </div>
469
+ </div>
470
+ </div>
471
+ """)
472
+
473
+ # ──────── Event Handlers ────────
474
+ def update_status_display():
475
+ """Check backend status and update display"""
476
+ status_msg, is_ready = try_connect_backend()
477
+
478
+ if is_ready:
479
+ css_class = "status-ready"
480
+ elif "starting up" in status_msg:
481
+ css_class = "status-starting"
482
+ else:
483
+ css_class = "status-error"
484
+
485
+ status_html = f'<div class="status-banner {css_class}">{status_msg}</div>'
486
+ return status_html
487
+
488
+ # Status check button click
489
+ check_status_btn.click(
490
+ fn=update_status_display,
491
+ outputs=[status_display]
492
+ )
493
+
494
+ # Generate button click
495
+ generate_btn.click(
496
+ fn=call_backend_with_retry,
497
+ inputs=[print_image, product_image],
498
+ outputs=[result_img, status_text],
499
+ show_progress="full",
500
+ concurrency_limit=8,
501
+ )
502
+
503
+ # ──────── Footer ────────
504
+ gr.HTML("""
505
+ <div style="text-align:center;padding:40px 20px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:16px;margin:30px 0;">
506
+ <h3 style="color:#333;">πŸš€ Powered by Snapwear AI</h3>
507
+ <p style="color:#666;">
508
+ Transform your creative vision with professional-grade AI technology.<br/>
509
+ Join thousands of designers, brands, and creators already using our tools.
510
+ </p>
511
+ <div class="social-links">
512
+ <a href="https://snapwear.io" target="_blank">🌐 Website</a>
513
+ <a href="https://www.instagram.com/snapwearai/" target="_blank">πŸ“Έ Instagram</a>
514
+ <a href="https://huggingface.co/spaces/SnapwearAI/Snapwear-Virtual-Try-On" target="_blank">πŸ‘— Virtual Try-On</a>
515
+ </div>
516
+ <p style="font-size:12px;color:#999;margin-top:20px;">
517
+ Β© 2024 Snapwear AI. Professional AI tools for fashion and design.
518
+ </p>
519
+ </div>
520
+ """)
521
+
522
+ if __name__ == "__main__":
523
+ demo.queue(
524
+ max_size=20,
525
+ default_concurrency_limit=8,
526
+ api_open=False
527
+ ).launch(
528
+ server_name="0.0.0.0",
529
+ server_port=7860,
530
+ share=False,
531
+ show_api=False
532
+ )
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ gradio>=5.9.0
2
+ gradio-client>=0.8.0
3
+ pillow>=9.0.0