How to resize an image using tkinter? - python-3.x

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

Related

How to get the image coordinates with tkinter and not the canvas coordinates

So, I am using this code: Tkinter: How to scroll an entire canvas using arrow keys?. And this guy's code: Selecting an area of an image with a mouse and recording the dimensions of the selection and more specifically this:
def get_mouse_posn(event):
global topy, topx
topx, topy = event.x, event.y
def update_sel_rect(event):
global rect_id
global topy, topx, botx, boty
botx, boty = event.x, event.y
canvas.coords(rect_id, topx, topy, botx, boty) # Update selection rect.
The idea is that I depict a big image, that does not fit in my laptop's screen. It is 10.000 * 9.000 pixels. So by using the arrows: Up, Down, Right, Left from my keyboard I can navigate throughout the image. Everything works fine up to here. But, when I use mouse click I use the guy's code in order to get the pixel coordinates (x,y). The problem is that I get the canvas' coordinates, so even I navigate to the top down of the image, when I place the mouse at the upper left corner it will give me 0,0. The latter are the canvas' coordinates and not the image's coordinates. I searched on google, and I found this suggestion: Coordinates of image pixel on tkinter canvas in OOP which does not bring something new. The rationale is more or less implemented in the first code (link that I posted). So, how can I get the image's coordinates and not the canvas' coordinates? I cannot post minimum runnable code, things are too complex and the whole code contains many lines....
You can actually create a function that will check the anchor position of the image, based on the tag you give it(or the Id) and then give the image coordinate based on the clicked canvas coordinate.
def canvas_to_image_cords(canvas: Canvas, x: int, y: int, image: PhotoImage, tagOrId=''):
anchor = 'center'
if tagOrId:
anchor = canvas.itemcget(tagOrId, 'anchor')
w, h = canvas.winfo_reqwidth(), canvas.winfo_reqheight()
if anchor == 'center':
img_xpos, img_ypos = image.width()/2, image.height()/2
start_x, start_y = img_xpos-w/2, img_ypos-h/2
elif anchor == 'nw':
start_x, start_y = 0, 0
# And so on for different anchor positions if you want to make this more modular
req_x, req_y = start_x+x, start_y+y
return req_x, req_y
The way this would work in 'center' anchor is because image is centered and kept in the canvas, so now you can find out where the image starts from the width/height of the canvas. And then you will have to subtract it from the anchor point. By default, the anchor of a canvas image is center, so you may not have to create it for all the other anchor positions if you leave the anchor option empty.
Usage:
from tkinter import * # Avoid this and use import tkinter as tk
from PIL import Image, ImageTk
root = Tk()
root['bg'] = 'black'
def callback(e):
print()
x,y = canvas_to_image_cords(canvas=canvas, x=e.x, y=e.y, image=img, tagOrId='img') # Can also pass img_tag as tagOrId
print(x,y)
def canvas_to_image_cords(canvas: Canvas, x: int, y: int, image: PhotoImage, tagOrId=''):
anchor = 'center'
if tagOrId:
anchor = canvas.itemcget(tagOrId, 'anchor')
w, h = canvas.winfo_reqwidth(), canvas.winfo_reqheight()
if anchor == 'center':
img_xpos, img_ypos = image.width()/2, image.height()/2
start_x, start_y = img_xpos-w/2, img_ypos-h/2
elif anchor == 'nw':
start_x, start_y = 0, 0
req_x, req_y = start_x+x, start_y+y
return req_x, req_y
img = ImageTk.PhotoImage(Image.open('hero-big.png')) # 10000x9000 pixel image
canvas = Canvas(root, highlightthickness=0)
canvas.pack(padx=20, pady=20)
img_tag = canvas.create_image(0, 0, image=img, tag='img') # By default anchor is center
canvas.bind('<1>', callback)
root.mainloop()
Hopefully the color coded image will explain this better.
Our current image position is at the green circle at the center and we need it to be the top left corner of the canvas(the black & white circle). So we need to push back(subtract) half of canvas's width/height inorder to reach the black & white circle. And then you can add the x,y coordinate you need and continue to get the image position you need.
And why do we need to push back to the top left corner? Because e.x and e.y starts from top left corner. It is rather easy(IMO) to find the image coordinate at the top left corner of the canvas, than to make e.x and e.y work with the image coordinate at the center.
Note that (event.x, event.y) is the screen coordinates relative to the top-left corner of the canvas. To get the real canvas coordinates, you can use canvas.canvasx() and canvas.canvasy():
# get the real coordinates in the canvas
# note that canvasx() and canvasy() return float number
x, y = int(canvas.canvasx(event.x)), int(canvas.canvasy(event.y))
So if the top-left corner of the image is at (img_x, img_y) inside the canvas, then the coordinates in the image will be (x-img_x, y-img_y).
To apply on your posted code:
def get_mouse_posn(event):
global topx, topy
topx, topy = int(canvas.canvasx(event.x)), int(canvas.canvasy(event.y))
def update_sel_rect(event):
global botx, boty
botx, boty = int(canvas.canvasx(event.x)), int(canvas.canvasy(event.y))
canvas.coords(rect_id, topx, topy, botx, boty)
To get the selected region in the image:
def get_selected_region():
global topx, topy, botx, boty
# make sure topx < botx and topy < boty
topx, botx = min(topx, botx), max(topx, botx)
topy, boty = min(topy, boty), max(topy, boty)
# top-left corner of image is at (img_x, img_y) inside canvas
region = (topx-img_x, topy-img_y, botx-img_x, boty-img_y)
return region

