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
#7
Thanks deanhystad,
I got this sample code and modified it . It works fine extracts the images and saves them in a temp folder and then displays them in the tkinter window.
import fitz # PyMuPDF
import io
import os
import tempfile
from PIL import Image
import tkinter as tk
from tkinter import ttk
from PIL import ImageTk

# file path you want to extract images from
file = 'G:\\Patient OPG\\Arshita Nagpal\\CBCT 48,38\\Axials.pdf'
# open the file
pdf_file = fitz.open(file)

# create temporary folder to save images
with tempfile.TemporaryDirectory() as temp_folder:
    # iterate over PDF pages
    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 = Image.open(io.BytesIO(image_bytes))
            # save it to temporary folder
            image.save(os.path.join(temp_folder, f"image{page_index+1}_{image_index}.{image_ext}"))
    print(f"[+] All images saved to {temp_folder}")

    # create a window using Tkinter
    root = tk.Tk()
    root.title("Extracted Images")

    # create a label to display the images
    image_label = ttk.Label(root)
    image_label.pack()

    # iterate over the image files in the temporary folder and display them
    image_files = sorted(os.listdir(temp_folder))
    global current_index
    current_index = 0
    pil_image = Image.open(os.path.join(temp_folder, image_files[current_index]))
    tk_image = ImageTk.PhotoImage(pil_image)
    image_label.configure(image=tk_image)

    def on_key_press(event):
        global current_index
        if event.keysym == "Right":
            current_index = (current_index + 1) % len(image_files)
            pil_image = Image.open(os.path.join(temp_folder, image_files[current_index]))
            tk_image = ImageTk.PhotoImage(pil_image)
            image_label.configure(image=tk_image)
            image_label.image = tk_image
        elif event.keysym == "Left":
            current_index = (current_index - 1) % len(image_files)
            pil_image = Image.open(os.path.join(temp_folder, image_files[current_index]))
            tk_image = ImageTk.PhotoImage(pil_image)
            image_label.configure(image=tk_image)
            image_label.image = tk_image

    # bind the left and right arrow keys to change the displayed image
    root.bind("<Left>", on_key_press)
    root.bind("<Right>", on_key_press)

    # start the Tkinter event loop
    root.mainloop()
(Feb-26-2023, 02:12 PM)deanhystad Wrote: For fun I combined this thread with your other thread about a tkinter app that displays images:

https://python-forum.io/thread-39420.html

This is a tkinter app that displays images extracted from a pdf file. And for some bizarre reason they start spinning when clicked.
import math
import statistics
import fitz
import numpy as np
import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import Image, ImageTk
from io import BytesIO

IMAGE_SIZE = (100, 100)  # Resize all images to this size
LABEL_SIZE = 140  # Max size of rotated image


class SpinningImageButton(tk.Frame):
    """A Button that has an image you can rotate"""
    def __init__(self, parent, image, *args, frames=20, command=None, **kwargs):
        super().__init__(parent, *args, **kwargs)
        self.running = False
        self.index = 0
        self.command = command

        # Guess a fill color using the the top row of pixels
        pixels = [tuple(p) for p in np.array(image)[0]]
        rgb = statistics.mode(pixels)[:3]

        # Create movie frames
        image.thumbnail(IMAGE_SIZE)
        angle = 360 / frames
        self.images = [
            ImageTk.PhotoImage(image.rotate(i*angle, fillcolor=rgb, expand=True))
            for i in range(frames)
        ]

        # Make a label to display the image.
        self.image = tk.Label(
            self,
            image=self.images[0],
            width=LABEL_SIZE,
            height=LABEL_SIZE,
            bg=f'#{rgb[0]:02x}{rgb[1]:02x}{rgb[2]:02x}')
        self.image.pack(anchor=tk.CENTER)
        self.image.bind('<Button-1>', func=self._click)

    def _click(self, *args):
        """Called when mouse clicks on me"""
        if self.command:
            self.command(self)

    def _next(self, wait):
        """Display successive images to make it appear the image is spinning"""
        if self.running:
            self.index = (self.index + 1) % len(self.images)
            self.image.config(image=self.images[self.index])
            self.after(wait, self._next, wait)

    def start(self, period=2):
        """Start spinning the image"""
        self.running = True
        self._next(int(period * 1000 / len(self.images)))

    def stop(self):
        """Stop spinning the image"""
        self.running = False


