Open In App

Python Image Editor Using Python

Last Updated : 26 Dec, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

You can create a simple image editor using Python by using libraries like Pillow(PIL) which will provide a wide range of image-processing capabilities. In this article, we will learn How to create a simple image editor that can perform various operations like opening an image, resizing it, blurring the image, flipping and rotating the image, and so on.

Prerequisites

Before getting started, You need to install the latest version of Python. Refer to this article to install Python

Download and Install Python 3 Latest Version

After the successful installation of Python, We need to install some Python libraries: Pillow – Image processing, Tkinter – Graphical User Interface. To install these libraries you need to run this command in the terminal.

pip install pillow
pip install Tkinter

By combining these two libraries, we are going to create an image editor that provides a graphical interface for users to easily enhance and manipulate their images.

By the end of the completion of our image editor, we will get a user interface as shown below:

Resource

Output

Getting Started

Below code describes how to upload image and creating buttons like Reset, close, Rotate, flip, Resize, Crop, Blur, Emboss, Edge Enhance , save to edit images.

Python3




#importing the required modules
from tkinter import *      # importing the tkinter module
from tkinter import ttk                                   
# importing the PIL i.e pillow module
from PIL import ImageTK, Image, ImageEnhance, ImageFilter 
from tkinter import filedialog
import os
 
# Calling the TK
mains = Tk()
 
# creating a string of 215 space characters
space = (" ")*215
 
# It retrieves the screen width of the user's display
screen_width = mains.winfo_screenwidth()
 
# It retrieves the screen height of the user's display
screen_height = mains.winfo_screenheight()
 
#Using an f-string to construct the window size in the
#format width x height
mains.geometry(f"{screen_width}x{screen_height}")
 
#setting the title for the window
mains.title(f"{space}Image Editor")
 
#setting the background color of the window
mains.configure(bg = '#323946')
 
#Creating Default image
img = Image.open("logo.png")  
# "logo.png" image will be available after this code
# To run this code, this image must be saved in your PC's or you should change
# the "logo.png" to your image name in this code.
 
#resizing the image to 600 x 700
img = img.resize((600,700))
 
#creating the label widget
panel = Label(mains)         
panel.grid(row = 0, column = 0, rowspan = 12, padx = 50, pady = 50)
 
#calling a function named 'displayimage' with
#an argument 'img'
displayimage(img)
 
#brightnessSlider stores the scale widget
#Inside the widget,
#sets the label next to the slider
#from_ = 0, to = 2 specifies the brightness range
#length determines the length of the slider
brightnessSlider = Scale(mains, label = "Brightness", from_ = 0, to = 2, orient = HORIZONTAL,
                         length = 200, resolution = 0.1, command = brightness_callback, bg = '#1f242d')
#initially, brightness position set to 1
brightnessSlider.set(1)
 
#setting the font style, font size, weight
brightnessSlider.configure(font=('poppins',11,'bold'),foreground='white')
brightnessSlider.place(x=1070,y=15)
 
#contrastSlider stores the scale widget
#Inside the widget,
#sets the label next to the slider
#from_ = 0, to = 2 specifies the contrast range
#length determines the length of the slider
contrastSlider = Scale(mains, label="Contrast", from_=0, to=2, orient=HORIZONTAL, length=200,
                       command=contrast_callback, resolution=0.1, bg="#1f242d")
#initially, contrast position set to 1
contrastSlider.set(1)
#setting the font style, font size, weight
contrastSlider.configure(font=('poppins',11,'bold'),foreground='white')
contrastSlider.place(x=1070,y=90)
 
#sets the label next to the slider
#from_ = 0, to = 2 specifies the sharpness range
#length determines the length of the slider
sharpnessSlider = Scale(mains, label="Sharpness", from_=0, to=2, orient=HORIZONTAL, length=200,
                        command=sharpen_callback, resolution=0.1, bg="#1f242d")
#initially, sharpness position set to 1
sharpnessSlider.set(1)
#setting the font style, font size, weight
sharpnessSlider.configure(font=('poppins',11,'bold'),foreground='white')
sharpnessSlider.place(x=1070,y=165)
 
#colorSlider stores the scale widget
#Inside the widget,
#sets the label next to the slider
#from_ = 0, to = 2 specifies the color range
#length determines the length of the slider
colorSlider = Scale(mains, label="Colors", from_=0, to=2, orient=HORIZONTAL, length=200,
                    command=color_callback, resolution=0.1, bg="#1f242d")
