Search code examples
pythontkinterbase64

How do I pull a thumbnail from a JPG , convert to base64, then display that in Tkinter (Python)


I'm trying to show a file listing with details of files including size, dimensions, and thumbnail. Most of this is pretty straightforward, but I've tried days of searching for various posts and guides and none of them seem to do the job. This is what I have so far:

import subprocess, sys
from pathlib import Path
import json
from functions import *
import os
import glob
from tkinter import *
from PIL import Image, ImageTk, ImageOps
from datetime import datetime
import base64
import io
import ffmpeg

file_deets = []
blank_movie = "/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxMTEhUSEhAVFhIVGBUWGBgXEhgYGBYVGBUYFxUZFxgYHikgGBslHhUVLTEhJSktLi4uGB86ODMsNygtLisBCgoKDg0OFRAQFysdFR0rKystKysrLS0tLSstKystNy0rKystLTcrLS0tKy03NysrKysrLSstLS0rKysrKysrK//AABEIAOEA4QMBIgACEQEDEQH/xAAcAAEAAgMBAQEAAAAAAAAAAAAABgcEBQgDAgH/xABTEAABAwEEBQQJEAcHBQEBAAABAAIDEQQFEiEGBzFBURNhcYEUIjJScpGTobEVGCM1QlNiZXOCpLPB0dLjFzM0VZLC4RZDVIOUorIkY4S000Ul/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAGREBAQEAAwAAAAAAAAAAAAAAAAERAhIh/9oADAMBAAIRAxEAPwC8UREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERARFj223RQtL5pWRsG1z3tY0dbiAgyEUBvvW/dVnqBO6d49zAwu8T3UYepyg95a955XcnYbvGImjTIXSOd0Rx0oesoL2Wtve/7LZRW02qKLgHyNaT0NJqepc/3rbNI7UGm0SzWeN9S0EizCgyILWUe4Z7wdy1Vm0EbXFaLUXE5kRjedvbv2/woLZvnXhdsWUImtDs82MwMrzukofE0qITa4r0thMd32ANNKdpG+0SNrsNaBo620yWw1eaP3YLRyUlkZIXt7R03snbNzphd2uYru3DirkiLI2hrGta0bA0AAdACCq9TusW0WqSWyW94dK2jmPwNY7bhe14aAMjhoabzVW6ua7wb2BpI+mUcsuIc7bQMYA5g91Pmro6yS4mNdxA8e9B7IiICIiAiIgIiICIiAiIgIiICLRX1pjYLJUWi2wscMyzHif5NlXeZQK+9fFijqLNZ5Z3DYXUiYes1d/tQW0vl7wASSABtJNAFzxa9bF82uoskDYmE5OjhxkDeHSSVb10C0druC8bWcVutpIrWkkrpS0/BYDgG/YQgvi+dZV12aofbY3OFRhirKajaDydQ09JCgV86/oxlZLE923tpnhlDu7RmKo+cFlaI6mrudFHPLNNaMTc24hGyuxwoztgQQR3asW59GrD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"
def get_file_deets(name):
    global file_deets
    global thumbs

    full_path_filename = f"{settings['dest_dir']}\\{name}"

    temp = {}
    temp['name'], temp['ext'] = name.rsplit('.')
    # keep track of the whole name
    temp['name_ext'] = name
    try:
        image = Image.open(full_path_filename)
        temp['type'] = 'image'
        # Grab it's "taken on" date
        exif = image.getexif();
        temp['dtime'] = exif.get(306).replace(":", "")
        temp['width'],temp['height'] = image.size
        # first make a thumbnail, then B64 THAT (not the whole image)
        thumbnail = ImageOps.fit(image,(100,100))
        # Convert the thumbnail to base64
        with io.BytesIO() as output_buffer:
            thumbnail.save(output_buffer, format="JPEG")
            temp['thumb'] = base64.b64encode(output_buffer.getvalue()).decode("utf-8")
    except IOError:
        vid=True
        temp['type'] = ['movie']
        temp['dtime'] = datetime.fromtimestamp(os.path.getmtime(full_path_filename)).strftime("%Y%m%d %H%M%S")
        temp['thumb'] = blank_movie
        probe = ffmpeg.probe(full_path_filename)
        video_streams = [stream for stream in probe["streams"] if stream["codec_type"] == "video"][0]
        temp['width'], temp['height'] = video_streams['width'], video_streams['height']

    temp['size'] = f"{os.path.getsize(full_path_filename)/1000000:.2f}MBs"

    file_deets.append(temp)

def list_dest_dir():
    global settings
    if (not os.path.isdir(settings['dest_dir'])):
        status_msg("Output directory doesn't exist. Unable to show files")
        return
    # clear previous results
    #transit_folder.delete(0, END)

    folder_contents = os.listdir(settings['dest_dir'])
    if not len(folder_contents):
        status_msg("No files found - was the phone empty?")
        return

    folder_sorted=[]
    for index,value in enumerate(folder_contents):
        if (not os.path.isdir(settings['dest_dir']+'\\'+value)):
            folder_sorted.append(folder_contents[index])
    folder_sorted = sorted(folder_sorted)
    for file in folder_sorted:
        get_file_deets(file)
        # we store them in a list, but no need to iterate twice, just print the last one added
        lastfile = file_deets[-1]
        pre_len(lastfile)
        temp = Frame(transit_folder)
        temp.pack(expand=True,fill=X)
        b64Img = PhotoImage(data=lastfile['thumb'])
        thumbnail = Label(temp, image=b64Img)
        thumbnail.pack(padx=5,pady=5)
        #saves it from garbage collection apparently
        thumbnail.image = b64Img

# FILE LISTING
file_frame = Frame(root)
file_frame.pack(expand=True, fill=BOTH)
transit_folder = Frame(file_frame)
transit_folder.pack(expand=True, fill=BOTH, padx=10)
list_dest_dir()


root.mainloop()

In theory, it should pull all files from the folder (which will be photo and movie files from a cellphone). It should pull details from the files like size, dimensions, etc. It sets the thumbnail to either a thumbnail of the pic or a static image of a movie icon (I validated the b64 image date resolves to the proper pics using an online converter).

So I have a nice list of files with a dict of details for each file.

Then I go through each and try to display them in my tkinter window. When I try, I get an error:

Traceback (most recent call last):
  File "<path>\main.py", line 168, in <module>
    list_dest_dir()
  File "<path>\main.py", line 102, in list_dest_dir
    b64Img = PhotoImage(data=lastfile['thumb'])
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\t\AppData\Local\Programs\Python\Python311\Lib\tkinter\__init__.py", line 4125, in __init__
    Image.__init__(self, 'photo', name, cnf, master, **kw)
  File "C:\Users\t\AppData\Local\Programs\Python\Python311\Lib\tkinter\__init__.py", line 4072, in __init__
    self.tk.call(('image', 'create', imgtype, name,) + options)
_tkinter.TclError: couldn't recognize image data

I've tried many different guides and combinations, but nothing seems to work.


Solution

  • I tried using a thumbnails folder instead, but ran into serious problems when other details of my program changed (such as files being in different folders). So storing the image as b64 in the dict was far superior and I tried it again. Here's what worked:

    #grabbing the image from a named file
    #thumb_size is a function that returns a height based on a target width and the ratio of the original height and width
            image = Image.open(full_path_filename)
            temp['width'],temp['height'] = image.size
            # first make a thumbnail, then B64 THAT (not the whole image)
            image.thumbnail(thumb_size(temp['width'],temp['height'],100))
            image_byte_array = io.BytesIO()
            image.save(image_byte_array, format="JPEG")
            temp['thumb'] = base64.b64encode(image_byte_array.getvalue()).decode()
            image.close()
    

    Then adding it to tkinter and making it viewable:

            # Decode the base64 string to bytes
            image_bytes = base64.b64decode(this_file['thumb'])
            # Create a PIL Image from the decoded bytes
            image = Image.open(io.BytesIO(image_bytes))
            thumb = ImageTk.PhotoImage(image)
            thumbnail = tk.Label(file_row, image=thumb)
            thumbnail.pack(side='left',padx=5,pady=5)
            #saves it from garbage collection apparently
            thumbnail.image = thumb