Server-side SVG to PNG (or some other image format) in python
Asked Answered
C

5

15

Currently I'm using rsvg to load the svg (from a string, not from a file) and drawing to cairo. Anyone know a better way? I use PIL elsewhere in my application, but I don't know of a way to do this with PIL.

Colligan answered 28/5, 2010 at 20:44 Comment(4)
PIL doesn't support SVG; a quick surf indicates you probably have the right toolchain.Allineallis
I just posted a more recent comment about this over here - https://mcmap.net/q/47920/-convert-svg-to-png-in-python - a comment below states that "ImageMagick support appears to be terrible", but that commenter didn't build it/test it. It's now 10/2013, and I just tested using ImageMagick (via Wand-py) to import a wide variety of SVGs and it worked great! I still have more testing to do and will definitely pull this comment down if I'm horribly mistaken, but at this point it has worked flawlessly on a few SVGs that were known to be buggy using other methods.Finalist
Simple SVGs: github.com/aslpavel/svgrasterize.pyFornication
For a simple solution with CairoSVG see this answer: https://mcmap.net/q/48557/-convert-svg-to-png-with-python-on-windowsHemmer
C
14

Here's what I currently have:

import cairo
import rsvg

def convert(data, ofile, maxwidth=0, maxheight=0):

    svg = rsvg.Handle(data=data)

    x = width = svg.props.width
    y = height = svg.props.height
    print "actual dims are " + str((width, height))
    print "converting to " + str((maxwidth, maxheight))

    yscale = xscale = 1

    if (maxheight != 0 and width > maxwidth) or (maxheight != 0 and height > maxheight):
        x = maxwidth
        y = float(maxwidth)/float(width) * height
        print "first resize: " + str((x, y))
        if y > maxheight:
            y = maxheight
            x = float(maxheight)/float(height) * width
            print "second resize: " + str((x, y))
        xscale = float(x)/svg.props.width
        yscale = float(y)/svg.props.height

    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, x, y)
    context = cairo.Context(surface)
    context.scale(xscale, yscale)
    svg.render_cairo(context)
    surface.write_to_png(ofile)
Colligan answered 28/5, 2010 at 20:52 Comment(2)
Welcome to Stackoverflow! The general rule of thumb is if what you are posting is a way to solve the problem then it may be an answer; if it's context or attempts at solving the problem that do not work, or feel to hacked-together to be a good answer then it should go in the question as an edit. The fact that this code seems to be the 'what you were doing' that you were looking to get comments on, ("Anyone know a better way") rather than a solution to a problem suggests that this should really be in your question.Claypan
There are some errors inside. When create an ImageSurface you need Integer surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, round(int(x)), round(int(y)) And you should make sure that maxwidth and maxheight is always set to a high number which would be better than 0. I have many SVGs with heights of 32000 which will result in a memory error.Elene
G
4

How about imagemagic? - http://www.imagemagick.org/script/magick-vector-graphics.php It can read/write from/to stdin/stdout so You can integrate it with your app even if You don't want to use files

Groot answered 28/5, 2010 at 20:53 Comment(1)
ImageMagick convert versions older than May 2010 do a horrible job of interpreting SVG. Given the changelog, it doesn't seem like they've yet gotten SVG support working well (although I didn't build it to see).Allineallis
V
4

You can also use PhantomJS for this (see http://phantomjs.org/screen-capture.html)

From a shell:

phantomjs rasterize.js http://ariya.github.com/svg/tiger.svg tiger.png

Or from python using selenium:

from selenium import webdriver  
driver = webdriver.PhantomJS()
driver.set_window_size(1024, 768) 
driver.get('http://ariya.github.com/svg/tiger.svg')
driver.save_screenshot('tiger.png')
Vilayet answered 8/3, 2014 at 8:14 Comment(0)
O
3

I have inkscape installed so I am just farming out the process to the inkscape command with inkscape -f file.svg -e file.png

Using this code:

import subprocess
inkscape_dir=r"C:\Program Files (x86)\Inkscape"
assert os.path.isdir(inkscape_dir)
os.chdir(inkscape_dir)
subprocess.Popen(['inkscape.exe',"-f",fname,"-e",fname_png])

I am on windows 7, and got the Windows 5 Error [Access Denied] (or something like that) until I switched to the inkscape directory

O answered 20/8, 2011 at 9:4 Comment(1)
Consider passing cwd=inkscape_dir to Popen, rather than changing the directory for the parent process.Lehr
N
0
import pygame

surface = pygame.image.load("shrubbery.svg")
pygame.image.save(surface, "shrubbery.png")

WebP, AVIF, and JPEG XL are replacing PNG.

Northeasterly answered 14/4 at 10:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.