冰朔 c80d804bf9
Some checks failed
自动更新代码和重启 / update-and-restart (push) Has been cancelled
CI检查 + 自动部署 / check (push) Has been cancelled
CI检查 + 自动部署 / deploy (push) Has been cancelled
D144: 新增SVG转PNG渲染工具·解决FFmpeg无SVG解码器问题
- 新增 tools/svg-to-png.py:CairoSVG渲染工具,支持单文件/批量SVG→PNG转换
- 新增 tools/README-SVG-TO-PNG.md:工具使用文档
- 更新 ENTRY.hdlp:工具链增加 svg-to-png.py 条目
- 依赖:pip install cairosvg Pillow + brew install cairo
- 路径:video-ai-system/tools/svg-to-png.py
2026-06-23 23:07:48 +08:00

190 lines
5.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
SVG to PNG Renderer
==========
将 SVG 文件渲染为 PNG 图片。
依赖:
pip install cairosvg Pillow
用法:
# 基本用法(自动读取 SVG 尺寸)
python svg-to-png.py input.svg output.png
# 指定输出宽度(高度等比缩放)
python svg-to-png.py input.svg output.png --width 1920
# 指定输出高度(宽度等比缩放)
python svg-to-png.py input.svg output.png --height 1080
# 指定缩放因子(基于 SVG 原始尺寸放大 / 缩小)
python svg-to-png.py input.svg output.png --scale 2
# 批量转换目录下的所有 SVG
python svg-to-png.py ./svg-dir/ ./png-dir/ --batch
# 作为模块导入
from svg_to_png import convert_svg_to_png
convert_svg_to_png("input.svg", "output.png", scale=2)
路径:
video-ai-system/tools/svg-to-png.py
"""
import argparse
import os
import sys
from pathlib import Path
try:
import cairosvg
from PIL import Image
except ImportError as e:
print(f"[ERROR] 缺少依赖:{e}")
print("请先安装pip install cairosvg Pillow")
sys.exit(1)
def convert_svg_to_png(
svg_path: str,
png_path: str,
width: int = None,
height: int = None,
scale: float = None,
background: str = "white",
) -> bool:
"""
将单个 SVG 文件转换为 PNG。
:param svg_path: 输入 SVG 文件路径
:param png_path: 输出 PNG 文件路径
:param width: 输出宽度px为 None 时保留 SVG 原始宽度
:param height: 输出高度px为 None 时保留 SVG 原始高度
:param scale: 缩放因子,基于 SVG 原始尺寸等比缩放
:param background: 背景色,默认白色;设为 None 保留透明
:return: 是否转换成功
"""
if not os.path.isfile(svg_path):
print(f"[ERROR] SVG 文件不存在:{svg_path}")
return False
# 确保输出目录存在
os.makedirs(os.path.dirname(os.path.abspath(png_path)), exist_ok=True)
try:
# 构造 cairosvg 参数
kwargs = {
"url": svg_path,
"write_to": png_path,
}
if background:
kwargs["background_color"] = background
if scale is not None:
kwargs["scale"] = scale
else:
if width is not None:
kwargs["output_width"] = width
if height is not None:
kwargs["output_height"] = height
cairosvg.svg2png(**kwargs)
# 验证输出文件
if os.path.isfile(png_path):
file_size = os.path.getsize(png_path)
print(f"[OK] {svg_path}{png_path} ({file_size // 1024} KB)")
return True
else:
print(f"[ERROR] 输出文件未生成:{png_path}")
return False
except Exception as e:
print(f"[ERROR] 转换失败 {svg_path}{e}")
return False
def batch_convert(
svg_dir: str,
png_dir: str,
width: int = None,
height: int = None,
scale: float = None,
) -> tuple:
"""
批量转换目录下的所有 SVG 文件。
:param svg_dir: 输入目录(包含 SVG 文件)
:param png_dir: 输出目录
:return: (成功数, 总数)
"""
if not os.path.isdir(svg_dir):
print(f"[ERROR] 输入目录不存在:{svg_dir}")
return 0, 0
os.makedirs(png_dir, exist_ok=True)
svg_files = sorted(Path(svg_dir).glob("*.svg"))
if not svg_files:
print(f"[WARN] 目录中没有找到 SVG 文件:{svg_dir}")
return 0, 0
print(f"[INFO] 找到 {len(svg_files)} 个 SVG 文件,开始批量转换...")
success = 0
total = len(svg_files)
for svg_file in svg_files:
png_file = os.path.join(png_dir, svg_file.stem + ".png")
if convert_svg_to_png(
str(svg_file), png_file,
width=width, height=height, scale=scale
):
success += 1
print(f"\n[INFO] 批量转换完成:{success}/{total} 成功")
return success, total
def main():
parser = argparse.ArgumentParser(
description="SVG to PNG 渲染工具(基于 CairoSVG",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
示例:
python svg-to-png.py input.svg output.png
python svg-to-png.py input.svg output.png --width 1920
python svg-to-png.py ./svg/ ./png/ --batch --scale 2
"""
)
parser.add_argument("input", help="输入 SVG 文件或目录")
parser.add_argument("output", help="输出 PNG 文件或目录")
parser.add_argument("--width", type=int, default=None, help="输出宽度px")
parser.add_argument("--height", type=int, default=None, help="输出高度px")
parser.add_argument("--scale", type=float, default=None, help="缩放因子")
parser.add_argument("--batch", action="store_true", help="批量转换模式")
parser.add_argument("--background", default="white", help="背景色(默认 white设为 'none' 保留透明)")
args = parser.parse_args()
if args.batch or os.path.isdir(args.input):
# 批量模式
success, total = batch_convert(
args.input, args.output,
width=args.width, height=args.height, scale=args.scale
)
sys.exit(0 if success == total else 1)
else:
# 单文件模式
bg = None if args.background.lower() == "none" else args.background
ok = convert_svg_to_png(
args.input, args.output,
width=args.width, height=args.height,
scale=args.scale, background=bg
)
sys.exit(0 if ok else 1)
if __name__ == "__main__":
main()