2018-09-27 20:24:09 +00:00
|
|
|
#!/usr/bin/env python
|
2019-10-23 20:10:03 +00:00
|
|
|
import PySimpleGUI as sg
|
2018-09-03 20:52:22 +00:00
|
|
|
import os
|
|
|
|
from PIL import Image, ImageTk
|
|
|
|
import io
|
2019-10-23 20:10:03 +00:00
|
|
|
|
2018-09-03 20:52:22 +00:00
|
|
|
"""
|
|
|
|
Simple Image Browser based on PySimpleGUI
|
|
|
|
--------------------------------------------
|
|
|
|
There are some improvements compared to the PNG browser of the repository:
|
|
|
|
1. Paging is cyclic, i.e. automatically wraps around if file index is outside
|
|
|
|
2. Supports all file types that are valid PIL images
|
|
|
|
3. Limits the maximum form size to the physical screen
|
|
|
|
4. When selecting an image from the listbox, subsequent paging uses its index
|
|
|
|
5. Paging performance improved significantly because of using PIL
|
|
|
|
|
|
|
|
Dependecies
|
|
|
|
------------
|
2019-10-23 20:10:03 +00:00
|
|
|
Python3
|
2018-09-03 20:52:22 +00:00
|
|
|
PIL
|
|
|
|
"""
|
2019-10-23 20:10:03 +00:00
|
|
|
|
2018-10-08 17:30:33 +00:00
|
|
|
# Get the folder containin:g the images from the user
|
2019-10-23 20:10:03 +00:00
|
|
|
folder = sg.popup_get_folder('Image folder to open', default_path='')
|
2018-10-08 17:30:33 +00:00
|
|
|
if not folder:
|
2019-10-23 20:10:03 +00:00
|
|
|
sg.popup_cancel('Cancelling')
|
2018-09-03 20:52:22 +00:00
|
|
|
raise SystemExit()
|
|
|
|
|
|
|
|
# PIL supported image types
|
|
|
|
img_types = (".png", ".jpg", "jpeg", ".tiff", ".bmp")
|
|
|
|
|
|
|
|
# get list of files in folder
|
|
|
|
flist0 = os.listdir(folder)
|
|
|
|
|
|
|
|
# create sub list of image files (no sub folders, no wrong file types)
|
2019-10-23 20:10:03 +00:00
|
|
|
fnames = [f for f in flist0 if os.path.isfile(
|
|
|
|
os.path.join(folder, f)) and f.lower().endswith(img_types)]
|
2018-09-03 20:52:22 +00:00
|
|
|
|
|
|
|
num_files = len(fnames) # number of iamges found
|
|
|
|
if num_files == 0:
|
2019-10-23 20:10:03 +00:00
|
|
|
sg.popup('No files in folder')
|
2018-09-03 20:52:22 +00:00
|
|
|
raise SystemExit()
|
|
|
|
|
|
|
|
del flist0 # no longer needed
|
|
|
|
|
2019-10-23 20:10:03 +00:00
|
|
|
# ------------------------------------------------------------------------------
|
2018-09-03 20:52:22 +00:00
|
|
|
# use PIL to read data of one image
|
2019-10-23 20:10:03 +00:00
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
def get_img_data(f, maxsize=(1200, 850), first=False):
|
2018-09-03 20:52:22 +00:00
|
|
|
"""Generate image data using PIL
|
|
|
|
"""
|
|
|
|
img = Image.open(f)
|
|
|
|
img.thumbnail(maxsize)
|
|
|
|
if first: # tkinter is inactive the first time
|
|
|
|
bio = io.BytesIO()
|
2019-10-23 20:10:03 +00:00
|
|
|
img.save(bio, format="PNG")
|
2018-09-03 20:52:22 +00:00
|
|
|
del img
|
|
|
|
return bio.getvalue()
|
|
|
|
return ImageTk.PhotoImage(img)
|
2019-10-23 20:10:03 +00:00
|
|
|
# ------------------------------------------------------------------------------
|
2018-09-03 20:52:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
# make these 2 elements outside the layout as we want to "update" them later
|
|
|
|
# initialize to the first file in the list
|
|
|
|
filename = os.path.join(folder, fnames[0]) # name of first file in list
|
2019-10-23 20:10:03 +00:00
|
|
|
image_elem = sg.Image(data=get_img_data(filename, first=True))
|
2018-09-03 20:52:22 +00:00
|
|
|
filename_display_elem = sg.Text(filename, size=(80, 3))
|
2019-10-23 20:10:03 +00:00
|
|
|
file_num_display_elem = sg.Text('File 1 of {}'.format(num_files), size=(15, 1))
|
2018-09-03 20:52:22 +00:00
|
|
|
|
|
|
|
# define layout, show and read the form
|
|
|
|
col = [[filename_display_elem],
|
2019-10-23 20:10:03 +00:00
|
|
|
[image_elem]]
|
2018-09-03 20:52:22 +00:00
|
|
|
|
2019-10-23 20:10:03 +00:00
|
|
|
col_files = [[sg.Listbox(values=fnames, change_submits=True, size=(60, 30), key='listbox')],
|
|
|
|
[sg.Button('Next', size=(8, 2)), sg.Button('Prev', size=(8, 2)), file_num_display_elem]]
|
2018-09-03 20:52:22 +00:00
|
|
|
|
2019-11-08 17:38:12 +00:00
|
|
|
layout = [[sg.Column(col_files), sg.Column(col)]]
|
2018-09-03 20:52:22 +00:00
|
|
|
|
2019-10-23 20:10:03 +00:00
|
|
|
window = sg.Window('Image Browser', layout, return_keyboard_events=True,
|
|
|
|
location=(0, 0), use_default_focus=False)
|
2018-09-03 20:52:22 +00:00
|
|
|
|
|
|
|
# loop reading the user input and displaying image, filename
|
2019-10-23 20:10:03 +00:00
|
|
|
i = 0
|
2018-09-03 20:52:22 +00:00
|
|
|
while True:
|
|
|
|
# read the form
|
2019-10-23 20:10:03 +00:00
|
|
|
event, values = window.read()
|
2018-10-15 20:07:23 +00:00
|
|
|
print(event, values)
|
2018-09-03 20:52:22 +00:00
|
|
|
# perform button and keyboard operations
|
2018-10-15 20:07:23 +00:00
|
|
|
if event is None:
|
2018-09-03 20:52:22 +00:00
|
|
|
break
|
2018-10-15 20:07:23 +00:00
|
|
|
elif event in ('Next', 'MouseWheel:Down', 'Down:40', 'Next:34'):
|
2018-09-03 20:52:22 +00:00
|
|
|
i += 1
|
|
|
|
if i >= num_files:
|
|
|
|
i -= num_files
|
|
|
|
filename = os.path.join(folder, fnames[i])
|
2018-10-15 20:07:23 +00:00
|
|
|
elif event in ('Prev', 'MouseWheel:Up', 'Up:38', 'Prior:33'):
|
2018-09-03 20:52:22 +00:00
|
|
|
i -= 1
|
|
|
|
if i < 0:
|
|
|
|
i = num_files + i
|
|
|
|
filename = os.path.join(folder, fnames[i])
|
2018-10-15 20:07:23 +00:00
|
|
|
elif event == 'listbox': # something from the listbox
|
2018-09-03 20:52:22 +00:00
|
|
|
f = values["listbox"][0] # selected filename
|
|
|
|
filename = os.path.join(folder, f) # read this file
|
|
|
|
i = fnames.index(f) # update running index
|
|
|
|
else:
|
|
|
|
filename = os.path.join(folder, fnames[i])
|
|
|
|
|
|
|
|
# update window with new image
|
2019-11-08 17:38:12 +00:00
|
|
|
image_elem.update(data=get_img_data(filename, first=True))
|
2018-09-03 20:52:22 +00:00
|
|
|
# update window with filename
|
2019-10-23 20:10:03 +00:00
|
|
|
filename_display_elem.update(filename)
|
2018-09-03 20:52:22 +00:00
|
|
|
# update page display
|
2019-10-23 20:10:03 +00:00
|
|
|
file_num_display_elem.update('File {} of {}'.format(i+1, num_files))
|
2018-09-04 18:07:42 +00:00
|
|
|
|
2019-10-23 20:10:03 +00:00
|
|
|
window.close()
|