19

I have several images which I would like to show the user with Python. The user should enter some description and then the next image should be shown.

This is my code:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import os, glob
from PIL import Image

path = '/home/moose/my/path/'
for infile in glob.glob( os.path.join(path, '*.png') ):
    im = Image.open(infile)
    im.show()
    value = raw_input("Description: ")
    # store and do some other stuff. Now the image-window should get closed

It is working, but the user has to close the image himself. Could I get python to close the image after the description has been entered?

I don't need PIL. If you have another idea with another library / bash-program (with subprocess), it'll be also fine.

Jeremy
  • 1
  • 85
  • 340
  • 366
Martin Thoma
  • 124,992
  • 159
  • 614
  • 958

3 Answers3

18

psutil can get the pid of the display process created by im.show() and kill the process with that pid on every operating system:

import time

import psutil
from PIL import Image

# open and show image
im = Image.open('myImageFile.jpg')
im.show()

# display image for 10 seconds
time.sleep(10)

# hide image
for proc in psutil.process_iter():
    if proc.name() == "display":
        proc.kill()
Bengt
  • 14,011
  • 7
  • 48
  • 66
  • @IDelgado psutil should work under OS X. Please describe your problem on the project's [issue tracker](https://github.com/giampaolo/psutil/issues). – Bengt Nov 23 '14 at 16:58
  • @Bengt After `proc.name` a method so you can call it like `proc.name()` and only then will works. Please fix it and you and you get a vote up. – Geeocode Jul 27 '15 at 09:19
  • @IDelgado see the previous comment. – Geeocode Jul 27 '15 at 09:19
  • 2
    @GyörgySolymosi @IDelgadoYes, in newer versions of psutil `proc.name` is a method rather than a string property. If one checks for the name property, the script exits without effect, because they look something like this: `>` Thanks for pointing this out, I updated my answer. Hopefully, nobody will trip over that in the future. – Bengt Jul 27 '15 at 20:05
  • 1
    In macOS, proc.name() will be 'Preview'. – Aniket Deshpande Oct 08 '21 at 23:27
15

The show method "is mainly intended for debugging purposes" and spawns an external process for which you don't get a handle, so you can't kill it in a proper way.

With PIL, you may want to use one of its GUI modules , such as ImageTk, ImageQt or ImageWin.

Otherwise, just manually spawn an image viewer from Python with the subprocess module:

for infile in glob.glob( os.path.join(path, '*.png')):
    viewer = subprocess.Popen(['some_viewer', infile])
    viewer.terminate()
    viewer.kill()  # make sure the viewer is gone; not needed on Windows
Fred Foo
  • 355,277
  • 75
  • 744
  • 836
6

I've modified this recipe before to do some image work in Python. It uses Tkinter, so it doesn't require any modules besides PIL.

'''This will simply go through each file in the current directory and
try to display it. If the file is not an image then it will be skipped.
Click on the image display window to go to the next image.

Noah Spurrier 2007'''
import os, sys
import Tkinter
import Image, ImageTk

def button_click_exit_mainloop (event):
    event.widget.quit() # this will cause mainloop to unblock.

root = Tkinter.Tk()
root.bind("<Button>", button_click_exit_mainloop)
root.geometry('+%d+%d' % (100,100))
dirlist = os.listdir('.')
old_label_image = None
for f in dirlist:
    try:
        image1 = Image.open(f)
        root.geometry('%dx%d' % (image1.size[0],image1.size[1]))
        tkpi = ImageTk.PhotoImage(image1)
        label_image = Tkinter.Label(root, image=tkpi)
        label_image.place(x=0,y=0,width=image1.size[0],height=image1.size[1])
        root.title(f)
        if old_label_image is not None:
            old_label_image.destroy()
        old_label_image = label_image
        root.mainloop() # wait until user clicks the window
    except Exception, e:
        # This is used to skip anything not an image.
        # Warning, this will hide other errors as well.
        pass
Nick T
  • 25,754
  • 12
  • 83
  • 121
  • It requires ImageTK. But I've just found the proper Ubuntu-Package: sudo apt-get install python-imaging-tk. Am I missing something or isn't it possible for the user to give an input? I wanted to close the current window and open the next (or simply open the next in the current window) without any other user interaction than writing a description (finisihing with enter). – Martin Thoma Jul 18 '11 at 08:01
  • ImageTK should come with PIL... You can modify the window and tack on a text field and button if you like. My `Tkinter` is very old, usually I use `wx`. – Nick T Jul 18 '11 at 11:35