1

I am using python( my version is 2.7 ). I want to add an image to GUI (Tkinter) and then convert into executable format using pyinstaller. I did followed as on SO, and also as said on ActiveState

When i mention the image's path on the code, it works only if i run it directly. If i convert it to exe it doesnt open.

Changing the code as mentioned from other solutions, like by converting it into encoded string, it runs fine on linux. But on windows it throws error

code:

from Tkinter import *
from PIL import ImageTk, Image

logo = '''
----- encoded string -----
'''

root = Tk()
logoimage = Tkinter.PhotoImage(master=root, data=logo)
Label(root, image=logoimage).pack()
root.mainloop()

Change 1: The above code works on linux. On windows i get error on the line logoimage = Tkinter.PhotoImage(master=root, data=logo) as

NameError: name 'Tkinter' is not defined

Change 2: So i tries changing the line as logoimage = ImageTk.PhotoImage(master=root, data=logo). The error i get is

File "C:\Python27\lib\site-packages\PIL\ImageTk.py", line 88, in __init__
    image = Image.open(BytesIO(kw["data"]))
  File "C:\Python27\lib\site-packages\PIL\Image.py", line 2330, in open
    % (filename if filename else fp))
IOError: cannot identify image file <_io.BytesIO object at 0x00000000024BB150>
Exception AttributeError: "'PhotoImage' object has no attribute '_PhotoImage__photo'" in <bound method PhotoImage.__del__ of <PIL.ImageTk.PhotoImage object at 0x00000000024D49E8>> ignored

Change 3: But, if i change the line as iconImage= ImageTk.PhotoImage(Image.open('path_to_image.png')). It works only if i run directly. If i convert it to executable, then console opens for 2-3 seconds and displaying error something like Unable to locate the image file

Community
  • 1
  • 1
arvindh
  • 739
  • 4
  • 12
  • 28

2 Answers2

2

Doing the decoding and converting explicitly may be more robust than what you're currently doing. This code works on Python 2.6.6 on Linux.

import io, base64
from Tkinter import *
from PIL import ImageTk, Image

#A simple 64x64 PNG fading from orange in the top left corner 
# to red in the bottom right, encoded in base64
logo_b64 = '''
iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIA
AAAlC+aJAAAA/0lEQVR4nO3Zyw7CMAxEUdP//+W2rCqBoJA2noclS1kn9yjLeex7xKY76+
wNS+l6KSCjXgdIqhcB8uoVgNR6OiC7ngsA1BMBmHoWAFZPASDr8QBwPRiAr0cCKPUwAKse
AyDWAwDc+mwAvT4VoKjPA4jqkwC6+gyAtD7WSYC6fu4HDOonAB71dwE29bcATvXXAWb1Fw
F+9VcAlvXDANf6MYBx/QDAu/4fwL7+J6BC/TmgSP0JoE79N0Cp+g9Atfp3QMH6F0DN+gNQ
tj62WErXB2PgQNZLAb3U6wC91OsAvdTrAL3U6wC91OsAvdTrAL3U6wC91OsAvdTrAL3Uz7
z+BNmX4gqbppsaAAAAAElFTkSuQmCC
'''

#Decode the PNG data & "wrap" it into a file-like object
fh = io.BytesIO(base64.b64decode(logo_b64))

#Create a PIL image from the PNG data
img = Image.open(fh, mode='r')

#We must open the window before calling ImageTk.PhotoImage
root = Tk()

photo = ImageTk.PhotoImage(image=img)
Label(root, image=photo).pack()
Label(root, text='An embedded\nbase64-encoded PNG').pack()
root.mainloop()

For reference, here's what that embedded PNG looks like.

fading from orange in the top left corner to red in the bottom right

PM 2Ring
  • 54,345
  • 6
  • 82
  • 182
  • Great, Thanks,.. This works on windows, and works after converting the code to executable file.. i have to try this one on mac too – arvindh Aug 04 '15 at 16:12
  • 1
    @arvindh: If it doesn't work properly on a given machine there's a chance that all the required libraries aren't installed. ImageTk needs the tk and tcl dev packages. So you _may_ need to uninstall Pillow, install those dev packages, and then re-install Pillow. – PM 2Ring Aug 04 '15 at 16:24
  • it works on mac while running the code. But unable to run the executable version of the code. I got errors as you said(mentioning something about tcl),.. And tried uninstalling `pillow`, reinstalled `tcl dev` from activestate, and then installed `pillow`. still unable to get through. I have asked question about that over [here](http://stackoverflow.com/questions/31834267/python-pyinstaller-warning-while-making-executable-on-mac). Please help if you can. – arvindh Aug 05 '15 at 14:46
  • Sorry, @arvindh, but I'm not very familiar with OSX. But I'll ask around for you. – PM 2Ring Aug 05 '15 at 15:18
0
from Tkinter import *
#...
logoimage = Tkinter.PhotoImage(master=root, data=logo)

If you dump the Tkinter module straight into the global scope using import *, then you shouldn't prefix class and function names with the module name. Either remove the prefix, or remove the import *.

import Tkinter
#...
logoimage = Tkinter.PhotoImage(master=root, data=logo)

Or

from Tkinter import *
#...
logoimage = PhotoImage(master=root, data=logo)

I suspect you're not getting the error in Linux because your version of Python imports common modules automatically. Effectively, there's an invisible import Tkinter at the top of all your scripts.

Kevin
  • 74,910
  • 12
  • 133
  • 166
  • on changing line to `logoimage = PhotoImage(master=root, data=logo)`. I get error as `File "C:\Python27\lib\lib-tk\Tkinter.py", line 3362, in __init__ Image.__init__(self, 'photo', name, cnf, master, **kw) File "C:\Python27\lib\lib-tk\Tkinter.py", line 3316, in __init__ self.tk.call(('image', 'create', imgtype, name,) + options) _tkinter.TclError: couldn't recognize image data` – arvindh Aug 04 '15 at 14:03
  • Maybe your encoded string is improperly formed. In your sample code, it's represented as three quote marks, then a newline, then your data, then a newline, then three quote marks. Is that how it is in your actual code? It's possible that those newlines are causing the data to be unreadable. Try deleting them, so the quote marks are on the same line as the data. – Kevin Aug 04 '15 at 14:07
  • actually, its a huge code that has been written based on `from Tkinter import *`. and i cannot change those portion of code which is written by someone else. – arvindh Aug 04 '15 at 14:08
  • That's fine. You can leave `from Tkinter import *` the way it is, if you use my second suggested approach. – Kevin Aug 04 '15 at 14:10
  • no change on error on changing string like you said on windows,.. but on linux, its not accepting that as string. And as mentioned on [ActiveState](http://code.activestate.com/recipes/52264-inline-gifs-with-tkinter/), that is the right way to mention that string it seems – arvindh Aug 04 '15 at 14:22