multimodalart HF Staff commited on
Commit
0720854
·
verified ·
1 Parent(s): c820dc0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +230 -158
app.py CHANGED
@@ -100,7 +100,9 @@ def _generate_video_segment(input_image_path: str, output_image_path: str, promp
100
  )
101
  return result[0]["video"]
102
 
103
- def build_relight_prompt(light_type, light_direction, light_intensity, illumination_env, prompt):
 
 
104
  """Build the relighting prompt based on user selections - Qwen style."""
105
 
106
  # Priority 1: User's prompt (translated to Chinese if needed)
@@ -231,16 +233,28 @@ def build_relight_prompt(light_type, light_direction, light_intensity, illuminat
231
  }
232
 
233
  # Build the prompt - Qwen style (comma-separated, Chinese)
234
- if light_type != "none":
 
 
 
235
  prompt_parts.append(light_descriptions.get(light_type, ""))
236
 
237
- if illumination_env != "none":
 
 
 
238
  prompt_parts.append(illumination_envs.get(illumination_env, ""))
239
 
240
- if light_direction != "none":
 
 
 
241
  prompt_parts.append(direction_descriptions.get(light_direction, ""))
242
 
243
- if light_intensity != "none":
 
 
 
244
  prompt_parts.append(intensity_descriptions.get(light_intensity, ""))
245
 
246
  final_prompt = ",".join([p for p in prompt_parts if p])
@@ -256,9 +270,13 @@ def build_relight_prompt(light_type, light_direction, light_intensity, illuminat
256
  def infer_relight(
257
  image,
258
  light_type,
 
259
  light_direction,
 
260
  light_intensity,
 
261
  illumination_env,
 
262
  prompt,
263
  seed,
264
  randomize_seed,
@@ -269,7 +287,10 @@ def infer_relight(
269
  prev_output = None,
270
  progress=gr.Progress(track_tqdm=True)
271
  ):
272
- final_prompt = build_relight_prompt(light_type, light_direction, light_intensity, illumination_env, prompt)
 
 
 
273
  print(f"Generated Prompt: {final_prompt}")
274
 
275
  if randomize_seed:
@@ -339,7 +360,7 @@ css = '''
339
  '''
340
 
341
  def reset_all():
342
- return ["none", "none", "none", "none", "", False, True]
343
 
344
  def end_reset():
345
  return False
@@ -365,6 +386,10 @@ def update_dimensions_on_upload(image):
365
 
366
  return new_width, new_height
367
 
 
 
 
 
368
 
369
  with gr.Blocks(theme=gr.themes.Citrus(), css=css) as demo:
370
  with gr.Column(elem_id="col-container"):
@@ -380,143 +405,169 @@ with gr.Blocks(theme=gr.themes.Citrus(), css=css) as demo:
380
  prev_output = gr.Image(value=None, visible=False)
381
  is_reset = gr.Checkbox(value=False, visible=False)
382
 
383
- with gr.Accordion("💡 Light Type", open=True):
384
- light_type = gr.Radio(
385
- choices=[
386
- ("None", "none"),
387
- ("Soft Window Light", "soft_window"),
388
- ("Golden Hour", "golden_hour"),
389
- ("Studio Lighting", "studio"),
390
- ("Dramatic", "dramatic"),
391
- ("Natural Daylight", "natural"),
392
- ("Neon", "neon"),
393
- ("Candlelight", "candlelight"),
394
- ("Moonlight", "moonlight"),
395
- ("Sunrise", "sunrise"),
396
- ("Sunset over Sea", "sunset_sea"),
397
- ("Overcast", "overcast"),
398
- ("Harsh Sunlight", "harsh_sun"),
399
- ("Twilight", "twilight"),
400
- ("Aurora", "aurora"),
401
- ("Firelight", "firelight"),
402
- ("Lightning", "lightning"),
403
- ("Underwater", "underwater"),
404
- ("Foggy", "foggy"),
405
- ("Magic Light", "magic"),
406
- ("Cyberpunk", "cyberpunk"),
407
- ("Warm Home", "warm_home"),
408
- ("Cold Industrial", "cold_industrial"),
409
- ("Spotlight", "spotlight"),
410
- ("Rim Light", "rim_light"),
411
- ],
412
- value="none",
413
- elem_classes="radio-group"
414
- )
415
-
416
- with gr.Accordion("🧭 Light Direction", open=True):
417
- light_direction = gr.Radio(
418
- choices=[
419
- ("None", "none"),
420
- ("Front", "front"),
421
- ("Side", "side"),
422
- ("Left", "left"),
423
- ("Right", "right"),
424
- ("Back (Backlight)", "back"),
425
- ("Top", "top"),
426
- ("Bottom", "bottom"),
427
- ("Diagonal", "diagonal"),
428
- ],
429
- value="none",
430
- elem_classes="radio-group"
431
- )
432
-
433
- with gr.Accordion("⚡ Light Intensity", open=True):
434
- light_intensity = gr.Radio(
435
- choices=[
436
- ("None", "none"),
437
- ("Soft", "soft"),
438
- ("Medium", "medium"),
439
- ("Strong", "strong"),
440
- ],
441
- value="none",
442
- elem_classes="radio-group"
443
- )
444
-
445
- with gr.Accordion("🌍 Illumination Environment", open=False):
446
- illumination_env = gr.Radio(
447
- choices=[
448
- ("None", "none"),
449
- ("Sunshine from Window", "sunshine_window"),
450
- ("Neon Night, City", "neon_city"),
451
- ("Sci-Fi RGB Glowing, Cyberpunk", "sci_fi_rgb"),
452
- ("Warm Atmosphere, at Home, Bedroom", "warm_bedroom"),
453
- ("Magic Lit", "magic_lit"),
454
- ("Evil, Gothic, in a Cave", "gothic_cave"),
455
- ("Light and Shadow", "light_shadow"),
456
- ("Shadow from Window", "window_shadow"),
457
- ("Soft Studio Lighting", "soft_studio"),
458
- ("Home Atmosphere, Cozy Bedroom", "cozy_bedroom"),
459
- ("Neon, Wong Kar-wai, Warm", "wong_kar_wai"),
460
- ("Moonlight through Curtains", "moonlight_curtains"),
461
- ("Stormy Sky Lighting", "stormy_sky"),
462
- ("Underwater Glow, Deep Sea", "underwater_glow"),
463
- ("Foggy Forest at Dawn", "foggy_forest"),
464
- ("Golden Hour in a Meadow", "meadow_golden"),
465
- ("Rainbow Reflections, Neon", "rainbow_neon"),
466
- ("Apocalyptic, Smoky Atmosphere", "apocalyptic"),
467
- ("Red Glow, Emergency Lights", "emergency_red"),
468
- ("Mystical Glow, Enchanted Forest", "mystical_forest"),
469
- ("Campfire Light", "campfire"),
470
- ("Harsh, Industrial Lighting", "industrial_harsh"),
471
- ("Sunrise in the Mountains", "mountain_sunrise"),
472
- ("Evening Glow in the Desert", "desert_evening"),
473
- ("Moonlight in a Dark Alley", "dark_alley"),
474
- ("Golden Glow at a Fairground", "fairground"),
475
- ("Midnight in the Forest", "forest_midnight"),
476
- ("Purple and Pink Hues at Twilight", "twilight_purple"),
477
- ("Foggy Morning, Muted Light", "foggy_morning"),
478
- ("Candle-lit Room, Rustic Vibe", "rustic_candle"),
479
- ("Fluorescent Office Lighting", "office_fluorescent"),
480
- ("Lightning Flash in Storm", "storm_lightning"),
481
- ("Night, Cozy Warm Light from Fireplace", "fireplace_night"),
482
- ("Ethereal Glow, Magical Forest", "ethereal_magic"),
483
- ("Dusky Evening on a Beach", "beach_dusky"),
484
- ("Afternoon Light Filtering through Trees", "trees_afternoon"),
485
- ("Blue Neon Light, Urban Street", "urban_blue_neon"),
486
- ("Red and Blue Police Lights in Rain", "rain_police"),
487
- ("Aurora Borealis Glow, Arctic Landscape", "aurora_arctic"),
488
- ("Sunrise through Foggy Mountains", "foggy_mountains"),
489
- ("Golden Hour on a City Skyline", "city_skyline"),
490
- ("Mysterious Twilight, Heavy Mist", "twilight_mist"),
491
- ("Early Morning Rays, Forest Clearing", "forest_rays"),
492
- ("Colorful Lantern Light at Festival", "festival_lantern"),
493
- ("Soft Glow through Stained Glass", "stained_glass"),
494
- ("Harsh Spotlight in Dark Room", "dark_spotlight"),
495
- ("Mellow Evening Glow on a Lake", "lake_evening"),
496
- ("Crystal Reflections in a Cave", "cave_crystal"),
497
- ("Vibrant Autumn Lighting in a Forest", "autumn_forest"),
498
- ("Gentle Snowfall at Dusk", "snowfall_dusk"),
499
- ("Hazy Light of a Winter Morning", "winter_hazy"),
500
- ("Rain-soaked Reflections in City Lights", "rain_city"),
501
- ("Golden Sunlight Streaming through Trees", "trees_golden_sun"),
502
- ("Fireflies Lighting up a Summer Night", "fireflies_summer"),
503
- ("Glowing Embers from a Forge", "forge_embers"),
504
- ("Dim Candlelight in a Gothic Castle", "gothic_castle"),
505
- ("Midnight Sky with Bright Starlight", "starlight_midnight"),
506
- ("Warm Sunset in a Rural Village", "rural_sunset"),
507
- ("Flickering Light in a Haunted House", "haunted_flicker"),
508
- ("Desert Sunset with Mirage-like Glow", "desert_mirage"),
509
- ("Golden Beams Piercing through Storm Clouds", "storm_beams"),
510
- ],
511
- value="none",
512
- elem_classes="radio-group"
513
- )
514
-
515
- with gr.Accordion("✍️ Custom Prompt", open=False):
516
- prompt = gr.Textbox(
517
- placeholder="Example: Add warm sunset lighting from the right",
518
- lines=3
519
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
520
 
521
  with gr.Row():
522
  reset_btn = gr.Button("🔄 Reset")
@@ -532,22 +583,31 @@ with gr.Blocks(theme=gr.themes.Citrus(), css=css) as demo:
532
 
533
  with gr.Column(scale=1):
534
  result = gr.Image(label="Output Image", interactive=False)
535
- prompt_preview = gr.Textbox(label="Processed Prompt", interactive=False)
536
  create_video_button = gr.Button("🎥 Create Video Between Images", variant="secondary", visible=False)
537
  with gr.Group(visible=False) as video_group:
538
  video_output = gr.Video(label="Generated Video", show_download_button=True, autoplay=True)
539
 
540
  inputs = [
541
- image, light_type, light_direction, light_intensity, illumination_env, prompt,
542
- seed, randomize_seed, true_guidance_scale, num_inference_steps, height, width, prev_output
 
543
  ]
544
  outputs = [result, seed, prompt_preview]
545
 
 
 
 
 
 
 
546
  # Reset behavior
547
  reset_btn.click(
548
  fn=reset_all,
549
  inputs=None,
550
- outputs=[light_type, light_direction, light_intensity, illumination_env, prompt, is_reset],
 
 
551
  queue=False
552
  ).then(fn=end_reset, inputs=None, outputs=[is_reset], queue=False)
553
 
@@ -579,12 +639,13 @@ with gr.Blocks(theme=gr.themes.Citrus(), css=css) as demo:
579
  # Examples
580
  gr.Examples(
581
  examples=[
582
- ["harold.png", "dramatic", "side", "soft", "none", "", 0, True, 1.0, 4, 672, 1024],
583
- ["distracted.png", "golden_hour", "side", "strong", "none", "", 0, True, 1.0, 4, 640, 1024],
584
- ["disaster.jpg", "moonlight", "front", "medium", "neon_city", "", 0, True, 1.0, 4, 640, 1024],
585
  ],
586
- inputs=[image, light_type, light_direction, light_intensity, illumination_env, prompt,
587
- seed, randomize_seed, true_guidance_scale, num_inference_steps, height, width],
 
588
  outputs=outputs,
589
  fn=infer_relight,
590
  cache_examples="lazy",
@@ -599,7 +660,9 @@ with gr.Blocks(theme=gr.themes.Citrus(), css=css) as demo:
599
  ).then(
600
  fn=reset_all,
601
  inputs=None,
602
- outputs=[light_type, light_direction, light_intensity, illumination_env, prompt, is_reset],
 
 
603
  queue=False
604
  ).then(
605
  fn=end_reset,
@@ -609,7 +672,7 @@ with gr.Blocks(theme=gr.themes.Citrus(), css=css) as demo:
609
  )
610
 
611
 
612
- # Live updates
613
  def maybe_infer(is_reset, progress=gr.Progress(track_tqdm=True), *args):
614
  if is_reset:
615
  return gr.update(), gr.update(), gr.update(), gr.update()
@@ -620,13 +683,22 @@ with gr.Blocks(theme=gr.themes.Citrus(), css=css) as demo:
620
  return result_img, result_seed, result_prompt, gr.update(visible=show_button)
621
 
622
  control_inputs = [
623
- image, light_type, light_direction, light_intensity, illumination_env, prompt,
624
- seed, randomize_seed, true_guidance_scale, num_inference_steps, height, width, prev_output
 
625
  ]
626
  control_inputs_with_flag = [is_reset] + control_inputs
627
 
 
 
 
 
628
  for control in [light_type, light_direction, light_intensity, illumination_env]:
629
- control.input(fn=maybe_infer, inputs=control_inputs_with_flag, outputs=outputs + [create_video_button])
 
 
 
 
630
 
631
  run_event.then(lambda img, *_: img, inputs=[result], outputs=[prev_output])
632
 
 
100
  )
101
  return result[0]["video"]
102
 
103
+ def build_relight_prompt(light_type, light_type_custom, light_direction, light_direction_custom,
104
+ light_intensity, light_intensity_custom, illumination_env,
105
+ illumination_env_custom, prompt):
106
  """Build the relighting prompt based on user selections - Qwen style."""
107
 
108
  # Priority 1: User's prompt (translated to Chinese if needed)
 
233
  }
234
 
235
  # Build the prompt - Qwen style (comma-separated, Chinese)
236
+ # Handle custom light type
237
+ if light_type == "custom" and light_type_custom and light_type_custom.strip():
238
+ prompt_parts.append(translate_to_chinese(light_type_custom))
239
+ elif light_type != "none":
240
  prompt_parts.append(light_descriptions.get(light_type, ""))
241
 
242
+ # Handle custom illumination environment
243
+ if illumination_env == "custom" and illumination_env_custom and illumination_env_custom.strip():
244
+ prompt_parts.append(translate_to_chinese(illumination_env_custom))
245
+ elif illumination_env != "none":
246
  prompt_parts.append(illumination_envs.get(illumination_env, ""))
247
 
248
+ # Handle custom light direction
249
+ if light_direction == "custom" and light_direction_custom and light_direction_custom.strip():
250
+ prompt_parts.append(translate_to_chinese(light_direction_custom))
251
+ elif light_direction != "none":
252
  prompt_parts.append(direction_descriptions.get(light_direction, ""))
253
 
254
+ # Handle custom light intensity
255
+ if light_intensity == "custom" and light_intensity_custom and light_intensity_custom.strip():
256
+ prompt_parts.append(translate_to_chinese(light_intensity_custom))
257
+ elif light_intensity != "none":
258
  prompt_parts.append(intensity_descriptions.get(light_intensity, ""))
259
 
260
  final_prompt = ",".join([p for p in prompt_parts if p])
 
270
  def infer_relight(
271
  image,
272
  light_type,
273
+ light_type_custom,
274
  light_direction,
275
+ light_direction_custom,
276
  light_intensity,
277
+ light_intensity_custom,
278
  illumination_env,
279
+ illumination_env_custom,
280
  prompt,
281
  seed,
282
  randomize_seed,
 
287
  prev_output = None,
288
  progress=gr.Progress(track_tqdm=True)
289
  ):
290
+ final_prompt = build_relight_prompt(light_type, light_type_custom, light_direction,
291
+ light_direction_custom, light_intensity,
292
+ light_intensity_custom, illumination_env,
293
+ illumination_env_custom, prompt)
294
  print(f"Generated Prompt: {final_prompt}")
295
 
296
  if randomize_seed:
 
360
  '''
361
 
362
  def reset_all():
363
+ return ["none", "", "none", "", "none", "", "none", "", "", False, True]
364
 
365
  def end_reset():
366
  return False
 
386
 
387
  return new_width, new_height
388
 
389
+ def toggle_custom_textbox(choice):
390
+ """Show textbox when Custom is selected"""
391
+ return gr.update(visible=(choice == "custom"))
392
+
393
 
394
  with gr.Blocks(theme=gr.themes.Citrus(), css=css) as demo:
395
  with gr.Column(elem_id="col-container"):
 
405
  prev_output = gr.Image(value=None, visible=False)
406
  is_reset = gr.Checkbox(value=False, visible=False)
407
 
408
+ with gr.Tab("Compose Prompt"):
409
+ with gr.Accordion("💡 Light Type", open=True):
410
+ light_type = gr.Radio(
411
+ choices=[
412
+ ("None", "none"),
413
+ ("Soft Window Light", "soft_window"),
414
+ ("Golden Hour", "golden_hour"),
415
+ ("Studio Lighting", "studio"),
416
+ ("Dramatic", "dramatic"),
417
+ ("Natural Daylight", "natural"),
418
+ ("Neon", "neon"),
419
+ ("Candlelight", "candlelight"),
420
+ ("Moonlight", "moonlight"),
421
+ ("Sunrise", "sunrise"),
422
+ ("Sunset over Sea", "sunset_sea"),
423
+ ("Overcast", "overcast"),
424
+ ("Harsh Sunlight", "harsh_sun"),
425
+ ("Twilight", "twilight"),
426
+ ("Aurora", "aurora"),
427
+ ("Firelight", "firelight"),
428
+ ("Lightning", "lightning"),
429
+ ("Underwater", "underwater"),
430
+ ("Foggy", "foggy"),
431
+ ("Magic Light", "magic"),
432
+ ("Cyberpunk", "cyberpunk"),
433
+ ("Warm Home", "warm_home"),
434
+ ("Cold Industrial", "cold_industrial"),
435
+ ("Spotlight", "spotlight"),
436
+ ("Rim Light", "rim_light"),
437
+ ("Custom", "custom"),
438
+ ],
439
+ value="none",
440
+ elem_classes="radio-group"
441
+ )
442
+ light_type_custom = gr.Textbox(
443
+ label="Custom Light Type",
444
+ placeholder="e.g., Bioluminescent glow, Laser light show, etc.",
445
+ visible=False
446
+ )
447
+
448
+ with gr.Accordion("🧭 Light Direction", open=True):
449
+ light_direction = gr.Radio(
450
+ choices=[
451
+ ("None", "none"),
452
+ ("Front", "front"),
453
+ ("Side", "side"),
454
+ ("Left", "left"),
455
+ ("Right", "right"),
456
+ ("Back (Backlight)", "back"),
457
+ ("Top", "top"),
458
+ ("Bottom", "bottom"),
459
+ ("Diagonal", "diagonal"),
460
+ ("Custom", "custom"),
461
+ ],
462
+ value="none",
463
+ elem_classes="radio-group"
464
+ )
465
+ light_direction_custom = gr.Textbox(
466
+ label="Custom Light Direction",
467
+ placeholder="e.g., From 45 degrees above left, Rotating around subject, etc.",
468
+ visible=False
469
+ )
470
+
471
+ with gr.Accordion("⚡ Light Intensity", open=True):
472
+ light_intensity = gr.Radio(
473
+ choices=[
474
+ ("None", "none"),
475
+ ("Soft", "soft"),
476
+ ("Medium", "medium"),
477
+ ("Strong", "strong"),
478
+ ("Custom", "custom"),
479
+ ],
480
+ value="none",
481
+ elem_classes="radio-group"
482
+ )
483
+ light_intensity_custom = gr.Textbox(
484
+ label="Custom Light Intensity",
485
+ placeholder="e.g., Very dim, Blinding bright, Pulsating, etc.",
486
+ visible=False
487
+ )
488
+
489
+ with gr.Accordion("🌍 Illumination Environment", open=False):
490
+ illumination_env = gr.Radio(
491
+ choices=[
492
+ ("None", "none"),
493
+ ("Sunshine from Window", "sunshine_window"),
494
+ ("Neon Night, City", "neon_city"),
495
+ ("Sci-Fi RGB Glowing, Cyberpunk", "sci_fi_rgb"),
496
+ ("Warm Atmosphere, at Home, Bedroom", "warm_bedroom"),
497
+ ("Magic Lit", "magic_lit"),
498
+ ("Evil, Gothic, in a Cave", "gothic_cave"),
499
+ ("Light and Shadow", "light_shadow"),
500
+ ("Shadow from Window", "window_shadow"),
501
+ ("Soft Studio Lighting", "soft_studio"),
502
+ ("Home Atmosphere, Cozy Bedroom", "cozy_bedroom"),
503
+ ("Neon, Wong Kar-wai, Warm", "wong_kar_wai"),
504
+ ("Moonlight through Curtains", "moonlight_curtains"),
505
+ ("Stormy Sky Lighting", "stormy_sky"),
506
+ ("Underwater Glow, Deep Sea", "underwater_glow"),
507
+ ("Foggy Forest at Dawn", "foggy_forest"),
508
+ ("Golden Hour in a Meadow", "meadow_golden"),
509
+ ("Rainbow Reflections, Neon", "rainbow_neon"),
510
+ ("Apocalyptic, Smoky Atmosphere", "apocalyptic"),
511
+ ("Red Glow, Emergency Lights", "emergency_red"),
512
+ ("Mystical Glow, Enchanted Forest", "mystical_forest"),
513
+ ("Campfire Light", "campfire"),
514
+ ("Harsh, Industrial Lighting", "industrial_harsh"),
515
+ ("Sunrise in the Mountains", "mountain_sunrise"),
516
+ ("Evening Glow in the Desert", "desert_evening"),
517
+ ("Moonlight in a Dark Alley", "dark_alley"),
518
+ ("Golden Glow at a Fairground", "fairground"),
519
+ ("Midnight in the Forest", "forest_midnight"),
520
+ ("Purple and Pink Hues at Twilight", "twilight_purple"),
521
+ ("Foggy Morning, Muted Light", "foggy_morning"),
522
+ ("Candle-lit Room, Rustic Vibe", "rustic_candle"),
523
+ ("Fluorescent Office Lighting", "office_fluorescent"),
524
+ ("Lightning Flash in Storm", "storm_lightning"),
525
+ ("Night, Cozy Warm Light from Fireplace", "fireplace_night"),
526
+ ("Ethereal Glow, Magical Forest", "ethereal_magic"),
527
+ ("Dusky Evening on a Beach", "beach_dusky"),
528
+ ("Afternoon Light Filtering through Trees", "trees_afternoon"),
529
+ ("Blue Neon Light, Urban Street", "urban_blue_neon"),
530
+ ("Red and Blue Police Lights in Rain", "rain_police"),
531
+ ("Aurora Borealis Glow, Arctic Landscape", "aurora_arctic"),
532
+ ("Sunrise through Foggy Mountains", "foggy_mountains"),
533
+ ("Golden Hour on a City Skyline", "city_skyline"),
534
+ ("Mysterious Twilight, Heavy Mist", "twilight_mist"),
535
+ ("Early Morning Rays, Forest Clearing", "forest_rays"),
536
+ ("Colorful Lantern Light at Festival", "festival_lantern"),
537
+ ("Soft Glow through Stained Glass", "stained_glass"),
538
+ ("Harsh Spotlight in Dark Room", "dark_spotlight"),
539
+ ("Mellow Evening Glow on a Lake", "lake_evening"),
540
+ ("Crystal Reflections in a Cave", "cave_crystal"),
541
+ ("Vibrant Autumn Lighting in a Forest", "autumn_forest"),
542
+ ("Gentle Snowfall at Dusk", "snowfall_dusk"),
543
+ ("Hazy Light of a Winter Morning", "winter_hazy"),
544
+ ("Rain-soaked Reflections in City Lights", "rain_city"),
545
+ ("Golden Sunlight Streaming through Trees", "trees_golden_sun"),
546
+ ("Fireflies Lighting up a Summer Night", "fireflies_summer"),
547
+ ("Glowing Embers from a Forge", "forge_embers"),
548
+ ("Dim Candlelight in a Gothic Castle", "gothic_castle"),
549
+ ("Midnight Sky with Bright Starlight", "starlight_midnight"),
550
+ ("Warm Sunset in a Rural Village", "rural_sunset"),
551
+ ("Flickering Light in a Haunted House", "haunted_flicker"),
552
+ ("Desert Sunset with Mirage-like Glow", "desert_mirage"),
553
+ ("Golden Beams Piercing through Storm Clouds", "storm_beams"),
554
+ ("Custom", "custom"),
555
+ ],
556
+ value="none",
557
+ elem_classes="radio-group"
558
+ )
559
+ illumination_env_custom = gr.Textbox(
560
+ label="Custom Illumination Environment",
561
+ placeholder="e.g., Inside a crystal palace, Underwater volcano, etc.",
562
+ visible=False
563
+ )
564
+
565
+ with gr.Tab("Custom Prompt"):
566
+ with gr.Accordion("✍️ Custom Prompt (in any language)", open=False):
567
+ prompt = gr.Textbox(
568
+ placeholder="Example: Add warm sunset lighting from the right",
569
+ lines=3
570
+ )
571
 
572
  with gr.Row():
573
  reset_btn = gr.Button("🔄 Reset")
 
583
 
584
  with gr.Column(scale=1):
585
  result = gr.Image(label="Output Image", interactive=False)
586
+ prompt_preview = gr.Textbox(label="Processed Prompt (in Chinese)", interactive=False)
587
  create_video_button = gr.Button("🎥 Create Video Between Images", variant="secondary", visible=False)
588
  with gr.Group(visible=False) as video_group:
589
  video_output = gr.Video(label="Generated Video", show_download_button=True, autoplay=True)
590
 
591
  inputs = [
592
+ image, light_type, light_type_custom, light_direction, light_direction_custom,
593
+ light_intensity, light_intensity_custom, illumination_env, illumination_env_custom,
594
+ prompt, seed, randomize_seed, true_guidance_scale, num_inference_steps, height, width, prev_output
595
  ]
596
  outputs = [result, seed, prompt_preview]
597
 
598
+ # Toggle custom textboxes visibility
599
+ light_type.change(fn=toggle_custom_textbox, inputs=[light_type], outputs=[light_type_custom], queue=False)
600
+ light_direction.change(fn=toggle_custom_textbox, inputs=[light_direction], outputs=[light_direction_custom], queue=False)
601
+ light_intensity.change(fn=toggle_custom_textbox, inputs=[light_intensity], outputs=[light_intensity_custom], queue=False)
602
+ illumination_env.change(fn=toggle_custom_textbox, inputs=[illumination_env], outputs=[illumination_env_custom], queue=False)
603
+
604
  # Reset behavior
605
  reset_btn.click(
606
  fn=reset_all,
607
  inputs=None,
608
+ outputs=[light_type, light_type_custom, light_direction, light_direction_custom,
609
+ light_intensity, light_intensity_custom, illumination_env, illumination_env_custom,
610
+ prompt, is_reset],
611
  queue=False
612
  ).then(fn=end_reset, inputs=None, outputs=[is_reset], queue=False)
613
 
 
639
  # Examples
640
  gr.Examples(
641
  examples=[
642
+ ["harold.png", "dramatic", "", "side", "", "soft", "", "none", "", "", 0, True, 1.0, 4, 672, 1024],
643
+ ["distracted.png", "golden_hour", "", "side", "", "strong", "", "none", "", "", 0, True, 1.0, 4, 640, 1024],
644
+ ["disaster.jpg", "moonlight", "", "front", "", "medium", "", "neon_city", "", "", 0, True, 1.0, 4, 640, 1024],
645
  ],
646
+ inputs=[image, light_type, light_type_custom, light_direction, light_direction_custom,
647
+ light_intensity, light_intensity_custom, illumination_env, illumination_env_custom,
648
+ prompt, seed, randomize_seed, true_guidance_scale, num_inference_steps, height, width],
649
  outputs=outputs,
650
  fn=infer_relight,
651
  cache_examples="lazy",
 
660
  ).then(
661
  fn=reset_all,
662
  inputs=None,
663
+ outputs=[light_type, light_type_custom, light_direction, light_direction_custom,
664
+ light_intensity, light_intensity_custom, illumination_env, illumination_env_custom,
665
+ prompt, is_reset],
666
  queue=False
667
  ).then(
668
  fn=end_reset,
 
672
  )
673
 
674
 
675
+ # Live updates - only trigger on non-custom radio selections
676
  def maybe_infer(is_reset, progress=gr.Progress(track_tqdm=True), *args):
677
  if is_reset:
678
  return gr.update(), gr.update(), gr.update(), gr.update()
 
683
  return result_img, result_seed, result_prompt, gr.update(visible=show_button)
684
 
685
  control_inputs = [
686
+ image, light_type, light_type_custom, light_direction, light_direction_custom,
687
+ light_intensity, light_intensity_custom, illumination_env, illumination_env_custom,
688
+ prompt, seed, randomize_seed, true_guidance_scale, num_inference_steps, height, width, prev_output
689
  ]
690
  control_inputs_with_flag = [is_reset] + control_inputs
691
 
692
+ # Only trigger live updates when selecting non-custom options
693
+ def should_trigger_infer(choice):
694
+ return choice != "custom"
695
+
696
  for control in [light_type, light_direction, light_intensity, illumination_env]:
697
+ control.input(
698
+ fn=lambda choice, *args: maybe_infer(*args) if should_trigger_infer(choice) else (gr.update(), gr.update(), gr.update(), gr.update()),
699
+ inputs=[control] + control_inputs_with_flag,
700
+ outputs=outputs + [create_video_button]
701
+ )
702
 
703
  run_event.then(lambda img, *_: img, inputs=[result], outputs=[prev_output])
704