#initially, color position set to 1
colorSlider.set(1)
#setting the font style, font size, weight
colorSlider.configure(font=('poppins',11,'bold'),foreground='white')
colorSlider.place(x=1070,y=240)
 
#rotate button
#btnrotate stores the Button widget for rotating an image
#Inside the widget,
#setting the text displayed on the button
#setting the width of the button
#adding the command that indicates the rotate function
#will be executed when the button is clicked
btnRotate = Button(mains, text='Rotate', width=25, command=rotate, bg="#1f242d")
btnRotate.configure(font=('poppins',11,'bold'),foreground='white')
btnRotate.place(x=805,y=110)
 
#reset button
#reset_button stores the Button widget for reseting the image
 
reset_button=Button(mains,text="Reset",command=reset,bg="black",activebackground="ORANGE")
reset_button.configure(font=('poppins',10,'bold'),foreground='white')
reset_button.place(x=380,y=15)
 
#Image changing button
#btnchaImg stores the Button widget for changing the image
 
btnChaImg = Button(mains, text='Change Image', width=25,command=ChangeImg,bg="#1f242d",activebackground="ORANGE")
btnChaImg.configure(font=('poppins',11,'bold'),foreground='white')
btnChaImg.place(x=805,y=35)
 
#flip button
#btnFlip stores the Button widget to flip the image
#Inside the widget,
btnFlip = Button(mains, text='Flip', width=25, command=flip, bg="#1f242d")
btnFlip.configure(font=('poppins',11,'bold'),foreground='white')
btnFlip.place(x=805,y=180)
#setting the width of the button
#adding the command that indicates the resize function
#will be executed when the button is clicked
btnResize = Button(mains, text='Resize', width=25, command=resize, bg="#1f242d")
btnResize.configure(font=('poppins',11,'bold'),foreground='white')
btnResize.place(x=805,y=255)
 
#Crop button
#btnCrop stores the Button widget to crop the image
#Inside the widget,
#setting the text displayed on the button
#setting the width of the button
#adding the command that indicates the crop function
#will be executed when the button is clicked
btnCrop = Button(mains, text='Crop', width=25, command=crop, bg="#1f242d")
btnCrop.configure(font=('poppins',11,'bold'),foreground='white')
btnCrop.place(x=805,y=340)
 
#Blur button
#btnBlur stores the Button widget to blur the image
#Inside the widget,
#setting the text displayed on the button
#setting the width of the button
#adding the command that indicates the blurr function
#will be executed when the button is clicked
btnBlur = Button(mains, text='Blur', width=25, command=blurr, bg="#1f242d")
btnBlur.configure(font=('poppins',11,'bold'),foreground='white')
btnBlur.place(x=805,y=425)
 
#Emboss button
#btnEmboss stores the Button widget for Embossing an image
#Inside the widget,
#setting the text displayed on the button
#setting the width of the button
#adding the command that indicates the emboss function
#will be executed when the button is clicked
btnEmboss = Button(mains, text='Emboss', width=25, command=emboss, bg="#1f242d")
btnEmboss.configure(font=('poppins',11,'bold'),foreground='white')
btnEmboss.place(x=805,y=510)
 
#Edge Enhance button
#btnEdgeEnhance stores the Button widget for enhancing an image
#Inside the widget,
#setting the text displayed on the button
#setting the width of the button
#adding the command that indicates the edgenhance function
#will be executed when the button is clicked
btnEdgeEnhance = Button(mains, text='EdgeEnhance', width=25, command=edgeEnhance, bg="#1f242d")
btnEdgeEnhance.configure(font=('poppins',11,'bold'),foreground='white')
btnEdgeEnhance.place(x=805,y=595)
btnSave = Button(mains, text='Save', width=25, command=save, bg="black")
btnSave.configure(font=('poppins',11,'bold'),foreground='white')
btnSave.place(x=805,y=675)
#adding the command that indicates the close function
#will be executed when the button is clicked
btnClose = Button(mains, text='Close', command=close, bg="black",activebackground="ORANGE")
btnClose.configure(font=('poppins',10,'bold'),foreground='white')
btnClose.place(x=430,y=15)
 
mains.mainloop()


Resources Used:

logo

logo.png

Below code describes the actions that are performed on image when we click the buttons in image editor.

Python3




# function to display this image
# it convberts a pillow image into a format
# that Tkinter can display
# and updating the panel widget to show this image
def displayimage(img):
    dispimage = ImageTk.PhotoImage(img)
    panel.configure(image=dispimage)
    panel.image = dispimage
     
