Displaying SVG in tkinter using cairo and rsvg

Discussion in 'Python' started by Martin P. Hellwig, Feb 15, 2011.

  1. Hi all,

    Information on using tkinter for displaying an svg image seems a bit low
    spread on the Internet. I recently played around with pygame and svg and
    realized, hold on this can be done with tk too. So I thought I post a
    little example for future generations :) (and also have stored at
    http://dcuktec.googlecode.com/hg/source/examples/cairo_rsvg_tkinter.py).

    So here it is if you are interested:

    ---
    #! /usr/bin/env python
    """
    Tkinter example for displaying SVG in a PhotoImage class using cairo and
    rsvg.
    Note that this is relatively slow, this is mainly due to converting the
    cairo
    surface data to the appropriate rgb values and putting each pixel in the
    PhotoImage class.
    """
    import cairo
    import rsvg
    # I had a bit of trouble finding the rsvg python wrapper, turns out it
    is part
    # of the GnomePythonDesktop package, windows users are even less
    supported see:
    # http://cairographics.org/cairo_rsvg_and_python_in_windows/ to get it
    working.
    import Tkinter

    def _alpha_blending(rgba, back):
    "Return a rgb tuple composed from a rgba and back(ground) tuple/list."
    paired = zip(rgba[:-1], back)
    alpha = rgba[-1]
    tmp = list()
    for upper, lower in paired:
    blend = (((255 - alpha) * lower) + (alpha * upper)) / 255
    tmp.append(blend)

    return(tuple(tmp))

    def convert(bgra_buffer, width, height):
    "Convert bgra buffer to photoimage put"
    idx = 0
    end = len(bgra_buffer)
    arguments = list()

    while idx < end:
    rgba = (ord(bgra_buffer[idx + 2]),
    ord(bgra_buffer[idx + 1]),
    ord(bgra_buffer[idx + 0]),
    ord(bgra_buffer[idx + 3]))
    back = (255, 255, 255)
    rgb = _alpha_blending(rgba, back)
    arguments += rgb
    idx += 4

    template = ' '.join(height *['{%s}' % ('
    '.join(width*["#%02x%02x%02x"]))])
    return(template % tuple(arguments))


    def photoimage_from_svg(file_path_name):
    "Return a Tkinter.PhotoImage with the content set to the rendered
    SVG."
    svg = rsvg.Handle(file=file_path_name)
    width, height = svg.get_dimension_data()[:2]
    surface = cairo.ImageSurface(cairo.FORMAT_RGB24, int(width),
    int(height))
    context = cairo.Context(surface)
    svg.render_cairo(context)
    image = Tkinter.PhotoImage(width=width, height=height)
    data = convert(surface.get_data(), width, height)
    image.put(data)
    return(image)

    if __name__ == '__main__':
    SVG = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <svg
    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"
    id="test" version="1.1" width="900" height="600">
    <rect id="red" width="300" height="300" x="000" y="000"
    style="fill:#ff0000;fill-opacity:1.0;stroke:none" />
    <rect id="green" width="300" height="300" x="300" y="000"
    style="fill:#00ff00;fill-opacity:1.0;stroke:none" />
    <rect id="blue" width="300" height="300" x="600" y="000"
    style="fill:#0000ff;fill-opacity:1.0;stroke:none" />
    <rect id="black" width="300" height="300" x="000" y="300"
    style="fill:#000000;fill-opacity:1.0;stroke:none" />
    <rect id="grey" width="300" height="300" x="300" y="300"
    style="fill:#000000;fill-opacity:0.5;stroke:none" />
    <rect id="white" width="300" height="300" x="600" y="300"
    style="fill:#ffffff;fill-opacity:1.0;stroke:none" />
    </svg>"""
    import os, tempfile
    #
    PATH = tempfile.mkstemp()[1]
    OPEN = open(PATH, 'w')
    OPEN.writelines(SVG)
    OPEN.close()
    ROOT = Tkinter.Tk()
    #
    IMAGE = photoimage_from_svg(PATH)
    #
    os.remove(PATH)
    BUTTON = Tkinter.Button(ROOT, image=IMAGE)
    BUTTON._photoimage = IMAGE
    BUTTON.grid()
    Tkinter.mainloop()
    ---
    --
    mph
    Martin P. Hellwig, Feb 15, 2011
    #1
    1. Advertising

  2. Martin P. Hellwig schrieb:
    > Hi all,
    >
    > Information on using tkinter for displaying an svg image seems a bit low
    > spread on the Internet. I recently played around with pygame and svg and
    > realized, hold on this can be done with tk too. So I thought I post a
    > little example for future generations :) (and also have stored at
    > http://dcuktec.googlecode.com/hg/source/examples/cairo_rsvg_tkinter.py).
    >
    > So here it is if you are interested:

    [snip]

    raster images from SVG:
    There are multiple methods to convert a scalable vector graphic
    into a bitmap.
    In addition to cairo, librsvg and rsvg imageMagick contains a
    vector graphic format similar to svg--gradients and transparency
    are problematic for this approach, but its a while since I had
    looked into it...

    My product Jeszra imports svg into Tk(using tkpath
    http://jeszra.sourceforge.net/jeszra/Jeszra_TechnicalNotes.html#d0e10279
    ), preserving it as a vector graphics.
    There are, of course, limitations to what can be preserved in Tk:

    http://jeszra.sourceforge.net/jeszra/SVG_Import.html

    The other way is much simpler to convert a Tk graphics into
    svg, which is also implemented in Jeszra.
    All svg graphics on http://jeszra.sourceforge.net and
    http://gestaltitems.sourceforge.net are generated by Jeszra from
    Tk (there are some hundred graphics)...

    The generator API is open and a draft documentation is online at:
    http://jeszra.sourceforge.net/api/ch01s04.html
    http://jeszra.sourceforge.net/api/index.html

    Jeszra API Concerning svg:
    http://jeszra.sourceforge.net/api/ch04.html
    http://jeszra.sourceforge.net/api/ch05.html
    http://jeszra.sourceforge.net/api/ch06.html
    http://jeszra.sourceforge.net/api/ch07.html
    http://jeszra.sourceforge.net/api/ch08.html

    Here is an overview about Jeszra, SVG and Tk:
    http://jeszra.sourceforge.net/api/pictures/overview.svg


    The svg on those page gets on-demand converted into flash,
    for the internet explorer.

    Is there anyting else You want to know about svg?

    -roger
    Arndt Roger Schneider, Feb 16, 2011
    #2
    1. Advertising

  3. On 02/16/11 09:04, Arndt Roger Schneider wrote:
    <cut>
    > raster images from SVG:
    > There are multiple methods to convert a scalable vector graphic
    > into a bitmap.
    > In addition to cairo, librsvg and rsvg imageMagick contains a
    > vector graphic format similar to svg--gradients and transparency
    > are problematic for this approach, but its a while since I had
    > looked into it...
    >
    > My product Jeszra imports svg into Tk(using tkpath
    > http://jeszra.sourceforge.net/jeszra/Jeszra_TechnicalNotes.html#d0e10279
    > ), preserving it as a vector graphics.
    > There are, of course, limitations to what can be preserved in Tk:


    tkpath does not seem to come standard with Python's tk version when I
    looked into it a couple of years ago, but maybe it has now?

    <cut>
    > Is there anyting else You want to know about svg?
    >


    No not really :), I just wanted to display a SVG in tkinter with the
    minimal amount of external dependencies, since I have achieved that I
    thought I share my experience, so that the next time someone google
    tkinter and display svg it will return something that (well at least of
    the time of this writing) worked.

    Thanks for the info though.

    --
    mph
    Martin P. Hellwig, Feb 16, 2011
    #3
  4. Martin P. Hellwig schrieb:
    > On 02/16/11 09:04, Arndt Roger Schneider wrote:


    [snip]

    > tkpath does not seem to come standard with Python's tk version when I
    > looked into it a couple of years ago, but maybe it has now?
    >

    tk canvas and tkpath share the same interface, the first tkpath was
    a plugin into the tk canvas. A tkinter wrapper class will
    be a simple subclass of tk canvas introducing the new item types:
    path, ppolygone, polyline, circle, elipsis, pimage, prect, ptext, group
    and for tkpath 0.3 three
    additional messages for: style, gradient and distance, that's all
    ~50 lines of code.

    >> Is there anyting else You want to know about svg?
    >>

    >
    > No not really :), I just wanted to display a SVG in tkinter with the
    > minimal amount of external dependencies, since I have achieved that I
    > thought I share my experience, so that the next time someone google
    > tkinter and display svg it will return something that (well at least of
    > the time of this writing) worked.
    >


    Well CAIRO is sort of a shifting target...
    --currently I am stuck with PPC and new CAIRO versions cannot longer
    being built on it anymore :-(--

    CAIRO can be real pain on non-X11-linux platforms. ImageMagick
    is simpler than CAIRO cross-platform wise.

    -roger
    Arndt Roger Schneider, Feb 16, 2011
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Arne Nordmann
    Replies:
    0
    Views:
    510
    Arne Nordmann
    Jun 28, 2004
  2. Mardagg
    Replies:
    0
    Views:
    792
    Mardagg
    May 12, 2006
  3. Tim Grove
    Replies:
    0
    Views:
    470
    Tim Grove
    Sep 2, 2008
  4. Hilmar Bunjes

    Error in Pango while using cairo/librsvg

    Hilmar Bunjes, Jun 15, 2009, in forum: Python
    Replies:
    1
    Views:
    737
  5. Mike Durham
    Replies:
    5
    Views:
    210
    Mike Durham
    Nov 11, 2006
Loading...

Share This Page