用Python将服务器端的SVG转换为PNG(或其他图像格式)

13

目前我正在使用rsvg从字符串中加载SVG,然后绘制到cairo上。有人知道更好的方法吗?我在我的应用程序中其他地方使用PIL,但我不知道如何使用PIL实现这个。


PIL不支持SVG;快速搜索表明您可能拥有正确的工具链。 - msw
我刚刚在这里发布了一条关于此事的最新评论 - https://dev59.com/omw15IYBdhLWcg3weLoF#19718153 - 下面的评论指出“ImageMagick支持似乎很糟糕”,但是那个评论者没有构建或测试它。现在是2013年10月,我刚刚使用ImageMagick(通过Wand-py)测试了导入各种SVG文件,效果非常好!我还有更多的测试要做,如果我错了,我肯定会删除这条评论,但目前为止,在其他方法无法处理的一些已知存在问题的SVG文件上,它已经完美地工作了。 - streetlogics
简单的SVG:https://github.com/aslpavel/svgrasterize.py - doublemax
4个回答

14

这是我目前拥有的代码:

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)

3
欢迎来到Stackoverflow!通常情况下,如果您发布的内容是解决问题的方法,那么它可能是一个答案;如果它是上下文或尝试解决问题但不起作用,或者感觉太过零散以至于不是一个好答案,那么它应该作为编辑放在问题中。这段代码似乎是您想要得到评论的“您正在做的事情”的表示,而不是解决问题的答案,这表明它应该真正出现在您的问题中。 - Sean Vieira
内部存在一些错误。创建ImageSurface时,您需要整数 surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, round(int(x)), round(int(y)),并确保maxwidth和maxheight始终设置为一个高数字,这比0更好。我有许多高度为32000的SVG文件,这将导致内存错误。 - therealmarv

4

ImageMagick convert 2010年5月之前的版本在解释SVG方面表现非常糟糕。根据更新日志,似乎他们还没有完全解决SVG支持的问题(尽管我没有构建它来查看)。 - msw

3
你也可以使用PhantomJS来实现这个功能(见http://phantomjs.org/screen-capture.html)。
从shell中可以执行以下命令:
phantomjs rasterize.js http://ariya.github.com/svg/tiger.svg tiger.png

或者使用selenium从Python中:

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

3
我已经安装了Inkscape,所以我只需要使用Inkscape命令进行转换:inkscape -f file.svg -e file.png 使用以下代码:
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])

我使用的是Windows 7,之前出现了Windows 5错误[访问被拒绝](或类似的错误),直到我切换到inkscape目录才解决了问题。


3
考虑将cwd=inkscape_dir传递给Popen,而不是更改父进程的目录。 - Jason R. Coombs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接