如何用Python获取SVG文件中所有元素的整体边界框?
Python获取带变换的SVG图形边界框解决方案
方案一:svgpathtools + svgtransforms 手动处理变换
svgpathtools本身不会自动处理元素的继承变换,但可以通过手动解析并累积变换矩阵,将变换应用到路径的边界框顶点上,最终计算整体边界。
依赖安装
pip install svgpathtools svgtransforms
实现代码
from svgpathtools import svg2paths2 from svgtransforms import parse_transform, Transform def get_transformed_bbox(svg_file): paths, attributes, svg_root = svg2paths2(svg_file) all_transformed_points = [] for path, attr in zip(paths, attributes): # 累积当前路径的所有祖先变换矩阵 current_transform = Transform() elem = attr['element'] while elem is not None: if 'transform' in elem.attrib: transform = parse_transform(elem.attrib['transform']) # 祖先变换先应用,左乘累积矩阵 current_transform = transform @ current_transform elem = elem.parent # 获取原始路径边界框的四个顶点 xmin, xmax, ymin, ymax = path.bbox() bbox_points = [ complex(xmin, ymin), complex(xmax, ymin), complex(xmax, ymax), complex(xmin, ymax) ] # 应用变换并收集所有顶点 for pt in bbox_points: transformed_pt = current_transform.apply(pt) all_transformed_points.append((transformed_pt.real, transformed_pt.imag)) # 计算整体边界框 xs = [p[0] for p in all_transformed_points] ys = [p[1] for p in all_transformed_points] min_x, max_x = min(xs), max(xs) min_y, max_y = min(ys), max(ys) return (min_x, min_y), max_x - min_x, max_y - min_y # 测试示例SVG origin, width, height = get_transformed_bbox("example.svg") print(f"边界框原点: ({origin[0]:.3f}, {origin[1]:.3f})") print(f"宽度: {width:.3f}, 高度: {height:.3f}")
运行后结果会和Inkscape测量值高度吻合(浮点误差范围内),因为它完整处理了所有继承的transform属性。
方案二:Pycairo 渲染获取边界框
通过Pycairo直接渲染SVG,利用其内置的边界计算功能自动处理所有变换,结果准确。
依赖安装
pip install pycairo
实现代码
import cairo def get_svg_bbox_cairo(svg_file): with open(svg_file, 'rb') as f: svg_data = f.read() # 创建SVG图案并获取边界 surface = cairo.SVGSurface(None, 0, 0) ctx = cairo.Context(surface) svg_pattern = cairo.SVGPattern.create_for_data(svg_data) extents = svg_pattern.get_extents() return (extents.x, extents.y), extents.width, extents.height # 测试 origin, width, height = get_svg_bbox_cairo("example.svg") print(f"边界框原点: ({origin[0]:.3f}, {origin[1]:.3f})") print(f"宽度: {width:.3f}, 高度: {height:.3f}")
注意:Pycairo依赖系统级的cairo库,Linux通常预装,Windows需手动安装对应版本的二进制包。
方案三:Wand 基于ImageMagick实现
Wand是ImageMagick的Python绑定,通过裁剪功能获取实际图形边界。
依赖安装
pip install wand
(需先安装ImageMagick系统库)
实现代码
from wand.image import Image def get_svg_bbox_wand(svg_file): with Image(filename=svg_file) as img: img.trim() # 自动裁剪到图形实际边界 origin = (img.page.x, img.page.y) return origin, img.width, img.height # 测试 origin, width, height = get_svg_bbox_wand("example.svg") print(f"边界框原点: ({origin[0]:.3f}, {origin[1]:.3f})") print(f"宽度: {width:.3f}, 高度: {height:.3f}")
内容的提问来源于stack exchange,提问作者Tim Kolar
相关产品推荐
相关产品推荐

