【问题标题】:PIL Tkinter weird bug: couldn't recognize data in [png] image filePIL Tkinter 奇怪的错误:无法识别 [png] 图像文件中的数据
【发布时间】:2017-02-03 09:10:26
【问题描述】:

我有一个图像处理程序。该程序本身运行良好,但是当我更改台式机或笔记本电脑(全部在 Windows 7 上)我正在使用它时,它有时会随机显示:

Traceback (most recent call last):
  File "P:\ISN\Projets\Traitement image\Test 2.py", line 152, in <module>
    im1 = Tkinter.PhotoImage(file=a)
  File "C:\Program Files\EduPython\App\lib\tkinter\__init__.py", line 3287, in __init__
    Image.__init__(self, 'photo', name, cnf, master, **kw)
  File "C:\Program Files\EduPython\App\lib\tkinter\__init__.py", line 3243, in __init__
    self.tk.call(('image', 'create', imgtype, name,) + options)
_tkinter.TclError: couldn't recognize data in image file "P:/ISN/Projets/Traitement image/Images/obama.png"

如您所见,图像格式为.png。我正在使用 PIL,因此应该支持 png 图像,并且我的图像文件没有损坏。我一直在使用它们,它们工作正常。但这是随机发生的,我担心在我必须展示我的程序的那一天,它会在我身上崩溃。 这是我的代码:

from tkinter import*
import tkinter as Tkinter
from tkinter import filedialog, DISABLED, messagebox as tkMessageBox
import os
import ntpath
from PIL import Image
from collections import Counter


def EchelleDeGris():
    Ima2=Image.new("RGB",(z[0],z[1]))
    px=Ima1.load()
    px1=Ima2.load()
    for x in range(z[0]):
        for y in range(z[1]):
            p=px[x,y]
            o=int((p[0]+p[1]+p[2])/3)
            px1[x,y]=(o,o,o)
    Ima2.save("ImageMod.png")
    im2 = PhotoImage(file="ImageMod.png")
    main.image = im2
    I2 = Tkinter.Label(main, image=im2)
    I2.grid(row=0, column=3, rowspan =6)

def SupprimerImage():
    I2 = Tkinter.Label(main, image=imt)
    I2.grid(row=0, column=3, rowspan =6)

def Luminosite():
    Ima2=Image.new("RGB",(z[0],z[1]))
    px=Ima1.load()
    px1=Ima2.load()
    for x in range(z[0]):
        for y in range(z[1]):
            p=px[x,y]
            px1[x,y]=(p[0]+S1.get(),p[1]+S1.get(),p[2]+S1.get())
    Ima2.save("ImageMod.png")
    im2 = PhotoImage(file="ImageMod.png")
    main.image = im2
    I2 = Tkinter.Label(main, image=im2)
    I2.grid(row=0, column=3, rowspan =6)

def AnnulerModifications():
    I2 = Tkinter.Label(main, image=im1)
    I2.grid(row=0, column=3, rowspan =6)

def get_pixel(pixels, x, y):
    try:
        return pixels[x, y]
    except IndexError:
        return None


def get_neighbors(pixels, x, y):
    neighbors = list()
    neighbors.append(get_pixel(pixels, x, y - 1))
    neighbors.append(get_pixel(pixels, x, y + 1))
    neighbors.append(get_pixel(pixels, x - 1, y))
    neighbors.append(get_pixel(pixels, x + 1, y))
    neighbors.append(get_pixel(pixels, x - 1, y - 1))
    neighbors.append(get_pixel(pixels, x - 1, y + 1))
    neighbors.append(get_pixel(pixels, x + 1, y - 1))
    neighbors.append(get_pixel(pixels, x + 1, y + 1))
    return neighbors


def filter_art(pixels, size):
    indexes = dict()
    for x in range(size[0]):
        for y in range(size[1]):
            color = get_pixel(pixels, x, y)
            neighbors = get_neighbors(pixels, x, y)
            new_color = Counter(neighbors).most_common()[0][0]
            if new_color is not None:
                indexes[x, y] = new_color
    for x, y in indexes:
        pixels[x, y] = indexes[x, y]


def pop_art(path_orig, path_mod, coef):  # coef is integer value, meant how deep filtering would be (for example, coef=4)
    image_orig = Image.open(path_orig)
    size = image_orig.size
    image_mod = Image.new("RGB",(size[0],size[1]))
    pixels_orig = image_orig.load()
    pixels_mod = image_mod.load()
    for x in range(size[0]):
        for y in range(size[1]):
            p = pixels_orig[x, y]
            if isinstance(p, int): # this should be done using PIL palletes and converting to exact pallete at first,
                # but now I omit this for my quick test
                rgb = (p,p,p)
            elif isinstance(p, tuple) and len(p) in (3, 4):
                rgb = p[:3]
            else:
                raise TypeError('Unknown pallete')
            average_color = sum(rgb) / 3
            if average_color <= 85:
                pixels_mod[x, y] = (255, 0, 0)  # you also need care about guarantee correct PIL pallete format here (omitted)
            elif 85 < average_color <= 170:
                pixels_mod[x, y] = (0, 255, 0)
            elif average_color > 170:
                pixels_mod[x, y] = (0, 0, 255)
    for _ in range(coef):
        filter_art(pixels_mod, size)
    image_mod.save(path_mod)

