A quick "refresh"... user bsawlor (thank you!) pointed out a float crash. Sliders return floats now and thus needs casting in this demo.

This commit is contained in:
PySimpleGUI 2021-11-10 13:37:11 -05:00
parent cf2f99c8d8
commit d84ee84caf
1 changed files with 68 additions and 22 deletions

View File

@ -1,11 +1,23 @@
#!/usr/bin/env python #!/usr/bin/env python
import PIL
from PIL import Image from PIL import Image
from sys import exit from sys import exit
import PySimpleGUI as sg import PySimpleGUI as sg
import os import os
import io import io
import numpy as np import base64
"""
Demo PNG Thumbnail Viewer
Displays PNG files from a folder.
OK, so... this isn't the best Demo Program, that's for sure. It's one of the older
demos in the repo. There are likely better ones to use. The convert_to_bytes function is
the best thing in this demo.
Copyright 2021 PySimpleGUI.org
"""
thumbnails = {} thumbnails = {}
@ -13,28 +25,62 @@ ROWS = 8
COLUMNS = 8 COLUMNS = 8
sg.set_options(border_width=0) sg.set_options(border_width=0)
# Get the folder containing the images from the user # Get the folder containing the images from the user
# folder = 'A:/TEMP/pdfs'
folder = sg.popup_get_folder('Image folder to open') folder = sg.popup_get_folder('Image folder to open')
if folder is None: if folder is None:
sg.popup_cancel('Cancelling') sg.popup_cancel('Cancelling')
exit(0) exit(0)
def image_file_to_bytes(filename, size):
def convert_to_bytes(file_or_bytes, resize=None):
"""
Will convert into bytes and optionally resize an image that is a file or a base64 bytes object.
Turns into PNG format in the process so that can be displayed by tkinter
:param file_or_bytes: either a string filename or a bytes base64 image object
:type file_or_bytes: (Union[str, bytes])
:param resize: optional new size
:type resize: (Tuple[int, int] or None)
:param fill: If True then the image is filled/padded so that the image is not distorted
:type fill: (bool)
:return: (bytes) a byte-string object
:rtype: (bytes)
"""
if isinstance(file_or_bytes, str):
img = PIL.Image.open(file_or_bytes)
else:
try: try:
image = Image.open(filename) img = PIL.Image.open(io.BytesIO(base64.b64decode(file_or_bytes)))
image.thumbnail(size, Image.ANTIALIAS) except Exception as e:
bio = io.BytesIO() # a binary memory resident stream dataBytesIO = io.BytesIO(file_or_bytes)
image.save(bio, format='PNG') # save image as png to it img = PIL.Image.open(dataBytesIO)
imgbytes = bio.getvalue()
except: cur_width, cur_height = img.size
imgbytes = None if resize:
return imgbytes new_width, new_height = resize
scale = min(new_height / cur_height, new_width / cur_width)
img = img.resize((int(cur_width * scale), int(cur_height * scale)), PIL.Image.ANTIALIAS)
with io.BytesIO() as bio:
img.save(bio, format="PNG")
del img
return bio.getvalue()
#
# old, original PIL code.
# def image_file_to_bytes(filename, size):
# try:
# image = Image.open(filename)
# image.thumbnail(size, Image.ANTIALIAS)
# bio = io.BytesIO() # a binary memory resident stream
# image.save(bio, format='PNG') # save image as png to it
# imgbytes = bio.getvalue()
# except:
# imgbytes = None
# return imgbytes
def set_image_to_blank(key): def set_image_to_blank(key):
img = Image.new('RGB', (100, 100), (255, 255, 255)) img = PIL.Image.new('RGB', (100, 100), (255, 255, 255))
img.thumbnail((1, 1), Image.ANTIALIAS) img.thumbnail((1, 1), PIL.Image.ANTIALIAS)
bio = io.BytesIO() bio = io.BytesIO()
img.save(bio, format='PNG') img.save(bio, format='PNG')
imgbytes = bio.getvalue() imgbytes = bio.getvalue()
@ -43,8 +89,8 @@ def set_image_to_blank(key):
# get list of PNG files in folder # get list of PNG files in folder
png_files = [os.path.join(folder, f) png_files = [os.path.join(folder, f)
for f in os.listdir(folder) if '.png' in f] for f in os.listdir(folder) if f.endswith('.png')]
filenames_only = [f for f in os.listdir(folder) if '.png' in f] filenames_only = [f for f in os.listdir(folder) if f.endswith('.png')]
if len(png_files) == 0: if len(png_files) == 0:
sg.popup('No PNG images in folder') sg.popup('No PNG images in folder')
@ -65,7 +111,7 @@ col_buttons = [[]]
# define layout, show and read the window # define layout, show and read the window
col = [[sg.Text(png_files[0], size=(80, 3), key='filename')], col = [[sg.Text(png_files[0], size=(80, 3), key='filename')],
[sg.Image(data=image_file_to_bytes(png_files[0], (500, 500)), key='image')], ] [sg.Image(data=convert_to_bytes(png_files[0], (500, 500)), key='image')], ]
layout = [ layout = [
[sg.Menu(menu)], [sg.Menu(menu)],
@ -82,11 +128,11 @@ while True:
for x in range(ROWS): # update thumbnails for x in range(ROWS): # update thumbnails
for y in range(COLUMNS): for y in range(COLUMNS):
cur_index = display_index + (x * 4) + y cur_index = display_index + (x * COLUMNS) + y
if cur_index < len(png_files): if cur_index < len(png_files):
filename = png_files[cur_index] filename = png_files[cur_index]
if filename not in thumbnails: if filename not in thumbnails:
imgbytes = image_file_to_bytes(filename, (100, 100)) imgbytes = convert_to_bytes(filename, (100, 100))
thumbnails[filename] = imgbytes thumbnails[filename] = imgbytes
else: else:
imgbytes = thumbnails[filename] imgbytes = thumbnails[filename]
@ -96,7 +142,7 @@ while True:
set_image_to_blank((x, y)) set_image_to_blank((x, y))
event, values = window.read() event, values = window.read()
display_index = values['-slider-'] display_index = int(values['-slider-'])
# --------------------- Button & Keyboard --------------------- # --------------------- Button & Keyboard ---------------------
if event in (sg.WIN_CLOSED, 'Exit'): if event in (sg.WIN_CLOSED, 'Exit'):
break break
@ -128,10 +174,10 @@ while True:
sg.popup('Demo PNG Viewer Program', 'Please give PySimpleGUI a try!') sg.popup('Demo PNG Viewer Program', 'Please give PySimpleGUI a try!')
elif type(event) is tuple: elif type(event) is tuple:
x, y = event x, y = event
image_index = display_index + (x * 4) + y image_index = display_index + (x * COLUMNS) + y
if image_index < len(png_files): if image_index < len(png_files):
filename = png_files[image_index] filename = png_files[image_index]
imgbytes = image_file_to_bytes(filename, (500, 500)) imgbytes = convert_to_bytes(filename, (500, 500))
window['image'].update(data=imgbytes) window['image'].update(data=imgbytes)
window['filename'].update(filename) window['filename'].update(filename)