#this function adjusts the brightness of an image
#based on the brightness_pos value from a slider
#uses the pillow library to enhance the image brightness
#and updates outputImage
def brightness_callback(brightness_pos):
    brightness_pos = float(brightness_pos)
    global outputImage
    enhancer = ImageEnhance.Brightness(img)
    outputImage = enhancer.enhance(brightness_pos)
    displayimage(outputImage)
 
 
# This function modifies an image's contrast
# based on the contrast_pos value from a slider
# and updates the output image
def contrast_callback(contrast_pos):
    contrast_pos = float(contrast_pos)
    global outputImage
    enhancer = ImageEnhance.Contrast(img)
    outputImage = enhancer.enhance(contrast_pos)
    displayimage(outputImage)
 
 
#This function adjusts the sharpness of an image
#based on the sharpness_pos vale from the slider
#and updates the outputImage
def sharpen_callback(sharpness_pos):
    sharpness_pos = float(sharpness_pos)
    global outputImage
    enhancer = ImageEnhance.Sharpness(img)
    outputImage = enhancer.enhance(sharpness_pos)
    displayimage(outputImage)
 
 
# This function modifies the color intensity of an image
# based on value from the slider
# and updates the outputImage
def color_callback(Color_pos):
    Color_pos = float(Color_pos)
    global outputImage
    enhancer = ImageEnhance.Color(img)
    outputImage = enhancer.enhance(Color_pos)
    displayimage(outputImage)
 
 
# This function rotates the image by 90 degrees clockwise
# updates the img variable
#displays the image using the 'displayimage' function
def rotate():
    global img
    img = img.rotate(90)
    displayimage(img)
 
 
# this function flips the image
# horizontally from left to right
# updates the img variable
#displays the image using the 'displayimage' function
def flip():
    global img
    img = img.transpose((Image.FLIP_LEFT_RIGHT))
    displayimage(img)
 
 
# This function applies a blur filter to the image
# updates the img variable
#displays the image using the 'displayimage' function
def blurr():
    global img
    img = img.filter(ImageFilter.BLUR)
    displayimage(img)
 
 
# this function applies a emboss filter to the image
# updates the img variable
#displays the image using the 'displayimage' function
def emboss():
    global img
    img = img.filter(ImageFilter.EMBOSS)
    displayimage(img)
 
# this function enhances the edges of the image using a filter
# updates the img variable
#displays the image using the 'displayimage' function
def edgeEnhance():
    global img
    img = img.filter(ImageFilter.FIND_EDGES)
    displayimage(img)
 
# This function resizes the image to 200 x 300
# updates the img variable
#displays the image using the 'displayimage' function
def resize():
    global img
    img = img.resize((200, 300))
    displayimage(img)
 
 
# this function extracts the portion of the image from
# coordinates (100,100) to (400,400)
# updates the img variable
#displays the image using the 'displayimage' function
def crop():
    global img
    img = img.crop((100, 100, 400, 400))
    displayimage(img)
 
# this function closes the current tkinter window
def reset():
    mains.destroy()
    os.popen("main.py")
 
# this function allows user to change the image
# if an image is selected, it's opened, resized to 600x600
# updates the img variable
#displays the image using the 'displayimage' function
def ChangeImg():
    global img
    imgname = filedialog.askopenfilename(title="Change Image")
    if imgname:
        img = Image.open(imgname)
        img = img.resize((600, 600))
        displayimage(img)
 
 
# this function allows user to save the currently displayed image
# the outputImage is then saved to the selected file.
def save():
    global img
    savefile = filedialog.asksaveasfile(defaultextension=".png")
    outputImage.save(savefile)
 
#this function is to close the main tkinter window.
def close():
    mains.destroy()


Complete Code:

To run this code, you need to have the Pillow library installed and replace”logo.png” with the path to your desired initial image. The code provides a basic image editor with options for image adjustments and simple image manipulation operations.

Python3




#importing the required modules
from tkinter import *
from tkinter import ttk
#importing PIL i.e pillow module
from PIL import ImageTk, Image, ImageEnhance, ImageFilter
from tkinter import filedialog
import os
 
# function to display this image
# and updating the panel widget to show this image
def displayimage(img):
    dispimage = ImageTk.PhotoImage(img)
    panel.configure(image=dispimage)
    panel.image = dispimage
# function for brightness slider
#this function adjusts the brightness of an image
#and updates outputImage
def brightness_callback(brightness_pos):
    brightness_pos = float(brightness_pos)
    global outputImage
    enhancer = ImageEnhance.Brightness(img)
    outputImage = enhancer.enhance(brightness_pos)
    displayimage(outputImage)
 
 
