How to update an image on a tkinter button after edditing it with PILLOW

Question:

I am trying to work on a tkinter application that takes uploaded images and add a watermark to them and I am facing challenge rendering the newly watermarked image.

Here is my code, I am trying to get the ‘add_watermark()’ function to update the image after writing a text to it but I keep receiving

AttributeError: ‘PhotoImage’ object has no attribute ‘_PhotoImage__photo"

which I know what am trying to do is wrong but I just can’t figure out the right thing to do.

from tkinter import *
from tkinter import ttk, filedialog
from PIL import  ImageTk,ImageDraw,Image

def upload_file():
    global img
    f_types = [('image Files', ['*.png','*.jpg','*.jpeg'])]
    upload_file.filename = filedialog.askopenfilename(filetypes=f_types)

    img = ImageTk.PhotoImage(file=upload_file.filename)

    upload_image.configure(image=img)
    upload_image.grid(row=0, column=0,)
    
    watermark=ttk.Button(main_frame, text='add watermark', command=add_watermark)
    watermark.grid(row=0,column=1)

    new_file=ttk.Button(main_frame, text='upload deferent file', command=upload_file)
    new_file.grid(row=0, column=1,sticky='N')

def add_watermark():
    my_image=Image.open(upload_file.filename)
    edit=ImageDraw.Draw(my_image)
    edit.text(xy=(0,0), text="hello", align='center',fill=(254, 256, 255))
    watermarked= ImageTk.PhotoImage(file=my_image)
    upload_image.configure(image=watermarked)
    upload_image.grid(row=0,column=0)


root=Tk()
root.title('image water marker')
root.geometry('800x500')

main_frame=ttk.Frame(root)
main_frame.grid(row=1,column=1, sticky=(N, W, E, S))

upload_image=ttk.Button(main_frame, text='upload image', command=upload_file)
upload_image.grid(row=0, column=0)

root.mainloop()
Asked By: nkdtech

||

Answers:

The following line:

watermarked= ImageTk.PhotoImage(file=my_image)

should be changed to:

watermarked= ImageTk.PhotoImage(my_image)  # removed file=

Also you need to save the reference of the image, for example using an attribute of upload_image, to avoid the image being garbage collected:

upload_image.image = watermarked

Below is the updated add_watermark():

def add_watermark():
    my_image=Image.open(upload_file.filename)
    edit=ImageDraw.Draw(my_image)
    edit.text(xy=(0,0), text="hello", align='center',fill=(254, 256, 255))
    watermarked= ImageTk.PhotoImage(my_image)
    upload_image.configure(image=watermarked)
    upload_image.grid(row=0,column=0)
    upload_image.image = watermarked
Answered By: acw1668