DawnC commited on
Commit
3e422be
·
verified ·
1 Parent(s): 38105e5

Update scene_templates.py

Browse files
Files changed (1) hide show
  1. scene_templates.py +652 -333
scene_templates.py CHANGED
@@ -1,297 +1,620 @@
1
  import logging
 
2
  from typing import Dict, List, Optional
3
- from dataclasses import dataclass
4
 
5
  logger = logging.getLogger(__name__)
6
 
 
7
  @dataclass
8
- class SceneTemplate:
9
- """Data class representing a scene template"""
 
10
  key: str
11
  name: str
12
- prompt: str
13
- negative_extra: str
14
  category: str
15
  icon: str
 
 
 
 
 
 
 
 
 
16
  guidance_scale: float = 7.5
 
 
 
 
 
 
 
 
 
 
17
 
18
 
19
- class SceneTemplateManager:
20
  """
21
- Manages curated scene templates for background generation.
22
- Provides categorized presets that users can select with one click.
 
 
 
 
 
 
 
 
 
 
 
23
  """
24
 
25
- # Scene template definitions
26
- TEMPLATES: Dict[str, SceneTemplate] = {
27
- # Professional Category
28
- "office_modern": SceneTemplate(
29
- key="office_modern",
30
- name="Modern Office",
31
- prompt="modern minimalist office interior, clean white desk, large floor-to-ceiling windows, natural daylight, professional corporate environment, soft shadows, contemporary furniture",
32
- negative_extra="messy, cluttered, dark, old",
33
- category="Professional",
34
- icon="🏢",
35
- guidance_scale=7.5
36
- ),
37
- "office_executive": SceneTemplate(
38
- key="office_executive",
39
- name="Executive Suite",
40
- prompt="luxurious executive office, mahogany desk, leather chair, city skyline view through windows, warm ambient lighting, bookshelf, elegant professional setting",
41
- negative_extra="cheap, cramped, messy",
42
- category="Professional",
43
- icon="👔",
44
- guidance_scale=7.5
45
- ),
46
- "studio_white": SceneTemplate(
47
- key="studio_white",
48
- name="White Studio",
49
- prompt="clean white photography studio background, professional lighting setup, seamless white backdrop, soft diffused light, minimal shadows",
50
- negative_extra="colored, textured, dirty",
51
- category="Professional",
52
- icon="📷",
53
- guidance_scale=8.0
54
- ),
55
- "coworking": SceneTemplate(
56
- key="coworking",
57
- name="Coworking Space",
58
- prompt="modern coworking space, open plan office, plants, exposed brick, industrial chic design, natural light, collaborative environment",
59
- negative_extra="empty, dark, boring",
60
- category="Professional",
61
- icon="💼",
62
- guidance_scale=7.0
63
- ),
64
- "conference": SceneTemplate(
65
- key="conference",
66
- name="Conference Room",
67
- prompt="modern conference room, large meeting table, glass walls, professional presentation screen, bright corporate lighting, clean minimal design",
68
- negative_extra="small, cramped, outdated",
69
- category="Professional",
70
- icon="🤝",
71
- guidance_scale=7.5
72
  ),
73
 
74
- # Nature Category
75
- "beach_sunset": SceneTemplate(
76
- key="beach_sunset",
77
- name="Sunset Beach",
78
- prompt="beautiful tropical beach at golden hour sunset, palm trees silhouette, calm turquoise ocean waves, warm orange and pink sky, soft sand, paradise vacation vibes",
79
- negative_extra="storm, rain, crowded, trash",
80
- category="Nature",
81
- icon="🏖️",
82
- guidance_scale=7.0
83
- ),
84
- "forest_enchanted": SceneTemplate(
85
- key="forest_enchanted",
86
- name="Enchanted Forest",
87
- prompt="magical enchanted forest, sunlight streaming through tall trees, lush green foliage, mystical atmosphere, morning mist, fairy tale woodland",
88
- negative_extra="dead trees, dark, scary, barren",
89
- category="Nature",
90
- icon="🌲",
91
- guidance_scale=7.0
92
- ),
93
- "mountain_scenic": SceneTemplate(
94
- key="mountain_scenic",
95
- name="Mountain Vista",
96
- prompt="breathtaking mountain landscape, snow-capped peaks, alpine meadow, clear blue sky, majestic scenic view, pristine nature, peaceful atmosphere",
97
- negative_extra="industrial, polluted, crowded",
98
- category="Nature",
99
- icon="🏔️",
100
- guidance_scale=7.5
101
- ),
102
- "garden_spring": SceneTemplate(
103
- key="garden_spring",
104
- name="Spring Garden",
105
- prompt="beautiful spring flower garden, colorful blooming flowers, roses and tulips, manicured hedges, sunny day, botanical paradise, fresh and vibrant",
106
- negative_extra="dead, winter, wilted, dry",
107
- category="Nature",
108
- icon="🌸",
109
- guidance_scale=7.0
110
- ),
111
- "lake_serene": SceneTemplate(
112
- key="lake_serene",
113
- name="Serene Lake",
114
- prompt="peaceful serene lake at dawn, mirror-like water reflection, surrounding mountains, soft morning light, tranquil atmosphere, pristine natural beauty",
115
- negative_extra="stormy, polluted, industrial",
116
- category="Nature",
117
- icon="🏞️",
118
- guidance_scale=7.0
119
  ),
120
- "cherry_blossom": SceneTemplate(
121
- key="cherry_blossom",
122
- name="Cherry Blossom",
123
- prompt="stunning cherry blossom trees in full bloom, pink sakura petals falling gently, Japanese garden aesthetic, soft spring sunlight, romantic atmosphere",
124
- negative_extra="winter, dead, brown, wilted",
125
- category="Nature",
126
- icon="🌸",
127
- guidance_scale=7.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  ),
129
 
130
- # Urban Category
131
- "city_skyline": SceneTemplate(
132
- key="city_skyline",
133
- name="City Skyline",
134
- prompt="modern city skyline at blue hour, impressive skyscrapers, glass buildings reflecting sunset, urban metropolitan view, cinematic atmosphere",
135
- negative_extra="slums, dirty, abandoned, ruins",
136
- category="Urban",
137
- icon="🌆",
138
- guidance_scale=7.5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  ),
140
- "cafe_cozy": SceneTemplate(
141
- key="cafe_cozy",
142
- name="Cozy Cafe",
143
- prompt="warm cozy coffee shop interior, wooden furniture, ambient lighting, exposed brick walls, plants, comfortable atmosphere, artisan cafe vibes",
144
- negative_extra="fast food, plastic, harsh lighting",
145
- category="Urban",
146
- icon="",
147
- guidance_scale=7.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  ),
149
- "street_european": SceneTemplate(
150
- key="street_european",
151
- name="European Street",
152
- prompt="charming European cobblestone street, historic buildings, outdoor cafe, flowers on balconies, warm afternoon light, romantic Paris or Rome vibes",
153
- negative_extra="modern, industrial, ugly, dirty",
154
- category="Urban",
155
- icon="🏛️",
156
- guidance_scale=7.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  ),
158
- "night_neon": SceneTemplate(
159
- key="night_neon",
160
- name="Neon Nightlife",
161
- prompt="vibrant city nightlife scene, neon lights and signs, urban night atmosphere, colorful reflections on wet street, cyberpunk aesthetic, electric energy",
162
- negative_extra="daytime, boring, plain",
163
- category="Urban",
164
- icon="🌃",
165
- guidance_scale=6.5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
  ),
167
- "rooftop_view": SceneTemplate(
168
- key="rooftop_view",
169
- name="Rooftop Terrace",
170
- prompt="luxury rooftop terrace, city panoramic view, modern outdoor furniture, string lights, sunset golden hour, sophisticated urban oasis",
171
- negative_extra="cheap, dirty, crowded",
172
- category="Urban",
173
- icon="🏙️",
174
- guidance_scale=7.5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
  ),
176
 
177
- # Artistic Category
178
- "gradient_soft": SceneTemplate(
179
- key="gradient_soft",
180
- name="Soft Gradient",
181
- prompt="smooth soft gradient background, pastel colors blending beautifully, pink to blue to purple transition, dreamy aesthetic, professional portrait backdrop",
182
- negative_extra="harsh, noisy, textured, busy",
183
- category="Artistic",
184
  icon="🎨",
185
- guidance_scale=8.0
186
- ),
187
- "abstract_modern": SceneTemplate(
188
- key="abstract_modern",
189
- name="Modern Abstract",
190
- prompt="modern abstract art background, geometric shapes, bold colors, contemporary design, artistic composition, museum gallery aesthetic",
191
- negative_extra="realistic, plain, boring",
192
- category="Artistic",
193
- icon="🖼️",
194
- guidance_scale=6.5
 
 
 
 
 
 
 
 
 
 
 
195
  ),
196
- "vintage_retro": SceneTemplate(
197
- key="vintage_retro",
198
- name="Vintage Retro",
199
- prompt="vintage retro aesthetic background, warm sepia tones, nostalgic 70s vibes, film grain texture, classic photography style, timeless elegance",
200
- negative_extra="modern, digital, cold, harsh",
201
- category="Artistic",
202
  icon="📻",
203
- guidance_scale=7.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  ),
205
- "watercolor_dream": SceneTemplate(
206
- key="watercolor_dream",
207
- name="Watercolor Dream",
208
- prompt="beautiful watercolor painting background, soft flowing colors, artistic brush strokes, dreamy ethereal atmosphere, delicate artistic aesthetic",
209
- negative_extra="digital, sharp, photorealistic",
210
- category="Artistic",
211
- icon="🖌️",
212
- guidance_scale=6.5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
  ),
214
 
215
- # Seasonal Category
216
- "autumn_foliage": SceneTemplate(
217
- key="autumn_foliage",
218
- name="Autumn Foliage",
219
- prompt="beautiful autumn scenery, vibrant fall foliage, orange red and golden leaves, maple trees, warm sunlight filtering through, cozy seasonal atmosphere",
220
- negative_extra="spring, summer, green, snow",
221
- category="Seasonal",
222
- icon="🍂",
223
- guidance_scale=7.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
  ),
225
- "winter_snow": SceneTemplate(
226
- key="winter_snow",
227
- name="Winter Wonderland",
228
- prompt="magical winter wonderland, fresh white snow covering everything, snow-laden pine trees, soft snowfall, peaceful cold atmosphere, holiday season vibes",
229
- negative_extra="summer, green, rain, mud",
230
- category="Seasonal",
231
- icon="❄️",
232
- guidance_scale=7.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
  ),
234
- "summer_tropical": SceneTemplate(
235
- key="summer_tropical",
236
- name="Tropical Summer",
237
- prompt="vibrant tropical summer scene, lush palm trees, bright sunny day, exotic flowers, paradise vacation destination, warm and inviting atmosphere",
238
- negative_extra="winter, cold, snow, gray",
239
- category="Seasonal",
240
- icon="🌴",
241
- guidance_scale=7.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
  ),
243
- "spring_meadow": SceneTemplate(
244
- key="spring_meadow",
245
- name="Spring Meadow",
246
- prompt="beautiful spring meadow, wildflowers blooming, fresh green grass, butterflies, soft warm sunlight, renewal and new beginnings, pastoral beauty",
247
- negative_extra="winter, autumn, dead, dry",
248
- category="Seasonal",
249
- icon="🌷",
250
- guidance_scale=7.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251
  ),
252
  }
