I've been working on a small program to convert PNG, JPG and JPEG files to .ICO files. This was relatively simple to do, but while I was trying to display the selected PNG image in Tkinter using PIL's ImageTk, I get a strange error.
from tkinter import *
from tkinter import filedialog
import re
from PIL import Image, ImageTk
root = Tk()
pathToImage = ''
selectedImage = ''
def make_square(im, min_size=256, fill_color = (0, 0, 0)): # Puts the selected image into a black square
x, y = im.size
size = max(min_size, x, y)
new_im = Image.new('RGB', (size,size), fill_color)
new_im.paste(im, (int((size - x) / 2), int((size - y) / 2)))
return new_im
def select_image(): # Function that is run when Select PNG button is clicked
global pathToImage
pathToImage = filedialog.askopenfilename(filetypes=[('PNG Files','*.png'),('JPG Files','*.jpg'),('JPEG Files','*.jpeg')]) # Gets path to PNG, JPG or JPEG image
image = Image.open(pathToImage) # Opens image in PIL
image = make_square(im=image) # Turns image into square for ICO conversion
#!!!!!!!!!!!!!!!!!!!!! ERROR Among these 3 lines
global selectedImage # Here I try to tell Python I'm referring to the global variable selectedImage
selectedImage = (ImageTk.PhotoImage(image=pathToImage)) # selectedImage is given the value of ImageTk.PhotoImage with the source image being the path of the selected image
Label(root, image=selectedImage).pack() # Throws an error for some reason
# Rest of the code works fine
image.save('output.ico')
Label(root,text='Converted file stored in the same folder as \'PNG to ICO.py\'').pack()
Button(root,text='Select PNG', command=select_image).pack()
root.mainloop()
I've tried saving the image to display to a variable, but that doesn't seem to work either. Could anyone help point out what I did wrong? I'd really appreciate it.
There are couple of issues with your code.
In your line (ImageTk.PhotoImage(image=pathToImage)) you are passing a path (str) which is not what it should take, ImageTk.PhotoImage takes instance of Image(path). So change it to the image getting returned by make_square function.
Every time when the button is clicked, it'll create a new label if that's what you want then ignore this, if not then create your labels outside of the function select_image after you create the Button and later in the function update them.
I don't really get why you are using global when you can achieve your purpose without making variables pathToImage or selectedImage unless you want to access that image later in the program.
Here is the improved version of your code.
from tkinter import *
from tkinter import filedialog
import re
from PIL import Image, ImageTk
def make_square(im, min_size=256, fill_color = (0, 0, 0)): # Puts the selected image into a black square
x, y = im.size
size = max(min_size, x, y)
new_im = Image.new('RGB', (size,size), fill_color)
new_im.paste(im, (int((size - x) / 2), int((size - y) / 2)))
return new_im
def select_image(): # Function that is run when Select PNG button is clicked
pathToImage = filedialog.askopenfilename(filetypes=[('PNG Files','*.png'),('JPG Files','*.jpg'),('JPEG Files','*.jpeg')])
image = Image.open(str(pathToImage)) # Opens image in PIL
image = make_square(im=image) # Turns image into square for ICO conversion
selectedImage = ImageTk.PhotoImage(image=image)
imglabel.img = selectedImage # create a reference of the image
imglabel['image'] = selectedImage
# selectedImage is given the value of ImageTk.PhotoImage with the source image being the path of the selected image
# Rest of the code works fine
image.save('output.ico', 'ICO')
infolabel['text'] = 'Converted file stored in the same folder as \'PNG to ICO.py\''
root = Tk()
but1 = Button(root,text='Select PNG', command=select_image)
but1.pack()
imglabel = Label(root)
imglabel.pack()
infolabel = Label(root)
infolabel.pack()
root.mainloop()
Related
I have 2 files one with the GUI and another with the background code. I am sending the file path to the image from my background code but I cannot show it successfully. see below the code:
the function img_update returns a string path to the image.
self.Canvas1 = tk.Canvas(self.top)
self.Canvas1.place(relx=0.646, rely=0.026, relheight=0.251
, relwidth=0.32)
self.Canvas1.configure(background="#d9d9d9")
self.Canvas1.configure(borderwidth="2")
self.Canvas1.configure(highlightbackground="#d9d9d9")
self.Canvas1.configure(highlightcolor="black")
self.Canvas1.configure(insertbackground="black")
self.Canvas1.configure(relief="ridge")
self.Canvas1.configure(selectbackground="#c4c4c4")
self.Canvas1.configure(selectforeground="black")
root.img = img = tk.PhotoImage(file = GUI_support.img_update)
self.Canvas1.create_image(100, 75, image = img)
I am trying to build a GUI that displays sequence of images as videos. The images are numpy arrays.
The code is working when I try to display one image at a time but it crashes when I try to run them as a sequence.
The code:
from tkinter import *
from scipy.io import loadmat
from PIL import ImageTk, Image
import time
data = loadmat('DepthFrames.mat')['DepthFrames'].squeeze(axis=0)
print(data.shape)
counter = 0
root = Tk()
image = ImageTk.PhotoImage(image = Image.fromarray(data[counter]))
root.title("WUDU VIDEOS LABEL TOOL")
myLabel = Label(root, image = image)
myLabel.grid(row = 0)
def changeImg():
global counter
counter +=1
print(counter)
image = ImageTk.PhotoImage(image = Image.fromarray(data[counter]))
myLabel.configure(image = image)
myLabel.image = image
def playVideo():
for i in range(10):
image = ImageTk.PhotoImage(image = Image.fromarray(data[i]))
myLabel.configure(image = image)
myLabel.image = image
time.sleep(0.03333)
my_Button = Button(text = "Play video",command = playVideo)
my_Button.grid(row = 1)
root.mainloop()
time.sleep blocks the main thread of tkinter. Your code will freeze the GUI until the for loop is completed and the image will be shown as the last image. For more details, see this post.
You need to use the after method. Something like this:
def playVideo(frame=0):
try:
image = ImageTk.PhotoImage(image = Image.fromarray(data[frame]))
except IndexError:
return
myLabel.configure(image = image)
myLabel.image = image
root.after(33, playVideo, frame+1)
Some weeks ago i load a png image into my Tkinter Canvas and drawed with create_image, but now i can't do this anymore, i tried convert with ImageTk but png did not display
I have the following code:
load = Image.open("mouse.png")
self.img = ImageTk.PhotoImage(load)
self.draw.create_image(100,100,image=self.img,anchor = NW)
self.draw.image = self.img
I just need to present a png image
Try this
vSmallIco = (15, 15)
self.original = Image.open('.//data//img//plus.png')
resized = self.original.resize(vSmallIco, Image.ANTIALIAS)
self.plusIco = ImageTk.PhotoImage(resized)
self.medIco = ttk.Label(self.mf, image=self.plusIco, style='Main.TLabel')
this is done with this import
from PIL import Image, ImageTk
Also, please use a *.png image if you wish to use png.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I want to store .jpg images from a folder in an array, and than use them to add it to a buttons in my frame of Python.
I am using tkinter and PIL library in Python 3.4.3 .I am using windows 8.1 os I want to load the image for a folder with few lines of code and I also element border of the grid to show them like a single image
Below is some code to get you started.
To simplify testing I wrote a small program that uses PIL to generate colored squares and saves them to a folder. I tested these programs using Python 2.6.6 on Linux. They should work on Python 3, (assuming Tkinter & PIL are installed properly on your system) but you will need to change import Tkinter as tk to
import tkinter as tk in tk_frame_grid.py.
This program generates 30 colored squares, saving them to the 'squares' folder in the current directory. You need to create 'squares' before running the program.
PIL_2colorsquares.py
#! /usr/bin/env python
''' Create squares that fade from one color to another & save
Written by PM 2Ring 2015.07.18
'''
from PIL import Image
from itertools import permutations
def color_squares(size, colorpairs, basename, ftype):
#Make the composition mask
m = 255.0 / (2 * size - 2)
r = range(size)
mask = Image.new('L', (size, size))
mask.putdata([int(m * (x + y)) for y in r for x in r])
for count, (c0, c1) in enumerate(colorpairs):
im0 = Image.new('RGB', (size, size), color=c0)
im1 = Image.new('RGB', (size, size), color=c1)
im = Image.composite(im0, im1, mask)
im.save('%s%03d%s' % (basename, count, ftype))
def main():
size = 64
colors = ('red', 'yellow', 'green', 'cyan', 'blue', 'magenta')
colorpairs = permutations(colors, 2)
basename = 'squares/sq'
ftype = '.png'
color_squares(size, colorpairs, basename, ftype)
if __name__ == '__main__':
main()
This program first fills a list with PIL images, using image files from a named directory; these images can be in any file format that PIL can read. It then creates a Tkinter window containing a Frame that holds a grid of Buttons using the images. There is no error checking, so don't put non-image files into the 'squares' folder.
You need to specify the grid dimensions. If there aren't enough images to fill the grid you will get a StopIteration error.
tk_frame_grid.py
#!/usr/bin/env python
''' Create a grid of Tkinter Buttons with PIL images in a Frame
See http://stackoverflow.com/q/31489121/4014959
Written by PM 2Ring 2015.07.18
'''
from __future__ import print_function
import os
import Tkinter as tk
from PIL import Image, ImageTk
class FrameDemo(object):
''' A Frame containing a grid of image Buttons '''
def __init__(self, rows, columns, images):
images = iter(images)
master = tk.Tk()
master.title("Image Buttons in a Frame")
frame = tk.Frame(master)
frame.pack()
for y in range(rows):
for x in range(columns):
#Get the next image from the list and
#convert it to a TK Photo object
name, img = next(images)
photo = ImageTk.PhotoImage(img)
#Create the button & put it in the Frame
b = tk.Button(frame, image=photo)
b.grid(row=y, column=x)
#Add a call-back function
func = lambda t=name: self.button_cb(t)
b.config(command=func)
#We have to save a reference to the photo or it gets
#garbage-collected, so we attach it as a button attribute
b.photo = photo
master.mainloop()
def button_cb(self, name):
print("'%s' button pressed" % name)
def main():
image_folder = 'squares'
#Load all files in image_folder as PIL images
#and put them into a list
images = [(name, Image.open(os.path.join(image_folder, name)))
for name in sorted(os.listdir(image_folder))]
gui = FrameDemo(rows=5, columns=6, images=images)
if __name__ == '__main__':
main()
I would like to load an image in tkinter from a pygame surface and I am having a problem.
This is what I am currently trying:
image= pygame.image.tostring(surf, 'RGB')
tkimage= tkinter.PhotoImage(data= image)
canvas.create_image(0, 0, tkimage)
but I unfortunately get this error:
_tkinter.TclError: couldn't recognize image data
The PhotoImage class can only read GIF and PGM/PPM files, either directly from a file or as base64 encoded string.
You should use the Python Imaging Library for loading and creating the image for Tk.
Here's an example:
import pygame
from PIL import Image
import ImageTk
import Tkinter
# load image in pygame
pygame.init()
surf = pygame.image.load('bridge.png')
# export as string / import to PIL
image_str = pygame.image.tostring(surf, 'RGB') # use 'RGB' to export
w, h = surf.get_rect()[2:]
image = Image.fromstring('RGB', (w, h), image_str) # use 'RGB' to import
# create Tk window/widgets
root = Tkinter.Tk()
tkimage = ImageTk.PhotoImage(image) # use ImageTk.PhotoImage class instead
canvas = Tkinter.Canvas(root)
canvas.create_image(0, 0, image=tkimage)
canvas.pack()
root.mainloop()
------- UPDATE ------
import pygame
from pygame.locals import *
from PIL import Image
import ImageTk
import Tkinter
# load image in pygame
pygame.init()
surf = pygame.image.load('pic_temp.png') # you can use any Surface a Camers is also an Surface
mode = "RGB"
# export as string / import to PIL
image_str = pygame.image.tostring(surf, mode) # use 'RGB' to export
size = (640, 480)
#image = Image.fromstring(mode, size, image_str)
# use frombuffer() - fromstring() is no longer supported
image = Image.frombuffer(mode, size, image_str, 'raw', mode, 0, 1) # use 'RGB' to import
# create Tk window/widgets
root = Tkinter.Tk()
tkimage = ImageTk.PhotoImage(image) # use ImageTk.PhotoImage class instead
label = Tkinter.Label(root, image=tkimage)
label.pack()
root.mainloop()