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
and feFlood
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')