Zexelon
Zexelon

Reputation: 494

Python extract part of SVG to PNG

I have been doing a ton of searching but cant quite find the answer to this one.

I have a series of relatively simple SVG images. I have drawn SVG rectangles over key areas of the images that I am interested in and would now like to extract those areas as PNG images. I have no idea the best way to approach this problem.

Idea 1) Convert the whole SVG to PNG then use say PIL to crop the image down after somehow converting the SVG rect coordinates to PNG coordinates. I am starting to work towards this method now, but I am hoping there is a better, and/or easier way to do this!

I am using Python 3.7 for this.

Edit 1:

This is a screen shot of what I am looking at. The original image is SVG, I would like to extract the areas under the green rectangles as PNG images. Sample of SVG image to extract PNG from.

Edit 2:

Working from Idea 1, I have the following code that basically sets the viewBox on the SVG image to one of the green rectangles, then sets the width and height of it. From there I am using CairoSVG to export the SVG as 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")

Unfortunately it is EXTREMELY slow! On the order of more than a minute to extract two PNGs. The SVG files are quite large (2 - 3 mb zipped) and very detailed. I am not certain how CairoSVG works, but does it render everything in the SVG even if it isnt visible before saving the visible part to PNG?

Any advise on optimising or speeding this up would be a huge help.

Upvotes: 0

Views: 1470

Answers (1)

Zexelon
Zexelon

Reputation: 494

This worked for me in the end, though it is quite slow on larger SVG images:

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")

Upvotes: 1

Related Questions