How to Create a Photo Editor App Using Python

3411 VIEWS

· ·

As human beings in general, many times we won’t be impressed by the outcome of our photos and so adding some retouching and features to make it bright and professional becomes necessary. When it comes to editing photos we usually opt for different professional tools such as Photoshop, Inshot etc… Even though these tools will still have the features to adjust our photos, getting them fully may require paying for the features.

However, if you are a programmer, you can always utilize your skills by developing tools that can serve the same purpose as other softwares you need, like in this case a photo editor app. Doing so will make it much easier to edit your photos in Python.

In this tutorial guide we will be using Python to demonstrate how to achieve most of the photo editing features which can help you accomplish the same basic tasks as any other software available out there.

Let’s get started!

How to Edit an Image

We live in a society where as human beings we want our photos to look more impressive than our personalities, where our social media timelines are filled with beautiful photos. In order to achieve this understanding the basics of how to edit an image becomes very important.

When it comes to editing photos, some of the key features many people sort to go after include:

  • Cropping
  • Adding beauty filters
  • Resizing the image
  • Adjusting contrast
  • Adding the blur effect

The good news is, you can achieve all this with Python and with the help of some image processing libraries. Now, it’s time to implement the above mentioned features.

Python Libraries Needed

In order for us to have our application up and running, we will need to make use of some Python libraries that will make it easier develop the application They include:

  • Pillow – It is used to manipulate, read, and save images. It also adds the image processing capabilities to the Python interpreter.
  • Tkinter – Used to create the GUI of our app.

The project code is available on GitHub here.

Creating a Photo-Editor App

Now, before we get started with writing the code for our app, we need to make sure that we have all necessary tools for this task set in place. That includes confirming that you have Python installed in your local machine and also that you have access to a code editor of your choice.

To check whether Python is installed, No matter the operating system you are using, the command below works across both Windows, Mac and Linux systems:

python --version

Having confirmed that, we can move ahead and begin with writing out code. Earlier we listed some of the libraries that we will need to create our app, now let’s begin by first installing them into our system.

Step 1: Installing the Libraries

To get started we need to install the pillow library. We will use PIP to run the installation command.

pip install pillow

Similarly to install tkinter we will make use of PIP by executing the command below:

pip install tk
Step 2: Import Required Modules

In order for us to use the modules that we have installed, we will need to import them, specifically some packages that align with our project. The code below allows us to do this. Remember, all the code is written in a python file, make sure you already have one created:

from tkinter import *
from tkinter import ttk
from tkinter import filedialog
from tkinter.filedialog import askopenfilename,asksaveasfilename
from PIL import Image, ImageTk, ImageFilter, ImageEnhance, ImageOps
import os

The above code adds the modules directly into our project by making use of the import statement.

Step 3: Create a Tkinter Window

This is the point where we get to create our interactive interface. It’s going to act like the layout of our app housing all components needed including different functional buttons for interactivity. With the code below we are able to set the window title and also the dimensions. (feel free to try out different dimensions you are comfortable with).

root = Tk()
root.title("Simple Photo Editor")
root.geometry("640x640")
Step 4: Loading an Image

First we begin by creating a function def select(), which will allow us to pass in the code that will be used to load an image for editing.

def select():
    global img_path, img 
    img_path = filedialog.askopenfilename(initialdir=os.getcwd()) 
    img = Image.open(img_path) 
    img.thumbnail((350, 350)) 
    img1 = ImageTk.PhotoImage(img) 
    canvas2.create_image(300, 210, image=img1) 
    canvas2.image=img1

On the first line we have the function that describes what we will be handling in this code block, that is selecting an image. Next, three global variables are declared which will assist us in defining different attributes related to our image.

On the third line, the code allows us to get the path of the image that we intend to use. Line four, opens the selected image and sets it ready for editing. Next, using the img.thumnail() the image is converted into a thumbnail version of itself.

The Tkinter PhotoImage widget supports different file formats. In order for it to support other file formats such as JPG or JPEG, the use of Pillow is necessary to enable the conversion that is understood by PhotoImage widget. That’s what line 6 in our code block does.

The create_image, is used to create an image object on the canvas, this is because it does not accept an image directly it uses an object created by the PhotoImage() method.

Step 5: The Beauty Filters

By using Pillow we are able to gain access to tons of beauty filters which can be used to enhance the image quality. Some filters which we will be implementing in this project include: Blur, Brightness, Contrast etc. Read more about pillow filters here.

To add a filter, the following syntax is used:

