Last active
January 24, 2026 03:21
-
-
Save mistivia/e5a0890f688225e3b6eb0f98b97cefa4 to your computer and use it in GitHub Desktop.
Convert LaTeX formula to SVG
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Usage: echo '$$E = mc^2$$' | tex2svg > einstein.svg | |
| # 遇到错误立即退出 | |
| set -e | |
| # 检查依赖工具 | |
| command -v xelatex >/dev/null 2>&1 || { echo >&2 "Error: xelatex not found."; exit 1; } | |
| command -v pdf2svg >/dev/null 2>&1 || { echo >&2 "Error: pdf2svg not found."; exit 1; } | |
| command -v magick >/dev/null 2>&1 || { echo >&2 "Error: magick not found."; exit 1; } | |
| # 创建临时目录,并在脚本结束时自动清理 | |
| TMP_DIR=$(mktemp -d) | |
| cleanup() { | |
| rm -rf "$TMP_DIR" | |
| } | |
| trap cleanup EXIT | |
| # 1. 从 Stdin 读取 Latex 公式 | |
| # 读取所有输入到变量中 | |
| INPUT_LATEX=$(cat) | |
| if [ -z "$INPUT_LATEX" ]; then | |
| echo >&2 "Error: No input provided via stdin." | |
| exit 1 | |
| fi | |
| # 2. 构造 Latex 文件并调用 xelatex 渲染成 PDF | |
| # 使用 article 类生成整页,这样才有白边可以让我们裁切 | |
| cat <<EOF > "$TMP_DIR/formula.tex" | |
| \documentclass[12pt]{article} | |
| \usepackage{amsmath,amssymb,amsfonts} | |
| \usepackage{fontspec} | |
| \usepackage{geometry} | |
| % 设置页边距为0,方便计算,但通常pdf2svg处理整页坐标 | |
| \geometry{paper=a4paper, margin=1in} | |
| \pagestyle{empty} | |
| \begin{document} | |
| % 使用 display math 环境 | |
| $INPUT_LATEX | |
| \end{document} | |
| EOF | |
| # 编译 PDF (静默模式) | |
| cd "$TMP_DIR" | |
| xelatex -interaction=nonstopmode -output-directory="$TMP_DIR" formula.tex >/dev/null 2>&1 | |
| if [ ! -f "formula.pdf" ]; then | |
| echo >&2 "Error: xelatex compilation failed. Check your latex syntax." | |
| exit 1 | |
| fi | |
| # 3. 调用 pdf2svg 渲染成 SVG (此时是整页 SVG) | |
| pdf2svg "formula.pdf" "formula.svg" | |
| # 4. 把 SVG 渲染成 PNG | |
| # 关键点:设置 density 72,这样 1 pixel = 1 point (SVG默认单位) | |
| # 这样 magick 计算出的像素坐标可以直接用于 SVG 的 viewBox | |
| magick -density 72 "formula.svg" "formula.png" | |
| # 5. 用 magick 查看切掉白边需要的参数 | |
| # -format "%@" 返回类似 "100x50+20+30" (WxH+X+Y) 的字符串,表示非空白区域的边界框 | |
| CROP_GEOMETRY=$(magick "formula.png" -format "%@" info:) | |
| # 解析几何参数 | |
| # 格式: WIDTHxHEIGHT+X+Y | |
| # 使用 bash 字符串操作解析 | |
| rest=${CROP_GEOMETRY#*x} | |
| WIDTH=${CROP_GEOMETRY%%x*} | |
| HEIGHT=${rest%%+*} | |
| rest=${rest#*+} | |
| X=${rest%%+*} | |
| Y=${rest#*+} | |
| # 6. 用这个参数,裁切原来的 svg | |
| # SVG 的 viewBox 属性格式为: viewBox="min-x min-y width height" | |
| # 我们直接修改 SVG 文件的头部 | |
| # 为了安全起见,我们添加一点点 padding (例如 2pt),避免边缘笔画被切断 | |
| PADDING=2 | |
| WIDTH=$(($WIDTH + $PADDING * 2)) | |
| HEIGHT=$(($HEIGHT + $PADDING * 2)) | |
| X=$(($X - $PADDING)) | |
| Y=$(($Y - $PADDING)) | |
| # 确保 X, Y 不小于 0 | |
| if [ "$X" -lt 0 ]; then X=0; fi | |
| if [ "$Y" -lt 0 ]; then Y=0; fi | |
| # 使用 sed 修改 svg 文件 | |
| # 替换 width, height 和 viewBox | |
| # pdf2svg 输出的 svg 头部通常很标准,包含 width="..." height="..." viewBox="..." | |
| sed -i \ | |
| -e "s/width=\"[^\"]*\"/width=\"${WIDTH}pt\"/" \ | |
| -e "s/height=\"[^\"]*\"/height=\"${HEIGHT}pt\"/" \ | |
| -e "s/viewBox=\"[^\"]*\"/viewBox=\"$X $Y $WIDTH $HEIGHT\"/" \ | |
| "formula.svg" | |
| # 7. 在 stdout 输出 SVG 结果 | |
| cat "formula.svg" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment