So I want to render SVG from python code having target resolution WxH (having SVG text as str, like this that I generate dynamically):
<svg width="200" height="200" viewBox="0 0 220 220"
xmlns="http://www.w3.org/2000/svg">
<filter id="displacementFilter">
<feTurbulence type="turbulence" baseFrequency="0.05"
numOctaves="2" result="turbulence"/>
<feDisplacementMap in2="turbulence" in="SourceGraphic"
scale="50" xChannelSelector="R" yChannelSelector="G"/>
</filter>
<circle cx="100" cy="100" r="100"
style="filter: url(#displacementFilter)"/>
</svg>
into a png image. How to do such a thing in Python?
CodePudding user response:
you can use CairoSVG
CairoSVG is available on PyPI, you can install it with pip:
pip3 install cairosvg
in your code:
import cairosvg
width = 640
height = 480
cairosvg.svg2png(url='logo.svg', write_to='image.png', output_width=width, output_height=height)
CodePudding user response:
solution | filter works? | alpha channel? | call directly from python? |
---|---|---|---|
cairosvg | no* | yes | yes |
svglib | no | no | yes |
inkscape | yes | yes | no** |
* from cairosvg documentation:
Only
feOffset
,feBlend
andfeFlood
filters are supported.
** calling external program via subprocess
note: i've added a solid white background to all the sample images to make them easier to see on a dark background, the originals did have transparent backgrounds unless stated in the table above
import cairosvg
cairosvg.svg2png(url='input.svg', write_to='output_cairosvg.png', output_width=200, output_height=200)
from svglib.svglib import svg2rlg
from reportlab.graphics import renderPM
renderPM.drawToFile(svg2rlg('input.svg'), 'output_svglib.png', fmt='PNG')
full documentation for CLI options here
import os
inkscape = ... # path to inkscape executable
# svg file -> png file
subprocess.run([inkscape, '--export-type=png', f'--export-filename={output_path}', f'--export-width={width}', f'--export-height={height}', input_path])
# svg string -> save png file
subprocess.run([inkscape, '--export-type=png', f'--export-filename={output_path}', f'--export-width={width}', f'--export-height={height}', '--pipe'], input=svg_str.encode())
# svg string -> png data in variable
result = subprocess.run([inkscape, '--export-type=png', '--export-filename=-', f'--export-width={width}', f'--export-height={height}', '--pipe'], input=svg_str.encode(), capture_output=True)
# (result.stdout will have the png data as a bytes object)