Tkinter错误:无法识别图像文件中的数据

23

我正在尝试将一个jpg图片放到tkinter画布上。但是tkinter给了我这个错误:

无法识别图像文件中的数据

我使用了官方文档中的代码:

canv = Canvas(root, width=80, height=80, bg='white')
canv.grid(row=2, column=3)

img = PhotoImage(file="bll.jpg")
canv.create_image(20,20, anchor=NW, image=img)

使用 PNG 图像也是同样的情况。甚至尝试将图像放入标签小部件中,但仍然出现了相同的错误。有什么问题吗?

我在 Mac 上使用 Python 3。Python 文件和图像位于同一个文件夹中。

11个回答

21

你的代码看起来没问题,在我的Windows 7上可以运行(Python 3.6):

from tkinter import *
root = Tk()

canv = Canvas(root, width=80, height=80, bg='white')
canv.grid(row=2, column=3)

img = PhotoImage(file="bll.jpg")
canv.create_image(20,20, anchor=NW, image=img)

mainloop()

导致这个tkinter GUI的结果:

GUI,使用此图像bll.jpgimage

(imgur将其转换为bll.png,但对我来说也可以工作。)


更多选项:

  • 此答案提到,tkinter仅适用于gif图像。尝试使用.gif图像。
  • 如果这不起作用,请使用如此答案所述的PIL

更新:使用PIL的解决方案:

from tkinter import *
from PIL import ImageTk, Image
root = Tk()

canv = Canvas(root, width=80, height=80, bg='white')
canv.grid(row=2, column=3)

img = ImageTk.PhotoImage(Image.open("bll.jpg"))  # PIL solution
canv.create_image(20, 20, anchor=NW, image=img)

mainloop()

14

我遇到了同样的问题。我的电脑系统是Windows,Python版本是3.6。所以我找到了两种解决方法,要么使用/转换成.png格式的图片(使用你已经用过的同一个函数):

photo = PhotoImage('xyz.png')
l = Label(image = photo)
l.pack()

如果你只想读取.jpg文件,则可以使用PIL库读取并展示图片,代码如下:

from PIL import ImageTk, Image
img = ImageTk.PhotoImage(Image.open("xyz.jpg"))  
l=Label(image=img)
l.pack()

这很有帮助。虽然我建议添加window和mainloop()来实际显示图像。window = Tk()并以window.mainloop()结束。 - Batata

7

使用以下方法安装PIL/Pillow:

pip install Pillow

或者:

sudo pip install pillow

from PIL import Image
from PIL import ImageTk
import tkinter

image = Image.open('bll.jpg')
image = image.resize((20, 20))
image = ImageTk.PhotoImage(image)

canv = Canvas(root, width=80, height=80, bg='white')
canv.grid(row=2, column=3)

img = PhotoImage(file=image)

在Tkinter中,使用.PNG格式而非.JPG格式更好。


7
直接回答原问题:Tkinter目前不支持JPG图片,PNG支持取决于系统的Tcl/Tk版本——这是一个单独的库,用C语言编写,Python通过Tkinter进行接口交互(因此有“inter”部分)。流行的第三方库pillow提供了Tkinter PhotoImage类的即插即用替代品,使其支持更多图像格式。
Tkinter支持的图像格式
Tcl/Tk手册描述了对两种不同图片类型的支持——bitmap和photo,如下所述:
位图是一种图像,其像素可以显示两种颜色或是透明。

一张照片是一个像素可以显示任何颜色或透明的图像。照片图像以全彩(每像素32位)存储在内部,并在必要时使用抖动显示。

在Tkinter中,它们分别被表示为BitmapImagePhotoImage类。 Tkinter支持的格式将略有不同,具体取决于安装的 Tcl / Tk版本 但是,从3.10开始,官方Python二进制发行版中包含了Tcl / Tk 8.6的线程构建

Python Tkinter文档主要集中在解释Tkinter在Tcl/Tk上添加的功能。对于大多数事情,用户应该参考Tcl/Tk文档(或第三方来源;Python文档提供了一些建议),并理解接口的工作原理

Donal Fellows在另一个Stack Overflow问题中所指出的, Tcl/Tk无法处理单个内存分配超过约2GB,这从理论上限制了图像大小。

BitmapImage

Tcl/Tk中的bitmapphoto功能更加有限,因此实际上PhotoImage会更常用。但为了完整起见:BitmapImage支持BMP(跨平台), XPM格式(用于pixmap / 彩色位图,主要在X11上),以及ICO格式(ICO是一种特殊的位图,主要用于Windows图标)。

PhotoImage

如Tcl/Tk文档所述,可以从包含原始图像数据的数据字符串创建photo

该字符串应包含二进制数据或某些格式的base64编码数据(目前保证支持PNG和GIF图像)。

PhotoImage支持GIFPPMPGM图像,无论Tcl/Tk版本如何。

Tcl/Tk版本8.4 需要支持透明度。(然而,由于8.3分支自2002年以来未得到维护,因此当前带有Tkinter支持的Python安装几乎可以保证具有透明度支持。)

