Jun-03-2021, 03:27 AM
(This post was last modified: Jun-03-2021, 03:27 AM by deanhystad.)
The snapshot method opens a dialog, and if successful opens a second dialog. It opens two dialogs because you wrote the code that way. Then it proceeds to perform actions that don't make sense. Your problem is not with the image stuff, it is with everything else that has become a real mess because you've been thrashing away on this problem. Time to step back and get a simple example working.
I gutted your code, removing the video capture, and pared it down to a program that opens image files and pastes them on an existing image. The pasted image is centered where the cursor was when the mouse button was pressed inside the canvas object. There is a save button to write the resulting image to a file.
When you are trying something new you should write a short example instead of messing up existing code. The test program should be only as long as it has to be to test the idea. A nice side benefit of this type of development is you can keep all these programs in a folder, like a design notebook, and reference them later when you have questions about how to use different Python libraries. The short examples are also great for posting to the forum.
I gutted your code, removing the video capture, and pared it down to a program that opens image files and pastes them on an existing image. The pasted image is centered where the cursor was when the mouse button was pressed inside the canvas object. There is a save button to write the resulting image to a file.
import tkinter as tk from PIL import Image, ImageTk from tkinter import filedialog filetypes = (('PNG', '*.png'), ('JPEG', '*.jpg'), ('All', '*.*')) class App: def __init__(self): self.image = None self.tk_image = None window = tk.Tk() self.canvas = tk.Canvas(window, width=360, height=360) self.canvas.pack() self.canvas.bind('<Button>', self.open) button = tk.Button(window, text="Save", command=self.save) button.pack(side=tk.LEFT, padx=10) window.mainloop() def open(self, event): """Open image file and paste to existing image""" filename = filedialog.askopenfile(mode='rb', filetypes=filetypes) if filename: # Open image file. This creates a PIL image file object image = Image.open(filename) if self.image is None: # Set initial image self.image = image else: # Paste new image on existing image x = event.x - image.width//2 y = event.y - image.height//2 Image.Image.paste(self.image, image, (x, y)) # Draw image on canvas. Must convert to Tk image first self.tk_image = ImageTk.PhotoImage(self.image) self.canvas.delete(tk.ALL) self.canvas.create_image(180, 180, image=self.tk_image) def save(self): """Save image to a file""" filename = filedialog.asksaveasfilename(filetypes=filetypes) if filename: self.image.save(filename) if __name__ == "__main__": App()I have never used PIL this way and I was surprised to see that paste is a function and not a method. You pass the base and pasted images as arguments. There may be a paste method for ImageTk objects, I haven't looked, but you should. You can use my short example to experiment around with that.
When you are trying something new you should write a short example instead of messing up existing code. The test program should be only as long as it has to be to test the idea. A nice side benefit of this type of development is you can keep all these programs in a folder, like a design notebook, and reference them later when you have questions about how to use different Python libraries. The short examples are also great for posting to the forum.