253
 
254
  # Category display order
255
- CATEGORIES = ["Professional", "Nature", "Urban", "Artistic", "Seasonal"]
256
 
257
  def __init__(self):
258
- """Initialize the scene template manager"""
259
- logger.info(f"SceneTemplateManager initialized with {len(self.TEMPLATES)} templates")
 
 
 
 
260
 
261
- def get_all_templates(self) -> Dict[str, SceneTemplate]:
262
- """Get all available templates"""
 
 
 
263
  return self.TEMPLATES
264
 
265
- def get_template(self, key: str) -> Optional[SceneTemplate]:
266
- """Get a specific template by key"""
 
 
 
 
 
 
 
 
 
 
 
 
267
  return self.TEMPLATES.get(key)
268
 
269
- def get_templates_by_category(self, category: str) -> List[SceneTemplate]:
270
- """Get all templates in a specific category"""
 
 
 
 
 
 
 
 
 
 
 
 
271
  return [t for t in self.TEMPLATES.values() if t.category == category]
272
 
273
  def get_categories(self) -> List[str]:
274
- """Get list of all categories in display order"""
 
 
 
 
 
 
 
275
  return self.CATEGORIES
276
 
277
  def get_template_choices_sorted(self) -> List[str]:
278
  """
279
  Get template choices formatted for Gradio dropdown.
280
- Returns list of display strings sorted A-Z: "🏢 Modern Office"
 
 
 
 
 
 
 
281
  """
