tkinter gif not moving, can tkinter display moving pictures? - python-3.x

My gif picture is not moving in tkinter. Help please. Thank you
canvas = Canvas(width = 450, height = 450, bg = 'white')
canvas.grid(row=2, column=0,sticky = 'W')
gif = PhotoImage(file = "picture.gif")
canvas.create_image(0, 0, image = gif, anchor = NW)
mainloop()

Tkinter does not support animated gifs.
The tk photo image class supports creating an image from each of the sub-images of an animated gif, and with that you can create your own animation. I don't know of any examples in python, but the tcl/tk version can be seen here: http://wiki.tcl.tk/4882

Related

RGBA image not showing up with Pillow and tkinter

I am trying to get a PNGA image to show up in my UI using Pillow and Tkinter. I'm on python 3.7.7 on macOS.
import sys
import tkinter as tk
from PIL import ImageTk, Image
path = "path_to_image.png"
im = Image.open(path)
print(im.mode) # prints RGBA
root = tk.Tk()
root.title("Karel")
frame = tk.Frame(root)
frame.pack()
canvas = tk.Canvas(frame, bg="white", width=500, height=500)
canvas.pack()
img = Image.open(path) # PIL solution
img = img.resize((250, 250), Image.ANTIALIAS) #The (250, 250) is (height, width)
img = ImageTk.PhotoImage(img) # convert to PhotoImage
image = canvas.create_image(150,150, image = img)
root.mainloop()
When I try this with images without an alpha channel, it works. Adding img = ImageTk.PhotoImage(img.convert("RGB")) to remove the alpha channel makes a black box appear.
Any help would be greatly appreciated.
The image:
I don't understand what you are trying to do, but the issue is that all the information in your image is in the alpha (i.e. transparency) channel. I can demonstrate that by splitting out the R, G, B and A channels using ImageMagick in the Terminal like this and laying them out beside each other:
magick image.png -channel RGBA -separate -background none +smush 10 result.png
So, the Red, Green and Blue channels are all zero (i.e. black), and the alpha channel has white where it is transparent and you can see through to the RGB black, and it has black where it is transparent.
So, as regards your question, since all the info is in the alpha channel, you could take just the alpha channel as your image:
#!/usr/bin/env python3
import tkinter as tk
from PIL import ImageTk, Image
root = tk.Tk()
root.title("Karel")
frame = tk.Frame(root)
frame.pack()
canvas = tk.Canvas(frame, bg="red", width=500, height=500)
canvas.pack()
path = "image.png"
img = Image.open(path).getchannel('A') # Take just alpha channel
img = img.point(lambda a: 255-a) # Invert black/white
img = img.resize((250, 250), Image.ANTIALIAS)
img = ImageTk.PhotoImage(img)
image = canvas.create_image(150,150, image = img)
root.mainloop()
Note that you can easily install ImageMagick on macOS with homebrew:
brew install imagemagick
If you work with images, while you are there, get these packages too:
brew install pngcheck exiftool jhead

size of a background image in tkinter

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.

PNG image that support scaling and changing transparency in python

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()

Drawing a png image on a tkinter canvas python

I am trying to create a simple game using tkinter in python 3.5 using the canvas widget. For this game I am need to be able to use a transparent (png) image. Here is my code:
from PIL import ImageTk
from tkinter import Tk, Canvas
root = Tk()
im = ImageTk.PhotoImage(file="test.png")
canvas = Canvas(root, width=900, height=900)
canvas.pack()
canvasImage = canvas.create_image(0, 0, image=im, anchor="nw")
root.mainloop()
The problem is that, despite getting no errors i can't load an image with a transparent background but i can load png images with no transparent background.
You should try this:
from tkinter import *
root = Tk()
canvas = Canvas(root, width=500, height=500)
canvas.pack()
img = PhotoImage(file='path/your_image.png')
canvas.create_image(250, 250, image=img)
root.mainloop()
Output here

How to resize an image using tkinter?

