I want to show PNG picture on canvas.
Before it I need to resize it and change transparency.
I found that I can load image and change alpha channel with PhotoImage like this:
image1 = PIL.Image.open('aqua.png')
image1.putalpha(128)
gif1 = ImageTk.PhotoImage(image1)
Also I can load PhotoImage and resize it like this:
gif1 = PhotoImage(file = 'aqua.png')
gif1 = gif1.subsample(5)
But I can't perform both this things on same PhotoImage
I understand that PhotoImage and ImageTk.PhotoImage are different classes in my code.
>> print (ImageTk.PhotoImage)
<class 'PIL.ImageTk.PhotoImage'>
>> print (PhotoImage)
<class 'tkinter.PhotoImage'>
I tried to found functionality that I need in both classes but without success.
Maybe I need perform subsample and than convert my tkinter.PhotoImage to PIL.ImageTk.PhotoImage and then perform putalpha but it sounds weird.
Please refer me to right direction about png cooking in Python.
Here is all my code:
from tkinter import *
import PIL
from PIL import Image, ImageTk
canvas = Canvas(width = 200, height = 200)
canvas.pack(expand = YES, fill = BOTH)
image1 = PIL.Image.open('aqua.png')
image1.putalpha(128)
gif1 = ImageTk.PhotoImage(image1)
# gif1 = PhotoImage(file = 'aqua.png')
# next line will not work in my case
gif1 = gif1.subsample(5)
canvas.create_image(0, 0, image = gif1, anchor = NW)
mainloop()
You can use the resize method included in the Image class. Here is the modified code:
from tkinter import *
from PIL import Image, ImageTk
canvas = Canvas(width = 200, height = 200)
canvas.pack(expand = YES, fill = BOTH)
image1 = Image.open('aqua.png')
image1.putalpha(128)
image1 = image1.resize((image1.width//5,image1.height//5))
gif1 = ImageTk.PhotoImage(image1)
canvas.create_image(0, 0, image = gif1, anchor = NW)
mainloop()
Related
Let's say I have some ImageTk.PhotoImage image stored in the variable imgtk. How can I convert it back to an Image.Image?
The reason is that I want to resize it, but it seems that .resize() only works for Image.Images.
I know it is awfully late, but I just came across the same issue and I just discovered that there is a getimage(imagetk) function in the ImageTk interface.
So, to get your imgtk back as an PIL Image you can do:
img = ImageTk.getimage( imgtk )
I just did a quick test on Windows (Python 3.8.5/Pillow 8.1.2/Tkinter 8.6) and it seems to work fine:
# imgtk is an ImageTk.PhotoImage object
img = ImageTk.getimage( imgtk )
img.show()
img.close()
Ok, that was not easy but I think I have a solution though you need to go into some private methods of label.image. Maybe there is a better way if so I would love to see.
import tkinter as tk
from tkinter import Label
import numpy as np
from PIL import Image, ImageTk
root = tk.Tk()
# create label1 with an image
image = Image.open('pic1.jpg')
image = image.resize((500, 750), Image.ANTIALIAS)
picture = ImageTk.PhotoImage(image=image)
label1 = Label(root, image=picture)
label1.image = picture
# extract rgb from image of label1
width, height = label1.image._PhotoImage__size
rgb = np.empty((height, width, 3))
for j in range(height):
for i in range(width):
rgb[j, i, :] = label1.image._PhotoImage__photo.get(x=i, y=j)
# create new image from rgb, resize and use for label2
new_image = Image.fromarray(rgb.astype('uint8'))
new_image = new_image.resize((250, 300), Image.ANTIALIAS)
picture2 = ImageTk.PhotoImage(image=new_image)
label2 = Label(root, image=picture2)
label2.image = picture2
# grid the two labels
label1.grid(row=0, column=0)
label2.grid(row=0, column=1)
root.mainloop()
Actually you can zoom and reduce the original picture by using the methods zoom to enlarge the picture (zoom(2) doubles the size) and subsample to reduce the size (subsample(2) halves the picture size).
for example
picture2 = label1.image._PhotoImage__photo.subsample(4)
reduces the size of the picture to a quarter and you can skip all the conversion to an Image.
According to label1.image._PhotoImage__photo.subsample.__doc__:
Return a new PhotoImage based on the same image as this widget but use only every Xth or Yth pixel. If y is not given, the default value is the same as x
and label1.image._PhotoImage__photo.zoom.__doc__:
Return a new PhotoImage with the same image as this widget but zoom it with a factor of x in the X direction and y in the Y direction. If y is not given, the default value is the same as x.
I have a dataset called "df_db" in which I have stored images in base64 format in a column called "Images". Now, I would like to use tkinter to scroll through the images one after the other. So far I have implemented a scrollbar and I use that value to extract a base64 string from my database which I then convert to an image and try to show in tkinter:
from tkinter import *
from PIL import ImageTk, Image
import os
def show_frame(val):
#Covert from base64
b64 = df_db["Images"][int(val)]
imgdata = base64.b64decode(b64)
#Show image
img = ImageTk.PhotoImage(Image.open(io.BytesIO(imgdata)))
panel = Label(root, image = img)
panel.pack(side = "bottom", fill = "both", expand = "yes")
root = Tk()
w1 = Scale(root, from_=0, to=42, orient=HORIZONTAL, command=show_frame)
w1.pack()
root.mainloop()
So far it doesn't work.
I want to be able to display photos dynamically in Tkinter I have one button that will find the paths to the photos I want to display and as I add photos I want them to be displayed at the top of the canvas
I have already tried going through a for loop of the array after I upload the photos but that doesn't seem to do what I want, and now I am trying to iterate with a while loop but that doesn't work. I am kind of at a loss now. Below is my code
import tkinter as tk
from tkinter import filedialog as tkfd
from PIL import ImageTk, Image
import time
photo_name_list = []
def find_photos():
photo = tkfd.askopenfile()
photo_name_list.append(photo.name)
window = tk.Tk()
#creates the canvas
canvas = tk.Canvas(window, width = WINDOW_WIDTH,
height = WINDOW_HEIGHT, bg="green")
canvas.pack()
b1 = tk.Button(canvas, text="Click me to add 5 photos of yourself",
height = 5, width = 30, command = find_photos)
canvas.create_window(WINDOW_WIDTH//3, WINDOW_HEIGHT//3, window = b1)
while True:
if len(photo_name_list) > 0:
for image in photo_name_list:
img = Image.open(image)
tkimage = ImageTk.PhotoImage(img)
tk.Label(window, image=tkimage).pack()
canvas.update()
time.sleep(1/60)
window.mainloop()
So as you can see in the code I have one button that does that takes the path to an image as a string and appends it to the list. I want to display photos as they are appended.
This should work
import tkinter as tk
from tkinter import filedialog as tkfd
from PIL import ImageTk, Image
import time
WINDOW_WIDTH = 500
WINDOW_HEIGHT = 500
phat_list = []
images_reference_list = []
def find_photos():
photo = tkfd.askopenfile()
file_path = photo.name
img = Image.open(file_path)
photo_image = ImageTk.PhotoImage(img)
tk.Label(window, image=photo_image).pack(side=tk.TOP)
images_reference_list.append(photo_image)
phat_list.append(file_path)
window = tk.Tk()
#creates the canvas
canvas = tk.Canvas(window, width = WINDOW_WIDTH,
height = WINDOW_HEIGHT, bg="green")
canvas.pack(side=tk.BOTTOM)
b1 = tk.Button(canvas, text="Click me to add 5 photos of yourself",
height = 5, width = 30, command = find_photos)
canvas.create_window(WINDOW_WIDTH//3, WINDOW_HEIGHT//3, window = b1)
window.mainloop()
I've added the code lines that display the photo inside the function find_photos().
The while statement was causing some troubles i assume, you have always to check if the while will ever end for have a working code
and if you want to display an image you have always to keep a solid reference of it , the best way is to add it into a list
I need to resize my window(tkinter) according to the width and height of my background image.
My code
from tkinter import *
from PIL import ImageTk
import cv2
image=cv2.imread("New_refImg.png")
width_1, height_1,channels = image.shape
canvas = Canvas(width = width_1, height = height_1, bg = 'blue')
canvas.pack(expand = YES, fill = BOTH)
img = ImageTk.PhotoImage(file = "New_refImg.png")
canvas.create_image(10, 10, image = img, anchor = NW)
mainloop()
I'm using a simple method, I call the same image twice : image=cv2.imread("New_refImg.png") and img = ImageTk.PhotoImage(file = "New_refImg.png") but is there a way change this line img = ImageTk.PhotoImage(file = "New_refImg.png") to something like that img = ImageTk.PhotoImage(image) (image already has been called in the 3rd line of the code)
Thank you
I don't know about PIL, but I can show you how to do it in tkinter:
from tkinter import *
root = Tk() # Create Tk before you can create an image
img = PhotoImage(file='pilner.png')
w, h = img.width(), img.height()
canvas = Canvas(root, width=w, height=h, bg='blue', highlightthickness=0)
canvas.pack(expand = YES, fill = BOTH)
canvas.create_image(0, 0, image=img, anchor=NW)
root.mainloop()
highlightthickness=0 rmoves the highlight border on the canvas. I'm positioning it at 0,0 so as to not show the bg.
I just wondering what I should do to apply an image as background of my tkinter window.
I want this window with a gif image in the background and a few buttons on top of it..
the error msg says: "x.image = bg_image.grid(row = 0, column = 0)
AttributeError: 'PhotoImage' object has no attribute 'grid'"
do I need to import something else?
whats wrong? I dont even know if this PhotoImage code is supported by this version of python (python 3.1.1)...
from tkinter import*
window = Tk()
window.title("ksdasndsnadn")
bg_image = PhotoImage(file ="pic.gif")
x = Label (image = bg_image)
x.image = bg_image.grid(row = 0, column = 0)
window.geometry("600x300")
app = Application(window)
window.mainloop()
You need to apply the grid method to the label that contains the image, not the image object:
bg_image = PhotoImage(file ="pic.gif")
x = Label (image = bg_image)
x.grid(row = 0, column = 0)
http://effbot.org/tkinterbook/photoimage.htm