2013-03-10 102 views
1

我在使用下面的代码将一些SVG渲染为PNG数据时遇到了一些麻烦。由于该图像最终旨在用作HTTP响应的主体,所以使用了StringIO编写器。使用pyrsvg和Cairo在Python中渲染SVG的问题

结果是正确尺寸的PNG,但它是完全透明的。

import rsvg 
import cairo 
import StringIO 

def render_svg_to_png(svg_data): 
    # Render 
    svg = rsvg.Handle() 
    svg.write(buffer=svg_data) 

    img = cairo.ImageSurface(cairo.FORMAT_ARGB32, 
          svg.props.width, 
          svg.props.height) 
    ctx = cairo.Context(img) 
    svg.render_cairo(ctx) 

    # Write to StringIO 
    png_io = StringIO.StringIO() 
    img.write_to_png(png_io) 
    img.finish() 

    return png_io.getvalue() 

所呈现的SVG数据如下:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
    <!-- Created with Inkscape (http://www.inkscape.org/) --> 

<svg 
    xmlns:dc="http://purl.org/dc/elements/1.1/" 
    xmlns:cc="http://creativecommons.org/ns#" 
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
    xmlns:svg="http://www.w3.org/2000/svg" 
    xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink" 
    version="1.1" 
    width="40" 
    height="40" 
    id="svg2"> 
    <defs 
     id="defs4"> 
     <linearGradient 
     id="linearGradient3769"> 
     <stop 
      id="stop3771" 
      style="stop-color:#ffffff;stop-opacity:1" 
      offset="0" /> 
     <stop 
      id="stop3773" 
      style="stop-color:#000000;stop-opacity:1" 
      offset="1" /> 
     </linearGradient> 
     <radialGradient 
     cx="13.895907" 
     cy="15.277355" 
     r="19.6875" 
     fx="13.895907" 
     fy="15.277355" 
     id="radialGradient3775" 
     xlink:href="#linearGradient3769" 
     gradientUnits="userSpaceOnUse" 
     gradientTransform="matrix(0.96746783,-0.96746783,0.95701248,0.95701249,-12.884457,12.690532)" /> 
    </defs> 
    <metadata 
     id="metadata7"> 
     <rdf:RDF> 
     <cc:Work 
      rdf:about=""> 
      <dc:format>image/svg+xml</dc:format> 
      <dc:type 
      rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 
      <dc:title></dc:title> 
     </cc:Work> 
     </rdf:RDF> 
    </metadata> 
    <g 
     transform="translate(0,-1012.3622)" 
     id="layer1"> 
     <path 
      d="m 39.375,19.776785 a 19.6875,19.6875 0 1 1 -39.375,0 19.6875,19.6875 0 1 1 39.375,0 z" 
      transform="matrix(1.015873,0,0,1.015873,0,1012.2715)" 
      id="path2991" 
      style="fill:url(#radialGradient3775);fill-opacity:1;fill-rule:nonzero;stroke:none" /> 
    </g> 
</svg> 

回答

1

为我工作好这里:

import rsvg 
import cairo 
import StringIO 

def render_svg_to_png(svg_data): 
    # Render 
    svg = rsvg.Handle(data=svg_data) 
    img = cairo.ImageSurface(cairo.FORMAT_ARGB32, 
     svg.props.width, 
     svg.props.height) 
    ctx = cairo.Context(img) 
    svg.render_cairo(ctx) 

    # Write to StringIO 
    png_io = StringIO.StringIO() 
    img.write_to_png(png_io) 

    return png_io.getvalue() 

svg_data = open('test.svg', 'r').read() 
print render_svg_to_png(svg_data) 

与输出重定向冉到一个.png文件,并证实了它想出了在图像查看程序中可以。

+0

问题实际上是使用ElementTree来修改XML。来自ET的XML输出的命名空间已经搞乱了。这并没有打扰Chrome,我用它来测试代码,但似乎让rsvg感到不安。我没有注意到这一点,直到我更仔细地查看ET的输出。切换到minidom解决了这个问题。 – dlp 2013-03-13 14:20:27