【问题标题】:Putting .SVG images into tkinter Frame将 .SVG 图像放入 tkinter Frame
【发布时间】:2021-10-30 03:12:06
【问题描述】:

我一直在尝试将来自https://betacssjs.chesscomfiles.com/bundles/web/favicons/safari-pinned-tab.f387b3f2.svg 的图像放入 Tkinter 框架中。我从here 的帖子中发现,在 rsvg 和 cairo 的帮助下,这是可能的。

我在 Windows 10 上使用 python 3.6。我从 here 获得 rsvg,从 here 获得 cairo,然后将文件夹解压缩到“C:\Users...\site_packages”文件夹。它们可以很好地导入,但我不知道如何使用它们。我尝试使用代码:

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)

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

在尝试了这些脚本后,我不断收到错误消息:

AttributeError: module 'rsvg' has no attribute 'Handle'

我确信我在这个过程中做错了,但经过数小时的搜索仍然无法弄清楚如何让它工作。我也尝试安装 pycairo(通过 pip),但收到错误消息

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\

我不知道现在该做什么

编辑:我终于能够从 https://www.lfd.uci.edu/~gohlke/pythonlibs/ 现在让它工作。 我终于让 rsvg 通过引用不给我上面的错误消息 here 并从 here开罗是 工作正常,但 RSVG 正在创建一个空白屏幕。我尝试了另一个 7班 here 并获得一个空白文件的输出,而不是转换后的文件。 显然 RSVG 不工作,我认为这是一个安装问题 (例如,不正确的 .dll 文件)。帮忙?

如果我尝试使用 cairo 和 rsvg,因为它们占用空间小而且速度非常快;魔杖或其他一些图书馆不是一种选择。我只想能够将 SVG 文件放入 tkinter 框架中。如果有人知道如何正确安装 rsvg,我将不胜感激。

任何帮助将不胜感激。 感谢您的任何建议。

【问题讨论】:

  • 显示你的代码。
  • 嗨,我主要使用的代码出现在最后一个链接和第二个链接中。
  • 链接中的代码有效,但您的代码无效。因此,如果您显示代码,那么我们可以搜索差异。
  • 我将代码添加到问题中。我认为错误来自我如何安装 cairo 和 rsvg 而不是代码本身。
  • 我认为你应该可以使用 PIL.Image 和 PIL.ImageTk 来做到这一点

标签: python python-3.x tkinter cairo rsvg


【解决方案1】:

我已经设法使用 svglib 做到了:

from svglib.svglib import svg2rlg
from reportlab.graphics import renderPDF, renderPM

drawing = svg2rlg("safari-pinned-tab.f387b3f2.svg")
renderPM.drawToFile(drawing, "temp.png", fmt="PNG")


from tkinter import *

tk = Tk()


from PIL import Image, ImageTk

img = Image.open('temp.png')
pimg = ImageTk.PhotoImage(img)
size = img.size


frame = Canvas(tk, width=size[0], height=size[1])
frame.pack()
frame.create_image(0,0,anchor='nw',image=pimg)

tk.mainloop()

【讨论】:

  • 谢谢!不过,问题是关于 rsvg 的。有什么见解吗?另外,是否可以在不下载形状的情况下使用 svglib/reportlab?是否有可能以某种方式完全跳过报告实验室?
【解决方案2】:

我终于设法在 Windows 上使用 Python 3 和 PyCairo 转换 SVG,但没有 rsvg。 Rsvg 仍然不会合作,但显然没有它仍然可以加载 SVG。

安装过程不是很简单,但是,嘿,它的工作原理!

 

说明:

请注意,这些说明是特定于 Windows 的。在 Linux 上,可以简单地通过 pip 安装 pycairo 并使用 PyGObject 的 rsvg。

  1. https://www.lfd.uci.edu/~gohlke/pythonlibs/ 下载用于 Windows 安装的 pycairo .whl 文件。
  2. 通过 pip 安装下载的文件:pip install /path/to/your/pycairo/whl.whl 如果这不起作用,请尝试使用与上述链接不同的文件。可能需要尝试几次。
  3. 运行pip install tinycss cssselect2 defusedxml。这将为下一步安装依赖项。
  4. 转到https://github.com/Kozea/CairoSVG。下载 cairosvg 文件夹并将其解压缩到您的站点包文件夹中,使您的代码能够导入它。
  5. 转到cairosvg 文件夹并打开文件surface.py
  6. 查找显示import cairocffi as cairo 的行并将其替换为import cairo

这应该足以在没有 C++ 编译器的 Windows 上使用 PyCairo。不幸的是,这仍然不能解决 rsvg 问题(而是取代了 rsvg),但至少它有效。

 

以下是一些如何使用它的示例:

将 SVG 转换为 PNG:

import cairosvg
cairosvg.svg2png(url="example.svg", write_to="output.png")

将 SVG 放入 Tkinter 窗口而不下载输出:

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

 

由于还是使用 Cairo,所以这个解决方案非常快,并且依赖很少。

希望这个答案对以后阅读本文的人有用!

【讨论】:

    【解决方案3】:

    这是另一种方法:

    from pylunasvg import Document
    import numpy as np
    from urllib import request
    from PIL import Image
    
    contents = request.urlopen("https://betacssjs.chesscomfiles.com/bundles/web/favicons/safari-pinned-tab.f387b3f2.svg").read()
    
    document = Document.loadFromData(contents)
    bitmap = document.renderToBitmap()
    
    svgArray = np.array(bitmap, copy=False)
    img = Image.fromarray(svgArray)
    
    # Insert tkinter code here
    

    免责声明:我为该库编写了绑定,这里是 github 链接:pylunasvg 和指向用 c++ 编写的原始库的链接:lunasvg

    【讨论】:

      猜你喜欢
      • 2021-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-01
      • 1970-01-01
      相关资源
      最近更新 更多