# function for contrast slider
# and updates the output image
def contrast_callback(contrast_pos):
    contrast_pos = float(contrast_pos)
    global outputImage
    enhancer = ImageEnhance.Contrast(img)
    outputImage = enhancer.enhance(contrast_pos)
    displayimage(outputImage)
 
# function for sharpness slider
#and updates the outputImage
def sharpen_callback(sharpness_pos):
    sharpness_pos = float(sharpness_pos)
    global outputImage
    enhancer = ImageEnhance.Sharpness(img)
    outputImage = enhancer.enhance(sharpness_pos)
    displayimage(outputImage)
 
# function for color slider
# and updates the outputImage
def color_callback(Color_pos):
    Color_pos = float(Color_pos)
    #print(Color_pos)
    global outputImage
    enhancer = ImageEnhance.Color(img)
    outputImage = enhancer.enhance(Color_pos)
    displayimage(outputImage)
# updates the img variable
#displays the image using the 'displayimage' function
def rotate():
    global img
    img = img.rotate(90)
    displayimage(img)
# Function to flip the image
#displays the image using the 'displayimage' function
def flip():
    global img
    img = img.transpose((Image.FLIP_LEFT_RIGHT))
    displayimage(img)
 
# function to Blur the image
# This function applies a blur filter to the image
# updates the img variable
#displays the image using the 'displayimage' function
def blurr():
    global img
    img = img.filter(ImageFilter.BLUR)
    displayimage(img)
 
# function to emboss the image
# this function applies a emboss filter to the image
# updates the img variable
#displays the image using the 'displayimage' function
def emboss():
    global img
    img = img.filter(ImageFilter.EMBOSS)
    displayimage(img)
 
# this function enhances the edges of the image using a filter
#displays the image using the 'displayimage' function
def edgeEnhance():
    global img
    img = img.filter(ImageFilter.FIND_EDGES)
    displayimage(img)
 
# function to resize the button
#displays the image using the 'displayimage' function
def resize():
    global img
    img = img.resize((200, 300))
    displayimage(img)
# updates the img variable
#displays the image using the 'displayimage' function
def crop():
    global img
    img = img.crop((100, 100, 400, 400))
    displayimage(img)
 
# function to reset the button
# this function closes the current tkinter window
def reset():
    mains.destroy()
    os.popen("main.py")
 
# this function allows user to change the image
#displays the image using the 'displayimage' function
def ChangeImg():
    global img
    imgname = filedialog.askopenfilename(title="Change Image")
    if imgname:
        img = Image.open(imgname)
        img = img.resize((600, 600))
        displayimage(img)
# function to save the image
# this function allows user to save the currently displayed image
# the outputImage is then saved to the selected file.
def save():
    global img
    savefile = filedialog.asksaveasfile(defaultextension=".jpg")
    outputImage.save(savefile)
     
#this function is to close the main tkinter window.
def close():
    mains.destroy()
 
# Creating the window for image editor
# Calling the TK
mains = Tk()
 
# creating a string of 215 space characters
space=(" ")*215
# It retrieves the screen width of the user's display
screen_width=mains.winfo_screenwidth()
 
# It retrieves the screen height of the user's display
screen_height = mains.winfo_screenheight()
 
#Using an f-string to construct the window size in the
#format width x height
mains.geometry(f"{screen_width}x{screen_height}")
#setting the title for the window
mains.title(f"{space}Image Editor")
mains.configure(bg='#323946')
 
 
# Default image
img = Image.open("logo.png")
# "logo.png" image will be available after this code
# To run this code, this image must be saved in your PC's or you should change
# the "logo.png" to your image name in this code.
 
#resizing the image to 600 x 700
img = img.resize((600, 700))
panel = Label(mains)
panel.grid(row=0, column=0, rowspan=12, padx=50, pady=50)
displayimage(img)
 
#brightnessSlider stores the scale widget
#Inside the widget,
 
brightnessSlider = Scale(mains, label="Brightness", from_=0, to=2, orient=HORIZONTAL, length=200,
                         resolution=0.1, command=brightness_callback, bg="#1f242d")
#initially, color position set to 1
brightnessSlider.set(1)
#setting the font style, font size, weight
brightnessSlider.configure(font=('poppins',11,'bold'),foreground='white')
brightnessSlider.place(x=1070,y=15)
 
 
#contrastSlider stores the scale widget
#length determines the length of the slider
contrastSlider = Scale(mains, label="Contrast", from_=0, to=2, orient=HORIZONTAL, length=200,
                       command=contrast_callback, resolution=0.1, bg="#1f242d")
