| Store | Cart

Displaying SVG in tkinter using cairo and rsvg

From: Martin P. Hellwig <mart...@dcuktec.org>
Tue, 15 Feb 2011 20:01:49 +0000
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
-- 
http://mail.python.org/mailman/listinfo/python-list

Recent Messages in this Thread
Martin P. Hellwig Feb 15, 2011 08:01 pm
Arndt Roger Schneider Feb 16, 2011 09:04 am
Martin P. Hellwig Feb 16, 2011 09:49 am
Arndt Roger Schneider Feb 16, 2011 11:00 am
Messages in this thread