I have been trying to put the image from https://betacssjs.chesscomfiles.com/bundles/web/favicons/safari-pinned-tab.f387b3f2.svg into a Tkinter frame. I found from the post here that it is possible with the help from rsvg and cairo.
I was using python 3.6 on Windows 10. I got rsvg from here and cairo from here and then extracted the folders to the 'C:\Users...\site_packages' folder. They import fine but I cannot figure out how to use them. I tried using the code:
import tkinter as tk
main=tk.Tk()
frame=tk.Frame(main)
def svgPhotoImage(self,file_path_name):
from PIL import Image,ImageTk
import rsvg,cairo
svg = rsvg.Handle(file=file_path_name)
width, height = svg.get_dimension_data()[:2]
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
context = cairo.Context(surface)
#context.set_antialias(cairo.ANTIALIAS_SUBPIXEL)
svg.render_cairo(context)
tk_image=ImageTk.PhotoImage('RGBA')
image=Image.frombuffer('RGBA',(width,height),surface.get_data(),'raw','BGRA',0,1)
tk_image.paste(image)
return(tk_image)
tk_image=self.svgPhotoImage(filename)
frame.configure(image=tk_image)
and
#rsvg.py
import os
try:
import rsvg
WINDOWS=False
except ImportError:
print"Warning, could not import 'rsvg'"
if os.name == 'nt':
print "Detected windows, creating rsvg."
#some workarounds for windows
from ctypes import *
l=CDLL('librsvg-2-2.dll')
g=CDLL('libgobject-2.0-0.dll')
g.g_type_init()
class rsvgHandle():
class RsvgDimensionData(Structure):
_fields_ = [("width", c_int),
("height", c_int),
("em",c_double),
("ex",c_double)]
class PycairoContext(Structure):
_fields_ = [("PyObject_HEAD", c_byte * object.__basicsize__),
("ctx", c_void_p),
("base", c_void_p)]
def __init__(self, path):
self.path = path
error = ''
self.handle = l.rsvg_handle_new_from_file(self.path,error)
def get_dimension_data(self):
svgDim = self.RsvgDimensionData()
l.rsvg_handle_get_dimensions(self.handle,byref(svgDim))
return (svgDim.width,svgDim.height)
def render_cairo(self, ctx):
ctx.save()
z = self.PycairoContext.from_address(id(ctx))
l.rsvg_handle_render_cairo(self.handle, z.ctx)
ctx.restore()
class rsvgClass():
def Handle(self,file):
return rsvgHandle(file)
rsvg = rsvgClass()).
h = rsvg.Handle("box.svg")
s = cairo.ImageSurface(cairo.FORMAT_ARGB32, 100, 100)
ctx = cairo.Context(s)
h.render_cairo(ctx)
After trying those scripts, I kept getting the error message:
AttributeError: module 'rsvg' has no attribute 'Handle'
I am sure I did something wrong in the process but after hours of searching still could not figure out how to get it to work. I also tried installing pycairo (via pip) but got the error message
ERROR: Command "'c:\...\python36-32\python.exe' -u -c 'import setuptools, tokenize;__file__='"'"'C:\\...\\pip-install-peqhj3x1\\pycairo\\setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record 'C:\...\Temp\pip-record-jfozfbuc\install-record.txt' --single-version-externally-managed --compile" failed with error code 1 in C:\...\pip-install-peqhj3x1\pycairo\
I have no clue as to what to do now
EDIT: I was finally able to obtain pycairo from https://www.lfd.uci.edu/~gohlke/pythonlibs/ and now have it working. I finally got rsvg to not give me the error message above by referring here and got the nessary DLL files from here. Cairo is working fine but RSVG is creating a blank screen. I tried another 7-liner here and get the output of a blank file instead of a converted one. Evidently RSVG is not working and I think it is an installation issue (eg. incorrect .dll's). Help?
If am trying to use cairo and rsvg because they take up little space and are really fast; wand or some other library is not an option. I just want to be able to put an SVG file into a tkinter frame. If anyone knows how install rsvg properly, I'd appreciate knowing.
Any help would be hugely appreciated. Thank you for any suggestions.
I have finally managed to convert SVGs with Python 3 and PyCairo on Windows, but without rsvg. Rsvg still won't cooperate, but apparently it is still possible to load SVGs without it.
The installation process is not very straightforward, but hey, it works!
Instructions:
Note that these instructions are Windows-specific. On Linux, one can simply install pycairo via pip and use PyGObject's rsvg.
pip install /path/to/your/pycairo/whl.whl
If that doesn't work, try using a different file from the above link. It may take a few tries.pip install tinycss cssselect2 defusedxml
. This will install the dependacies for the next step.cairosvg
folder to your site packages folder, enabling your code to import it.cairosvg
folder and open the file surface.py
.import cairocffi as cairo
and replace it with import cairo
That should be enough to use PyCairo on Windows without a C++ compiler. Unfortionately, this still doesn't fix the rsvg issues (instead it replaces rsvg), but at least it works.
Here are some examples of how to use it:
To convert an SVG to a PNG:
import cairosvg
cairosvg.svg2png(url="example.svg", write_to="output.png")
To put an SVG into a Tkinter window without downloading the output:
import cairosvg
import io
import tkinter as tk
from PIL import Image,ImageTk
main=tk.Tk()
image_data = cairosvg.svg2png(url="example.svg")
image = Image.open(io.BytesIO(image_data))
tk_image = ImageTk.PhotoImage(image)
button=tk.Label(main, image=tk_image)
button.pack(expand=True, fill="both")
main.mainloop()
Since it still uses Cairo, this solution is very quick, and has few dependencies.
Hopefully this answer will be useful for anyone reading this in the future!