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?
there are multiple solutions available for converting svgs to pngs in python, but not all of them will work for your particular use case since you're working with svg filters.
solution | filter works? | alpha channel? | call directly from python? |
---|---|---|---|
cairosvg | some* | yes | yes |
svglib | no | no | yes |
inkscape | yes | yes | via subprocess
|
wand | yes | yes | yes |
* from cairosvg documentation:
Only
feOffset
,feBlend
andfeFlood
filters are supported.
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
cairosvg
import cairosvg
# read svg file -> write png file
cairosvg.svg2png(url=input_svg_path, write_to=output_png_path, output_width=width, output_height=height)
# read svg file -> png data
png_data = cairosvg.svg2png(url=input_svg_path, output_width=width, output_height=height)
# svg string -> write png file
cairosvg.svg2png(bytestring=svg_str.encode(), write_to=output_png_path, output_width=width, output_height=height)
# svg string -> png data
png_data = cairosvg.svg2png(bytestring=svg_str.encode(), output_width=width, output_height=height)
svglib
from svglib.svglib import svg2rlg
from reportlab.graphics import renderPM
# read svg -> write png
renderPM.drawToFile(svg2rlg(input_svg_path), output_png_path, fmt='PNG')
inkscape
to read a file as input, put the path to the file as the last argument.
to use a string as input, add the --pipe
argument and pass the string to stdin.
to write to a file as output, add the argument --export-filename=
+path to output file.
to get the output contents directly without writing to a file, use --export-filename=-
and it will be sent to stdout instead.
full documentation for CLI options here
import subprocess
inkscape = ... # path to inkscape executable
# read svg file -> write png file
subprocess.run([inkscape, '--export-type=png', f'--export-filename={output_png_path}', f'--export-width={width}', f'--export-height={height}', input_svg_path])
# read svg file -> png data
result = subprocess.run([inkscape, '--export-type=png', '--export-filename=-', f'--export-width={width}', f'--export-height={height}', input_svg_path], capture_output=True)
# (result.stdout will have the png data)
# svg string -> write png file
subprocess.run([inkscape, '--export-type=png', f'--export-filename={output_png_path}', f'--export-width={width}', f'--export-height={height}', '--pipe'], input=svg_str.encode())
# svg string -> png data
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)
wand
from wand.image import Image
from wand.Color import Color
with Color('#00000000') as bgcolor,\
# to read input from a file:
Image(filename=input_svg_path, width=width, height=height, background=bgcolor) as img:
# or, to use input from a string:
Image(blob=svg_str.encode(), format='svg', width=width, height=height, background=bgcolor) as img:
# to save output to a file:
with img.convert('png') as output_img:
output_img.save(filename=output_png_path)
# or, to get the output data in a variable:
png_data = img.make_blob(format='png')
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With