How to convert ImageTk to Image?

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.

Is there a function to display an image in tkinter (that is any file type) and display it as a specific x-y position on the canvas

I have an array of image paths and a function that finds the paths connected to buttons that are where I want to display the image
I have already tried adding
file_path = photo.name
img = Image.open(file_path)
photo_image = ImageTk.PhotoImage(img)
tk.Label(window, image=photo_image).pack(side=tk.TOP)
to my function but the photos end up being too big and I want the pictures to be placed right above the buttons so I know the exact x-y coordinates I want the pictures to be I just need a way to get them there and to make them smaller
To resize your image, pass a tuple of size in pixels:
img = Image.open("1.bmp").resize((640, 480))
To place your image right above the buttons, you can use place.
tk.Label(root, image=photo_image).place(x=0,y=0) #change x and y to your desired value
You can also get the current loc of your button widget to calculate the exact location on where you need to place your label:
x,y = widget.winfo_x(), widget.winfo_y()
To sum it up:
import tkinter as tk
from PIL import Image, ImageTk
root = tk.Tk()
root.geometry("500x500")
def place_image():
x, y = button1.winfo_x(), button1.winfo_y()
tk.Label(root, image=photo_image).place(x=x,y=y+20)
button1 = tk.Button(root,text="Click me",command=place_image)
button1.pack()
img = Image.open("1.bmp").resize((400, 300))
photo_image = ImageTk.PhotoImage(img)
root.mainloop()
You can place the label at specific pixel coordinates within the canvas using .place(). You can also define the label's width and height in pixels, inside the brackets. This will therefore define the width and height in pixels, of the image.
E.g:
tk.Label(window, image=photo_image).place(x=300, y=400, width=200, height=50)
place() Pixel coordinates work like this in tkinter (for a 600 pixel by 600 pixel canvas):
Increasing a tkinter widget's X coordinate moves it rightwards.
Increasing a tkinter widget's Y coordinate moves it downwards.

Updating image in tkinter window with newly made images

I have written a program that simulate orbits of planets around a star, I would like a visualiser to display current planet positions around the star. Since all the planets have their x and y co-ords stored, plotting them on an image is straightforward, but I don't know a good way to update the image and re-display after each simulation step.
Currently I draw the image like so (use the planet position to turn a pixel red)
def createwindow():
img = Image.new( 'RGB', (750,730), "black")
pixels = img.load()
for thing in celestials:
pixels[thing.xpos+375+sun.xpos,thing.ypos+375+sun.xpos]=250,20,20
So I have an image which displays the planets quite well, which can be remade after each time the planets move. But how do I display this in a tkinter window?
Is there a way of doing this without using a Photoimage which must be saved and loaded? Or a better way of doing this all together? Maybe assigning each planet a label and drawing them directly on a tkinter black window, updating the position of the label with each simulation step?
All help appreciated
You should probably draw the animation on a canvas, instead of on a static image; You can then move the elements of the animation that are modified at each step of the simulation.
Something along those lines: (press start at the bottom to start)
import tkinter as tk
def animate():
canvas.move(1, 5, 0) # 1 refers to the object to be moved ID, dx=5, dy=0
root.update()
root.after(50, animate)
if __name__ == '__main__':
root = tk.Tk()
frame = tk.Frame(root)
canvas = tk.Canvas(root, width=800, height=400)
canvas.pack()
canvas.create_polygon(10, 10, 50, 10, 50, 50, 10, 50) # canvas object ID created here by tkinter
btn = tk.Button(root, text='start', command=animate)
btn.pack()
root.mainloop()
There're many ways to display dynamic content, like moving planets. It depends on whether you prefer working with widgets, pixels, images or graphical primitives.
Widgets
If you prefer to move widgets, as you said, you can assign each planet to a Label. Then you can place it on a window using Place Geometry Manager:
yourLabel.place(anchor=CENTER, relx=0.5, rely=0.5, x=-100, y=50)
That'd put a center of the label to coords (-100,50) relative to its parent center (relx=0.5, rely=0.5). To change the position call .place() again with different (x,y) coords.
Pixels
To change image pixels at runtime you can use .blank(), .get() and .put() methods of PhotoImage. They're not in TkInter book, but you can see them in help(PhotoImage) in python console. To set a single pixel (x,y) to color #fa1414 use:
yourPhotoImage.put("{#fa1414}", to=(x,y))
The "{#fa1414}" argument here is actually a pixels list. Tk can put a rectangular block of pixels in one call. Colors are specified row-by-row, separated by spaces, each row enclosed in curly braces. Block of NxM colors would look like "{C0,0 C1,0 ... CN-1,0} {C0,1 C1,1 ... CN-1,1} ... {C0,M-1 C1,M-1 ... CN-1,M-1}". For example, to put 2x2 pixels to coords (4,6) use:
yourPhotoImage.put("{red green} {#7f007f blue}", to=(4,6))
Tk recognizes many symbolic color names in addition to #rrggbb syntax.
Note that all the changes are displayed right away. You don't need to manually "re-display" images. E.g. if you have a Label(image=yourPhotoImage) defined somewhere, it'd display the changes after you modify yourPhotoImage.
Images
Also PhotoImage can load images from base64-encoded strings. So, technically, to skip saving/loading a file, you can load your image from a string, containing base64-encoded .gif or .png (formats supported natively in Tk):
newimg = PhotoImage(data="R0lGODlhHgAUAPAAAP//AAAAACH5BAAAAAAALAAAAAAeABQAAAIXhI+py+0Po5y02ouz3rz7D4biSJZmUgAAOw==")
.put() also supports base64-strings. For example, if you have planets as images, loaded into base64-strings, you can put them into your image with:
yourPhotoImage.put(base64_mars_image_string, to=(100,50))
Finally, if you're using PIL anyway, you can create PIL.ImageTk.PhotoImage from your PIL.Image img and use it everywhere Tkinter accepts an image object[ref]
from PIL import ImageTk
photoimg = ImageTk.PhotoImage(img)
Graphical primitives
If you want lines or arcs you can also use Canvas. It provides a way to put together different widgets, images, texts, graphical primitives, and move them around, or configure interaction with them. A canvas-based planetary system could look like this (python2 syntax):
from Tkinter import *
import math, time
color = ["#fffc00", "#a09991", "#b6b697", "#2c81ca", "#a36447", "#b16811", "#e5ca9d", "#bcdaf2", "#7e96bc", "#d3ac8b"]
size = [20, 4, 7, 7, 5, 15, 13, 9, 9, 4]
start_time = time.time()
def update_positions():
dt = (time.time() - start_time)*5
for i in range(len(planets)):
px, py = 350+35*i*math.cos(dt/(i+1)/size[i]+4*i), 350+35*i*math.sin(dt/(i+1)/size[i]+4*i)
canvas.coords(planets[i], (px-size[i],py-size[i],px+size[i],py+size[i]))
root.after(100, update_positions)
root = Tk()
canvas = Canvas(root, width=700, height=700, bg="black")
arcs = [canvas.create_oval(350-35*i, 350-35*i, 350+35*i, 350+35*i, outline=color[i]) for i in range(len(color))]
planets = [canvas.create_oval(350, 350, 350, 350, fill=color[i]) for i in range(len(color))]
update_positions()
canvas.pack()
root.mainloop()
Note that items created on the canvas are kept until you remove them. If you want to change the drawing, you can either use methods like .coords(), .itemconfig(), and .move() to modify the items, or use .delete() to remove them.

How do I get my program to update this tkinter label in my nested loop so that it shows the grayscale process?

So I made a program that converts an image to grayscale. I first used graphics.py from a Zelle's Python Programming An Introduction To Computer Science book. I believe this is based on tkinter. I finished the program using a nested loop to iterate through a .gif picture and grab each individual pixel, replacing it with a grayscale algorithm. I had the change happen in a loop and it gave it an effect that shows the grayscale happening across the window. This was slow but it looked neat, but I realized I wanted to be able to use more file types. I found PIL for Python 3.3 and tkinter, using PIL to open the images, turning them into a tkinter PhotoImage, than displaying them in a tkinter window. Now my program will show the image before being processed and after, I would simply like to see the program update the image in the loop so that it shows the grayscale process. Any help would be great appreciated.
Here is my code:
from PIL import Image, ImageTk
from graphics import GraphWin
import tkinter
window = tkinter.Tk()
window.title('# Grayscale')
def GrayScaleConvertor():
#Opens image, creates window and draws image
picToConvert = 'sea.jpg'
pic = Image.open(picToConvert)
picWidth, picHeight = pic.size
# Treats the image as a 2d array, iterates through changing the
#values of each pixel with the algorithm for gray
tkPic = ImageTk.PhotoImage(pic, master = window)
label1 = tkinter.Label(window, image = tkPic)
rgbList = pic.load() #Get a 2d array of the pixels
for row in range(picWidth):
for column in range(picHeight):
rgb = rgbList[row,column]
r,g,b = rgb # Unpacks the RGB value tuple per pixel
grayAlgorithm1 = (r+g+b) // 3
rgbList[row,column] = (grayAlgorithm1, grayAlgorithm1, grayAlgorithm1)
# Converting to a tkinter PhotoImage
tkPic1 = ImageTk.PhotoImage(pic, master = window)
label2 = tkinter.Label(window, image = tkPic1)
# Draws the images to the window
label1.pack() # The image before grayscale
label2.pack() # The image after being grayscaled
window.mainloop()
GrayScaleConvertor()
You could use after(time, function_name) to call function (for example) every 10ms and change one (or more) pixel.
pseudocode:
tkinter.after(10, change_one_pixel)
def change_one_pixel():
change_next_pixel() # if you change more pixels you get faster animation
create_new_image()
update_label()
if any_pixel_left:
tkinter.after(10, change_one_pixel)
EDIT:
Full working code
#import Tkinter as tk # Python 2.7.x
import tkinter as tk # Python 3.x
from PIL import Image, ImageTk
class GrayScaleConvertor():
def __init__(self):
self.window = tk.Tk()
self.window.title('# Grayscale')
#Opens image, creates window and draws image
picToConvert = 'sea.jpg'
#picToConvert = 'background.jpg'
self.pic = Image.open(picToConvert)
# Treats the image as a 2d array, iterates through changing the
#values of each pixel with the algorithm for gray
self.tkPic1 = ImageTk.PhotoImage(self.pic, master = self.window)
self.label1 = tk.Label(self.window, image = self.tkPic1)
# Converting to a tkinter PhotoImage
self.tkPic2 = ImageTk.PhotoImage(self.pic, master = self.window)
self.label2 = tk.Label(self.window, image = self.tkPic2)
# Draws the images to the window
self.label1.pack() # The image before grayscale
self.label2.pack() # The image after being grayscaled
self.column = 0 # start column
self.step = 10 # number columns in one step
self.window.after(1, self.change_pixel) # 1ms
def run(self):
self.window.mainloop()
def change_pixel(self):
rgbList = self.pic.load() #Get a 2d array of the pixels
picWidth, picHeight = self.pic.size
# not to leave image
if self.column + self.step > picWidth:
self.step = picWidth - self.column
# change columns
for column in range(self.column, self.column+self.step):
for row in range(picHeight):
rgb = rgbList[column,row]
r,g,b = rgb # Unpacks the RGB value tuple per pixel
grayAlgorithm1 = (r+g+b) // 3
rgbList[column,row] = (grayAlgorithm1, grayAlgorithm1, grayAlgorithm1)
# change image in label
if self.tkPic2:
del self.tkPic2
self.tkPic2 = ImageTk.PhotoImage(self.pic, master = self.window)
self.label2.config(image = self.tkPic2)
# move start column
self.column += self.step
# if still are columns - call again
if self.column < picWidth:
print "change image"
self.window.after(1, self.change_pixel)
else:
print "the end"
GrayScaleConvertor().run()

Resources