首页 > 解决方案 > Python将SVG的一部分提取为PNG

问题描述

我一直在做大量的搜索,但找不到这个答案。

我有一系列相对简单的 SVG 图像。我在我感兴趣的图像的关键区域上绘制了 SVG 矩形,现在想将这些区域提取为 PNG 图像。我不知道解决这个问题的最佳方法。

想法 1)将整个 SVG 转换为 PNG,然后在以某种方式将 SVG 矩形坐标转换为 PNG 坐标后,使用说 PIL 裁剪图像。我现在开始研究这种方法,但我希望有更好的和/或更简单的方法来做到这一点!

我为此使用 Python 3.7。

编辑1:

这是我正在查看的屏幕截图。原始图像是 SVG,我想将绿色矩形下方的区域提取为 PNG 图像。 要从中提取 PNG 的 SVG 图像示例。

编辑2:

从想法 1 开始,我有以下代码,基本上将 SVG 图像上的 viewBox 设置为绿色矩形之一,然后设置它的宽度和高度。从那里我使用 CairoSVG 将 SVG 导出为 PNG。

import cairosvg
import xml.etree.ElementTree as ET
...
with gzip.open(fileObj.filePath,'rb') as file:
    svg=file.read()
    svg=svg.decode('utf-8')
svgRoot=ET.fromstring(svg)
ET.register_namespace("","http://www.w3.org/2000/svg")
ET.register_namespace('xlink', "http://www.w3.org/1999/xlink")
annots = meta['annots']
for a in annots:
    r = ET.fromstring(a['g'])
    vb=" ".join([r.get('x'),r.get('y'),r.get('width'),r.get('height')])
    svgRoot.set("viewBox",vb)
    svgRoot.set("width",'128px')
    svgRoot.set("height",'128px')
    svg = ET.tostring(svgRoot, encoding="unicode")
    cairosvg.svg2png(svg,write_to="/home/test.png")

不幸的是,它非常慢!提取两个 PNG 大约需要一分钟多的时间。SVG 文件非常大(2 - 3 mb 压缩)并且非常详细。我不确定 CairoSVG 是如何工作的,但它是否会渲染 SVG 中的所有内容,即使在将可见部分保存到 PNG 之前它不可见?

任何有关优化或加快速度的建议都会有很大帮助。

标签: python-3.xsvgpngpython-imaging-librarycairo

解决方案


这最终对我有用,尽管在较大的 SVG 图像上速度很慢:

import gzip
import cairosvg
import xml.etree.ElementTree as ET
...
with gzip.open(fileObj.filePath,'rb') as file:
    svg=file.read()
    svg=svg.decode('utf-8')
svgRoot=ET.fromstring(svg)
ET.register_namespace("","http://www.w3.org/2000/svg")
ET.register_namespace('xlink', "http://www.w3.org/1999/xlink")
annots = meta['annots']
for a in annots:
    r = ET.fromstring(a['g'])
    vb=" ".join([r.get('x'),r.get('y'),r.get('width'),r.get('height')])
    svgRoot.set("viewBox",vb)
    svgRoot.set("width",'128px')
    svgRoot.set("height",'128px')
    svg = ET.tostring(svgRoot, encoding="unicode")
    cairosvg.svg2png(svg,write_to="/home/test.png")

推荐阅读