Is it possible to resize an image using tkinter only? If so, how can that be done?
You can resize a PhotoImage using the zoom and subsample methods. Both methods return a new PhotoImage object.
from tkinter import *
root = Tk() #you must create an instance of Tk() first
image = PhotoImage(file='path/to/image.gif')
larger_image = image.zoom(2, 2) #create a new image twice as large as the original
smaller_image = image.subsample(2, 2) #create a new image half as large as the original
However, both of these methods can only take integer values as arguments, so the functionality is limited.
It is possible to scale by decimal values but it is slow and loses quality. The below code demonstrates scaling by 1.5x:
new_image = image.zoom(3, 3) #this new image is 3x the original
new_image = new_image.subsample(2, 2) #halve the size, it is now 1.5x the original
from PIL import Image
img = Image.open("flower.png")
img = img.resize((34, 26), Image.ANTIALIAS)
For further information, go to http://effbot.org/imagingbook/image.htm
Here is a way to resize images (PhotoImages) using just tkinter. Here is a simple function that may suit your needs. This is a rudimentary function that reads the image pixel by pixel simply scaling from one image to another. It may be slow, but depending on your needs, it may suit you well. (In this context/discussion when I refer to an image, I am referring to a PhotoImage or instance of PhotoImage.)
Basically, it takes three arguments:
your image (an instance of a PhotoImage)
your desired width in pixels
your desired height in pixels
It returns a new instance of a PhotoImage.
If you want, you can reference your original image to the returned image effectively resizing your image. Or you can just retrieve a new image.
Here is the function and some examples:
from tkinter import *
def resizeImage(img, newWidth, newHeight):
oldWidth = img.width()
oldHeight = img.height()
newPhotoImage = PhotoImage(width=newWidth, height=newHeight)
for x in range(newWidth):
for y in range(newHeight):
xOld = int(x*oldWidth/newWidth)
yOld = int(y*oldHeight/newHeight)
rgb = '#%02x%02x%02x' % img.get(xOld, yOld)
newPhotoImage.put(rgb, (x, y))
return newPhotoImage
That function should resize an image, pixel by pixel and return a new image.
Basically in a nutshell, you create an image of the desired size and must fill it in pixel by pixel with your desired colors using data from the original image. You can think of this process maybe using a line (y=mx+b where b=0) or ratio or scale factor or however you want to think about it. Bottom line is you have to fill in the new pixel data by retrieving data from the original image.
To change the size of your image you could do something like this. Here would be example code:
from tkinter import *
#insert the resize function here
root = Tk()
myCanvas = Canvas(root, width=300, height=300)
myCanvas.pack()
puppyImage = PhotoImage(file="bassethound.png") # a 200px x 200px image
puppyImage = resizeImage(puppyImage, 150, 150) # resized to 150px x 150px
myCanvas.create_image(50, 50, anchor=NW, image=puppyImage)
myCanvas.create_text(0, 0, anchor=NW, text="original 200x200\nnow150x150")
root.mainloop()
And here is the result:
And here is the 200x200 image, shrunk to 100x100 and expanded to 300x300 with this code:
from tkinter import *
#insert the resize function here
root = Tk()
myCanvas = Canvas(root, width=600, height=300)
myCanvas.pack()
puppyImage = PhotoImage(file="bassethound.png") # a 200px x 200px image
puppySmall = resizeImage(puppyImage, 100, 100)
puppyLarge = resizeImage(puppyImage, 300, 300)
myCanvas.create_image(0, 0, anchor=NW, image=puppyImage)
myCanvas.create_text(0, 0, anchor=NW, text="original 200x200")
myCanvas.create_image(200, 0, anchor=NW, image=puppySmall)
myCanvas.create_text(200, 0, anchor=NW, text="small 100x100")
myCanvas.create_image(300, 0, anchor=NW, image=puppyLarge)
myCanvas.create_text(300, 0, anchor=NW, text="larger 300x300")
root.mainloop()
And here is the result of that code:
Here are just some arbitrary numbers, say 273px and 88px:
from tkinter import *
# put resize function here
root = Tk()
myCanvas = Canvas(root, width=400, height=100)
myCanvas.pack()
puppyImage = PhotoImage(file="bassethound.png") # a 200px x 200px image
puppyImage = resizeImage(puppyImage, 273, 88) # resized to 273px x 88px
myCanvas.create_image(0, 0, anchor=NW, image=puppyImage)
root.mainloop()
and the result:
This answer inspired by acw1668 and roninpawn at the following link:
How to rotate an image on a canvas without using PIL?
photo attribution:
n nlhyeyyeusysAnderson Nascimento, CC BY 2.0 https://creativecommons.org/licenses/by/2.0, via Wikimedia Commons
from: https://en.wikipedia.org/wiki/Puppy
Just in case anyone comes across this for future reference, as I was looking for this myself earlier. You can use tkinter's PhotoImage => subsample method
I wouldn't say it really resizes in a certain sense but if you look up the documentation it returns the same image but skips X amount of pixels specified in the method.
ie:
import tkinter as tk
root = tk.Tk()
canvas = tk.Canvas(root, ....)
canvas_image = tk.PhotoImage(file = path to some image)
#Resizing
canvas_image = canvas_image.subsample(2, 2) #See below for more:
#Shrinks the image by a factor of 2 effectively
canvas.create_image(0, 0, image = canvas_image, anchor = "nw")
self.canvas_image = canvas_image #or however you want to store a refernece so it's not collected as garbage in memory
So say our original image was 400x400 it is now effectively at 200x200. This is what I've been using when I need to compile a game or something I made and don't want to deal with PIL and it's compiling issues.
However, other than the above reason I'd just use PIL.
As far as I know (and it's been a while since I've touched Tkinter), it's a GUI toolkit. The closest it comes to "images" is the PhotoImage class which allows you to load them up and use them in your GUIs. If you want to edit/alter an image, I think you'd be better of using the Python imaging library (PIL).

Resources