I have an animated .webp file which is hosted online and I tried to display it using Tkinter.Here is my code.
import urllib.request
from PIL import Image, ImageTk
root=tkinter.Tk()
u = urllib.request.urlopen("https://..../.....webp")
raw_data = u.read()
u.close()
im = Image.open(BytesIO(raw_data))
image = ImageTk.PhotoImage(im.resize((470,210)))
Label(root,image=image).pack()
root.mainloop()
This works without raising any errors but only displays one frame.Why is that so?
Is there any way how I can solve this issue
Based on #Atlas435's comment I have made a code which can display webp files in tkinter without downloading them.This is the code:
from io import BytesIO
from tkinter import *
import tkinter
import urllib.request
from PIL import Image, ImageTk
root=tkinter.Tk()
ar=0
import tkinter as tk
from PIL import Image, ImageTk
u = urllib.request.urlopen(url)
raw_data = u.read()
u.close()
im = Image.open(BytesIO(raw_data))
from itertools import count
class ImageLabel(tk.Label):
"""a label that displays images, and plays them if they are gifs"""
def load(self, im):
if isinstance(im, str):
im = im
self.loc = 0
self.frames = []
try:
for i in count(1):
self.frames.append(ImageTk.PhotoImage(im.copy().resize((470,210))))
im.seek(i)
except EOFError:
pass
try:
self.delay = im.info['duration']
except:
self.delay = 100
if len(self.frames) == 1:
self.config(image=self.frames[0])
else:
self.next_frame()
def unload(self):
self.config(image="")
self.frames = None
def next_frame(self):
if self.frames:
self.loc += 1
self.loc %= len(self.frames)
self.config(image=self.frames[self.loc])
self.after(self.delay, self.next_frame)
lbl = ImageLabel(root)
lbl.pack()
lbl.load(im)
root.mainloop()
Related
I am trying to create pdf reader in python and I have used tkPDFViewer library but when i run this according to tkPDFViewer library
and i used tkPDFViewer Library example at first it shows 'Page' object has no attribute 'getPixmap' but when i searched this problem i got an answer in stackoverflow and it said pix = page.get_pixmap() in code font i mean edit tkPDFViewer library by replacing getPixmap to get_pixmap() but when i change that it shows Pixmap' object has no attribute 'getImageData
how do I solve it?
from tkinter import *
from tkinter import filedialog
from tkPDFViewer import tkPDFViewer as pdf
import os
root = Tk()
root.geometry('630x700+400+100')
root.title('PDF viewer')
root.configure(bg='white')
def browseFiles():
filename = filedialog.askopenfilename(initialdir=os.getcwd(),
title='Select a pdf file',
filetypes=(('PDF File','.pdf'),
('PDF File','.PDF'),
('All File','.txt')))
v1 = pdf.ShowPdf()
v2 = v1.pdf_view(root,pdf_location=open(filename,'r'),
width=77,height=100)
v2.pack(pady=(0,0))
Button(root,text='Open',width=40,
command=browseFiles,
font='arial 20',bd=4).pack()
root.mainloop()
#and tkPDFViewer library after editing
try:
from tkinter import*
import fitz
from tkinter.ttk import Progressbar
from threading import Thread
import math
except Exception as e:
print(f"This error occured while importing neccesary modules or library {e}")
class ShowPdf():
img_object_li = []
def pdf_view(self,master,width=1200,height=600,pdf_location="",bar=True,load="after"):
self.frame = Frame(master,width= width,height= height,bg="white")
scroll_y = Scrollbar(self.frame,orient="vertical")
scroll_x = Scrollbar(self.frame,orient="horizontal")
scroll_x.pack(fill="x",side="bottom")
scroll_y.pack(fill="y",side="right")
percentage_view = 0
percentage_load = StringVar()
if bar==True and load=="after":
self.display_msg = Label(textvariable=percentage_load)
self.display_msg.pack(pady=10)
loading = Progressbar(self.frame,orient= HORIZONTAL,length=100,mode='determinate')
loading.pack(side = TOP,fill=X)
self.text = Text(self.frame,yscrollcommand=scroll_y.set,xscrollcommand= scroll_x.set,width= width,height= height)
self.text.pack(side="left")
scroll_x.config(command=self.text.xview)
scroll_y.config(command=self.text.yview)
def add_img():
precentage_dicide = 0
open_pdf = fitz.open(pdf_location)
for page in open_pdf:
pix = page.get_pixmap()
pix1 = fitz.Pixmap(pix,0) if pix.alpha else pix
img = pix1.getImageData("ppm")
timg = PhotoImage(data = img)
self.img_object_li.append(timg)
if bar==True and load=="after":
precentage_dicide = precentage_dicide + 1
percentage_view = (float(precentage_dicide)/float(len(open_pdf))*float(100))
loading['value'] = percentage_view
percentage_load.set(f"Please wait!, your pdf is loading {int(math.floor(percentage_view))}%")
if bar==True and load=="after":
loading.pack_forget()
self.display_msg.pack_forget()
for i in self.img_object_li:
self.text.image_create(END,image=i)
self.text.insert(END,"\n\n")
self.text.configure(state="disabled")
def start_pack():
t1 = Thread(target=add_img)
t1.start()
if load=="after":
master.after(250,start_pack)
else:
start_pack()
return self.frame
def main():
root = Tk()
root.geometry("700x780")
d = ShowPdf().pdf_view(root,pdf_location=r"D:\DELL\Documents\Encyclopedia GUI.pdf",width=50,height=200)
d.pack()
root.mainloop()
if __name__ == '__main__':
main()
please use
img = pix1.tobytes("ppm")
instead of
img = pix1.getImageData("ppm")
in line no 48 in tkPDFViewer library
after editing the tkPDFViewer library it will be looked like this
try:
from tkinter import*
import fitz
from tkinter.ttk import Progressbar
from threading import Thread
import math
except Exception as e:
print(f"This error occured while importing neccesary modules or library {e}")
class ShowPdf():
img_object_li = []
def pdf_view(self,master,width=1200,height=600,pdf_location="",bar=True,load="after"):
self.frame = Frame(master,width= width,height= height,bg="white")
scroll_y = Scrollbar(self.frame,orient="vertical")
scroll_x = Scrollbar(self.frame,orient="horizontal")
scroll_x.pack(fill="x",side="bottom")
scroll_y.pack(fill="y",side="right")
percentage_view = 0
percentage_load = StringVar()
if bar==True and load=="after":
self.display_msg = Label(textvariable=percentage_load)
self.display_msg.pack(pady=10)
loading = Progressbar(self.frame,orient= HORIZONTAL,length=100,mode='determinate')
loading.pack(side = TOP,fill=X)
self.text = Text(self.frame,yscrollcommand=scroll_y.set,xscrollcommand= scroll_x.set,width= width,height= height)
self.text.pack(side="left")
scroll_x.config(command=self.text.xview)
scroll_y.config(command=self.text.yview)
def add_img():
precentage_dicide = 0
open_pdf = fitz.open(pdf_location)
for page in open_pdf:
pix = page.get_pixmap()
pix1 = fitz.Pixmap(pix,0) if pix.alpha else pix
img = pix1.tobytes("ppm")
timg = PhotoImage(data = img)
self.img_object_li.append(timg)
if bar==True and load=="after":
precentage_dicide = precentage_dicide + 1
percentage_view = (float(precentage_dicide)/float(len(open_pdf))*float(100))
loading['value'] = percentage_view
percentage_load.set(f"Please wait!, your pdf is loading {int(math.floor(percentage_view))}%")
if bar==True and load=="after":
loading.pack_forget()
self.display_msg.pack_forget()
for i in self.img_object_li:
self.text.image_create(END,image=i)
self.text.insert(END,"\n\n")
self.text.configure(state="disabled")
def start_pack():
t1 = Thread(target=add_img)
t1.start()
if load=="after":
master.after(250,start_pack)
else:
start_pack()
return self.frame
def main():
root = Tk()
root.geometry("700x780")
d = ShowPdf().pdf_view(root,pdf_location=r"D:\DELL\Documents\Encyclopedia GUI.pdf",width=50,height=200)
d.pack()
root.mainloop()
if __name__ == '__main__':
main()
import io
import base64
try:
# Python2
import Tkinter as tk
from urllib2 import urlopen
except ImportError:
# Python3
import tkinter as tk
from urllib.request import urlopen
def display_poster(image_url, x, y):
# image_url = "http://i46.tinypic.com/r9oh0j.gif"
image_byt = urlopen(image_url).read()
image_b64 = base64.encodebytes(image_byt)
photo = tk.PhotoImage(data=image_b64)
# create a white canvas
cv = tk.Canvas(bg='white')
cv.pack(side='top', fill='both', expand='yes')
# put the image on the canvas with
# create_image(xpos, ypos, image, anchor)
cv.create_image(x, y, image=photo, anchor='nw')
def btn_clicked():
display_poster("http://i46.tinypic.com/r9oh0j.gif", 630, 350)
I have tried the base64 package solution but its not working.
It would be nice if someone could help me out with the pakages i need to import and the function to display the image using Canvas.
use this snippets, its work fine :
import tkinter as tk
import urllib.request
#import base64
import io
from PIL import ImageTk, Image
root = tk.Tk()
root.title("Weather")
link = "http://i46.tinypic.com/r9oh0j.gif"
class WebImage:
def __init__(self, url):
with urllib.request.urlopen(url) as u:
raw_data = u.read()
#self.image = tk.PhotoImage(data=base64.encodebytes(raw_data))
image = Image.open(io.BytesIO(raw_data))
self.image = ImageTk.PhotoImage(image)
def get(self):
return self.image
img = WebImage(link).get()
imagelab = tk.Label(root, image=img)
imagelab.grid(row=0, column=0)
root.mainloop()
Output:
I am dealing with tkinter and opencv to display frames of video in tkinter canvas. my code is as following :
import tkinter as tk
from PIL import ImageTk as itk
from PIL import Image
from tkinter import filedialog as fd
import cv2
window = tk.Tk()
class window_tk():
def __init__(self,main):
self.canvas = tk.Canvas(main, bg='white' )
self.img = itk.PhotoImage(file=self.init_img_route)
self.bg= self.canvas.create_image(0,0,anchor = tk.NW,image=self.img)
self.vid = None
def load_video(self):
self.foldername = fd.askopenfilename(parent=window,initialdir="C:/",title='Select a video file to load.',filetypes=[('video files','*.wmv *.mp4 *.mov *.avi')])
self.label_foldername.config(text='Video Load : '+self.foldername)
self.current_pic_num=0
try:
self.vid = cv2.VideoCapture(self.foldername)
frame_number =0
print(self.vid,self.vid.isOpened())
self.frame_count = 0
if self.vid.isOpened():
vid_w = self.vid.get(cv2.CAP_PROP_FRAME_WIDTH)
vid_h = self.vid.get(cv2.CAP_PROP_FRAME_HEIGHT)
vid_f = self.vid.get(cv2.CAP_PROP_FPS)
ret,frame = self.vid.read()
#cv2.imshow('frame',frame)
frame_convert = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
#print(self.frame_count, vid_w,vid_h,vid_f,frame.shape)
imgg = itk.PhotoImage(Image.fromarray(frame_convert))
self.canvas.itemconfig(self.bg, image = imgg)
self.canvas.pack(fill='both',expand=1)
# frame_number+=1
except IndexError:
pass
I confirmed that frame has successfully loaded by checking it as cv2.imshow(), but The canvas only shows the white empty image. Is there anything I missed ?
I found answer and leave the solution for my study.
I changed imgg to self.img and let it globally used in class.
I don't know why it solved the problem so if anyone can explain the reason thank you very much.
import tkinter as tk
import time
from tkinter import *
from tkinter import messagebox
from time import sleep
from PIL import Image, ImageTk
from itertools import count
from time import sleep
class ImageLabel(tk.Label):
def load(self, im):
if isinstance(im, str):
im = Image.open(im)
self.loc = 0
self.frames = []
try:
for i in count(1):
self.frames.append(ImageTk.PhotoImage(im.copy()))
im.seek(i)
except EOFError:
pass
try:
self.delay = im.info['10']
except:
self.delay = 100
if len(self.frames) == 1:
self.config(image=self.frames[0])
else:
for i in range(1):
self.next_frame()
def unload(self):
self.config(image=None)
self.frames = None
def next_frame(self):
if self.frames:
self.loc += 1
self.loc %= len(self.frames)
self.config(image=self.frames[self.loc])
self.after(self.delay, self.next_frame)
root = tk.Tk()
root.geometry('400x200')
root.title("מערכת הסבת וואלה מייל")
lbl = ImageLabel(root)
lbl.pack()
lbl.load('Logo.gif')
I ran this code and I don't know how to update the tkinter win after one shows the gif.
Can someone help me and tell me how to do this? I tried many things and I don't know what to do.
When I run this program in IDLE it seems to work fine. The thing that IDLE does that is not in the program is running the mainloop. Try adding as the last line in the program:
root.mainloop()
Is there any way to display an animated GIF in Tkinter using Python Image Library?
I thought the ImageSequence module would be the way to do it, but I don't know how to use it and if it's possible.
The first question is if there is any easy way. For example: load a GIF using PIL and the ImageSequence and just draw it on a Tkinter window using ImageTk.PhotoImage and it will be animated.
Or do I have to set up a function myself, using the after method or something like time.sleep to loop through the GIF frames and draw them on a tkinter window?
The second question: even if I have to make a function to loop through the GIF frames, is the ImageSequence module supposed to do this or PIL has another module for it?
I'm using Python 3.1 and a private port of PIL, indicated in this topic.
Newsgroups: comp.lang.python
From: "Fredrik Lundh"
Date: Mon, 1 May 2006
Daniel Nogradi wrote:
'The source distribution of the 1.1.4 version comes with a Scripts
directory where you can find player.py, gifmaker.py and explode.py
which all deal with animated gif.'
they're still shipped with 1.1.5 (and 1.1.6), and they should work.
if all you're missing is a few files from the script directory, you can get
them here:
http://svn.effbot.org/public/pil/Scripts/
player.py is run from the command line
see if this one works for you:
from Tkinter import *
from PIL import Image, ImageTk
class MyLabel(Label):
def __init__(self, master, filename):
im = Image.open(filename)
seq = []
try:
while 1:
seq.append(im.copy())
im.seek(len(seq)) # skip to next frame
except EOFError:
pass # we're done
try:
self.delay = im.info['duration']
except KeyError:
self.delay = 100
first = seq[0].convert('RGBA')
self.frames = [ImageTk.PhotoImage(first)]
Label.__init__(self, master, image=self.frames[0])
temp = seq[0]
for image in seq[1:]:
temp.paste(image)
frame = temp.convert('RGBA')
self.frames.append(ImageTk.PhotoImage(frame))
self.idx = 0
self.cancel = self.after(self.delay, self.play)
def play(self):
self.config(image=self.frames[self.idx])
self.idx += 1
if self.idx == len(self.frames):
self.idx = 0
self.cancel = self.after(self.delay, self.play)
root = Tk()
anim = MyLabel(root, 'animated.gif')
anim.pack()
def stop_it():
anim.after_cancel(anim.cancel)
Button(root, text='stop', command=stop_it).pack()
root.mainloop()
Simple PIL version:
canvas = Image.new("RGB",(Width,Height),"white")
gif = Image.open('text.gif', 'r')
frames = []
try:
while 1:
frames.append(gif.copy())
gif.seek(len(frames))
except EOFError:
pass
for frame in frames:
canvas.paste(frame)
canvas.show()