Skip to content

Commit d84ee84

Browse files
committed
A quick "refresh"... user bsawlor (thank you!) pointed out a float crash. Sliders return floats now and thus needs casting in this demo.
1 parent cf2f99c commit d84ee84

File tree

1 file changed

+68
-22
lines changed

1 file changed

+68
-22
lines changed

DemoPrograms/Demo_PNG_Thumbnail_Viewer.py

Lines changed: 68 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,86 @@
11
#!/usr/bin/env python
2+
import PIL
23
from PIL import Image
34
from sys import exit
45
import PySimpleGUI as sg
56
import os
67
import io
7-
import numpy as np
8+
import base64
89

10+
"""
11+
Demo PNG Thumbnail Viewer
12+
13+
Displays PNG files from a folder.
14+
15+
OK, so... this isn't the best Demo Program, that's for sure. It's one of the older
16+
demos in the repo. There are likely better ones to use. The convert_to_bytes function is
17+
the best thing in this demo.
18+
19+
Copyright 2021 PySimpleGUI.org
20+
"""
921

1022

1123
thumbnails = {}
1224
ROWS = 8
1325
COLUMNS = 8
1426
sg.set_options(border_width=0)
1527
# Get the folder containing the images from the user
16-
# folder = 'A:/TEMP/pdfs'
1728
folder = sg.popup_get_folder('Image folder to open')
1829
if folder is None:
1930
sg.popup_cancel('Cancelling')
2031
exit(0)
2132

2233

23-
def image_file_to_bytes(filename, size):
24-
try:
25-
image = Image.open(filename)
26-
image.thumbnail(size, Image.ANTIALIAS)
27-
bio = io.BytesIO() # a binary memory resident stream
28-
image.save(bio, format='PNG') # save image as png to it
29-
imgbytes = bio.getvalue()
30-
except:
31-
imgbytes = None
32-
return imgbytes
34+
35+
36+
def convert_to_bytes(file_or_bytes, resize=None):
37+
"""
38+
Will convert into bytes and optionally resize an image that is a file or a base64 bytes object.
39+
Turns into PNG format in the process so that can be displayed by tkinter
40+
:param file_or_bytes: either a string filename or a bytes base64 image object
41+
:type file_or_bytes: (Union[str, bytes])
42+
:param resize: optional new size
43+
:type resize: (Tuple[int, int] or None)
44+
:param fill: If True then the image is filled/padded so that the image is not distorted
45+
:type fill: (bool)
46+
:return: (bytes) a byte-string object
47+
:rtype: (bytes)
48+
"""
49+
if isinstance(file_or_bytes, str):
50+
img = PIL.Image.open(file_or_bytes)
51+
else:
52+
try:
53+
img = PIL.Image.open(io.BytesIO(base64.b64decode(file_or_bytes)))
54+
except Exception as e:
55+
dataBytesIO = io.BytesIO(file_or_bytes)
56+
img = PIL.Image.open(dataBytesIO)
57+
58+
cur_width, cur_height = img.size
59+
if resize:
60+
new_width, new_height = resize
61+
scale = min(new_height / cur_height, new_width / cur_width)
62+
img = img.resize((int(cur_width * scale), int(cur_height * scale)), PIL.Image.ANTIALIAS)
63+
with io.BytesIO() as bio:
64+
img.save(bio, format="PNG")
65+
del img
66+
return bio.getvalue()
67+
#
68+
# old, original PIL code.
69+
# def image_file_to_bytes(filename, size):
70+
# try:
71+
# image = Image.open(filename)
72+
# image.thumbnail(size, Image.ANTIALIAS)
73+
# bio = io.BytesIO() # a binary memory resident stream
74+
# image.save(bio, format='PNG') # save image as png to it
75+
# imgbytes = bio.getvalue()
76+
# except:
77+
# imgbytes = None
78+
# return imgbytes
3379

3480

3581
def set_image_to_blank(key):
36-
img = Image.new('RGB', (100, 100), (255, 255, 255))
37-
img.thumbnail((1, 1), Image.ANTIALIAS)
82+
img = PIL.Image.new('RGB', (100, 100), (255, 255, 255))
83+
img.thumbnail((1, 1), PIL.Image.ANTIALIAS)
3884
bio = io.BytesIO()
3985
img.save(bio, format='PNG')
4086
imgbytes = bio.getvalue()
@@ -43,8 +89,8 @@ def set_image_to_blank(key):
4389

4490
# get list of PNG files in folder
4591
png_files = [os.path.join(folder, f)
46-
for f in os.listdir(folder) if '.png' in f]
47-
filenames_only = [f for f in os.listdir(folder) if '.png' in f]
92+
for f in os.listdir(folder) if f.endswith('.png')]
93+
filenames_only = [f for f in os.listdir(folder) if f.endswith('.png')]
4894

4995
if len(png_files) == 0:
5096
sg.popup('No PNG images in folder')
@@ -65,7 +111,7 @@ def set_image_to_blank(key):
65111

66112
# define layout, show and read the window
67113
col = [[sg.Text(png_files[0], size=(80, 3), key='filename')],
68-
[sg.Image(data=image_file_to_bytes(png_files[0], (500, 500)), key='image')], ]
114+
[sg.Image(data=convert_to_bytes(png_files[0], (500, 500)), key='image')], ]
69115

70116
layout = [
71117
[sg.Menu(menu)],
@@ -82,11 +128,11 @@ def set_image_to_blank(key):
82128

83129
for x in range(ROWS): # update thumbnails
84130
for y in range(COLUMNS):
85-
cur_index = display_index + (x * 4) + y
131+
cur_index = display_index + (x * COLUMNS) + y
86132
if cur_index < len(png_files):
87133
filename = png_files[cur_index]
88134
if filename not in thumbnails:
89-
imgbytes = image_file_to_bytes(filename, (100, 100))
135+
imgbytes = convert_to_bytes(filename, (100, 100))
90136
thumbnails[filename] = imgbytes
91137
else:
92138
imgbytes = thumbnails[filename]
@@ -96,7 +142,7 @@ def set_image_to_blank(key):
96142
set_image_to_blank((x, y))
97143

98144
event, values = window.read()
99-
display_index = values['-slider-']
145+
display_index = int(values['-slider-'])
100146
# --------------------- Button & Keyboard ---------------------
101147
if event in (sg.WIN_CLOSED, 'Exit'):
102148
break
@@ -128,10 +174,10 @@ def set_image_to_blank(key):
128174
sg.popup('Demo PNG Viewer Program', 'Please give PySimpleGUI a try!')
129175
elif type(event) is tuple:
130176
x, y = event
131-
image_index = display_index + (x * 4) + y
177+
image_index = display_index + (x * COLUMNS) + y
132178
if image_index < len(png_files):
133179
filename = png_files[image_index]
134-
imgbytes = image_file_to_bytes(filename, (500, 500))
180+
imgbytes = convert_to_bytes(filename, (500, 500))
135181
window['image'].update(data=imgbytes)
136182
window['filename'].update(filename)
137183

0 commit comments

Comments
 (0)