77 lines
2.3 KiB
Python
77 lines
2.3 KiB
Python
"""
|
|
Deterministic SVG to High-Resolution PNG Export Pipeline
|
|
Renders docs/diagram-alur.svg to docs/diagram-alur.png at 3840x2160 (4K UHD)
|
|
using Playwright Chromium with device_scale_factor=2.0.
|
|
|
|
Usage:
|
|
uv run python scripts/export_diagram_png.py
|
|
"""
|
|
|
|
import asyncio
|
|
from pathlib import Path
|
|
from playwright.async_api import async_playwright
|
|
from PIL import Image
|
|
|
|
|
|
async def export_svg_to_png(
|
|
svg_path: Path,
|
|
png_path: Path,
|
|
width: int = 1920,
|
|
height: int = 1080,
|
|
scale: float = 2.0
|
|
) -> None:
|
|
if not svg_path.exists():
|
|
raise FileNotFoundError(f"SVG file not found: {svg_path}")
|
|
|
|
svg_content = svg_path.read_text(encoding="utf-8")
|
|
|
|
async with async_playwright() as p:
|
|
browser = await p.chromium.launch()
|
|
page = await browser.new_page(
|
|
viewport={"width": width, "height": height},
|
|
device_scale_factor=scale
|
|
)
|
|
html_wrapper = f"""<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<style>
|
|
* {{ box-sizing: border-box; margin: 0; padding: 0; }}
|
|
html, body {{ width: 100vw; height: 100vh; overflow: hidden; background-color: #080c14; }}
|
|
svg {{ display: block; width: 100%; height: 100%; }}
|
|
</style>
|
|
</head>
|
|
<body>{svg_content}</body>
|
|
</html>"""
|
|
await page.set_content(html_wrapper)
|
|
# Ensure all drop shadows and fonts settle
|
|
await page.wait_for_timeout(350)
|
|
png_bytes = await page.screenshot(type="png")
|
|
await browser.close()
|
|
|
|
png_path.parent.mkdir(parents=True, exist_ok=True)
|
|
png_path.write_bytes(png_bytes)
|
|
|
|
# Verification
|
|
with Image.open(png_path) as img:
|
|
w, h = img.size
|
|
mode = img.mode
|
|
file_size_kb = len(png_bytes) / 1024
|
|
print(f"Exported PNG successfully: {png_path}")
|
|
print(f"Dimensions: {w}x{h} px | Mode: {mode} | Size: {file_size_kb:.1f} KB")
|
|
assert w >= 2400 and h >= 1350, f"Resolution check failed: {w}x{h}"
|
|
assert w == 3840 and h == 2160, f"Expected 3840x2160, got {w}x{h}"
|
|
|
|
|
|
def main():
|
|
root = Path(__file__).resolve().parent.parent
|
|
svg_file = root / "docs" / "diagram-alur.svg"
|
|
png_file = root / "docs" / "diagram-alur.png"
|
|
print(f"Rendering SVG from: {svg_file}")
|
|
print(f"Target PNG: {png_file}")
|
|
asyncio.run(export_svg_to_png(svg_file, png_file, scale=2.0))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|