如何在Tkinter标签中使用Base64编码的图像字符串?

3
我正在编写一个tkinter程序,其中利用了一些JPG文件作为背景。但是,我发现当使用“pyinstaller”将脚本转换为.exe文件时,用于tkinter窗口的图片未被编译/添加到.exe文件中。
因此,我决定在Python脚本中硬编码图像,以便没有外部依赖关系。为此,我已经完成了以下工作:
import base64
base64_encodedString= ''' b'hAnNH65gHSJ ......(continues...) '''
datas= base64.b64decode(base64_encodedString)

上面的代码用于解码base64编码的图像数据。 我想使用这个解码后的图片数据作为tkinter标签/按钮中的图片显示。 例如:
from tkinter import *
root=Tk()
l=Label(root,image=image=PhotoImage(data=datas)).pack()
root.mainloop()

然而,tkinter不接受存储在data中的值作为图像使用。它显示以下错误 -
Traceback (most recent call last):
  File "test.py", line 23, in <module>
    l=Label(root,image=PhotoImage(data=datas))
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 3394, in __init__

    Image.__init__(self, 'photo', name, cnf, master, **kw)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 3350, in __init__
    self.tk.call(('image', 'create', imgtype, name,) + options)
_tkinter.TclError: couldn't recognize image data

你使用的是Python2还是Python3?根据这个问题,似乎Python3是可以实现的。 - j_4321
@j_4321 我正在使用Python 3。我已经检查了那个问题,但似乎不能解决我的问题。 - Boudhayan Dev
除了使用base64编码技术,是否有其他嵌入图像到Python脚本并在tkinter GUI中使用的替代方法? - Boudhayan Dev
谢谢。我尝试了相同的代码,但是使用 .gif.png 格式都可以正常工作。因此问题在于你的背景图片是 JPG 格式,而 Tkinter 不支持该格式。尝试将你的图片转换为 PNGGIF 格式,然后它应该可以正常工作。 - j_4321
@j_4321 我已经尝试过了,似乎不起作用。你能发一下你的代码吗?我觉得我在编码部分搞错了。 - Boudhayan Dev
显示剩余2条评论
2个回答

11

在Python 3中,带有tk 8.6的Tkinter PhotoImage类仅能读取GIF、PGM/PPM和PNG图像格式。有两种方法可以读取图像:

  • 从文件中读取:PhotoImage(file="path/to/image.png")
  • 从base64编码的字符串中读取:PhotoImage(data=image_data_base64_encoded_string)

首先,若要将图像转换为base64编码字符串:

import base64

with open("path/to/image.png", "rb") as image_file:
    image_data_base64_encoded_string = base64.b64encode(image_file.read()) 

然后在Tkinter中使用它:

import tkinter as tk

root = tk.Tk()

im = tk.PhotoImage(data=image_data_base64_encoded_string)

tk.Label(root, image=im).pack()

root.mainloop()

我认为您的问题在于,在将字符串解码为datas = base64.b64decode(base64_encodedString)之后,使用它在PhotoImage中,而您应该直接使用base64_encodedString


确实,错误就像你所猜测的那样,我使用解码后的值来创建图像对象。谢谢! - Boudhayan Dev

3

仅纠正j_4321的非常好的答案,PhotoImage的正确代码行是:

im = tk.PhotoImage(data=image_data_base64_encoded_string)

我提供的解决方案是编写“image”字符串以便在导入后使用:

with open("image.py", "wb") as fichier:
    fichier.write(b'imageData=b\'' + image_data_base64_encoded_string + b'\'')

只需使用简单的import image as img命令,通过Pyinstaller(-F选项),图像数据将被存储在.exe文件中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接