56 lines
1.7 KiB
Python
56 lines
1.7 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""服务端 PNG 渲染:通过 sharp 将 SVG 转为 PNG。"""
|
||
|
||
import os
|
||
import subprocess
|
||
|
||
|
||
def _script_path():
|
||
return os.path.join(os.path.dirname(__file__), "svg_to_png.js")
|
||
|
||
|
||
def render_png_from_svg(svg_text, width, height, *, timeout_seconds=20):
|
||
if not svg_text or not str(svg_text).strip():
|
||
raise ValueError("SVG 内容为空")
|
||
|
||
script = _script_path()
|
||
if not os.path.isfile(script):
|
||
raise FileNotFoundError(f"未找到 SVG 转 PNG 脚本: {script}")
|
||
|
||
safe_width = max(1, min(4096, int(round(float(width or 0) or 0))))
|
||
safe_height = max(1, min(4096, int(round(float(height or 0) or 0))))
|
||
|
||
cmd = [
|
||
"node",
|
||
script,
|
||
"--width",
|
||
str(safe_width),
|
||
"--height",
|
||
str(safe_height),
|
||
]
|
||
|
||
try:
|
||
completed = subprocess.run(
|
||
cmd,
|
||
input=str(svg_text).encode("utf-8"),
|
||
stdout=subprocess.PIPE,
|
||
stderr=subprocess.PIPE,
|
||
timeout=timeout_seconds,
|
||
check=False,
|
||
)
|
||
except FileNotFoundError as error:
|
||
raise RuntimeError("未找到 node,请先安装 Node.js") from error
|
||
|
||
if completed.returncode != 0:
|
||
stderr = completed.stderr.decode("utf-8", errors="replace").strip()
|
||
if "Cannot find module 'sharp'" in stderr:
|
||
raise RuntimeError("缺少 sharp 依赖,请在项目根目录执行: npm install")
|
||
raise RuntimeError(stderr or f"PNG 渲染失败,退出码: {completed.returncode}")
|
||
|
||
png_bytes = completed.stdout
|
||
if not png_bytes:
|
||
raise RuntimeError("PNG 渲染失败,返回空内容")
|
||
|
||
return png_bytes
|