Why no image is opened using this function?

Hi,
This is a part of my code, which should open images one by one from an input directory, process them, and save in an output path.

 def open_image(self):
        if in_path:
            image_extensions = ('.jpg', '.jpeg', '.png', '.tiff')
            image_files = sorted([fn for fn in os.listdir(in_path) if fn.lower().endswith(image_extensions)])
            total_images = len(image_files)
            for i, image_file in enumerate(image_files):
                self.image = Image.open(os.path.join(in_path, image_file))
                self.show_image(image_file, i + 1, total_images)

# and at the end of the code:

root = tk.Tk()
app = Manual(root)
app.open_image()
root.mainloop()

However, no image is opened and shown on the resized screen (convas). Alternatively, when I use the below version, at least the first image is opened and shown.

    def open_image(self):
        folder_path = filedialog.askdirectory()
        if folder_path:
            image_files = sorted([f for f in os.listdir(folder_path) if f.lower().endswith('.jpg')])
            total_images = len(image_files)
            for i, image_file in enumerate(image_files):
                self.image = Image.open(os.path.join(folder_path, image_file))
                self.show_image(image_file, i + 1, total_images)

# and at the end of the code:

root = tk.Tk()
app = Manual(root)
app.open_image() 
root.mainloop()

Are you sure that in_path has the correct value in the first bit of code?

We’d probably need to see more of the code. Can you trim it down to the smallest complete runnable example that shows the problem?

1 Like

I have defined the directories in the first lines of the code as:

in_path = r"C:\Users\Ma\Desktop\input 3"
out_path1 = r"C:\Users\Ma\Desktop\Out 3"
out_path2 = r"C:\Users\Ma\Desktop\Out 4"

I will try to provide a runnable example.

It seems challenging for me to provide a brief runnable version of the code. I tried it, but new errors arises. I don’t know about the rules of the website for sharing the complete version of the codes, and whether it is a common practice or not?

Depends on how big it is. The basic deal is that the bigger the code,
the harder it is for people to read and understand, and possibly to run
locally to test. This is why a small example of the problem is
preferable. But if you can’t make a very small example, sometime the
whole code (or a lot of it) is the only way. How bigis it?

(Also, often the task of reducing the problem to a small example
isolates the problem for you, and may solve your problem for you.)

1 Like

Thanks. This part of the code is about 375 lines.

Below is a shortened version of the code. In this version, the problem seems to be solved (both using options 1 and 2 could open and display the image). However, still there is a difference in the size of displayed image:

import os
import tkinter as tk
from tkinter import filedialog, ttk
from PIL import Image, ImageTk

class Manual:
    def __init__(self, root):
        self.root = root
        self.root.title("Manual")
        window_width = 800
        window_height = 600
        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()
        x = int((screen_width / 2) - (window_width / 2))
        y = int((screen_height / 2) - (window_height / 2))
        self.root.geometry(f"{window_width}x{window_height}+{x}+{y}")
        self.canvas = None
        self.image_files = []
        self.current_image = 0
        self.total_images = 0
        self.image = None


        # Option 1:

        self.in_path = r"C:\Users\...\Desktop\input 3"


        self.canvas_frame = tk.Frame(self.root)
        self.canvas_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True)

        self.canvas_scrollbar_x = ttk.Scrollbar(self.canvas_frame, orient=tk.HORIZONTAL)
        self.canvas_scrollbar_x.pack(side=tk.BOTTOM, fill=tk.X)

        self.canvas_scrollbar_y = ttk.Scrollbar(self.canvas_frame)
        self.canvas_scrollbar_y.pack(side=tk.RIGHT, fill=tk.Y)

        self.canvas = tk.Canvas(self.canvas_frame, bg='white', xscrollcommand=self.canvas_scrollbar_x.set,
                                yscrollcommand=self.canvas_scrollbar_y.set)
        self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        self.canvas_scrollbar_x.config(command=self.canvas.xview)
        self.canvas_scrollbar_y.config(command=self.canvas.yview)


    def open_folder(self):

        # Option 2:

        #self.in_path = filedialog.askdirectory()
        if self.in_path:
            self.image_files = sorted([f for f in os.listdir(self.in_path) if f.lower().endswith('.jpg')])
            self.total_images = len(self.image_files)
            self.open_image()

    def open_image(self):
        if self.current_image < self.total_images:
            image_file = self.image_files[self.current_image]
            self.image = Image.open(os.path.join(self.in_path, image_file))
            self.show_image(image_file, self.current_image + 1, self.total_images)
        else:
            self.canvas.delete("all")
            self.canvas.pack_forget()  # Hide the canvas


    def show_image(self, image_file, current_image, total_images):
        if self.image:
            width, height = self.calculate_image_size()

            self.image = self.image.resize((width, height), Image.LANCZOS)

            self.tk_image = ImageTk.PhotoImage(self.image)

            self.canvas.config(scrollregion=(0, 0, width, height))
            self.canvas.delete("all")


            self.canvas.create_image(0, 0, anchor=tk.NW, image=self.tk_image)


    def calculate_image_size(self):
        if self.image:
            window_width = self.root.winfo_width()
            window_height = self.root.winfo_height()
            border = 20
            max_width = window_width - (2 * border)
            max_height = window_height - (2 * border)

            image_ratio = self.image.width / self.image.height
            window_ratio = max_width / max_height

            if image_ratio > window_ratio:
                width = max_width
                height = int(max_width / image_ratio)
            else:
                width = int(max_height * image_ratio)
                height = max_height

            return width, height


root = tk.Tk()
root.eval('tk::PlaceWindow . center')
app = Manual(root)
app.open_folder()  # Call open_folder() to open the folder only once
root.mainloop()

Based on this simplification, I could solve the problem in the original code. However, the similar problem about the image size is remained unsolved. Indeed, the first image in the list is displayed very small, but other images are shown correctly with their original dimensions.

As suggested by ChatGPT 3.5, adding “root.update()” at the end of the code, solved the problem:

...
root = tk.Tk()
root.eval('tk::PlaceWindow . center')
app = Manual(root)
root.update()  # Update the window to ensure the size is final
app.open_folder()  # Call open_folder() to open the folder only once
root.mainloop()