Python Image Viewer Improved
This is a new version of the Python Image Viewer posted earlier. It has now been updated to be Python 3 compatible and there is a couple of new features. The first feature is resizing of all images to the same resolution. The resolution is provided by an argument or will be 800x600 by default. The second feature is an extra button to browse to a random image.
The updated code:
#!/usr/bin/python3
from tkinter import *
from PIL import ImageTk, Image
import subprocess
import os
import random
class ImageView(Frame):
def __init__(self, images, command, resolution, master=None):
Frame.__init__(self, master)
self.master.bind("<Key>", self._key_press)
self.grid()
self._create_widgets()
self._images = images
self._command = command
self._resolution = tuple(map(int, resolution.split("x")))
self._offset = 0
self._browse(0) # Load first image!
def _browse(self, offset):
if offset == None:
self._offset = random.randint(0, len(self._images))
else:
self._offset += offset
if self._offset < 0:
self._offset = 0
elif self._offset >= len(self._images):
self._offset = (len(self._images) - 1)
self.master.title("%s (%d/%d)" % (os.path.basename(self._images[self._offset]), self._offset + 1, len(self._images)))
self._image_data = ImageTk.PhotoImage(Image.open(self._images[self._offset]).resize(self._resolution))
self._image = Button(image=self._image_data, bd=0, relief=FLAT, command=lambda: self._browse(1))
self._image.grid(column=0, row=0, columnspan=8, sticky="news")
def _exec(self):
subprocess.call([self._command, self._images[self._offset]])
def _create_widgets(self):
self._random = Button(text="Rnd", command=lambda: self._browse(None))
self._prev_1 = Button(text="<", command=lambda: self._browse(-1))
self._prev_10 = Button(text="<<", command=lambda: self._browse(-10))
self._prev_100 = Button(text="<<<", command=lambda: self._browse(-100))
self._next_1 = Button(text=">", command=lambda: self._browse(1))
self._next_10 = Button(text=">>", command=lambda: self._browse(10))
self._next_100 = Button(text=">>>", command=lambda: self._browse(100))
self._go = Button(text="Go!", command=self._exec)
self._random.grid (column=0, row=1, sticky="ew")
self._prev_100.grid(column=1, row=1, sticky="ew")
self._prev_10.grid (column=2, row=1, sticky="ew")
self._prev_1.grid (column=3, row=1, sticky="ew")
self._go.grid (column=4, row=1, sticky="ew")
self._next_1.grid (column=5, row=1, sticky="ew")
self._next_10.grid (column=6, row=1, sticky="ew")
self._next_100.grid(column=7, row=1, sticky="ew")
def _key_press(self, e):
if e.keysym == "Right":
self._browse(1)
elif e.keysym == "Left":
self._browse(-1)
elif e.keysym == "Up":
self._browse(10)
elif e.keysym == "Down":
self._browse(-10)
elif e.keysym == "Prior":
self._browse(100)
elif e.keysym == "Next":
self._browse(-100)
elif e.keysym == "Return":
self._exec()
elif e.keysym == "Escape":
self.master.destroy()
else:
pass
if __name__ == "__main__":
import sys
if len(sys.argv) < 3:
print("Usage: %s <image directory> <command> ['width'x'height']" % (sys.argv[0]))
sys.exit(1)
images = list()
for root, dirs, files in os.walk(sys.argv[1]):
for filename in files:
if filename.endswith(".jpg"):
images.append(os.path.join(root, filename))
if len(images) == 0:
print("No images found :-(")
sys.exit(1)
if len(sys.argv) > 3:
resolution = sys.argv[3]
else:
resolution = "800x600" # Default
iw = ImageView(sorted(images), sys.argv[2], resolution)
iw.master.resizable(0, 0)
iw.mainloop()
sys.exit(0)