← 返回 Skill 列表
extension
分类: 开发与工程API Key 暂未确认

SVG/HTML 转 PNG(Chrome 无头,零依赖)

用系统自带的 Chrome/Edge 无头模式把 SVG 或 HTML 渲染成高清 PNG,不需要 cairosvg/svglib/ImageMagick 等第三方依赖。适合把图表、示意图、报表页导出成图片插进文档/PPT/PDF,尤其适合 Windows 上 pip 装不上 cairo 相关库的环境。含浏览器探测、尺寸对齐、透明背景、整页/虚拟时间等踩坑经验。

person作者: MikkeyfhubOpenAPI
<!-- OB-S:0hfRyrm0b_sG7TOGTKOeGw -->

SVG / HTML → 高清 PNG(系统 Chrome headless)

为什么走这条路

Python 侧的 SVG 光栅化方案在 Windows 上普遍难装:

  • cairosvg 依赖 cairocffi,需要系统级 cairo DLL,pip 装完仍可能 import 失败。
  • svglib + reportlab 是纯 Python,但对 CSS、dominant-baseline、marker 等支持不全,常渲染错。
  • ImageMagick / Inkscape 不保证存在。

而 Chrome 和 Edge 在 Windows 上几乎总是存在,无头截图质量高、支持完整 SVG 与 CSS。 先探测浏览器,再决定是否退回 Python 方案。

步骤

1. 探测浏览器路径

import os
cands = [
    r"C:\Program Files\Google\Chrome\Application\chrome.exe",
    r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe",
    r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe",
    r"C:\Program Files\Microsoft\Edge\Application\msedge.exe",
]
print([p for p in cands if os.path.exists(p)])

macOS 用 /Applications/Google Chrome.app/Contents/MacOS/Google Chrome, Linux 用 google-chrome / chromium。

2. 准备 SVG(三个硬约束)

  1. 根 <svg> 必须带 width 和 height 属性,不能只有 viewBox——否则浏览器给的尺寸不确定。 惯例:viewBox="0 0 680 400" 同时写 width="1360" height="800"(2 倍输出)。
  2. 如果要白底图片,在 SVG 里显式画一个覆盖全幅的 <rect>,不要依赖浏览器背景色。
  3. 不要依赖外部字体 CSS 文件;用系统字体族,渲染时由浏览器解析。

3. 渲染

# 直接渲染 SVG 文件
chrome --headless=new --disable-gpu --hide-scrollbars \
  --force-device-scale-factor=2 \
  --screenshot="out.png" \
  --window-size=1360,800 \
  "file:///D:/path/to/fig.svg"

Windows PowerShell 版:

$chrome = "C:\Program Files\Google\Chrome\Application\chrome.exe"
& $chrome --headless=new --disable-gpu --hide-scrollbars `
  --force-device-scale-factor=2 `
  --screenshot="D:\out\fig.png" `
  --window-size=1360,800 `
  "file:///D:/path/to/fig.svg" 2>&1 | Out-String

参数说明:

| 参数 | 作用 | |---|---| | --headless=new | 新版无头模式(老版 --headless 在部分版本已弃用) | | --force-device-scale-factor=2 | 出 2 倍图,插进 PDF / 打印时更清晰 | | --window-size=W,H | 必须与 SVG 的 width/height 一致,否则留白或裁切 | | --hide-scrollbars | 避免边缘出现滚动条 | | --default-background-color=00000000 | 要透明背景时加这个(ARGB,8 位十六进制) |

4. 验证(不可省)

渲染完一定要用 Read 工具把 PNG 读出来看一眼,检查:

  • 边缘有没有元素被裁掉(--window-size 给小了)
  • 四周有没有多余留白(--window-size 给大了)
  • 中文有没有变成方块(字体族没落上)

只看文件大小或“命令返回 0”是不够的——截图失败也可能生成一个空白 PNG。

已知限制

  • --screenshot 只截视口,不截整页。 渲染 HTML 且高度不确定时,先估算一个足够大的 --window-size,或者用 playwright 的 fullPage: true(需要 pip install playwright && playwright install chromium,较重,非必要不用)。
  • 批量渲染要逐个调用,每次一个 --screenshot,不要试图一次渲染多个文件。
  • 首次启动 Chrome 可能较慢(初始化 profile),属正常;连续调用第二次会快很多。
  • 渲染含外部资源的 HTML 时,如果页面用 fetch / XHR 拉数据,截图时机可能早于数据到达。 这种情况改用 --virtual-time-budget=5000 给页面留出执行时间。

从 markdown 文档生成图片的配套做法

如果图是从 markdown 渲染出来的预览页(例如用 marked),常见两个坑:

  • 相对路径的本地图片在别处打不开:把 <img src="figures/x.png"> 转成 data:image/png;base64,... 内联,页面才自包含。
  • marked v12 不给标题生成 id:页内目录锚点会点不动,需要自己按 GitHub 的 slug 规则补 id (小写、去标点、空格转 -)。