akhaliq HF Staff commited on
Commit
4670eb3
·
verified ·
1 Parent(s): d5bf3b6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +106 -129
app.py CHANGED
@@ -7,7 +7,7 @@ from longcat_image.models import LongCatImageTransformer2DModel
7
  from longcat_image.pipelines import LongCatImageEditPipeline, LongCatImagePipeline
8
  import numpy as np
9
 
10
- # Load models directly at startup
11
  device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
12
 
13
  # Text-to-Image Model
@@ -60,6 +60,7 @@ edit_pipe.to(device, torch.bfloat16)
60
 
61
  print(f"✅ Image Edit model loaded successfully on {device}")
62
 
 
63
  @spaces.GPU(duration=120)
64
  def generate_image(
65
  prompt: str,
@@ -69,19 +70,12 @@ def generate_image(
69
  progress=gr.Progress()
70
  ):
71
  """Generate image from text prompt"""
72
-
73
  if not prompt or prompt.strip() == "":
74
  raise gr.Error("Please enter a prompt")
75
-
76
  try:
77
  progress(0.1, desc="Preparing generation...")
78
-
79
  progress(0.2, desc="Generating image...")
80
-
81
- # Set random seed for reproducibility
82
  generator = torch.Generator("cuda" if torch.cuda.is_available() else "cpu").manual_seed(seed)
83
-
84
- # Run the pipeline with default optimal settings
85
  with torch.inference_mode():
86
  output = t2i_pipe(
87
  prompt,
@@ -95,13 +89,8 @@ def generate_image(
95
  enable_cfg_renorm=True,
96
  enable_prompt_rewrite=True
97
  )
98
-
99
  progress(1.0, desc="Done!")
100
-
101
- generated_image = output.images[0]
102
-
103
- return generated_image
104
-
105
  except Exception as e:
106
  raise gr.Error(f"Error during image generation: {str(e)}")
107
 
@@ -113,26 +102,16 @@ def edit_image(
113
  progress=gr.Progress()
114
  ):
115
  """Edit image based on text prompt"""
116
-
117
  if input_image is None:
118
  raise gr.Error("Please upload an image first")
119
-
120
  if not prompt or prompt.strip() == "":
121
  raise gr.Error("Please enter an edit instruction")
122
-
123
  try:
124
  progress(0.1, desc="Preparing image...")
125
-
126
- # Convert to RGB if needed
127
  if input_image.mode != 'RGB':
128
  input_image = input_image.convert('RGB')
129
-
130
  progress(0.2, desc="Generating edited image...")
131
-
132
- # Set random seed for reproducibility
133
  generator = torch.Generator("cuda" if torch.cuda.is_available() else "cpu").manual_seed(seed)
134
-
135
- # Run the pipeline with optimal default settings
136
  with torch.inference_mode():
137
  output = edit_pipe(
138
  input_image,
@@ -143,30 +122,24 @@ def edit_image(
143
  num_images_per_prompt=1,
144
  generator=generator
145
  )
146
-
147
  progress(1.0, desc="Done!")
148
-
149
- edited_image = output.images[0]
150
-
151
- return edited_image
152
-
153
  except Exception as e:
154
  raise gr.Error(f"Error during image editing: {str(e)}")
155
 
156
- # Example for image editing
157
  edit_example_image_url = "https://huggingface.co/datasets/huggingface/brand-assets/resolve/main/hf-logo.png"
158
  edit_example_data = [
159
  [edit_example_image_url, "Add a mustache", 42],
160
  ]
161
 
162
- # Examples for text-to-image
163
  t2i_example_prompts = [
164
  ["一个年轻的亚裔女性,身穿黄色针织衫,搭配白色项链。她的双手放在膝盖上,表情恬静。背景是一堵粗糙的砖墙,午后的阳光温暖地洒在她身上,营造出一种宁静而温馨的氛围。", 1344, 768, 43],
165
  ["A serene mountain landscape at sunset with golden clouds", 1344, 768, 42],
166
  ["A cute robot sitting at a desk, digital art style", 1024, 1024, 44],
167
  ]
168
 
169
- # Custom CSS for Apple-style design and responsiveness
170
  custom_css = """
171
  @import url('https://fonts.googleapis.com/css2?family=SF+Pro+Display:wght@300;400;500;600;700&display=swap');
172
 
@@ -174,16 +147,19 @@ custom_css = """
174
  font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
175
  }
176
 
 
177
  .gradio-container {
178
  max-width: 1400px !important;
179
  margin: auto !important;
180
- padding: 0 16px; /* Added padding for mobile/small desktop */
181
  }
182
 
 
183
  #component-0 {
184
  background: linear-gradient(180deg, #f5f5f7 0%, #ffffff 100%) !important;
185
  }
186
 
 
187
  .tabs {
188
  border: none !important;
189
  background: transparent !important;
@@ -205,12 +181,11 @@ button.selected {
205
  font-weight: 500 !important;
206
  }
207
 
208
- /* Ensure images scale correctly on mobile */
209
  .input-image, .output-image {
210
  border-radius: 16px !important;
211
  overflow: hidden !important;
212
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06) !important;
213
- min-height: 250px; /* Base minimum height for better mobile scaling */
214
  }
215
 
216
  textarea, input[type="text"] {
@@ -226,6 +201,7 @@ textarea:focus, input[type="text"]:focus {
226
  box-shadow: 0 0 0 3px rgba(0, 122, 255, 0.1) !important;
227
  }
228
 
 
229
  .primary-btn {
230
  background: linear-gradient(180deg, #007aff 0%, #0051d5 100%) !important;
231
  border: none !important;
@@ -243,6 +219,7 @@ textarea:focus, input[type="text"]:focus {
243
  box-shadow: 0 6px 16px rgba(0, 122, 255, 0.4) !important;
244
  }
245
 
 
246
  .slider-container {
247
  margin: 16px 0 !important;
248
  }
@@ -259,7 +236,7 @@ label {
259
  font-size: 13px !important;
260
  }
261
 
262
- /* The .card class targets the underlying gr-panel component for the elevated look */
263
  .card {
264
  background: white !important;
265
  border-radius: 16px !important;
@@ -267,7 +244,7 @@ label {
267
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04) !important;
268
  }
269
 
270
- /* Mobile Responsiveness: Adjust padding/margins for smaller screens */
271
  @media (max-width: 768px) {
272
  .gradio-container {
273
  padding: 0 8px !important;
@@ -275,10 +252,6 @@ label {
275
  .card {
276
  padding: 16px !important;
277
  }
278
- .primary-btn {
279
- padding: 12px 24px !important;
280
- font-size: 15px !important;
281
- }
282
  }
283
  """
284
 
@@ -296,46 +269,47 @@ with gr.Blocks() as demo:
296
  """)
297
 
298
  with gr.Tabs(selected=0):
299
- # Image Edit Tab (Default)
300
  with gr.TabItem("Edit Image", id=0):
301
- # Use gr.Column with variant="panel" to get the 'card' look for inputs
302
- with gr.Column(variant="panel", scale=1):
303
- gr.Markdown("### 🖼️ Input Image & Controls")
304
- input_image = gr.Image(
305
- label="Upload Image",
306
- type="pil",
307
- sources=["upload", "clipboard"],
308
- height=450,
309
- elem_classes=["input-image"]
310
- )
311
-
312
- prompt = gr.Textbox(
313
- label="What would you like to change?",
314
- placeholder="e.g., Add a mustache, Change to sunset, Make it vintage...",
315
- lines=2,
316
- max_lines=3
317
- )
318
-
319
- seed = gr.Slider(
320
- minimum=0,
321
- maximum=999999,
322
- value=42,
323
- step=1,
324
- label="Seed",
325
- visible=False
326
- )
327
-
328
- edit_btn = gr.Button("Edit Image", variant="primary", size="lg", elem_classes=["primary-btn"])
329
-
330
- # Use gr.Column with variant="panel" for the output image
331
- with gr.Column(variant="panel", scale=1):
332
- gr.Markdown("### ✨ Result")
333
- output_image = gr.Image(
334
- label="Result",
335
- type="pil",
336
- height=450,
337
- elem_classes=["output-image"]
338
- )
 
339
 
340
  gr.HTML("<div style='margin: 30px 0 20px 0;'></div>")
341
 
@@ -349,53 +323,55 @@ with gr.Blocks() as demo:
349
  examples_per_page=3
350
  )
351
 
352
- # Text-to-Image Tab
353
  with gr.TabItem("Generate Image", id=1):
354
- with gr.Column(variant="panel", scale=1):
355
- gr.Markdown("### 🎨 Generation Controls")
356
- t2i_prompt = gr.Textbox(
357
- label="Describe your image",
358
- placeholder="e.g., A serene mountain landscape at sunset...",
359
- lines=4,
360
- max_lines=6
361
- )
362
-
363
- # Sliders remain vertical
364
- t2i_width = gr.Slider(
365
- minimum=512,
366
- maximum=2048,
367
- value=1344,
368
- step=64,
369
- label="Width",
370
- )
371
-
372
- t2i_height = gr.Slider(
373
- minimum=512,
374
- maximum=2048,
375
- value=768,
376
- step=64,
377
- label="Height",
378
- )
379
-
380
- t2i_seed = gr.Slider(
381
- minimum=0,
382
- maximum=999999,
383
- value=42,
384
- step=1,
385
- label="Seed",
386
- visible=False
387
- )
388
-
389
- generate_btn = gr.Button("Generate Image", variant="primary", size="lg", elem_classes=["primary-btn"])
390
-
391
- with gr.Column(variant="panel", scale=1):
392
- gr.Markdown("### Result")
393
- t2i_output = gr.Image(
394
- label="Result",
395
- type="pil",
396
- height=550,
397
- elem_classes=["output-image"]
398
- )
 
 
399
 
400
  gr.HTML("<div style='margin: 30px 0 20px 0;'></div>")
401
 
@@ -422,7 +398,7 @@ with gr.Blocks() as demo:
422
  outputs=output_image,
423
  )
424
 
425
- # Footer (HTML content is kept in Blocks, it is not an app-level parameter)
426
  gr.HTML("""
427
  <div style="text-align: center; margin-top: 60px; padding: 30px 20px; border-top: 1px solid #d2d2d7;">
428
  <p style="color: #86868b; font-size: 13px; margin: 0;">
@@ -432,9 +408,10 @@ with gr.Blocks() as demo:
432
  </div>
433
  """)
434
 
435
- # Launch the app
436
  if __name__ == "__main__":
437
  demo.launch(
438
  mcp_server=True,
 
439
  css=custom_css
440
  )
 
7
  from longcat_image.pipelines import LongCatImageEditPipeline, LongCatImagePipeline
8
  import numpy as np
9
 
10
+ # --- Model Loading (Kept for completeness) ---
11
  device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
12
 
13
  # Text-to-Image Model
 
60
 
61
  print(f"✅ Image Edit model loaded successfully on {device}")
62
 
63
+ # --- Core Functions (Kept for completeness) ---
64
  @spaces.GPU(duration=120)
65
  def generate_image(
66
  prompt: str,
 
70
  progress=gr.Progress()
71
  ):
72
  """Generate image from text prompt"""
 
73
  if not prompt or prompt.strip() == "":
74
  raise gr.Error("Please enter a prompt")
 
75
  try:
76
  progress(0.1, desc="Preparing generation...")
 
77
  progress(0.2, desc="Generating image...")
 
 
78
  generator = torch.Generator("cuda" if torch.cuda.is_available() else "cpu").manual_seed(seed)
 
 
79
  with torch.inference_mode():
80
  output = t2i_pipe(
81
  prompt,
 
89
  enable_cfg_renorm=True,
90
  enable_prompt_rewrite=True
91
  )
 
92
  progress(1.0, desc="Done!")
93
+ return output.images[0]
 
 
 
 
94
  except Exception as e:
95
  raise gr.Error(f"Error during image generation: {str(e)}")
96
 
 
102
  progress=gr.Progress()
103
  ):
104
  """Edit image based on text prompt"""
 
105
  if input_image is None:
106
  raise gr.Error("Please upload an image first")
 
107
  if not prompt or prompt.strip() == "":
108
  raise gr.Error("Please enter an edit instruction")
 
109
  try:
110
  progress(0.1, desc="Preparing image...")
 
 
111
  if input_image.mode != 'RGB':
112
  input_image = input_image.convert('RGB')
 
113
  progress(0.2, desc="Generating edited image...")
 
 
114
  generator = torch.Generator("cuda" if torch.cuda.is_available() else "cpu").manual_seed(seed)
 
 
115
  with torch.inference_mode():
116
  output = edit_pipe(
117
  input_image,
 
122
  num_images_per_prompt=1,
123
  generator=generator
124
  )
 
125
  progress(1.0, desc="Done!")
126
+ return output.images[0]
 
 
 
 
127
  except Exception as e:
128
  raise gr.Error(f"Error during image editing: {str(e)}")
129
 
130
+ # --- Examples (Kept for completeness) ---
131
  edit_example_image_url = "https://huggingface.co/datasets/huggingface/brand-assets/resolve/main/hf-logo.png"
132
  edit_example_data = [
133
  [edit_example_image_url, "Add a mustache", 42],
134
  ]
135
 
 
136
  t2i_example_prompts = [
137
  ["一个年轻的亚裔女性,身穿黄色针织衫,搭配白色项链。她的双手放在膝盖上,表情恬静。背景是一堵粗糙的砖墙,午后的阳光温暖地洒在她身上,营造出一种宁静而温馨的氛围。", 1344, 768, 43],
138
  ["A serene mountain landscape at sunset with golden clouds", 1344, 768, 42],
139
  ["A cute robot sitting at a desk, digital art style", 1024, 1024, 44],
140
  ]
141
 
142
+ # --- Custom CSS (Kept from previous refined version) ---
143
  custom_css = """
144
  @import url('https://fonts.googleapis.com/css2?family=SF+Pro+Display:wght@300;400;500;600;700&display=swap');
145
 
 
147
  font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
148
  }
149
 
150
+ /* Ensure padding on all screen sizes */
151
  .gradio-container {
152
  max-width: 1400px !important;
153
  margin: auto !important;
154
+ padding: 0 16px;
155
  }
156
 
157
+ /* Background gradient for the overall app (like a subtle card) */
158
  #component-0 {
159
  background: linear-gradient(180deg, #f5f5f7 0%, #ffffff 100%) !important;
160
  }
161
 
162
+ /* Tab bar styling for the segmented control look */
163
  .tabs {
164
  border: none !important;
165
  background: transparent !important;
 
181
  font-weight: 500 !important;
182
  }
183
 
184
+ /* Image and input component styling */
185
  .input-image, .output-image {
186
  border-radius: 16px !important;
187
  overflow: hidden !important;
188
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06) !important;
 
189
  }
190
 
191
  textarea, input[type="text"] {
 
201
  box-shadow: 0 0 0 3px rgba(0, 122, 255, 0.1) !important;
202
  }
203
 
204
+ /* Primary Button Styling */
205
  .primary-btn {
206
  background: linear-gradient(180deg, #007aff 0%, #0051d5 100%) !important;
207
  border: none !important;
 
219
  box-shadow: 0 6px 16px rgba(0, 122, 255, 0.4) !important;
220
  }
221
 
222
+ /* Slider and Label styling */
223
  .slider-container {
224
  margin: 16px 0 !important;
225
  }
 
236
  font-size: 13px !important;
237
  }
238
 
239
+ /* Card Style (targets gr-panel when variant="panel" is used) */
240
  .card {
241
  background: white !important;
242
  border-radius: 16px !important;
 
244
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04) !important;
245
  }
246
 
247
+ /* Mobile adjustments */
248
  @media (max-width: 768px) {
249
  .gradio-container {
250
  padding: 0 8px !important;
 
252
  .card {
253
  padding: 16px !important;
254
  }
 
 
 
 
255
  }
256
  """
257
 
 
269
  """)
270
 
271
  with gr.Tabs(selected=0):
272
+ # Image Edit Tab (Responsive Layout: Row on Desktop, Column on Mobile)
273
  with gr.TabItem("Edit Image", id=0):
274
+ with gr.Row(): # <-- Re-introducing the responsive row
275
+ # Left Column (Inputs)
276
+ with gr.Column(scale=1, variant="panel"):
277
+ gr.Markdown("### 🖼️ Input Image & Controls")
278
+ input_image = gr.Image(
279
+ label="Upload Image",
280
+ type="pil",
281
+ sources=["upload", "clipboard"],
282
+ height=450,
283
+ elem_classes=["input-image"]
284
+ )
285
+
286
+ prompt = gr.Textbox(
287
+ label="What would you like to change?",
288
+ placeholder="e.g., Add a mustache, Change to sunset, Make it vintage...",
289
+ lines=2,
290
+ max_lines=3
291
+ )
292
+
293
+ seed = gr.Slider(
294
+ minimum=0,
295
+ maximum=999999,
296
+ value=42,
297
+ step=1,
298
+ label="Seed",
299
+ visible=False
300
+ )
301
+
302
+ edit_btn = gr.Button("Edit Image", variant="primary", size="lg", elem_classes=["primary-btn"])
303
+
304
+ # Right Column (Output)
305
+ with gr.Column(scale=1, variant="panel"):
306
+ gr.Markdown("### ✨ Result")
307
+ output_image = gr.Image(
308
+ label="Result",
309
+ type="pil",
310
+ height=450,
311
+ elem_classes=["output-image"]
312
+ )
313
 
314
  gr.HTML("<div style='margin: 30px 0 20px 0;'></div>")
315
 
 
323
  examples_per_page=3
324
  )
325
 
326
+ # Text-to-Image Tab (Responsive Layout: Row on Desktop, Column on Mobile)
327
  with gr.TabItem("Generate Image", id=1):
328
+ with gr.Row(): # <-- Re-introducing the responsive row
329
+ # Left Column (Inputs)
330
+ with gr.Column(scale=1, variant="panel"):
331
+ gr.Markdown("### 🎨 Generation Controls")
332
+ t2i_prompt = gr.Textbox(
333
+ label="Describe your image",
334
+ placeholder="e.g., A serene mountain landscape at sunset...",
335
+ lines=4,
336
+ max_lines=6
337
+ )
338
+
339
+ t2i_width = gr.Slider(
340
+ minimum=512,
341
+ maximum=2048,
342
+ value=1344,
343
+ step=64,
344
+ label="Width",
345
+ )
346
+
347
+ t2i_height = gr.Slider(
348
+ minimum=512,
349
+ maximum=2048,
350
+ value=768,
351
+ step=64,
352
+ label="Height",
353
+ )
354
+
355
+ t2i_seed = gr.Slider(
356
+ minimum=0,
357
+ maximum=999999,
358
+ value=42,
359
+ step=1,
360
+ label="Seed",
361
+ visible=False
362
+ )
363
+
364
+ generate_btn = gr.Button("Generate Image", variant="primary", size="lg", elem_classes=["primary-btn"])
365
+
366
+ # Right Column (Output)
367
+ with gr.Column(scale=1, variant="panel"):
368
+ gr.Markdown("### ✨ Result")
369
+ t2i_output = gr.Image(
370
+ label="Result",
371
+ type="pil",
372
+ height=550,
373
+ elem_classes=["output-image"]
374
+ )
375
 
376
  gr.HTML("<div style='margin: 30px 0 20px 0;'></div>")
377
 
 
398
  outputs=output_image,
399
  )
400
 
401
+ # Footer
402
  gr.HTML("""
403
  <div style="text-align: center; margin-top: 60px; padding: 30px 20px; border-top: 1px solid #d2d2d7;">
404
  <p style="color: #86868b; font-size: 13px; margin: 0;">
 
408
  </div>
409
  """)
410
 
411
+ # Launch the app with theme and custom CSS
412
  if __name__ == "__main__":
413
  demo.launch(
414
  mcp_server=True,
415
+ theme=gr.themes.Soft(),
416
  css=custom_css
417
  )