img = PIL.filter(PIL.Imagefilter.FILTER_NAME)
Step 5.1: The Blur Effect

When talking about image blurring, it’s basically reducing the sharpness of the image. There isn’t much to add under this section except creating a function similar to the precious one only this time round we will name it def blur(event), and embed the option within a for statement, add a one liner code which will add the blur effect widget imgg = img.filter(ImageFilter.BoxBlur(m)).

def blur(event):
    global img_path, img1, imgg
    for m in range(0, v1.get()+1):
        img = Image.open(img_path)
        img.thumbnail((350, 350))
        imgg = img.filter(ImageFilter.BoxBlur(m))
        img1 = ImageTk.PhotoImage(imgg)
        canvas2.create_image(300, 210, image=img1)
        canvas2.image = img1
Step 5.2: The Brightness Effect

This code block is used to control the brightness of an image.

def brightness(event):  
    global img_path, img2, img3
    for m in range(0, v2.get()+1):
        img = Image.open(img_path)
        img.thumbnail((350, 350))
        imgg = ImageEnhance.Brightness(img)
        img2 = imgg.enhance(m)
        img3 = ImageTk.PhotoImage(img2)
        canvas2.create_image(300, 210, image=img3)
        canvas2.image = img3
Step 5.3: The Contrast Effect

This code block is used to control the contrast of an image, similar to the contrast control on a TV set. An enhancement factor of 0.0 gives a solid grey image. A factor of 1.0 gives the original image.

def contrast(event):
    global img_path, img4, img5
    for m in range(0, v3.get()+1):
        img = Image.open(img_path)
        img.thumbnail((350, 350))
        imgg = ImageEnhance.Contrast(img)
        img4 = imgg.enhance(m)
        img5 = ImageTk.PhotoImage(img4)
        canvas2.create_image(300, 210, image=img5)
        canvas2.image = img5
Step 5.4: The Rotation Effect

In this code block, the newly added line of code is img.rotate(int(rotate_combo.get())) which is used to rotate the image either from left to right or top to bottom.

def rotate(event):
    global img_path, img6, img7
    img = Image.open(img_path)
    img.thumbnail((350, 350))
    img6 = img.rotate(int(rotate_combo.get()))
    img7 = ImageTk.PhotoImage(img6)
    canvas2.create_image(300, 210, image=img7)
    canvas2.image = img7
Step 5.5: The Flip Effect

Image flipping is basically a time-reversed image on a horizontal axis. You can either flip your image in different directions that is either from top to bottom or left to right.

def flip(event):
    global img_path, img8, img9
    img = Image.open(img_path)
    img.thumbnail((350, 350))
    if flip_combo.get() == "FLIP LEFT TO RIGHT":
        img8 = img.transpose(Image.FLIP_LEFT_RIGHT)
    elif flip_combo.get() == "FLIP TOP TO BOTTOM":
        img8 = img.transpose(Image.FLIP_TOP_BOTTOM)
    img9 = ImageTk.PhotoImage(img8)
    canvas2.create_image(300, 210, image=img9)
    canvas2.image = img9
Step 5.6: Adding Borders

The ImageOps module contains a number of ready made image processing operations, it adds a border to the image. It’s syntax is as shown below:

PIL.ImageOps.expand(image, border = 0, fill = 0)

In our case, our borders will be set as follows:

def border(event):
    global img_path, img10, img11
    img = Image.open(img_path)
    img.thumbnail((350, 350))
    img10 = ImageOps.expand(img, border=int(border_combo.get()), fill=95)
    img11 = ImageTk.PhotoImage(img10)
    canvas2.create_image(300, 210, image=img11)
    canvas2.image = img11
Step 6: Saving Edited Image

Saving an image in Python is easier. The save function here will save the edited image in the same directory as the Python file.

def save():
    global img_path, imgg, img1, img2, img3, img4, img5, img6, img7, img8, img9, img10, img11
    ext = img_path.split(".")[-1]
    file = asksaveasfilename(defaultextension=f".{ext}", filetypes=[(
        "All Files", "*.*"), ("PNG file", "*.png"), ("jpg file", "*.jpg")])
    if file:
        if canvas2.image == img1:
            imgg.save(file)
        elif canvas2.image == img3:
            img2.save(file)
        elif canvas2.image == img5:
            img4.save(file)
        elif canvas2.image == img7:
            img6.save(file)
        elif canvas2.image == img9:
            img8.save(file)
        elif canvas2.image == img11:
            img10.save(file)
