python实现SVG文件解析

SVG文件简介

SVG 是使用 XML 来描述二维图形和绘图程序的语言。

  • SVG 指可伸缩矢量图形 (Scalable Vector Graphics)
  • SVG 用来定义用于网络的基于矢量的图形
  • SVG 使用 XML 格式定义图形
  • SVG 图像在放大或改变尺寸的情况下其图形质量不会有所损失
  • SVG 是万维网联盟的标准
  • SVG 与诸如 DOM 和 XSL 之类的 W3C 标准是一个整体

SVG文件包含的形状如下:

  • 矩形
    矩形包含起始点坐标以及宽高信息。
 
  • 圆形
    圆形包含中心点坐标以及半径。
    
  • 椭圆
    椭圆包含中心点坐标以及XY轴半径,圆形可以认为是特殊的椭圆,即XY轴半径相同。
    
  • 线
    直线包含起点与终点的坐标。
    
  • 折线
    折线包含多个点,每个点包含XY轴坐标。
    
  • 多边形
    多边形可以认为是封闭的折线。
    
  • 路径
    路径是使用命令的形式记录形状。
    

用于路径的命令如下:
M = moveto
L = lineto
H = horizontal lineto
V = vertical lineto
C = curveto
S = smooth curveto
Q = quadratic Belzier curve
T = smooth quadratic Belzier curveto
A = elliptical Arc
Z = closepath
注释:以上所有命令均允许小写字母。大写表示绝对定位,小写表示相对定位。

以上形状的效果如下:
python实现SVG文件解析_第1张图片

解析

SVG文件基于xml,针对xml解析的python库较多,这里采用ElementTree进行解析。
Element 对象的常用属性:

  • tag:string 对象,表示数据代表的种类
  • attrib:dictionary 对象,表示附有的属性
  • text:string 对象,表示 element 的内容
  • child elements:若干子元素
    Element 对象的常用方法:
  • iter(tag=None):遍历该 Element 所有后代,也可以指定 tag 进行遍历寻找
  • findall(match):查找当前元素下 tag 或 path 能够匹配的直系节点
  • find(match):查找当前元素下 tag 或 path 能够匹配的首个直系节点
  • get(key, default=None):获取元素指定 key 对应的属性值,如果没有该属性,则返回default值。

解析流程如下:
将SVG文件传入ElementTree模块,获取xml树根。
先获取SVG图形宽高。
对xml树枝进行遍历,符合SVG图形的树枝,对于图形参数进行解析。

主函数如下:

def parser(svg_file):
    tree = ET.parse(svg_file)
    root = tree.getroot()

    width = root.get('width')
    height = root.get('height')

    if len(width) == 0 or len(height) == 0:
        print "width or height is 0"
        exit(1)

    if "mm" in width:
        width = width[:-2]

    if "mm" in height:
        height = height[:-2]

    print width, height

    for elem in root.iter():
        try:
            _, tag_suffix = elem.tag.split('}')
        except ValueError:
            continue

        if tag_suffix in svg_shapes:
            tag_suffix = tag_suffix.capitalize()
            print tag_suffix
            shape_class = globals()[tag_suffix](elem)

图形解析以矩形为例,需要获取矩形的起始点及长宽:

class Rect:
    def __init__(self, xml_node):
        self.xml_node = xml_node

        if self.xml_node is not None:
            rect_el = self.xml_node
            self.x = float(rect_el.get('x')) if rect_el.get('x') else 0
            self.y = float(rect_el.get('y')) if rect_el.get('y') else 0
            self.rx = float(rect_el.get('rx')) if rect_el.get('rx') else 0
            self.ry = float(rect_el.get('ry')) if rect_el.get('ry') else 0
            self.width = float(rect_el.get('width')) if rect_el.get('width') else 0
            self.height = float(rect_el.get('height')) if rect_el.get('height') else 0
            print("Rect: x=%f, y=%f, rx=%f, ry=%f, width=%f, height=%f"
                  % (self.x, self.y, self.rx, self.ry, self.width, self.height))
        else:
            self.x = self.y = self.rx = self.ry = self.width = self.height = 0
            print("Rect: Unable to get the attributes for %s", self.xml_node)

完整代码及SVG文件可从github下载:
https://github.com/ai2robot/svg_parser

你可能感兴趣的:(Python)