class MyWindow(tk.Tk):
    """Window to show off my fancy spinning buttons"""
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # Make a menubar instead of a bunch of buttons
        menubar = tk.Menu(self)
        menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="File", menu=menu)
        menu.add_command(label="Open PDF", command=self.open_pdf)
        menu.add_separator()
        menu.add_command(label="Quit", command=self.destroy)
        self.config(menu=menubar)
        self.images = []
        self.frame = tk.Frame(self, width=300, height=300)
        self.frame.pack(expand=True, fill=tk.BOTH)

    def open_pdf(self):
        """Populate window with images extracted from pdf file"""
        pdf = filedialog.askopenfilename()
        if pdf:
            # Replace old image buttons with new
            for image in self.images:
                image.grid_forget()
            self.images = []
            try:
                doc = fitz.open(pdf)
                for page in doc:
                    for xref, *_ in page.get_images():
                        image_bytes = doc.extract_image(xref)["image"]
                        image = Image.open(BytesIO(image_bytes))
                        self.images.append(
                            SpinningImageButton(
                                self.frame,
                                image,
                                frames=60,
                                command=self.toggle
                            )
                        )
            except Exception as msg:
                messagebox.showerror('Error', str(msg))

            # Organize the images on a grid.
            cols = int(math.ceil(len(self.images)**0.5))
            for i, image in enumerate(self.images):
                image.grid(row=i // cols, column=i % cols)

    def toggle(self, image):
        """Toggle image spinning on/off when button clicked"""
        if image.running:
            image.stop()
        else:
            image.start()


MyWindow().mainloop()

How ever when I try to add a select button the select button is seen in the GUI , allows you to select a pdf file and displays only the first image and when arrow keys are pressed I get the error message.. here I am posting the second code and the error message . Can some one help solve this.
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()
# function to extract images from the PDF file
def extract_images(file_path):
    # open the file
    pdf_file = fitz.open(file_path)

    # create temporary folder to save images
    with tempfile.TemporaryDirectory() as temp_folder:
        # iterate over PDF pages
        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 = Image.open(io.BytesIO(image_bytes))
                # save it to temporary folder
                image.save(os.path.join(temp_folder, f"image{page_index+1}_{image_index}.{image_ext}"))
        print(f"[+] All images saved to {temp_folder}")
        # call the function to display images after a delay of 500ms
        root.after(500, display_images, temp_folder)

# function to display the images
def display_images(temp_folder):
    # iterate over the image files in the temporary folder and display them
    image_files = sorted(os.listdir(temp_folder))
    global current_index
    current_index = 0
    # create a canvas to display the images
    canvas = tk.Canvas(root, width=600, height=600)
    canvas.pack()
    # display the first image
    pil_image = Image.open(os.path.join(temp_folder, image_files[current_index]))
    tk_image = ImageTk.PhotoImage(pil_image)
    canvas.create_image(0, 0, anchor="nw", image=tk_image)

    def on_key_press(event):
        global current_index
        if event.keysym == "Right":
            current_index = (current_index + 1) % len(image_files)
            pil_image = Image.open(os.path.join(temp_folder, image_files[current_index]))
            tk_image = ImageTk.PhotoImage(pil_image)
            canvas.create_image(0, 0, anchor="nw", image=tk_image)
        elif event.keysym == "Left":
            current_index = (current_index - 1) % len(image_files)
            pil_image = Image.open(os.path.join(temp_folder, image_files[current_index]))
            tk_image = ImageTk.PhotoImage(pil_image)
            canvas.create_image(0, 0, anchor="nw", image=tk_image)

    # bind the canvas to the key press event
    canvas.bind("<KeyPress>", on_key_press)
    # set the focus on the canvas so that it can receive the key press events
    canvas.focus_set()

# function to get the path of the PDF file
def select_pdf_file():
    # 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)

        # create temporary folder to save images
        with tempfile.TemporaryDirectory() as temp_folder:
            # iterate over PDF pages
            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_folder, f"image{page_index+1}_{image_index}.{image_ext}"))
            print(f"[+] All images saved to {temp_folder}")

            # iterate over the image files in the temporary folder and display them
            image_files = sorted(os.listdir(temp_folder))
            global current_index
            current_index = 0
            show_image(temp_folder, image_files[current_index])

            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)

def show_image(folder, file_name):
    pil_image = PIL.Image.open(os.path.join(folder, file_name))
    tk_image = ImageTk.PhotoImage(pil_image)
    print(tk_image)
    image_label = tk.Label(root)
    image_label.pack()
    image_label.config(image=tk_image)
    image_label.image = tk_image

# create button to select a PDF file
select_file_button = tk.Button(root, text="Select PDF File", command=select_pdf_file)
select_file_button.pack()

root.mainloop()
Error:
[+] Found a total of 21 images in page 0 [+] All images saved to C:\Users\INDIAN\AppData\Local\Temp\tmpi1fk3lxi pyimage1 Exception in Tkinter callback Traceback (most recent call last): File "C:\Users\INDIAN\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 1883, in __call__ return self.func(*args) File "C:\Users\INDIAN\Desktop\python exercises\pygametooth\pdf2jpgtemporaryfoldertkinter3.py", line 124, in on_key_press pil_image = PIL.Image.open(os.path.join(temp_folder, image_files[current_index])) File "C:\Users\INDIAN\AppData\Local\Programs\Python\Python38\lib\site-packages\PIL\Image.py", line 3092, in open fp = builtins.open(filename, "rb") FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\INDIAN\\AppData\\Local\\Temp\\tmpi1fk3lxi\\image1_10.png' >>>
Reply


Messages In This Thread
RE: tuple indices must be integers or slices, not str - by cybertooth - Feb-28-2023, 07:24 AM

Possibly Related Threads…
Thread Author Replies Views Last Post
  No matter what I do I get back "List indices must be integers or slices, not list" Radical 4 1,305 Sep-24-2023, 05:03 AM
Last Post: deanhystad
  boto3 - Error - TypeError: string indices must be integers kpatil 7 1,368 Jun-09-2023, 06:56 PM
Last Post: kpatil
  Response.json list indices must be integers or slices, not str [SOLVED] AlphaInc 4 6,587 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,121 Feb-11-2023, 07:03 PM
Last Post: deanhystad
  Error "list indices must be integers or slices, not str" dee 2 1,524 Dec-30-2022, 05:38 PM
Last Post: dee
  TypeError: string indices must be integers JonWayn 12 3,600 Aug-31-2022, 03:29 PM
Last Post: deanhystad
  TypeError: list indices must be integers or slices, not range Anldra12 2 2,702 Apr-22-2022, 10:56 AM
Last Post: Anldra12
  string indices must be integers when parsing Json ilknurg 3 6,541 Mar-10-2022, 11:02 AM
Last Post: DeaD_EyE
  code with no tuple gets : IndexError: tuple index out of range Aggam 4 2,908 Nov-04-2020, 11:26 AM
Last Post: Aggam
  TypeError: string indices must be integers hendern 2 3,073 Oct-02-2020, 10:16 PM
Last Post: hendern

Forum Jump:

User Panel Messages

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