Spaces:
Sleeping
Sleeping
showcase
Browse files
app.py
CHANGED
|
@@ -59,20 +59,54 @@ def _image_data_uri(path: Path) -> str:
|
|
| 59 |
return f"data:{mime};base64,{data}"
|
| 60 |
|
| 61 |
|
| 62 |
-
def _showcase_marquee_html() -> str:
|
| 63 |
cards = []
|
| 64 |
for idx, path in enumerate(SHOWCASE_IMAGES):
|
| 65 |
uri = _image_data_uri(path)
|
| 66 |
if uri:
|
| 67 |
cards.append(f'<img src="{uri}" alt="Try-on showcase {idx + 1}" />')
|
| 68 |
row = "".join(cards)
|
|
|
|
| 69 |
return f"""
|
| 70 |
-
<div class="showcase-marquee" aria-label="效果展示">
|
| 71 |
<div class="showcase-track">{row}{row}</div>
|
| 72 |
</div>
|
| 73 |
"""
|
| 74 |
|
| 75 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
def _file_path(item) -> str | None:
|
| 77 |
if item is None:
|
| 78 |
return None
|
|
@@ -237,6 +271,9 @@ def _predict_from_prompt_files(prompt: str, files):
|
|
| 237 |
enhanced_prompt,
|
| 238 |
pe_status,
|
| 239 |
gr.update(value=display_status, visible=True),
|
|
|
|
|
|
|
|
|
|
| 240 |
)
|
| 241 |
|
| 242 |
except gr.Error:
|
|
@@ -465,10 +502,14 @@ body, .gradio-container {
|
|
| 465 |
.result-card-output {
|
| 466 |
border: 0 !important;
|
| 467 |
background: transparent !important;
|
|
|
|
|
|
|
|
|
|
| 468 |
}
|
| 469 |
.result-card-output img {
|
| 470 |
border-radius: 34px !important;
|
| 471 |
-
|
|
|
|
| 472 |
object-fit: contain !important;
|
| 473 |
box-shadow: none !important;
|
| 474 |
}
|
|
@@ -512,6 +553,23 @@ body, .gradio-container {
|
|
| 512 |
transform: scale(1.055);
|
| 513 |
box-shadow: 0 22px 56px rgba(0,0,0,.16);
|
| 514 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 515 |
@keyframes showcase-scroll {
|
| 516 |
from { transform: translateX(0); }
|
| 517 |
to { transform: translateX(calc(-50% - 17px)); }
|
|
@@ -524,6 +582,7 @@ body, .gradio-container {
|
|
| 524 |
.prompt-shell { width: min(100%, calc(100vw - 28px)); }
|
| 525 |
.prompt-shell textarea, .prompt-shell [contenteditable="true"] { font-size: 17px !important; min-height: 38px !important; padding-left: 58px !important; }
|
| 526 |
.showcase-track img { width: 430px; min-width: 430px; }
|
|
|
|
| 527 |
}
|
| 528 |
"""
|
| 529 |
|
|
@@ -538,8 +597,10 @@ with gr.Blocks(title="JoyAI Virtual Try-On", css=CSS) as demo:
|
|
| 538 |
"""
|
| 539 |
)
|
| 540 |
|
|
|
|
|
|
|
| 541 |
with gr.Column(elem_classes=["tryon-hero"]):
|
| 542 |
-
gr.HTML('<div class="tryon-title">开始虚拟试穿之旅,放入图像或写指令来看效果</div>')
|
| 543 |
prompt_box = gr.MultimodalTextbox(
|
| 544 |
label="",
|
| 545 |
placeholder="描述你想要的试穿效果",
|
|
@@ -563,9 +624,19 @@ with gr.Blocks(title="JoyAI Virtual Try-On", css=CSS) as demo:
|
|
| 563 |
used_garment_index = gr.Number(label="Used Garment Index", precision=0)
|
| 564 |
|
| 565 |
with gr.Column(elem_classes=["showcase-wrap"]):
|
| 566 |
-
gr.HTML(_showcase_marquee_html())
|
| 567 |
-
|
| 568 |
-
predict_outputs = [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 569 |
|
| 570 |
prompt_box.submit(
|
| 571 |
fn=predict_from_message,
|
|
|
|
| 59 |
return f"data:{mime};base64,{data}"
|
| 60 |
|
| 61 |
|
| 62 |
+
def _showcase_marquee_html(compact: bool = False) -> str:
|
| 63 |
cards = []
|
| 64 |
for idx, path in enumerate(SHOWCASE_IMAGES):
|
| 65 |
uri = _image_data_uri(path)
|
| 66 |
if uri:
|
| 67 |
cards.append(f'<img src="{uri}" alt="Try-on showcase {idx + 1}" />')
|
| 68 |
row = "".join(cards)
|
| 69 |
+
compact_class = " compact" if compact else ""
|
| 70 |
return f"""
|
| 71 |
+
<div class="showcase-marquee{compact_class}" aria-label="效果展示">
|
| 72 |
<div class="showcase-track">{row}{row}</div>
|
| 73 |
</div>
|
| 74 |
"""
|
| 75 |
|
| 76 |
|
| 77 |
+
RESULT_LAYOUT_CSS = """
|
| 78 |
+
<style>
|
| 79 |
+
.tryon-hero {
|
| 80 |
+
padding-top: 88px !important;
|
| 81 |
+
padding-bottom: 14px !important;
|
| 82 |
+
}
|
| 83 |
+
.workspace {
|
| 84 |
+
display: flex !important;
|
| 85 |
+
flex-direction: column !important;
|
| 86 |
+
align-items: center !important;
|
| 87 |
+
padding-top: 16px !important;
|
| 88 |
+
}
|
| 89 |
+
.result-card-output {
|
| 90 |
+
width: min(1180px, calc(100vw - 56px)) !important;
|
| 91 |
+
margin: 0 auto !important;
|
| 92 |
+
}
|
| 93 |
+
.showcase-wrap {
|
| 94 |
+
padding-top: 12px !important;
|
| 95 |
+
padding-bottom: 24px !important;
|
| 96 |
+
}
|
| 97 |
+
@media (max-width: 760px) {
|
| 98 |
+
.tryon-hero {
|
| 99 |
+
padding-top: 86px !important;
|
| 100 |
+
padding-bottom: 10px !important;
|
| 101 |
+
}
|
| 102 |
+
.result-card-output {
|
| 103 |
+
width: min(100%, calc(100vw - 24px)) !important;
|
| 104 |
+
}
|
| 105 |
+
}
|
| 106 |
+
</style>
|
| 107 |
+
"""
|
| 108 |
+
|
| 109 |
+
|
| 110 |
def _file_path(item) -> str | None:
|
| 111 |
if item is None:
|
| 112 |
return None
|
|
|
|
| 271 |
enhanced_prompt,
|
| 272 |
pe_status,
|
| 273 |
gr.update(value=display_status, visible=True),
|
| 274 |
+
gr.update(visible=False),
|
| 275 |
+
RESULT_LAYOUT_CSS,
|
| 276 |
+
_showcase_marquee_html(compact=True),
|
| 277 |
)
|
| 278 |
|
| 279 |
except gr.Error:
|
|
|
|
| 502 |
.result-card-output {
|
| 503 |
border: 0 !important;
|
| 504 |
background: transparent !important;
|
| 505 |
+
display: flex !important;
|
| 506 |
+
justify-content: center !important;
|
| 507 |
+
align-items: center !important;
|
| 508 |
}
|
| 509 |
.result-card-output img {
|
| 510 |
border-radius: 34px !important;
|
| 511 |
+
width: min(100%, 1180px) !important;
|
| 512 |
+
max-height: min(68vh, 680px) !important;
|
| 513 |
object-fit: contain !important;
|
| 514 |
box-shadow: none !important;
|
| 515 |
}
|
|
|
|
| 553 |
transform: scale(1.055);
|
| 554 |
box-shadow: 0 22px 56px rgba(0,0,0,.16);
|
| 555 |
}
|
| 556 |
+
.showcase-marquee.compact {
|
| 557 |
+
mask-image: linear-gradient(to right, transparent, black 10%, black 90%, transparent);
|
| 558 |
+
}
|
| 559 |
+
.showcase-marquee.compact .showcase-track {
|
| 560 |
+
gap: 14px;
|
| 561 |
+
animation-duration: 92s;
|
| 562 |
+
}
|
| 563 |
+
.showcase-marquee.compact .showcase-track img {
|
| 564 |
+
width: min(19vw, 286px);
|
| 565 |
+
min-width: 220px;
|
| 566 |
+
border-radius: 10px !important;
|
| 567 |
+
box-shadow: 0 8px 22px rgba(0,0,0,.08);
|
| 568 |
+
}
|
| 569 |
+
.showcase-marquee.compact .showcase-track img:hover {
|
| 570 |
+
transform: scale(1.035);
|
| 571 |
+
box-shadow: 0 12px 30px rgba(0,0,0,.12);
|
| 572 |
+
}
|
| 573 |
@keyframes showcase-scroll {
|
| 574 |
from { transform: translateX(0); }
|
| 575 |
to { transform: translateX(calc(-50% - 17px)); }
|
|
|
|
| 582 |
.prompt-shell { width: min(100%, calc(100vw - 28px)); }
|
| 583 |
.prompt-shell textarea, .prompt-shell [contenteditable="true"] { font-size: 17px !important; min-height: 38px !important; padding-left: 58px !important; }
|
| 584 |
.showcase-track img { width: 430px; min-width: 430px; }
|
| 585 |
+
.showcase-marquee.compact .showcase-track img { width: 168px; min-width: 168px; }
|
| 586 |
}
|
| 587 |
"""
|
| 588 |
|
|
|
|
| 597 |
"""
|
| 598 |
)
|
| 599 |
|
| 600 |
+
layout_css = gr.HTML("")
|
| 601 |
+
|
| 602 |
with gr.Column(elem_classes=["tryon-hero"]):
|
| 603 |
+
hero_title = gr.HTML('<div class="tryon-title">开始虚拟试穿之旅,放入图像或写指令来看效果</div>')
|
| 604 |
prompt_box = gr.MultimodalTextbox(
|
| 605 |
label="",
|
| 606 |
placeholder="描述你想要的试穿效果",
|
|
|
|
| 624 |
used_garment_index = gr.Number(label="Used Garment Index", precision=0)
|
| 625 |
|
| 626 |
with gr.Column(elem_classes=["showcase-wrap"]):
|
| 627 |
+
showcase = gr.HTML(_showcase_marquee_html())
|
| 628 |
+
|
| 629 |
+
predict_outputs = [
|
| 630 |
+
output_image,
|
| 631 |
+
used_seed,
|
| 632 |
+
used_garment_index,
|
| 633 |
+
enhanced_prompt,
|
| 634 |
+
pe_status,
|
| 635 |
+
status,
|
| 636 |
+
hero_title,
|
| 637 |
+
layout_css,
|
| 638 |
+
showcase,
|
| 639 |
+
]
|
| 640 |
|
| 641 |
prompt_box.submit(
|
| 642 |
fn=predict_from_message,
|