Step 7: Creating Interactive Labels and Buttons

This particular step is where we get to design the interface of our app that includes adding the canvas to display the image and buttons too, that is by setting the fonts, colors, text position etc…

blurr = Label(root, text="Blur:", font=("ariel 17 bold"), width=9, anchor='e')
blurr.place(x=15, y=8)
v1 = IntVar()
scale1 = ttk.Scale(root, from_=0, to=10, variable=v1,
                   orient=HORIZONTAL, command=blur)
scale1.place(x=150, y=10)
bright = Label(root, text="Brightness:", font=("ariel 17 bold"))
bright.place(x=8, y=50)
v2 = IntVar()
scale2 = ttk.Scale(root, from_=0, to=10, variable=v2,
                   orient=HORIZONTAL, command=brightness)
scale2.place(x=150, y=55)
contrast = Label(root, text="Contrast:", font=("ariel 17 bold"))
contrast.place(x=35, y=92)
v3 = IntVar()
scale3 = ttk.Scale(root, from_=0, to=10, variable=v3,
                   orient=HORIZONTAL, command=contrast)
scale3.place(x=150, y=100)
rotate = Label(root, text="Rotate:", font=("ariel 17 bold"))
rotate.place(x=370, y=8)
values = [0, 90, 180, 270, 360]
rotate_combo = ttk.Combobox(root, values=values, font=('ariel 10 bold'))
rotate_combo.place(x=460, y=15)
rotate_combo.bind("<<ComboboxSelected>>", rotate)
flip = Label(root, text="Flip:", font=("ariel 17 bold"))
flip.place(x=400, y=50)
values1 = ["FLIP LEFT TO RIGHT", "FLIP TOP TO BOTTOM"]
flip_combo = ttk.Combobox(root, values=values1, font=('ariel 10 bold'))
flip_combo.place(x=460, y=57)
flip_combo.bind("<<ComboboxSelected>>", flip)
border = Label(root, text="Add border:", font=("ariel 17 bold"))
border.place(x=320, y=92)
values2 = [i for i in range(10, 45, 5)]
border_combo = ttk.Combobox(root, values=values2, font=("ariel 10 bold"))
border_combo.place(x=460, y=99)
border_combo.bind("<<ComboboxSelected>>", border)

# create canvas to display image
canvas2 = Canvas(root, width="600", height="420", relief=RIDGE, bd=2)
canvas2.place(x=15, y=150)

# create buttons
btn1 = Button(root, text="Select Image", bg='black', fg='gold',
              font=('ariel 15 bold'), relief=GROOVE, command=select)
btn1.place(x=100, y=595)
btn2 = Button(root, text="Save", width=12, bg='black', fg='gold',
              font=('ariel 15 bold'), relief=GROOVE, command=save)
btn2.place(x=280, y=595)
btn3 = Button(root, text="Exit", width=12, bg='black', fg='gold',
              font=('ariel 15 bold'), relief=GROOVE, command=root.destroy)
btn3.place(x=460, y=595)

Now, we only have to do one more step. We just have to add the last piece of code that will execute the program.

Step 8: Run the App

To execute the app we use the mainloop() method. What it does is, it tells Python to run the tkinter event loop until the user exits it.

# Execute Tkinter
root.mainloop()
The Output

Running the above code will create a display of our photo editor app that will look as shown below with everything set as defined in the code.

Now, let’s get add an image to be sure everything is working out fine:

As you can we have successfully added an image into our editor, feel free to play with different features provided and after that go ahead and save the copy of your edited image.

It’s important to also highlight that with the Pillow you can do more than just the listed features provided in our code. You can also merge images, change image color etc. To learn more about how to implement this and more, check out the official Pillow documentation.

Conclusion

Now you can create your own Photo Editor App using Python that has most functionality just like other softwares out there. There is no limitation on the design of the app. Therefore, you can redesign it to meet your own specification and style. You can even add other interactivity features to it. It’s about time you start using your own creations.


Hillary ("Lary") Nyakundi is a Growing Developer, with great interest in technology, open-source and the Python programming language. He is also a technical writer aiming to help share knowledge with other developers through informative articles. Through this, he has been able to work with tech companies from the US, India and Kenya. His passion in the developer world led him to start a podcast, “Let’s Talk Developer” where he gets to connect with other developers, learn from them and share their stories to help inspire upcoming developers.


Discussion

Click on a tab to select how you'd like to leave your comment

Leave a Comment

Your email address will not be published.

Menu
Skip to toolbar