Feb-28-2023, 07:24 AM
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.
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.
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'
>>>