#initially, color position set to 1
contrastSlider.set(1)
#setting the font style, font size, weight
contrastSlider.configure(font=('poppins',11,'bold'),foreground='white')
contrastSlider.place(x=1070,y=90)
sharpnessSlider = Scale(mains, label="Sharpness", from_=0, to=2, orient=HORIZONTAL, length=200,
                        command=sharpen_callback, resolution=0.1, bg="#1f242d")
#initially, color position set to 1
sharpnessSlider.set(1)
#setting the font style, font size, weight
sharpnessSlider.configure(font=('poppins',11,'bold'),foreground='white')
sharpnessSlider.place(x=1070,y=165)
 
# Color Slider
#colorSlider stores the scale widget
#Inside the widget,
#sets the label next to the slider
#from_ = 0, to = 2 specifies the color range
#length determines the length of the slider
colorSlider = Scale(mains, label="Colors", from_=0, to=2, orient=HORIZONTAL, length=200,
                    command=color_callback, resolution=0.1, bg="#1f242d")
#initially, color position set to 1
colorSlider.set(1)
#setting the font style, font size, weight
colorSlider.configure(font=('poppins',11,'bold'),foreground='white')
colorSlider.place(x=1070,y=240)
 
#rotate button
#will be executed when the button is clicked
btnRotate = Button(mains, text='Rotate', width=25, command=rotate, bg="#1f242d")
btnRotate.configure(font=('poppins',11,'bold'),foreground='white')
btnRotate.place(x=805,y=110)
#reset button
#reset_button stores the Button widget for reseting the image
#Inside the widget,
#setting the text displayed on the button
reset_button=Button(mains,text="Reset",command=reset,bg="black",activebackground="ORANGE")
reset_button.configure(font=('poppins',10,'bold'),foreground='white')
reset_button.place(x=380,y=15)
 
#Image changing button
#btnchaImg stores the Button widget for changing the image
btnChaImg = Button(mains, text='Change Image', width=25,command=ChangeImg,bg="#1f242d",activebackground="ORANGE")
btnChaImg.configure(font=('poppins',11,'bold'),foreground='white')
btnChaImg.place(x=805,y=35)
 
#flip button
#btnFlip stores the Button widget to flip the image
#Inside the widget,
btnFlip = Button(mains, text='Flip', width=25, command=flip, bg="#1f242d")
btnFlip.configure(font=('poppins',11,'bold'),foreground='white')
btnFlip.place(x=805,y=180)
 
#resize button
#btnResize stores the Button widget for resizing the image
#Inside the widget,
btnResize = Button(mains, text='Resize', width=25, command=resize, bg="#1f242d")
btnResize.configure(font=('poppins',11,'bold'),foreground='white')
btnResize.place(x=805,y=255)
#setting the width of the button
#adding the command that indicates the crop function
btnCrop = Button(mains, text='Crop', width=25, command=crop, bg="#1f242d")
btnCrop.configure(font=('poppins',11,'bold'),foreground='white')
btnCrop.place(x=805,y=340)
 
#Blur button
#btnBlur stores the Button widget to blur the image
btnBlur = Button(mains, text='Blur', width=25, command=blurr, bg="#1f242d")
btnBlur.configure(font=('poppins',11,'bold'),foreground='white')
btnBlur.place(x=805,y=425)
 
#Emboss button
#btnEmboss stores the Button widget for Embossing an image
btnEmboss = Button(mains, text='Emboss', width=25, command=emboss, bg="#1f242d")
btnEmboss.configure(font=('poppins',11,'bold'),foreground='white')
btnEmboss.place(x=805,y=510)
 
#Edge Enhance button
#btnEdgeEnhance stores the Button widget for enhancing an image
#Inside the widget,
btnEdgeEnhance = Button(mains, text='EdgeEnhance', width=25, command=edgeEnhance, bg="#1f242d")
btnEdgeEnhance.configure(font=('poppins',11,'bold'),foreground='white')
btnEdgeEnhance.place(x=805,y=595)
#adding the command that indicates the save function
#will be executed when the button is clicked
btnSave = Button(mains, text='Save', width=25, command=save, bg="black")
btnSave.configure(font=('poppins',11,'bold'),foreground='white')
btnSave.place(x=805,y=675)
#adding the command that indicates the close function
#will be executed when the button is clicked
btnClose = Button(mains, text='Close', command=close, bg="black",activebackground="ORANGE")
btnClose.configure(font=('poppins',10,'bold'),foreground='white')
btnClose.place(x=430,y=15)
 
mains.mainloop()


Output



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads