How to convert SVG to PNG or JPEG in Python?
Asked Answered
P

4

21

I'm using svgwrite and generating svg-files, how do I convert them to PNG or JPEG?

Perigon answered 20/7, 2018 at 20:45 Comment(4)
I haven't found a similar question in SO. Upvoted.Ferne
There seem to be an answer for your question here: #6589858Crimple
But... it is another lib, right? But maybe you need it.Ferne
@qräbnö Well since svgwrite does not seem to handle svg to png conversion, then ... yes you need another library. Another example for the same question can also be found here: #2932908Crimple
L
13

pyvips supports SVG load. It's free, fast, needs little memory, and works on macOS, Windows and Linux.

You can use it like this:

import pyvips

image = pyvips.Image.new_from_file("something.svg", dpi=300)
image.write_to_file("x.png")

The default DPI is 72, which might be a little low, but you can set any DPI you like. You can write to JPG instead in the obvious way.

You can also load by the pixel dimensions you want like this:

import pyvips

image = pyvips.Image.thumbnail("something.svg", 200, height=300)
image.write_to_file("x.png")

That will render the SVG to fit within a 200 x 300 pixel box. The docs introduce all the options.

The pyvips SVG loader has some nice properties:

  • It uses librsvg for the actual rendering, so the PNG will have high-quality anti-aliased edges.
  • It's much faster than systems like ImageMagick, which simply shell out to inkscape for rendering.
  • It supports progressive rendering. Large images (more than a few thousand pixels a side) are rendered in sections, keeping memory use under control, even for very large images.
  • It supports streaming, so you can render an SVG directly to a huge Deep Zoom pyramid (for example) without needing any intermediate storage.
  • It supports input from memory areas, strings and pipes as well as files.

Rendering from strings can be handy, eg.:

import pyvips

x = pyvips.Image.svgload_buffer(b"""
<svg viewBox="0 0 200 200">
  <circle r="100" cx="100" cy="100" fill="#900"/>
</svg>
""")

x.write_to_file("x.png")
Langur answered 13/7, 2020 at 13:13 Comment(6)
This solution requires you to install libvips as per libvips.github.io/libvips/install.html. If you already have InkScape or such like you may not want another editor. Libvips is pretty low level and techie.Prepotency
After installing libvips still get error = "cannot load library 'libgobject-2.0-0.dll': error 0x7e. Additionally, ctypes.util.find_library() did not manage to locate a library called 'libgobject-2.0-0.dll'".Prepotency
Did you find the pyvips windows install notes? libvips.github.io/pyvips/README.html#non-conda-install ... if you're still having problems, please open an issue on the pyvips tracker and I'll try to help github.com/libvips/pyvips/issues/newLangur
The useful answer https://mcmap.net/q/48965/-how-to-convert-svg-to-png-or-jpeg-in-python below explains the windows install process.Langur
Tried the useful answer below and it works.Prepotency
unfortunately, this suffers from the rendering bugs in cairo/rsvg. it can't render a mermaid flowchart, for example.Spencerianism
B
7

For converting svg to png, there are 2 ways I can think of:

1. Here is lib which can do what you need: https://cairosvg.org/documentation/

$ pip3 install cairosvg

python3 code:

cairosvg.svg2png(url="/path/to/input.svg", write_to="/tmp/output.png")

Have used it on linux (debian 9+ and ubuntu 18+) and MacOS. It works as expect for large files about 1MB svg. Example: world map. Lib also allow to export pdf file.

Tip: cairosvg provide scaling up of png output image as default size looks blurry after working with vector graphics svg :) . I couldn't get DPI option working for me.

2. There is another method to do same by using browser to open svg file and take screenshot using Selenium webdriver either with Firefox or other browser. You can save screenshot as png.

One can use Pillow to convert png to jpeg: Convert png to jpeg using Pillow

Butterbur answered 22/5, 2020 at 8:1 Comment(1)
Here is a procedure to get the solution with CairoSVG running on WIndows: https://mcmap.net/q/48557/-convert-svg-to-png-with-python-on-windowsTrapes
P
5

On Windows, you get errors like libgobject-2.0-0.dll, libvips-42.dll, etc. not found when trying to import pyvips. To get pyvips working on Windows, do the following:

In code do this:

import os

# The bin folder has the DLLs
os.environ['path'] += r';C:\Path\ToYour\VIPsFolder\bin'

import pyvips

image = pyvips.Image.thumbnail("test.svg", 200)
image.write_to_file("test.png")

I recommend using pyvips over cairosvg. From my tests it's much faster than cairosvg, especially for large SVGs. You need to something similar to the above to get cairosvg working on Windows anyway.

Plumbaginaceous answered 7/5, 2021 at 4:32 Comment(0)
C
3

I looked several methods, including cairo (which I could not make it work on Windows), svglib+reportlab (dpi cannot be changed) and even inkscape (from command line).

At the end this is the best method I found. I tested it on python 3.7.

def convert(method, svg_file, png_file, resolution = 72):
    from wand.api import library
    import wand.color
    import wand.image

    with open(svg_file, "r") as svg_file:
        with wand.image.Image() as image:
            with wand.color.Color('transparent') as background_color:
                library.MagickSetBackgroundColor(image.wand, 
                                                 background_color.resource) 
            svg_blob = svg_file.read().encode('utf-8')
            image.read(blob=svg_blob, resolution = resolution)
            png_image = image.make_blob("png32")

    with open(png_file, "wb") as out:
        out.write(png_image)

I had to install the wand package (using pip) and then ImageMagick for Windows (http://docs.wand-py.org/en/latest/guide/install.html#install-imagemagick-on-windows).

Community answered 13/7, 2020 at 0:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.