def usepop():
    pop_art(a, 'result.png', coef=4)
    im2 = PhotoImage(file="result.png")
    main.image = im2
    I2 = Tkinter.Label(main, image=im2)
    I2.grid(row=0, column=3, rowspan =6)






main=Tk()

main.withdraw()
currdir = os.getcwd()
a = filedialog.askopenfilename()
main.deiconify()

main.configure(background="#a1dbcd")
main.title("Photoshop Version.Megzari")

Ima1=Image.open(a)
z=Ima1.size
nux=Image.new("RGB",(z[0],z[1]))
nuxy=nux.load()
for x in range(z[0]):
    for y in range(z[1]):
        nuxy[x,y]=(255,255,255)
nux.save("Blank.png")








if z>(400,400):
    main.withdraw()
    tkMessageBox.showinfo( "Resolution Error", "The image is too big, please select a smaller one.")
    sys.exit()


elif z<(400,400):
    im1 = Tkinter.PhotoImage(file=a)
    I1 = Tkinter.Label(main, image=im1)
    I1.grid(padx=20, pady=20, row=0, column=1, rowspan =6)
    imt = Tkinter.PhotoImage(file="Blank.png")
    T1 = Tkinter.Label(main, image=imt)
    T1.grid(padx=20, pady=20, row=0, column=3, rowspan =6)
    B1 = Tkinter.Button(main, text ="Echelle de gris", command = EchelleDeGris, fg="#a1dbcd", bg="#383a39", state=NORMAL)
    B1.grid(padx=20, pady=20, row=0, column=2)
    B3 = Tkinter.Button(main, text ="Appliquer Luminosité", command = Luminosite, fg="#a1dbcd", bg="#383a39")
    B3.grid(padx=20, pady=20, row=2, column=2)
    S1 = Scale(main, from_=0, to=254, orient=HORIZONTAL, fg="#a1dbcd", bg="#383a39", length = 200)
    S1.grid(row=1, column=2)
    B2 = Tkinter.Button(main, text ="Supprimer Image", command = SupprimerImage, fg="#a1dbcd", bg="#383a39")
    B2.grid(padx=20, pady=20, row=4, column=2)
    B3 = Tkinter.Button(main, text ="Annuler Modifications", command = AnnulerModifications, fg="#a1dbcd", bg="#383a39")
    B3.grid(padx=20, pady=20, row=3, column=2)
    B4 = Tkinter.Button(main, text ="Pop Art", command = usepop, fg="#a1dbcd", bg="#383a39")
    B4.grid(padx=20, pady=20, row=5, column=2)

    s=S1.get()




main.mainloop()

【问题讨论】:

  • 您使用来自不支持pngtkinter 模块的标准PhotoImage。你必须使用模块PIL中的ImageTk.PhotoImage
  • 但我不明白它是否不支持为什么它可以工作,有时它不支持?我将使用此修复程序,但我想了解它为什么会这样?
  • 你必须检查图像 - 也许你有扩展名为 .png 的 GIF 或者更新的 tkinter 可以处理一些 png 但不是所有类型。

标签: python python-3.x tkinter python-imaging-library


【解决方案1】:

您使用不支持pngTkinter.PhotoImage
你必须从模块PIL ude ImageTk.PhotoImage

from PIL import Image, ImageTk


img2 = ImageTk.PhotoImage(...)

effbot.org:The Tkinter PhotoImage Class


2021 年编辑:

在 2020 年,effbot.org 上的文档已被删除,但其副本仍可在 archive.org 上的链接 effbot.orgThe Tkinter PhotoImage Class 中获得

感谢@GiovanniG.PY

【讨论】:

  • @GiovanniG.PY 这个答案是 3 岁。并且 effbot 去年被删除了 :) 但是感谢您提供信息 - 我无法检查所有旧答案来进行此更正。
  • 我认为它可能会有所帮助。因为 effbot 是我最喜欢的 tkinter 文档站点
  • @GiovanniG.PY 我也喜欢 effbot - 即使某些信息不完整 - 我在许多答案中都添加了指向 effbot 的链接。几个月前,我发现他们删除了文档,但我无法在我的答案中找到所有链接并进行更改。所以你的信息很有用。如果您找到其他指向 effbot 的链接,那么还要添加注释说明文档已被删除,现在它仅在 archive.org 中可用。
  • 我当然是wii,我的博客主页上也有一个链接
猜你喜欢
  • 2018-05-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-28
  • 2019-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-11
相关资源
最近更新 更多