Tuesday, July 8, 2008

Showing a webcam image in the desktop window using Python. Part 2: displaying images in windows

In the previous post I have shown how to download an image from web with the use of Python. Today I will show code which takes this image and draws it in a standalone window.
Before we start it is necessary to be prepared somewhat. You need a specialised library to make windows. I 'm using Tkinter which comes with Python as default. There are more options like wxwidgets but I've started with Tkinter and so far it has covered all my needs. It seemed quite tricky to learn so I have found a good tutorial on Tkinter and learned it that way. Unfortunately, it is only in czech and currently seems offline so I cannot link to it anyway :-(.
To deal with images I'm using the PIL or Python Imaging Library. This you will need to download and install in order to use following code. Good news is that it's free :-)
Programming windowed applications is a lot more complicated than simple beginner stuff and in today's code there are commands which I don't know why they are there...
The code:

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

class Container:
pass

def drawwindow():
main = Tk()
main.title('Zatec webcam') # window title
main.resizable(width=False, height=False)
container.main = main
container.canvas = Canvas(main, width=container.width, height=container.height)
container.canvas.pack(expand=1, fill=BOTH)
container.statusbarVar = StringVar()
container.statusbar = Label(main, textvariable=container.statusbarVar)
container.statusbar.pack()
container.statusbarVar.set('Ready.')
container.statusbar.update()


def showimage(image):
'''Loads given image and puts it into the window'''
img = Image.open(image)
photo = ImageTk.PhotoImage(img)
container.canvas.create_image(container.width/2+2, container.height/2, image=photo)
container.obr = photo # why is this line necessary?

def getimagefromweb(url):
'''Downloads content from given url and saves it as image.'''
container.statusbarVar.set('Reading new image from web...')
container.statusbar.update()
try:
u = urllib.urlopen(url) # open url
container.statusbarVar.set('Url opened...')
container.statusbar.update()

content = u.read() # read the opened url
container.statusbarVar.set('Url read...')
container.statusbar.update()

u.close() # url was closed
container.statusbarVar.set('Url closed...')
container.statusbar.update()

except IOError:
print('IOError')
pass
except:
print('Unknown url error')

# saving what was downloaded
f = open('img.jpg','wb')
f.write(content)
f.close() # file was closed

# showing the image
showimage('img.jpg')
container.statusbarVar.set('Ready.')
container.statusbar.update()

# the script
myurl = 'http://siemens.mesto-zatec.cz/obrazek.jpg'
container = Container()
container.width = 800
container.height = 602

drawwindow()
getimagefromweb(myurl)

mainloop()
print 'end OK'

The class Container is used to store information which is passed between functions. The code could be rewritten to form a single class but it works this way too :-).
There are three functions. Drawwindow is used to create window with desired elements in it (Canvas and Label). To provide some info on download status there is a text in the Label. This is done with the help of StringVar() which is from Tkinter library. If we used only a string, it would be immutable later on. After the Label is changed, an .update() function must be called to change it on the display too.
The showimage() function gets an image file from disk and puts it into the Canvas. There is some magic in it, sorry about that.
The third function, getimagefromweb(), is adopted from previous post by adding info into the Label and after the image saved it calls the showimage() function.
In the script, we first draw the window elements with drawwindow() and then download an image and paste it into the Canvas with getimagefromweb().
The last command, mainloop(), tells Tkinter that we are ready and draws everything on the display. Without this command nothing will be shown (though it will be ready). Also, after mainloop is called, the focus is changed from your script to the GUI which is driven by user action. After you close the window the focus is returned to your python script.

No comments: