Merge pull request #112 from MikeTheWatchGuy/Dev-latest

Initial checkin into Dev branch
This commit is contained in:
MikeTheWatchGuy 2018-09-03 16:54:03 -04:00 committed by GitHub
commit db3017185c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 113 additions and 115 deletions

View File

@ -1,115 +1,113 @@
import PySimpleGUI as sg import PySimpleGUI as sg
import os import os
from PIL import Image, ImageTk from PIL import Image, ImageTk
import io import io
""" """
Simple Image Browser based on PySimpleGUI Simple Image Browser based on PySimpleGUI
-------------------------------------------- --------------------------------------------
There are some improvements compared to the PNG browser of the repository: 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 1. Paging is cyclic, i.e. automatically wraps around if file index is outside
2. Supports all file types that are valid PIL images 2. Supports all file types that are valid PIL images
3. Limits the maximum form size to the physical screen 3. Limits the maximum form size to the physical screen
4. When selecting an image from the listbox, subsequent paging uses its index 4. When selecting an image from the listbox, subsequent paging uses its index
5. Paging performance improved significantly because of using PIL 5. Paging performance improved significantly because of using PIL
Dependecies Dependecies
------------ ------------
Python v3 Python v3
PIL PIL
""" """
# Get the folder containing the images from the user # Get the folder containing the images from the user
rc, folder = sg.GetPathBox('Image Browser', 'Image folder to open', default_path='') rc, folder = sg.GetPathBox('Image Browser', 'Image folder to open', default_path='')
if not rc or not folder: if not rc or not folder:
sg.PopupCancel('Cancelling') sg.PopupCancel('Cancelling')
raise SystemExit() raise SystemExit()
# PIL supported image types # PIL supported image types
img_types = (".png", ".jpg", "jpeg", ".tiff", ".bmp") img_types = (".png", ".jpg", "jpeg", ".tiff", ".bmp")
# get list of files in folder # get list of files in folder
flist0 = os.listdir(folder) flist0 = os.listdir(folder)
# create sub list of image files (no sub folders, no wrong file types) # create sub list of image files (no sub folders, no wrong file types)
fnames = [f for f in flist0 if os.path.isfile(os.path.join(folder,f)) and f.lower().endswith(img_types)] fnames = [f for f in flist0 if os.path.isfile(os.path.join(folder,f)) and f.lower().endswith(img_types)]
num_files = len(fnames) # number of iamges found num_files = len(fnames) # number of iamges found
if num_files == 0: if num_files == 0:
sg.Popup('No files in folder') sg.Popup('No files in folder')
raise SystemExit() raise SystemExit()
del flist0 # no longer needed del flist0 # no longer needed
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# use PIL to read data of one image # use PIL to read data of one image
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
def get_img_data(f, maxsize = (1200, 850), first = False): def get_img_data(f, maxsize = (1200, 850), first = False):
"""Generate image data using PIL """Generate image data using PIL
""" """
img = Image.open(f) img = Image.open(f)
img.thumbnail(maxsize) img.thumbnail(maxsize)
if first: # tkinter is inactive the first time if first: # tkinter is inactive the first time
bio = io.BytesIO() bio = io.BytesIO()
img.save(bio, format = "PNG") img.save(bio, format = "PNG")
del img del img
return bio.getvalue() return bio.getvalue()
return ImageTk.PhotoImage(img) return ImageTk.PhotoImage(img)
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# create the form that also returns keyboard events # create the form that also returns keyboard events
form = sg.FlexForm('Image Browser', return_keyboard_events=True, form = sg.FlexForm('Image Browser', return_keyboard_events=True,
location=(0, 0), use_default_focus=False) location=(0, 0), use_default_focus=False)
# make these 2 elements outside the layout as we want to "update" them later # make these 2 elements outside the layout as we want to "update" them later
# initialize to the first file in the list # initialize to the first file in the list
filename = os.path.join(folder, fnames[0]) # name of first file in list filename = os.path.join(folder, fnames[0]) # name of first file in list
image_elem = sg.Image(data = get_img_data(filename, first = True)) image_elem = sg.Image(data = get_img_data(filename, first = True))
filename_display_elem = sg.Text(filename, size=(80, 3)) filename_display_elem = sg.Text(filename, size=(80, 3))
file_num_display_elem = sg.Text('File 1 of {}'.format(num_files), size=(15,1)) file_num_display_elem = sg.Text('File 1 of {}'.format(num_files), size=(15,1))
# define layout, show and read the form # define layout, show and read the form
col = [[filename_display_elem], col = [[filename_display_elem],
[image_elem]] [image_elem]]
col_files = [[sg.Listbox(values = fnames, select_submits=True, size=(60,30), key='listbox')], col_files = [[sg.Listbox(values = fnames, select_submits=True, size=(60,30), key='listbox')],
[sg.ReadFormButton('Next', size=(8,2)), sg.ReadFormButton('Prev', [sg.ReadFormButton('Next', size=(8,2)), sg.ReadFormButton('Prev',
size=(8,2)), file_num_display_elem]] size=(8,2)), file_num_display_elem]]
layout = [[sg.Column(col_files), sg.Column(col)]] layout = [[sg.Column(col_files), sg.Column(col)]]
form.Layout(layout) # Shows form on screen form.Layout(layout) # Shows form on screen
# loop reading the user input and displaying image, filename # loop reading the user input and displaying image, filename
i=0 i=0
while True: while True:
# read the form # read the form
button, values = form.Read() button, values = form.Read()
# perform button and keyboard operations # perform button and keyboard operations
if button is None: if button is None:
break break
elif button in ('Next', 'MouseWheel:Down', 'Down:40', 'Next:34'): elif button in ('Next', 'MouseWheel:Down', 'Down:40', 'Next:34'):
i += 1 i += 1
if i >= num_files: if i >= num_files:
i -= num_files i -= num_files
filename = os.path.join(folder, fnames[i]) filename = os.path.join(folder, fnames[i])
elif button in ('Prev', 'MouseWheel:Up', 'Up:38', 'Prior:33'): elif button in ('Prev', 'MouseWheel:Up', 'Up:38', 'Prior:33'):
i -= 1 i -= 1
if i < 0: if i < 0:
i = num_files + i i = num_files + i
filename = os.path.join(folder, fnames[i]) filename = os.path.join(folder, fnames[i])
elif button in ('Read', ''): # something from the listbox elif button in ('Read', ''): # something from the listbox
f = values["listbox"][0] # selected filename f = values["listbox"][0] # selected filename
filename = os.path.join(folder, f) # read this file filename = os.path.join(folder, f) # read this file
i = fnames.index(f) # update running index i = fnames.index(f) # update running index
else: else:
filename = os.path.join(folder, fnames[i]) filename = os.path.join(folder, fnames[i])
# update window with new image # update window with new image
image_elem.Update(data=get_img_data(filename)) image_elem.Update(data=get_img_data(filename))
# update window with filename # update window with filename
filename_display_elem.Update(filename) filename_display_elem.Update(filename)
# update page display # update page display
file_num_display_elem.Update('File {} of {}'.format(i+1, num_files)) file_num_display_elem.Update('File {} of {}'.format(i+1, num_files))