282
  display_list = []
283
- for key, template in self.TEMPLATES.items():
284
- display_name = f"{template.icon} {template.name}"
285
- display_list.append(display_name)
286
 
287
- # Sort alphabetically by name (ignoring emoji)
288
- display_list.sort(key=lambda x: x.split(' ', 1)[1] if ' ' in x else x)
 
 
 
 
289
  return display_list
290
 
291
  def get_template_key_from_display(self, display_name: str) -> Optional[str]:
292
  """
293
  Get template key from display name.
294
- Example: "🏢 Modern Office" -> "office_modern"
 
 
 
 
 
 
 
 
 
295
  """
296
  if not display_name:
297
  return None
@@ -301,33 +624,102 @@ class SceneTemplateManager:
301
  return key
302
  return None
303
 
304
- def get_prompt_for_template(self, key: str) -> Optional[str]:
305
- """Get the prompt string for a template"""
 
 
 
 
 
 
 
 
 
 
 
 
306
  template = self.get_template(key)
307
- return template.prompt if template else None
308
-
309
- def get_negative_prompt_for_template(
310
- self,
311
- key: str,
312
- base_negative: str = "blurry, low quality, distorted, people, characters"
313
- ) -> str:
314
- """Get combined negative prompt for a template"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
315
  template = self.get_template(key)
316
- if template and template.negative_extra:
317
- return f"{base_negative}, {template.negative_extra}"
318
- return base_negative
 
 
 
 
 
 
 
 
 
 
319
 
320
- def get_guidance_scale_for_template(self, key: str) -> float:
321
- """Get the recommended guidance scale for a template"""
 
 
 
322
  template = self.get_template(key)
323
- return template.guidance_scale if template else 7.5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
324
 
325
  def build_gallery_html(self) -> str:
326
  """
327
- Build HTML for the scene template gallery.
328
- Returns HTML string for display in Gradio.
 
 
 
 
329
  """
330
- html_parts = ['<div class="scene-gallery">']
331
 
332
  for category in self.CATEGORIES:
333
  templates = self.get_templates_by_category(category)
@@ -335,94 +727,21 @@ class SceneTemplateManager:
335
  continue
336
 
337
  html_parts.append(f'''
338
- <div class="scene-category">
339
- <h4 class="scene-category-title">{category}</h4>
340
- <div class="scene-grid">
341
  ''')
342
 
343
- for template in templates:
344
  html_parts.append(f'''
345
- <button class="scene-card" data-template="{template.key}" onclick="selectTemplate('{template.key}')">
346
- <span class="scene-icon">{template.icon}</span>
347
- <span class="scene-name">{template.name}</span>
348
- </button>
 
349
  ''')
350
 
351
  html_parts.append('</div></div>')
352
 
353
  html_parts.append('</div>')
354
- return ''.join(html_parts)
355
-
356
- def get_gallery_css(self) -> str:
357
- """Get CSS styles for the scene gallery"""
358
- return """
359
- /* Scene Gallery Styles */
360
- .scene-gallery {
361
- margin: 16px 0;
362
- }
363
-
364
- .scene-category {
365
- margin-bottom: 20px;
366
- }
367
-
368
- .scene-category-title {
369
- font-size: 0.9rem;
370
- font-weight: 600;
371
- color: #475569;
372
- margin-bottom: 12px;
373
- padding-bottom: 8px;
374
- border-bottom: 1px solid #e2e8f0;
375
- }
376
-
377
- .scene-grid {
378
- display: grid;
379
- grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
380
- gap: 8px;
381
- }
382
-
383
- .scene-card {
384
- display: flex;
385
- flex-direction: column;
386
- align-items: center;
387
- justify-content: center;
388
- padding: 12px 8px;
389
- background: #f8fafc;
390
- border: 1px solid #e2e8f0;
391
- border-radius: 8px;
392
- cursor: pointer;
393
- transition: all 0.2s ease;
394
- min-height: 70px;
395
- }
396
-
397
- .scene-card:hover {
398
- background: #dbeafe;
399
- border-color: #3b82f6;
400
- transform: translateY(-2px);
401
- box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
402
- }
403
-
404
- .scene-card.selected {
405
- background: #dbeafe;
406
- border-color: #3b82f6;
407
- box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.3);
408
- }
409
-
410
- .scene-icon {
411
- font-size: 1.5rem;
412
- margin-bottom: 4px;
413
- }
414
-
415
- .scene-name {
416
- font-size: 0.75rem;
417
- font-weight: 500;
418
- color: #1e293b;
419
- text-align: center;
420
- line-height: 1.2;
421
- }
422
-
423
- @media (max-width: 768px) {
424
- .scene-grid {
425
- grid-template-columns: repeat(3, 1fr);
426
- }
427
- }
428
- """
 
1
  import logging
2
+ from dataclasses import dataclass, field
3
  from typing import Dict, List, Optional
 
4
 
5
  logger = logging.getLogger(__name__)
6
 
7
+
8
  @dataclass
9
+ class InpaintingTemplate:
10
+ """Data class representing an inpainting template."""
11
+
12
  key: str
13
  name: str
 
 
14
  category: str
15
  icon: str
16
+ description: str
17
+
18
+ # Prompt templates
19
+ prompt_template: str
20
+ negative_prompt: str
21
+
22
+ # Recommended parameters
23
+ controlnet_conditioning_scale: float = 0.7
24
+ feather_radius: int = 8
25
  guidance_scale: float = 7.5
26
+ num_inference_steps: int = 25
27
+
28
+ # Conditioning type preference
29
+ preferred_conditioning: str = "canny" # "canny" or "depth"
30
+
31
+ # Difficulty level for UI display
32
+ difficulty: str = "medium" # "easy", "medium", "advanced"
33
+
34
+ # Tips for users
35
+ usage_tips: List[str] = field(default_factory=list)
36
 
37
 
38
+ class InpaintingTemplateManager:
39
  """
