Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| import base64 | |
| from pathlib import Path | |
| import html | |
| import gradio as gr | |
| ROOT = Path(__file__).resolve().parent | |
| REPO = "https://huggingface.co/spaces/zcahjl3/figmirror-code-aug10" | |
| CSS = """ | |
| <style> | |
| body { margin: 0; } | |
| .fm-wrap { font-family: Arial, sans-serif; color: #172033; background: #f5f6f8; padding: 0 0 28px; } | |
| .fm-header { background: #fff; border-bottom: 1px solid #d9dee7; padding: 22px 28px; } | |
| .fm-header h1 { margin: 0 0 8px; font-size: 25px; line-height: 1.2; } | |
| .fm-header p { margin: 0; color: #667085; font-size: 13px; line-height: 1.45; max-width: 1050px; } | |
| .fm-main { padding: 20px 28px; display: grid; gap: 18px; } | |
| .fm-card { background: #fff; border: 1px solid #d9dee7; border-radius: 8px; padding: 14px; } | |
| .fm-card h2 { margin: 0 0 10px; font-size: 15px; } | |
| .fm-card img { width: 100%; max-height: 720px; object-fit: contain; display: block; border: 1px solid #e5e7eb; background: #fff; } | |
| .fm-card p { margin: 8px 0; color: #667085; font-size: 12px; line-height: 1.45; } | |
| .fm-links { display: flex; flex-wrap: wrap; gap: 8px 14px; } | |
| .fm-links a { color: #0b61a4; text-decoration: none; font-size: 12px; } | |
| .fm-links a:hover { text-decoration: underline; } | |
| code { background: #f2f4f7; padding: 1px 4px; border-radius: 4px; } | |
| </style> | |
| """ | |
| def image_data(path: Path) -> str: | |
| data = base64.b64encode(path.read_bytes()).decode("ascii") | |
| return f"data:image/png;base64,{data}" | |
| def rel_url(slug: str, filename: str) -> str: | |
| return f"{REPO}/resolve/main/{slug}/{filename}" | |
| def build_html() -> str: | |
| cases = sorted(p for p in ROOT.iterdir() if p.is_dir() and (p / "comparison.png").exists()) | |
| cards = [] | |
| for case in cases: | |
| slug = case.name | |
| parts = slug.split("_", 2) | |
| chart_type = html.escape(parts[1] if len(parts) > 1 else slug) | |
| label = html.escape(parts[2] if len(parts) > 2 else slug) | |
| img = image_data(case / "comparison.png") | |
| cards.append(f""" | |
| <article class="fm-card"> | |
| <h2>{chart_type} · {label}</h2> | |
| <img src="{img}" alt="Original code render versus data-preserving FigMirror code augmentation"> | |
| <p>Both sides are generated from code. Left: unchanged <code>original.py</code>. Right: <code>augmented.py</code>, preserving the same data and chart topology while improving figure aesthetics.</p> | |
| <p class="fm-links"> | |
| <a href="{rel_url(slug, 'original_render.png')}" target="_blank">original render</a> | |
| <a href="{rel_url(slug, 'original.py')}" target="_blank">original code</a> | |
| <a href="{rel_url(slug, 'augmented_render.png')}" target="_blank">augmented render</a> | |
| <a href="{rel_url(slug, 'augmented.py')}" target="_blank">augmented code</a> | |
| <a href="{rel_url(slug, 'comparison.png')}" target="_blank">comparison PNG</a> | |
| </p> | |
| </article>""") | |
| return CSS + f""" | |
| <div class="fm-wrap"> | |
| <header class="fm-header"> | |
| <h1>FigMirror Data-Preserving Code Augmentation - 10 Cases</h1> | |
| <p>Each case compares two code-generated images. The right-hand figure is not a new task: it keeps the original data, labels, chart type/topology, and analytical relation, then applies FigMirror presentation improvements.</p> | |
| </header> | |
| <main class="fm-main">{''.join(cards)}</main> | |
| </div>""" | |
| with gr.Blocks(title="FigMirror Code Augmentation") as demo: | |
| gr.HTML(build_html()) | |
| if __name__ == "__main__": | |
| demo.launch() | |