Tcl/Tk版本8.6 添加了对PNG图像的支持。如果可能,图像将进行伽马校正:

此外,实现应该... [a]llow应用显示伽玛(如果已知)与导入图像的gAMA块相结合,如果存在,则通过-format“png -gamma value”

Tcl/Tk 8.7(目前处于alpha版本)计划支持SVG(有一些限制) 。如果版权问题得到解决,JPEG支持也可能会在未来被包含。

此外,还有几种方法可以扩展默认库的支持:

验证图片格式

许多其他关于Tkinter图像支持的问题在Stack Overflow上被问及,结果发现问题很简单,即程序员所期望的图像格式不正确。请注意,如果Tkinter尚未支持图像格式,则仅仅将文件重命名为适当的后缀是无法解决问题的。后缀只是提示文件中应该包含哪些数据。(底层的Tcl/Tk库也允许显式指定格式,但主要是从后缀和/或数据本身推断出来的。)
以下是验证图像格式的一些方法:
  • 使用图像编辑程序打开它。(重新保存图像为指定格式是解决不支持格式问题最简单的方法,因此这通常是最实用的方法。)

  • 使用命令行工具,例如Linux上的file命令。

  • 以编程方式打开文件并检查前几个字节,例如使用第三方filetype软件包。

  • 如果不支持所需的图像,则简单地使用异常处理(try/except)并回退到占位符图像。(这可能在图像损坏或丢失的情况下是必要的。)


在我看来,这应该是被接受的答案。 - Jack Griffin
最终我终于开始进行了计划中的主要编辑。我并不是很理解你所选择的用于解释“BitmapImage”格式支持的链接,但我还是按照之前的方式保留了这些链接。总体上,我做了很多工作 - 主要是重新组织信息,并澄清Tkinter本身和Tcl/Tk C库之间的区别。 - Karl Knechtel
@KarlKnechtel 谢谢,这些都是很好的改进,使答案更加简洁易读。我选择的位图链接展示了提供两种颜色位图的工作二进制数据的tcl代码,还有另一个线程,它说明它是平台限制的。由于这些陈述不是基于我的个人经验,我想引用我获取这些信息的来源,未来的访问者可以自行验证这些是否被正确提及。这也展示了Tcl/Tk的良好资源,因为TCL'er Wiki提供了文档之外的额外(但混乱的)信息。 - Thingamabobs

1
另一种替代方案:

filename = ImageTk.PhotoImage(Image.open('imagename.jpeg' ))
background_label = tk.Label(self.root, image=filename)
background_label.place(x=0, y=0, relwidth=1, relheight=1)

0

我也遇到了同样的错误。你只需要使用PNG文件而不是jpeg/jpg文件。 如果你没有PNG版本,你可以在这里转换你的图片 ---> https://cloudconvert.com/

from tkinter import *


root = Tk()

root.geometry("1920x1080")
photo = PhotoImage(file="Akatsuki.png")


label = Label(image=photo)
label.pack()

root.mainloop()

0

0

对我而言,使用Python中的Pillow库可行。

只需执行pip install pillow命令即可。

然后,请使用ImageTk.PhotoImage(Image.open("此处输入您的图片路径..."))代替tkinter.PhotoImage()。


0
# in terminal pip install pillow

from tkinter import *
from PIL import Image, ImageTk

a_root = Tk()

# WINDOW SIZING

a_root.geometry("600x400")
a_root.minsize(400, 400)
a_root.maxsize(800, 800)

# for PNG IMG
# photo = PhotoImage(file="mark1.png")
# for JPG IMG

image = Image.open("mark.jpg")
photo = ImageTk.PhotoImage(image)

img_label = Label(image=photo)
img_label.pack()

a_root.mainloop()

1
目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community
这些不是Python注释 - Matiiss

-1

这个错误可能是由于 相对文件路径 或者文件路径中存在 非英文字符 导致的。因此,我编写了这个函数,在Windows中以及任何类型的文件路径下都能够很好地工作:

def loadrelimages(relativepath):
    from PIL import ImageTk, Image
    import os
    directory_path = os.path.dirname(__file__)
    file_path = os.path.join(directory_path, relativepath)
    img = ImageTk.PhotoImage(Image.open(file_path.replace('\\', "/")))  
    return img

例如,加载与此代码在同一目录下的photo_2021-08-16_18-44-28.jpg文件:
from tkinter import *
import os

def loadrelimages(relativepath):
    from PIL import ImageTk, Image
    import os
    directory_path = os.path.dirname(__file__)
    file_path = os.path.join(directory_path, relativepath)
    img = ImageTk.PhotoImage(Image.open(file_path.replace('\\',"/")))  
    return img

root = Tk()

canvas = Canvas(root, width=500, height=500)
canvas.pack()

loadedimage=loadrelimages('photo_2021-08-16_18-44-28.jpg')
canvas.create_image(250, 250, image=loadedimage)

root.mainloop()

1
如果问题与文件路径有关,那么原帖作者会得到不同的错误提示。问题出在提问中的错误并非因为找不到文件。 - Bryan Oakley

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