40
+ Manages inpainting templates for various use cases.
41
+
42
+ Provides categorized presets optimized for different inpainting scenarios
43
+ including object replacement, removal, style transfer, and enhancement.
44
+
45
+ Attributes:
46
+ TEMPLATES: Dictionary of all available templates
47
+ CATEGORIES: List of category names in display order
48
+
49
+ Example:
50
+ >>> manager = InpaintingTemplateManager()
51
+ >>> template = manager.get_template("object_replacement")
52
+ >>> print(template.prompt_template)
53
  """
54
 
55
+ TEMPLATES: Dict[str, InpaintingTemplate] = {
56
+ # Object Replacement Category
57
+ "object_replacement": InpaintingTemplate(
58
+ key="object_replacement",
59
+ name="Object Replacement",
60
+ category="Replacement",
61
+ icon="🔄",
62
+ description="Replace selected objects with new content while preserving context",
63
+ prompt_template="{content}, seamlessly integrated into scene, matching lighting and perspective, realistic placement",
64
+ negative_prompt=(
65
+ "inconsistent lighting, wrong perspective, mismatched colors, "
66
+ "visible seams, floating objects, unrealistic placement, original object, "
67
+ "poorly integrated, disconnected from scene, keeping original, remnants of original"
68
+ ),
69
+ controlnet_conditioning_scale=0.32, # Optimized: Lower for clean replacement (was 0.38)
70
+ feather_radius=10, # Optimized: Tighter blending (was 14)
71
+ guidance_scale=11.0, # Optimized: Higher for object accuracy (was 10.0)
72
+ num_inference_steps=10, # Optimized: 10 steps (was 12)
73
+ preferred_conditioning="canny", # ✅ KEPT: Edge-based replacement
74
+ difficulty="medium",
75
+ usage_tips=[
76
+ "Draw mask PRECISELY around the object to replace (include small margin)",
77
+ "Low conditioning (0.32) helps remove original object completely",
78
+ "Be specific: Instead of 'plant', use 'large green potted fern with detailed leaves'",
79
+ "📝 Example prompts:",
80
+ " 'elegant white ceramic teacup with delicate gold rim and floral pattern'",
81
+ " • 'modern silver laptop computer with sleek metallic finish'",
82
+ " • 'vintage wooden desk lamp with warm brass details'"
83
+ ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  ),
85
 
86
+ "face_swap": InpaintingTemplate(
87
+ key="face_swap",
88
+ name="Face Enhancement",
89
+ category="Replacement",
90
+ icon="👤",
91
+ description="Enhance or modify facial features - SUBTLE adjustments only (skin, expression, lighting)",
92
+ prompt_template="{content}, natural skin texture, proper facial proportions, realistic lighting, detailed facial features",
93
+ negative_prompt=(
94
+ "deformed face, asymmetric features, unnatural skin, "
95
+ "plastic appearance, wrong eye direction, blurry features, "
96
+ "artificial smoothing, uncanny valley, distorted proportions"
97
+ ),
98
+ controlnet_conditioning_scale=0.88, # Very high - preserves facial structure
99
+ feather_radius=6,
100
+ guidance_scale=8.5,
101
+ num_inference_steps=10, # Optimized: 10 steps (was 12)
102
+ preferred_conditioning="canny",
103
+ difficulty="advanced", # ⚠️ Advanced: Faces are sensitive
104
+ usage_tips=[
105
+ "⚠️ ADVANCED: Best for SUBTLE enhancements (skin tone, blemishes, expression)",
106
+ "NOT for major changes (face shape, eye size, feature positions)",
107
+ "Draw mask CAREFULLY around face outline (avoid hair and neck)",
108
+ "High conditioning (0.88) preserves facial structure - only small modifications",
109
+ "📝 Example prompts:",
110
+ " • 'warm friendly smile with bright eyes and natural expression'",
111
+ " • 'professional headshot with confident neutral expression, clear smooth skin'",
112
+ " • 'gentle smile with soft natural lighting on face'"
113
+ ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  ),
115
+
116
+ "clothing_change": InpaintingTemplate(
117
+ key="clothing_change",
118
+ name="Clothing Change",
119
+ category="Replacement",
120
+ icon="👕",
121
+ description="Change clothing color, pattern, style - preserves fabric folds and texture",
122
+ prompt_template="CHANGE to {content}, vivid saturated color, natural fabric texture, proper folds and wrinkles, correct fit",
123
+ negative_prompt=(
124
+ "wrong body proportions, floating fabric, unrealistic wrinkles, "
125
+ "mismatched lighting, visible edges, original clothing style, "
126
+ "keeping same color, original color, faded colors, unchanged appearance, partial change, "
127
+ "black clothing, dark original color"
128
+ ),
129
+ controlnet_conditioning_scale=0.30, # Optimized: Much lower for color change freedom (was 0.42)
130
+ feather_radius=14,
131
+ guidance_scale=11.5, # Optimized: Higher for color accuracy (was 10.5)
132
+ num_inference_steps=10, # Optimized: 10 steps (was 12)
133
+ preferred_conditioning="depth", # ✅ KEPT: Preserves fabric folds and texture
134
+ difficulty="easy", # ✅ Easy: Good success rate
135
+ usage_tips=[
136
+ "✅ BALANCED: Low conditioning (0.30) allows color change while depth preserves folds",
137
+ "Works for both moderate and dramatic color changes (black→red now possible!)",
138
+ "For extreme changes, be VERY specific with color: 'BRIGHT red', 'PURE white'",
139
+ "📝 Example prompts:",
140
+ " • 'BRIGHT red polo shirt with vivid saturated color, clean collar and soft fabric'",
141
+ " • 'deep navy blue formal blazer with fine texture and professional fit'",
142
+ " • 'PURE white dress shirt with crisp clean fabric'"
143
+ ]
144
  ),
145
 
146
+ "dramatic_color_change": InpaintingTemplate(
147
+ key="dramatic_color_change",
148
+ name="Dramatic Color Change",
149
+ category="Replacement",
150
+ icon="🎨",
151
+ description="Extreme color transformations (dark↔light, black↔white) - especially for illustrations",
152
+ prompt_template="COMPLETELY SOLID {content}, entire area pure color, all fabric same vivid color, no original color remaining",
153
+ negative_prompt=(
154
+ "original color, keeping same shade, partial change, color bleeding, "
155
+ "faded colors, mixed tones, subtle change, gradual transition, "
156
+ "original appearance, unchanged, dark remnants, light patches, "
157
+ "black clothing, dark colors, keeping original darkness, "
158
+ "black fabric, keeping black, original black color, dark body, "
159
+ "partial color change, colored trim only, colored edges only, colored outline only, "
160
+ "black body with colored decoration, original color body"
161
+ ),
162
+ controlnet_conditioning_scale=0.15, # Optimized: Extremely low for anime/illustration (was 0.25)
163
+ feather_radius=16,
164
+ guidance_scale=15.5, # Optimized: Very high for strong color adherence (was 13.5)
165
+ num_inference_steps=10, # Optimized: 10 steps sufficient (was 12)
166
+ preferred_conditioning="canny", # Optimized: Canny for color freedom (was depth)
167
+ difficulty="medium", # ⚠️ Medium: Extreme changes challenging
168
+ usage_tips=[
169
+ "✅ OPTIMIZED for anime/illustration extreme color changes (black↔white, black↔red)",
170
+ "Use COMPLETE descriptors: 'solid PURE WHITE', 'completely BRIGHT RED', 'entire garment JET BLACK'",
171
+ "Very low conditioning (0.15) allows complete color transformation on flat-color illustrations",
172
+ "Add 'completely', 'solid', 'entire', 'pure' to ensure full coverage",
173
+ "📝 Example prompts:",
174
+ " • 'solid PURE WHITE dress shirt, completely white fabric'",
175
+ " • 'completely JET BLACK leather jacket, entire garment black'",
176
+ " • 'solid BRIGHT RED polo shirt, all fabric vivid red, no black'"
177
+ ]
178
  ),
179
+
180
+ "clothing_addition": InpaintingTemplate(
181
+ key="clothing_addition",
182
+ name="Add Accessories",
183
+ category="Replacement",
184
+ icon="👔",
185
+ description="⚡ EXPERIMENTAL: Add ties, pockets, buttons to clothing - challenging, may require multiple attempts",
186
+ prompt_template="{content}, clearly visible, highly detailed accessory, seamlessly integrated into clothing, proper placement and perspective",
187
+ negative_prompt=(
188
+ "missing details, incomplete, floating objects, disconnected, "
189
+ "unrealistic placement, wrong perspective, blurry, poorly integrated, "
190
+ "invisible, faint, unclear, hidden, absent, not visible"
191
+ ),
192
+ controlnet_conditioning_scale=0.20, # Optimized: Extremely low for object generation (was 0.25)
193
+ feather_radius=12,
194
+ guidance_scale=15.0, # Optimized: Very high for strong prompt adherence (was 14.0)
195
+ num_inference_steps=10, # Optimized: 10 steps (was 12)
196
+ preferred_conditioning="canny", # Optimized: Canny for maximum freedom (was depth)
197
+ difficulty="advanced", # ⚠️⚠️ ADVANCED: Low success rate, experimental
198
+ usage_tips=[
199
+ "⚡⚡ EXPERIMENTAL FEATURE: Adding new objects is very challenging",
200
+ "⚠️ Lower success rate due to complexity - may require multiple attempts",
201
+ "Draw mask from NECK to CHEST (vertical strip) for ties, not just collar area",
202
+ "Very low conditioning (0.20) gives model maximum freedom to generate new objects",
203
+ "📝 Example prompts:",
204
+ " • 'burgundy silk necktie with diagonal stripes and Windsor knot, hanging down from collar to chest'",
205
+ " • 'white pocket square with neat fold, visible in breast pocket'",
206
+ " • 'silver lapel pin with detailed engraving on left collar'",
207
+ "💡 TIP: For ties, mask should cover the entire length where tie should appear"
208
+ ]
209
  ),
210
+
211
+ # Object Removal Category
212
+ "object_removal": InpaintingTemplate(
213
+ key="object_removal",
214
+ name="Object Removal",
215
+ category="Removal",
216
+ icon="🗑️",
217
+ description="Remove unwanted objects and fill with matching background",
218
+ prompt_template="clean background, seamless continuation, {content}",
219
+ negative_prompt=(
220
+ "visible patches, color mismatch, texture inconsistency, "
221
+ "ghost artifacts, blur spots, repeated patterns, visible seams, remnants"
222
+ ),
223
+ controlnet_conditioning_scale=0.42, # Optimized: Lower for cleaner removal (was 0.48)
224
+ feather_radius=14,
225
+ guidance_scale=8.5, # Optimized: Higher for accuracy (was 8.0)
226
+ num_inference_steps=10, # Optimized: 10 steps (was 12)
227
+ preferred_conditioning="canny", # ✅ KEPT: Edge-based removal
228
+ difficulty="easy", # ✅ Easy: Inpainting core strength
229
+ usage_tips=[
230
+ "Draw mask slightly BEYOND object edges for better blending",
231
+ "Lower conditioning (0.42) ensures complete removal without traces",
232
+ "Describe what background SHOULD look like (e.g., 'grass lawn', 'wooden floor')",
233
+ "📝 Example prompts:",
234
+ " • 'clean grass lawn with natural green color'",
235
+ " • 'smooth wooden floor with consistent grain pattern'",
236
+ " • 'plain white wall with even texture'"
237
+ ]
238
  ),
239
+
240
+ "watermark_removal": InpaintingTemplate(
241
+ key="watermark_removal",
242
+ name="Watermark Removal",
243
+ category="Removal",
244
+ icon="💧",
245
+ description="Remove watermarks and text overlays",
246
+ prompt_template="clean image, no text, seamless background, {content}",
247
+ negative_prompt=(
248
+ "text, watermark, logo, signature, letters, numbers, visible artifacts, "
249
+ "color inconsistency, blur, remnants, ghost text"
250
+ ),
251
+ controlnet_conditioning_scale=0.40, # Optimized: Lower for complete removal (was 0.45)
252
+ feather_radius=12,
253
+ guidance_scale=9.0, # Optimized: Higher for clean result (was 8.5)
254
+ num_inference_steps=10, # Optimized: 10 steps (was 12)
255
+ preferred_conditioning="canny", # ✅ KEPT: Edge-based removal
256
+ difficulty="easy", # ✅ Easy: Good success rate
257
+ usage_tips=[
258
+ "Draw mask covering ALL watermark/text areas precisely",
259
+ "Lower conditioning (0.40) ensures watermark disappears completely",
260
+ "Describe what SHOULD be there instead (e.g., 'sky', 'fabric texture')",
261
+ "📝 Example prompts:",
262
+ " • 'clean blue sky with smooth gradient'",
263
+ " • 'natural skin texture without marks'",
264
+ " • 'smooth fabric surface with consistent color'"
265
+ ]
266
  ),
267
+
268
+ "blemish_removal": InpaintingTemplate(
269
+ key="blemish_removal",
270
+ name="Blemish Removal",
271
+ category="Removal",
272
+ icon="",
273
+ description="Remove skin blemishes, scratches, or small imperfections",
274
+ prompt_template="clean smooth surface, natural texture, {content}",
275
+ negative_prompt=(
276
+ "artificial smoothing, plastic texture, visible editing, "
277
+ "color patches, unnatural appearance, over-processed"
278
+ ),
279
+ controlnet_conditioning_scale=0.6,
280
+ feather_radius=6,
281
+ guidance_scale=6.5,
282
+ num_inference_steps=10, # Optimized: 10 steps (was 12)
283
+ preferred_conditioning="canny",
284
+ difficulty="easy", # ✅ Easy: Small areas, high success
285
+ usage_tips=[
286
+ "Draw small precise masks for EACH blemish/imperfection",
287
+ "Lower guidance (6.5) preserves natural skin texture",
288
+ "📝 Example prompts:",
289
+ " • 'natural clean skin with smooth texture'",
290
+ " • 'smooth surface without scratches or marks'",
291
+ " • 'clear skin with natural pores and texture'"
292
+ ]
293
  ),
294
 
295
+ # Style Transfer Category
296
+ "style_artistic": InpaintingTemplate(
297
+ key="style_artistic",
298
+ name="Artistic Style",
299
+ category="Style",
 
 
300
  icon="🎨",
301
+ description="Apply artistic style to selected region",
302
+ prompt_template="{content}, distinctive artistic style, strong painterly effect, creative interpretation, visible brushstrokes",
303
+ negative_prompt=(
304
+ "photorealistic, plain, boring, low contrast, unchanged, "
305
+ "inconsistent style, harsh transitions, original appearance, realistic photo"
306
+ ),
307
+ controlnet_conditioning_scale=0.42, # Optimized: Lower for style freedom (was 0.52)
308
+ feather_radius=12,
309
+ guidance_scale=12.5, # Optimized: Higher for style accuracy (was 11.5)
310
+ num_inference_steps=10, # Optimized: 10 steps (was 12)
311
+ preferred_conditioning="canny", # ✅ KEPT: Edge-based styling
312
+ difficulty="medium", # ⚠️ Medium: Style changes need steps
313
+ usage_tips=[
314
+ "Works best on larger areas (faces, clothing, backgrounds) for visible transformation",
315
+ "Lower conditioning (0.42) allows artistic reinterpretation",
316
+ "Be VERY specific about art style for best results",
317
+ "📝 Example prompts:",
318
+ " • 'impressionist oil painting with visible thick brushstrokes and vibrant colors'",
319
+ " • 'watercolor painting with soft edges and delicate color washes'",
320
+ " • 'Van Gogh style with swirling brushstrokes and bold color contrasts'"
321
+ ]
322
  ),
323
+
324
+ "style_vintage": InpaintingTemplate(
325
+ key="style_vintage",
326
+ name="Vintage Look",
327
+ category="Style",
 
328
  icon="📻",
329
+ description="Apply vintage or retro aesthetic to selected area",
330
+ prompt_template="{content}, strong vintage aesthetic, warm sepia tones, film grain texture, nostalgic atmosphere",
331
+ negative_prompt=(
332
+ "modern, digital, cold colors, harsh contrast, "
333
+ "oversaturated, neon colors, contemporary look, clean digital, crisp"
334
+ ),
335
+ controlnet_conditioning_scale=0.45, # Optimized: Lower for style freedom (was 0.55)
336
+ feather_radius=14,
337
+ guidance_scale=11.0, # Optimized: Higher for era accuracy (was 10.5)
338
+ num_inference_steps=10, # Optimized: 10 steps (was 12)
339
+ preferred_conditioning="depth", # Optimized: Depth for texture/grain (was canny)
340
+ difficulty="medium", # ⚠️ Medium: Color/texture adjustments
341
+ usage_tips=[
342
+ "Works best on medium to large regions for visible aesthetic change",
343
+ "Depth conditioning preserves texture while applying vintage look",
344
+ "Specify era and style for best results",
345
+ "📝 Example prompts:",
346
+ " • '1920s sepia photograph with faded brown tones and soft grain'",
347
+ " • '1970s vintage photo with warm orange tones and slight film grain'",
348
+ " • '1950s Kodachrome with saturated warm colors and nostalgic feel'"
349
+ ]
350
+ ),
351
+
352
+ "style_anime": InpaintingTemplate(
353
+ key="style_anime",
354
+ name="Anime Style",
355
+ category="Style",
356
+ icon="🎌",
357
+ description="⚡ Transform to anime style - dramatic change, may need multiple attempts",
358
+ prompt_template="{content}, anime illustration style, clean sharp lines, vibrant saturated colors, cel-shaded with flat colors",
359
+ negative_prompt=(
360
+ "photorealistic, blurry lines, muddy colors, realistic photo, "
361
+ "3D render, uncanny valley, western cartoon, gradient shading, photographic"
362
+ ),
363
+ controlnet_conditioning_scale=0.35, # Optimized: Lower for dramatic style change (was 0.48)
364
+ feather_radius=10,
365
+ guidance_scale=14.0, # Optimized: Higher for style accuracy (was 12.5)
366
+ num_inference_steps=10, # Optimized: 10 steps (was 12)
367
+ preferred_conditioning="canny",
368
+ difficulty="advanced", # ⚠️ Advanced: Extreme style transformation
369
+ usage_tips=[
370
+ "⚡ DRAMATIC transformation - best for portraits and characters",
371
+ "⚠️ Significant stylistic changes require good source image quality",
372
+ "Lower conditioning (0.35) allows dramatic style transformation",
373
+ "Expect anime-style interpretation, not exact anime conversion",
374
+ "📝 Example prompts:",
375
+ " • 'modern anime style with large expressive eyes and vibrant colors'",
376
+ " • 'Studio Ghibli style with soft features and warm color palette'",
377
+ " • 'manga style with clean black lines and cel-shaded coloring'"
378
+ ]
379
  ),
380
+
381
+ # Detail Enhancement Category
382
+ "detail_enhance": InpaintingTemplate(
383
+ key="detail_enhance",
384
+ name="Detail Enhancement",
385
+ category="Enhancement",
386
+ icon="🔍",
387
+ description="Add fine details and textures to selected area",
388
+ prompt_template="{content}, highly detailed, intricate textures, fine details, sharp focus",
389
+ negative_prompt=(
390
+ "blurry, smooth, low detail, soft focus, "
391
+ "oversimplified, lacking texture"
392
+ ),
393
+ controlnet_conditioning_scale=0.85, # Very high - preserves structure
394
+ feather_radius=4,
395
+ guidance_scale=8.0,
396
+ num_inference_steps=10, # Optimized: 10 steps (was 12)
397
+ preferred_conditioning="depth",
398
+ difficulty="easy", # ✅ Easy: Enhancement not generation
399
+ usage_tips=[
400
+ "High conditioning (0.85) preserves overall structure while adding detail",
401
+ "Best for adding fine details to existing objects",
402
+ "📝 Example prompts:",
403
+ " • 'highly detailed fabric with visible weave and fine threads'",
404
+ " • 'intricate wood grain with natural knots and detailed texture'",
405
+ " • 'sharp facial features with fine skin pores and detail'"
406
+ ]
407
  ),
408
 
409
+ "texture_add": InpaintingTemplate(
410
+ key="texture_add",
411
+ name="Texture Addition",
412
+ category="Enhancement",
413
+ icon="🧱",
414
+ description="Add or enhance surface textures",
415
+ prompt_template="{content} texture, realistic surface detail, natural material appearance",
416
+ negative_prompt=(
417
+ "flat, smooth, unrealistic, plastic, "
418
+ "wrong material, inconsistent texture"
419
+ ),
420
+ controlnet_conditioning_scale=0.8, # High - preserves shape
421
+ feather_radius=5,
422
+ guidance_scale=7.5,
423
+ num_inference_steps=10, # Optimized: 10 steps (was 12)
424
+ preferred_conditioning="depth",
425
+ difficulty="easy", # ✅ Easy: Texture overlay
426
+ usage_tips=[
427
+ "Specify material type clearly for best results",
428
+ "Depth conditioning preserves 3D form while changing texture",
429
+ "📝 Example prompts:",
430
+ " • 'rough wood texture with natural grain and knots'",
431
+ " • 'soft cotton fabric with gentle weave pattern'",
432
+ " • 'smooth marble surface with subtle veining'"
433
+ ]
434
  ),
435
+
436
+ "lighting_fix": InpaintingTemplate(
437
+ key="lighting_fix",
438
+ name="Lighting Correction",
439
+ category="Enhancement",
440
+ icon="💡",
441
+ description="Correct or enhance lighting in selected area",
442
+ prompt_template="{content}, proper lighting, natural shadows, balanced exposure",
443
+ negative_prompt=(
444
+ "harsh shadows, overexposed, underexposed, "
445
+ "flat lighting, unnatural highlights"
446
+ ),
447
+ controlnet_conditioning_scale=0.65,
448
+ feather_radius=15, # Large for smooth transitions
449
+ guidance_scale=7.0,
450
+ num_inference_steps=10, # Optimized: 10 steps (was 12)
451
+ preferred_conditioning="depth",
452
+ difficulty="easy", # ✅ Easy: Lighting adjustments
453
+ usage_tips=[
454
+ "Use large feather (15px) for smooth lighting transitions",
455
+ "Best for fixing uneven lighting or adding natural light",
456
+ "📝 Example prompts:",
457
+ " • 'soft natural lighting from window, gentle shadows'",
458
+ " • 'balanced exposure with warm golden hour light'",
459
+ " • 'even studio lighting with soft diffused shadows'"
460
+ ]
461
  ),
462
+
463
+ # Background Category
464
+ "background_extend": InpaintingTemplate(
465
+ key="background_extend",
466
+ name="Background Extension",
467
+ category="Background",
468
+ icon="📐",
469
+ description="Extend image background seamlessly",
470
+ prompt_template="seamless background extension, {content}, consistent style and lighting",
471
+ negative_prompt=(
472
+ "visible seams, style mismatch, lighting inconsistency, "
473
+ "repeated elements, unnatural continuation, abrupt changes"
474
+ ),
475
+ controlnet_conditioning_scale=0.45, # Optimized: Lower for extension freedom (was 0.55)
476
+ feather_radius=20, # Largest for smooth blending
477
+ guidance_scale=8.5, # Optimized: Higher for consistency (was 8.0)
478
+ num_inference_steps=10, # Optimized: 10 steps (was 12)
479
+ preferred_conditioning="canny", # ✅ KEPT: Edge-based extension
480
+ difficulty="medium", # ⚠️ Medium: Needs consistency
481
+ usage_tips=[
482
+ "Draw mask on area to extend (edges of image)",
483
+ "Large feather (20px) ensures smooth blending with existing background",
484
+ "Canny conditioning focuses on edges for seamless continuation",
485
+ "📝 Example prompts:",
486
+ " • 'continue the wooden floor with same grain pattern'",
487
+ " • 'extend blue sky with matching clouds and lighting'",
488
+ " • 'seamless continuation of brick wall texture'"
489
+ ]
490
  ),
491
+
492
+ "background_replace": InpaintingTemplate(
493
+ key="background_replace",
494
+ name="Background Replacement",
495
+ category="Background",
496
+ icon="🖼️",
497
+ description="Replace background while keeping subject intact",
498
+ prompt_template="{content}, professional background scene, seamless integration with subject, matching lighting and atmosphere",
499
+ negative_prompt=(
500
+ "floating subject, inconsistent lighting, disconnected, "
501
+ "wrong perspective, visible edges, color mismatch, original background, "
502
+ "poor integration, obvious composite"
503
+ ),
504
+ controlnet_conditioning_scale=0.48, # Optimized: Lower for background freedom (was 0.60)
505
+ feather_radius=12,
506
+ guidance_scale=10.5, # Optimized: Higher for scene accuracy (was 9.5)
507
+ num_inference_steps=10, # Optimized: 10 steps (was 12)
508
+ preferred_conditioning="depth", # ✅ KEPT: Preserves depth relationships
509
+ difficulty="medium", # ⚠️ Medium: Large area replacement
510
+ usage_tips=[
511
+ "Draw mask around ENTIRE background (leave subject unmasked with small margin)",
512
+ "Depth conditioning (0.48) preserves subject-background spatial relationship",
513
+ "Include lighting description to match subject for natural results",
514
+ "📝 Example prompts:",
515
+ " • 'professional photography studio with white backdrop and soft lighting'",
516
+ " • 'modern minimalist office with white walls and bright natural lighting'",
517
+ " • 'sunny beach with blue ocean and golden hour lighting'"
518
+ ]
519
  ),
520
  }
521
 
522
  # Category display order
523
+ CATEGORIES = ["Replacement", "Removal", "Style", "Enhancement", "Background"]
524
 
525
  def __init__(self):
526
+ """Initialize the InpaintingTemplateManager."""
527
+ logger.info(f"InpaintingTemplateManager initialized with {len(self.TEMPLATES)} templates")
528
+
529
+ def get_all_templates(self) -> Dict[str, InpaintingTemplate]:
530
+ """
531
+ Get all available templates.
532
 
533
+ Returns
534
+ -------
535
+ dict
536
+ Dictionary of all templates keyed by template key
537
+ """
538
  return self.TEMPLATES
539
 
540
+ def get_template(self, key: str) -> Optional[InpaintingTemplate]:
541
+ """
542
+ Get a specific template by key.
543
+
544
+ Parameters
545
+ ----------
546
+ key : str
547
+ Template identifier
548
+
549
+ Returns
550
+ -------
551
+ InpaintingTemplate or None
552
+ Template if found, None otherwise
553
+ """
554
  return self.TEMPLATES.get(key)
555
 
556
+ def get_templates_by_category(self, category: str) -> List[InpaintingTemplate]:
557
+ """
558
+ Get all templates in a specific category.
559
+
560
+ Parameters
561
+ ----------
562
+ category : str
563
+ Category name
564
+
565
+ Returns
566
+ -------
567
+ list
568
+ List of templates in the category
569
+ """
570
  return [t for t in self.TEMPLATES.values() if t.category == category]
571
 
572
  def get_categories(self) -> List[str]:
573
+ """
574
+ Get list of all categories in display order.
575
+
576
+ Returns
577
+ -------
578
+ list
579
+ Category names
580
+ """
581
  return self.CATEGORIES
582
 
583
  def get_template_choices_sorted(self) -> List[str]:
584
  """
585
  Get template choices formatted for Gradio dropdown.
586
+
587
+ Returns list of display strings sorted by category then A-Z.
588
+ Format: "icon Name"
589
+
590
+ Returns
591
+ -------
592
+ list
593
+ Formatted display strings for dropdown
594
  """
595
  display_list = []
 
 
 
596
 
597
+ for category in self.CATEGORIES:
598
+ templates = self.get_templates_by_category(category)
599
+ for template in sorted(templates, key=lambda t: t.name):
600
+ display_name = f"{template.icon} {template.name}"
601
+ display_list.append(display_name)
602
+
603
  return display_list
604
 
605
  def get_template_key_from_display(self, display_name: str) -> Optional[str]:
606
  """
607
  Get template key from display name.
608
+
609
+ Parameters
610
+ ----------
611
+ display_name : str
612
+ Display string like "🔄 Object Replacement"
613
+
614
+ Returns
615
+ -------
616
+ str or None
617
+ Template key if found
618
  """
619
  if not display_name:
620
  return None
 
624
  return key
625
  return None
626
 
627
+ def get_parameters_for_template(self, key: str) -> Dict[str, any]:
628
+ """
629
+ Get recommended parameters for a template.
630
+
631
+ Parameters
632
+ ----------
633
+ key : str
634
+ Template key
635
+
636
+ Returns
637
+ -------
638
+ dict
639
+ Dictionary of parameter names and values
640
+ """
641
  template = self.get_template(key)
642
+ if not template:
643
+ return {}
644
+
645
+ return {
646
+ "controlnet_conditioning_scale": template.controlnet_conditioning_scale,
647
+ "feather_radius": template.feather_radius,
648
+ "guidance_scale": template.guidance_scale,
649
+ "num_inference_steps": template.num_inference_steps,
650
+ "preferred_conditioning": template.preferred_conditioning
651
+ }
652
+
653
+ def build_prompt(self, key: str, content: str) -> str:
654
+ """
655
+ Build complete prompt from template and user content.
656
+
657
+ Parameters
658
+ ----------
659
+ key : str
660
+ Template key
661
+ content : str
662
+ User-provided content description
663
+
664
+ Returns
665
+ -------
666
+ str
667
+ Formatted prompt with content inserted
668
+ """
669
  template = self.get_template(key)
670
+ if not template:
671
+ return content
672
+
673
+ return template.prompt_template.format(content=content)
674
+
675
+ def get_negative_prompt(self, key: str) -> str:
676
+ """
677
+ Get negative prompt for a template.
678
+
679
+ Parameters
680
+ ----------
681
+ key : str
682
+ Template key
683
 
684
+ Returns
685
+ -------
686
+ str
687
+ Negative prompt string
688
+ """
689
  template = self.get_template(key)
690
+ if not template:
691
+ return ""
692
+ return template.negative_prompt
693
+
694
+ def get_usage_tips(self, key: str) -> List[str]:
695
+ """
696
+ Get usage tips for a template.
697
+
698
+ Parameters
699
+ ----------
700
+ key : str
701
+ Template key
702
+
703
+ Returns
704
+ -------
705
+ list
706
+ List of tip strings
707
+ """
708
+ template = self.get_template(key)
709
+ if not template:
710
+ return []
711
+ return template.usage_tips
712
 
713
  def build_gallery_html(self) -> str:
714
  """
715
+ Build HTML for template gallery display.
716
+
717
+ Returns
718
+ -------
719
+ str
720
+ HTML string for Gradio display
721
  """
722
+ html_parts = ['<div class="inpainting-gallery">']
723
 
724
  for category in self.CATEGORIES:
725
  templates = self.get_templates_by_category(category)
 
727
  continue
728
 
729
  html_parts.append(f'''
730
+ <div class="inpainting-category">
731
+ <h4 class="inpainting-category-title">{category}</h4>
732
+ <div class="inpainting-grid">
733
  ''')
734
 
735
+ for template in sorted(templates, key=lambda t: t.name):
736
  html_parts.append(f'''
737
+ <div class="inpainting-card" data-template="{template.key}">
738
+ <span class="inpainting-icon">{template.icon}</span>
739
+ <span class="inpainting-name">{template.name}</span>
740
+ <span class="inpainting-desc">{template.description[:50]}...</span>
741
+ </div>
742
  ''')
743
 
744
  html_parts.append('</div></div>')
745
 
746
  html_parts.append('</div>')
747
+ return ''.join(html_parts)