pythonrsvg

Issue rendering SVG in Python using pyrsvg and Cairo


I am having some trouble using the following code to render some SVG into PNG data. The StringIO writer is used since the image is ultimately intended for use as the body of an HTTP response.

The result is a PNG of the correct dimensions, but it is completely transparent.

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

The SVG data being rendered is as follows:

<?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>

Solution

  • Works okay for me here:

    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)
    

    Ran it with output redirection to a .png file and confirmed it came up okay in an image viewing program.