9

I can't seem to get my PIL Image to work on canvas. Code:

from Tkinter import*
import Image, ImageTk
root = Tk()
root.geometry('1000x1000')
canvas = Canvas(root,width=999,height=999)
canvas.pack()
image = ImageTk.PhotoImage("ball.gif")
imagesprite = canvas.create_image(400,400,image=image)
root.mainloop()

Error:

Traceback (most recent call last):
  File "C:/Users/Mark Malkin/Desktop/3d Graphics Testing/afdds.py", line 7, in <module>
    image = ImageTk.PhotoImage("ball.gif")
  File "C:\Python27\lib\site-packages\PIL\ImageTk.py", line 109, in __init__
    mode = Image.getmodebase(mode)
  File "C:\Python27\lib\site-packages\PIL\Image.py", line 245, in getmodebase
    return ImageMode.getmode(mode).basemode
  File "C:\Python27\lib\site-packages\PIL\ImageMode.py", line 50, in getmode
    return _modes[mode]
KeyError: 'ball.gif'

I need to use PIL images not PhotoImages because I want to resize my images. Please don't suggest switching to Pygame because I want to use Tkinter.

Laurel
  • 5,965
  • 14
  • 31
  • 57
user164814
  • 135
  • 2
  • 2
  • 5
  • 1
    I'm confused - you say you don't want to use `PhotoImage`s, but your code uses a `PhotoImage`. Do you mean you want to use `ImageTk.PhotoImage` rather than `Tkinter.PhotoImage`? – Brionius Aug 22 '13 at 00:47
  • 1
    Have you tried reading the docs for `PhotoImage`? It takes an image object, or a mode and a size. You're not passing it either; you're passing it a filename. (The `KeyError` on `return _modes[mode]` makes it pretty obvious that it's trying to treat the filename as a mode… but it wouldn't matter which one it tried, it would fail either way.) – abarnert Aug 22 '13 at 00:51

4 Answers4

17

Try creating a PIL Image first, then using that to create the PhotoImage.

from Tkinter import *
import Image, ImageTk
root = Tk()
root.geometry('1000x1000')
canvas = Canvas(root,width=999,height=999)
canvas.pack()
pilImage = Image.open("ball.gif")
image = ImageTk.PhotoImage(pilImage)
imagesprite = canvas.create_image(400,400,image=image)
root.mainloop()
Brionius
  • 13,858
  • 3
  • 38
  • 49
  • ImageTk.PhotoImage is what I wanted to use, because I want to be a able to resize. – user164814 Aug 22 '13 at 12:11
  • raise ImportError("The _imaging C module is not installed") ImportError: The _imaging C module is not installed – user164814 Aug 23 '13 at 23:58
  • @user164814 Ah, you're in for a fun time then. You're missing a PIL binary - this is a problem with your PIL install, not the code. See [this article](http://effbot.org/zone/pil-imaging-not-installed.htm). If you used MacPorts to install PIL, try installing a system build yourself. Good luck. – Brionius Aug 24 '13 at 00:05
  • @Brionius, How to save this image? – Mulagala Apr 30 '15 at 06:04
  • @Mulagala you should open a new question to get an answer for this. – Brionius Apr 30 '15 at 08:19
  • Using `Image` works, but this answer is only half-complete, see my answer below. – One Mar 06 '17 at 14:26
9

(An old question, but the answers so far are only half-complete.)

Read the docs:

class PIL.ImageTk.PhotoImage(image=None, size=None, **kw)
  • image – Either a PIL image, or a mode string. [...]
  • file – A filename to load the image from (using Image.open(file)).

So in your example, use

image = ImageTk.PhotoImage(file="ball.gif")

or explicitly

image = ImageTk.PhotoImage(Image("ball.gif"))

(And remember – as you did correctly: Keep a reference to the image object in your Python program, otherwise it is garbage-collected before you seee it.)

One
  • 255
  • 3
  • 9
5

You can import multiple image formats, and resize with this code. "basewidth" sets the width of your image.

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

root=Tk()
image = Image.open("/path/to/your/image.jpg")
canvas=Canvas(root, height=200, width=200)
basewidth = 150
wpercent = (basewidth / float(image.size[0]))
hsize = int((float(image.size[1]) * float(wpercent)))
image = image.resize((basewidth, hsize), PIL.Image.ANTIALIAS)
photo = ImageTk.PhotoImage(image)
item4 = canvas.create_image(100, 80, image=photo)

canvas.pack(side = TOP, expand=True, fill=BOTH)
root.mainloop()
3

I was banging my head against the wall for a while on this issue until I found the following:

http://effbot.org/pyfaq/why-do-my-tkinter-images-not-appear.htm

Apparently, Python's garbage collector can trash the ImageTk object. I imagine apps using alot of widgets (like mine) are more susceptible to this behavior.

DanCan
  • 61
  • 6