f



Displaying SVG in tkinter using cairo and rsvg

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
0
2/15/2011 8:01:49 PM
comp.lang.python 77058 articles. 6 followers. Post Follow

3 Replies
1072 Views

Similar Articles

[PageSpeed] 20

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
0
2/16/2011 9:04:52 AM
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




0
2/16/2011 9:49:10 AM
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
0
2/16/2011 11:00:30 AM
Reply: