Python Forum
tuple indices must be integers or slices, not str
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
tuple indices must be integers or slices, not str
#9
Thanks deanhystad . I rewrote the whole script and its working. However I have a few issues.
1) There seems to be lag in loading of the first image.
2) I would like to have the exit button to stop the program and allow for a new file/ folder to be selected .
import fitz  # PyMuPDF
import io
import os
import tempfile
import PIL.Image
from PIL import ImageTk
import tkinter as tk
from tkinter import filedialog
from tkinter import *

root = tk.Tk()
root.title("Viewer")
photo=PhotoImage(file="C:\\Users\\INDIAN\Desktop\\python exercises\\Viewer\\Logo Viewer.png")
label = Label(root,image = photo,bg="light blue")
label.image = photo # keep a reference!
label.grid(column=12,row=1,rowspan=2 ,ipadx=5, ipady=5,sticky=tk.W)
root.geometry("1200x800")
root.configure(background='light blue')
tk.Label(root, text="Viewer",font="Algerian 20 bold",bg="light blue").grid(column=12,row=1, ipadx=150, ipady=10,sticky=tk.NE)

canvas = tk.Canvas(root, width=800, height=600,bg='black')
canvas.grid(column=1,row=1,columnspan=10,ipadx=10,ipady=10,sticky=tk.NW)
############################################################################################
# Create a temporary directory
temp_dir = tempfile.TemporaryDirectory()
print(f"[+] All images saved to {temp_dir}")

###############################################################################################
def select_pdf_file():
    global images
    # open file dialog to choose a PDF file
    file_path = filedialog.askopenfilename(filetypes=[("PDF Files", "*.pdf")])
    if file_path:
        # open the file
        pdf_file = fitz.open(file_path)
        for page_index in range(len(pdf_file)):
            # get the page itself
            page = pdf_file[page_index]
            # get image list
            image_list = page.get_images()
            # printing number of images found in this page
            if image_list:
                print(f"[+] Found a total of {len(image_list)} images in page {page_index}")
            else:
                print("[!] No images found on page", page_index)
            for image_index, img in enumerate(image_list, start=1):
                # get the XREF of the image
                xref = img[0]
                # extract the image bytes
                base_image = pdf_file.extract_image(xref)
                image_bytes = base_image["image"]
                # get the image extension
                image_ext = base_image["ext"]
                # load it to PIL
                image = PIL.Image.open(io.BytesIO(image_bytes))
                # save it to temporary folder
                image.save(os.path.join(temp_dir.name, f"image{page_index+1}_{image_index}.{image_ext}"))
        print(f"[+] All images saved to {temp_dir}")

        # iterate over the image files in the temporary folder and display them
        image_files = sorted(os.listdir(temp_dir.name))
        global current_index
        current_index = 0
        images = []
        for filename in os.listdir(temp_dir.name):
            if filename.endswith('.png') or filename.endswith('.bmp') or filename.endswith('.jpg') or filename.endswith('.bmp') or filename.endswith('.dcm'):
                images.append(os.path.join(temp_dir.name, filename))
        if images:
            show_image(0, images)

####################################################################################################
def select_folder():
    global images
    global folder_path
    # Open a file dialog to select the folder
    folder_path = filedialog.askdirectory()

    # Load the images from the selected folder
    images=[]
    for filename in os.listdir(folder_path):
        if filename.endswith('.png') or filename.endswith('.bmp') or filename.endswith('.jpg') or filename.endswith('.bmp') or filename.endswith('.dcm'):
            images.append(os.path.join(folder_path,filename))
    
            show_image(0, images)
    global current_index
    current_index = 0

######################################################################################################

def show_image(index, images):
    global current_index
    current_index = index
    image_path = images[index]
    image = PIL.Image.open(image_path)
    image = image.resize((800, 600))
    photo = ImageTk.PhotoImage(image)
    canvas.create_image(0, 0, anchor=tk.NW, image=photo)
    canvas.image = photo
    current_index = index
######################################################################################################

def on_left_arrow(event):
    global current_index
    if current_index > 0:
        current_index -= 1
        show_image(current_index, images)


def on_right_arrow(event):
    global current_index
    if current_index < len(images) - 1:
        current_index += 1
        show_image(current_index, images)
def exit_program():
    root.destroy()

##########################################################################


    # Set the initial image
    current_image = 0
## Button & packing it and assigning it a command
tk.Button(text=" Select PDF ", command=select_pdf_file).grid(row=13, column=11)
button1 = tk.Button(root, text="Select Folder", command=select_folder).grid(row=13,column=12)
button2 = tk.Button(root, text="Exit", command=select_folder).grid(row=13,column=12,padx=60,pady=0,sticky=tk.W)
# bind the arrow keys to navigate the images
root.bind('<Left>', on_left_arrow)
root.bind('<Right>',on_right_arrow)


##Button(text=" Select File ",command=select_pdf_file).grid(row=13, column=3)

root.mainloop()
(Feb-28-2023, 05:04 PM)deanhystad Wrote: https://docs.python.org/3/library/tempfile.html

Quote:class tempfile.TemporaryDirectory(suffix=None, prefix=None, dir=None, ignore_cleanup_errors=False)
This class securely creates a temporary directory using the same rules as mkdtemp(). The resulting object can be used as a context manager (see Examples). On completion of the context or destruction of the temporary directory object, the newly created temporary directory and all its contents are removed from the filesystem.

In other words, as soon as you leave the context created by this:
    with tempfile.TemporaryDirectory() as temp_folder:
The temporary directory is deleted.

There is no need to write the image data to files. Create the images and keep them in a list. If you want to write files to a temporary directory, you could wrap you program in the temp_folder context.
with tempfile.TemporaryDirectory() as temp_folder:
    window = function_that_creates_your_main_window()
    window.mainloop()
Or you could make temp_folder a global variable
def select_pdf_file():
    global temp_folder, current_index
    
    file_path = filedialog.askopenfilename(filetypes=[("PDF Files", "*.pdf")])
    if file_path:
        pdf_file = fitz.open(file_path)
        current_index = 0
        temp_folder = tempfile.TemporaryDirectory()
        image_index = 0
        for page in pdf_file:
            for xref, *_ in page.get_images():
                # extract the image
                info = pdf_file.extract_image(xref)
                image = PIL.Image.open(io.BytesIO(info ["image"]))  #<-  Why not put this in a list??
                image_file = os.path.join(temp_folder.name, f"image{image_index}.{info ["ext"]}")
                image.save(os.path.join(temp_folder.name, image_file))
                show_image(temp_folder.name, image_file)
                image_index += 1
Making temp_folder a global variable means the temporary folder stays alive until you reassign the temp_folder variable (no reference->delete folder), exit the program, or call the cleanup() function (temp_folder.cleanup()).

One last thing, this does not belong inside select_pdf_file()
            def on_key_press(event):
                global current_index
                if event.keysym == "Right":
                    current_index = (current_index + 1) % len(image_files)
                    pil_image = PIL.Image.open(os.path.join(temp_folder, image_files[current_index]))
                    tk_image = ImageTk.PhotoImage(pil_image)
                    image_label.config(image=tk_image)
                elif event.keysym == "Left":
                    current_index = (current_index - 1) % len(image_files)
                    pil_image = PIL.Image.open(os.path.join(temp_folder, image_files[current_index]))
                    tk_image = ImageTk.PhotoImage(pil_image)
                    image_label.config(image=tk_image)
 
            root.bind("<Key>", on_key_press)
You can embed a function inside another function, but you should only do this with "helper" functions, or if you are making a closure. I don't think either applies in this case.
Reply


Messages In This Thread
RE: tuple indices must be integers or slices, not str - by cybertooth - Mar-03-2023, 06:37 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  TypeError: string indices must be integers, not 'str' LEMA 2 229 Jun-12-2024, 09:32 PM
Last Post: LEMA
  No matter what I do I get back "List indices must be integers or slices, not list" Radical 4 1,441 Sep-24-2023, 05:03 AM
Last Post: deanhystad
  boto3 - Error - TypeError: string indices must be integers kpatil 7 1,605 Jun-09-2023, 06:56 PM
Last Post: kpatil
  Response.json list indices must be integers or slices, not str [SOLVED] AlphaInc 4 6,872 Mar-24-2023, 08:34 AM
Last Post: fullytotal
  "TypeError: string indices must be integers, not 'str'" while not using any indices bul1t 2 2,287 Feb-11-2023, 07:03 PM
Last Post: deanhystad
  Error "list indices must be integers or slices, not str" dee 2 1,728 Dec-30-2022, 05:38 PM
Last Post: dee
  TypeError: string indices must be integers JonWayn 12 3,809 Aug-31-2022, 03:29 PM
Last Post: deanhystad
  TypeError: list indices must be integers or slices, not range Anldra12 2 2,863 Apr-22-2022, 10:56 AM
Last Post: Anldra12
  string indices must be integers when parsing Json ilknurg 3 6,867 Mar-10-2022, 11:02 AM
Last Post: DeaD_EyE
  code with no tuple gets : IndexError: tuple index out of range Aggam 4 3,019 Nov-04-2020, 11:26 AM
Last Post: Aggam

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020