From 91a813f5f483fe2fc64c4e370258b3df266160a4 Mon Sep 17 00:00:00 2001 From: PySimpleGUI Date: Wed, 24 Jun 2020 05:44:04 -0400 Subject: [PATCH] New Demo that displays any image format in the GUI window. Uses PIL --- .../Demo_Image_Elem_Image_Viewer_PIL_Based.py | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 DemoPrograms/Demo_Image_Elem_Image_Viewer_PIL_Based.py diff --git a/DemoPrograms/Demo_Image_Elem_Image_Viewer_PIL_Based.py b/DemoPrograms/Demo_Image_Elem_Image_Viewer_PIL_Based.py new file mode 100644 index 00000000..62776c78 --- /dev/null +++ b/DemoPrograms/Demo_Image_Elem_Image_Viewer_PIL_Based.py @@ -0,0 +1,94 @@ +import PySimpleGUI as sg +# import PySimpleGUIQt as sg +import os.path +import PIL.Image +import io +import base64 + +""" + Demo for displaying any format of image file. + + Normally tkinter only wants PNG and GIF files. This program uses PIL to convert files + such as jpg files into a PNG format so that tkinter can use it. + + The key to the program is the function "convert_to_bytes" which takes a filename or a + bytes object and converts (with optional resize) into a PNG formatted bytes object that + can then be passed to an Image Element's update method + + Copyright 2020 PySimpleGUI.org +""" + + +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) + :return: (bytes) a byte-string object + :rtype: (bytes) + ''' + if isinstance(file_or_bytes, str): + img = PIL.Image.open(file_or_bytes) + else: + img = PIL.Image.open(io.BytesIO(base64.b64decode(file_or_bytes))) + + cur_width, cur_height = img.size + if resize: + 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) + bio = io.BytesIO() + img.save(bio, format="PNG") + del img + return bio.getvalue() + + +# --------------------------------- Define Layout --------------------------------- + +# First the window layout...2 columns + +left_col = [[sg.Text('Folder'), sg.In(size=(25,1), enable_events=True ,key='-FOLDER-'), sg.FolderBrowse()], + [sg.Listbox(values=[], enable_events=True, size=(40,20),key='-FILE LIST-')]] + +# For now will only show the name of the file that was chosen +images_col = [[sg.Text('You choose from the list:')], + [sg.Text(size=(40,1), key='-TOUT-')], + [sg.Image(key='-IMAGE-')]] + +# ----- Full layout ----- +layout = [[sg.Column(left_col), sg.VSeperator(),sg.Column(images_col, element_justification='c')]] + +# --------------------------------- Create Window --------------------------------- +window = sg.Window('Multiple Format Image Viewer', layout,resizable=True) + +# ----- Run the Event Loop ----- +# --------------------------------- Event Loop --------------------------------- +while True: + event, values = window.read() + if event in (sg.WIN_CLOSED, 'Exit'): + break + if event == sg.WIN_CLOSED or event == 'Exit': + break + if event == '-FOLDER-': # Folder name was filled in, make a list of files in the folder + folder = values['-FOLDER-'] + try: + file_list = os.listdir(folder) # get list of files in folder + except: + file_list = [] + fnames = [f for f in file_list if os.path.isfile( + os.path.join(folder, f)) and f.lower().endswith((".png", ".jpg", "jpeg", ".tiff", ".bmp"))] + window['-FILE LIST-'].update(fnames) + elif event == '-FILE LIST-': # A file was chosen from the listbox + try: + filename = os.path.join(values['-FOLDER-'], values['-FILE LIST-'][0]) + window['-TOUT-'].update(filename) + window['-IMAGE-'].update(data=convert_to_bytes(filename)) + except: + pass # something weird happened making the full filename + +# --------------------------------- Close & Exit --------------------------------- + +window.close()