Image Viewer Using Python and Tkinter

PythonPythonBeginner
Practice Now

Introduction

In this project, we will create an image viewer application using Python and Tkinter. The image viewer will allow you to open an image file, display it, and perform actions such as zooming in, zooming out, and rotating the image. We will use the PIL (Python Imaging Library) library to handle image operations and Tkinter for creating the graphical user interface.

👀 Preview

Alt text

🎯 Tasks

In this project, you will learn:

  • How to create a GUI application using Tkinter.
  • How to handle image loading and display using PIL.
  • How to implement zoom in, zoom out, and rotate functionality for the displayed image.

🏆 Achievements

After completing this project, you will be able to:

  • Develop a functional image viewer application using Python and Tkinter.
  • Integrate image processing capabilities using the PIL library.
  • Implement basic image manipulation features such as zooming and rotating.

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("`Python`")) -.-> python/BasicConceptsGroup(["`Basic Concepts`"]) python(("`Python`")) -.-> python/FileHandlingGroup(["`File Handling`"]) tkinter(("`Tkinter`")) -.-> tkinter/ThemedWidgetsGroup(["`Themed Widgets`"]) tkinter(("`Tkinter`")) -.-> tkinter/ImagesGroup(["`Images`"]) python(("`Python`")) -.-> python/ControlFlowGroup(["`Control Flow`"]) python(("`Python`")) -.-> python/DataStructuresGroup(["`Data Structures`"]) python(("`Python`")) -.-> python/FunctionsGroup(["`Functions`"]) python(("`Python`")) -.-> python/ModulesandPackagesGroup(["`Modules and Packages`"]) python(("`Python`")) -.-> python/ObjectOrientedProgrammingGroup(["`Object-Oriented Programming`"]) python(("`Python`")) -.-> python/PythonStandardLibraryGroup(["`Python Standard Library`"]) python/BasicConceptsGroup -.-> python/comments("`Comments`") python/FileHandlingGroup -.-> python/with_statement("`Using with Statement`") tkinter/ThemedWidgetsGroup -.-> tkinter/button("`Clickable Button`") tkinter/ThemedWidgetsGroup -.-> tkinter/frame("`Container Frame`") tkinter/ThemedWidgetsGroup -.-> tkinter/label("`Text Label`") tkinter/ImagesGroup -.-> tkinter/photoimage("`Raster Image`") python/BasicConceptsGroup -.-> python/variables_data_types("`Variables and Data Types`") python/BasicConceptsGroup -.-> python/numeric_types("`Numeric Types`") python/BasicConceptsGroup -.-> python/type_conversion("`Type Conversion`") python/ControlFlowGroup -.-> python/conditional_statements("`Conditional Statements`") python/ControlFlowGroup -.-> python/for_loops("`For Loops`") python/DataStructuresGroup -.-> python/lists("`Lists`") python/DataStructuresGroup -.-> python/tuples("`Tuples`") python/FunctionsGroup -.-> python/function_definition("`Function Definition`") python/ModulesandPackagesGroup -.-> python/importing_modules("`Importing Modules`") python/ModulesandPackagesGroup -.-> python/using_packages("`Using Packages`") python/ModulesandPackagesGroup -.-> python/standard_libraries("`Common Standard Libraries`") python/ObjectOrientedProgrammingGroup -.-> python/classes_objects("`Classes and Objects`") python/ObjectOrientedProgrammingGroup -.-> python/constructor("`Constructor`") python/ObjectOrientedProgrammingGroup -.-> python/polymorphism("`Polymorphism`") python/ObjectOrientedProgrammingGroup -.-> python/encapsulation("`Encapsulation`") python/FileHandlingGroup -.-> python/file_opening_closing("`Opening and Closing Files`") python/PythonStandardLibraryGroup -.-> python/os_system("`Operating System and System`") python/FunctionsGroup -.-> python/build_in_functions("`Build-in Functions`") subgraph Lab Skills python/comments -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} python/with_statement -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} tkinter/button -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} tkinter/frame -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} tkinter/label -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} tkinter/photoimage -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} python/variables_data_types -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} python/numeric_types -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} python/type_conversion -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} python/conditional_statements -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} python/for_loops -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} python/lists -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} python/tuples -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} python/function_definition -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} python/importing_modules -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} python/using_packages -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} python/standard_libraries -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} python/classes_objects -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} python/constructor -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} python/polymorphism -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} python/encapsulation -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} python/file_opening_closing -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} python/os_system -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} python/build_in_functions -.-> lab-298890{{"`Image Viewer Using Python and Tkinter`"}} end

Create the project files

First, create a new file named ~/project/image_viewer.py and open it in a text editor or an integrated development environment (IDE).

cd ~/project
touch image_viewer.py

Import the required libraries

In the image_viewer.py file, import the necessary libraries:

import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox
from PIL import Image, ImageTk
import os

The tkinter library provides the functionality to create GUI elements, filedialog allows us to open a file dialog for selecting an image file, messagebox is used to display messages to the user, PIL is used for image processing, and os provides functions for interacting with the operating system.

Create the ImageViewer class

Define a new class named ImageViewer that will handle the image viewer application:

class ImageViewer:
    def __init__(self, root):
        self.root = root
        self.root.title('LabEx Image Viewer')
        self.root.geometry('800x600')
        self.root.configure(background='white')

        self.image_label = tk.Label(self.root)
        self.image_label.pack()

        self.control_frame = tk.Frame(self.root)
        self.control_frame.pack()

        self.open_button = tk.Button(self.control_frame, text='Open', command=self.open_image)
        self.open_button.pack(side='left')

        self.close_button = tk.Button(self.control_frame, text='Quit', command=self.root.quit)
        self.close_button.pack(side='left')

        self.zoom_in_button = tk.Button(self.control_frame, text='Zoom In', command=self.zoom_in)
        self.zoom_in_button.pack(side='left')

        self.zoom_out_button = tk.Button(self.control_frame, text='Zoom Out', command=self.zoom_out)
        self.zoom_out_button.pack(side='left')

        self.rotate_button = tk.Button(self.control_frame, text='Rotate', command=self.rotate)
        self.rotate_button.pack(side='left')

        self.current_image_path = ''
        self.zoom_level = 1

In the __init__ method, we initialize the root window with a title, size, and background color. Then, we create a label to display the image and a frame to hold the control buttons (Open, Quit, Zoom In, Zoom Out, Rotate). We also define instance variables to keep track of the current image path and the zoom level.

Implement the open_image method

Add the open_image method to the ImageViewer class:

    def open_image(self):
        self.current_image_path = filedialog.askopenfilename(defaultextension=".jpg",
            filetypes=[("All Files", "*.*"), ("JPEG", ".jpg"), ("PNG", ".png"), ("GIF", ".gif")])
        if self.current_image_path:
            self.load_image()

The open_image method opens a file dialog for selecting an image file. It sets the current_image_path variable to the selected file path and calls the load_image method to display the image.

Implement the load_image method

Implement the load_image method:

    def load_image(self):
        image = Image.open(self.current_image_path)

        ## Resize image for display
        max_size = (600, 600)
        image.thumbnail(max_size)

        ## Save a reference to the original image (for zooming/rotating)
        self.original_image = image

        ## Create a Tkinter-compatible image
        self.tk_image = ImageTk.PhotoImage(image)
        self.image_label.configure(image=self.tk_image)

        self.zoom_level = 1

The load_image method opens the selected image file using PIL's Image.open method. It resizes the image to fit within a maximum size of 600x600 pixels using the thumbnail method. Then, it saves a reference to the original image for zooming and rotating purposes. Next, it creates a Tkinter-compatible image using ImageTk.PhotoImage and updates the image label to display the loaded image. Finally, it sets the initial zoom level to 1.

Implement the zoom_in method

Implement the zoom_in method:

    def zoom_in(self):
        if not self.current_image_path:  ## No image loaded
            return
        self.zoom_level *= 1.1  ## Increase zoom level by 10%
        self.zoom_or_rotate_image()

The zoom_in method checks if an image is loaded. If no image is loaded, it returns. Otherwise, it increases the zoom level by 10% and calls the zoom_or_rotate_image method to update the displayed image.

Implement the zoom_out method

Implement the zoom_out method:

    def zoom_out(self):
        if not self.current_image_path:  ## No image loaded
            return
        if self.zoom_level < 0.1:  ## Limit outwards zoom
            return
        self.zoom_level *= 0.9  ## Decrease zoom level by 10%
        self.zoom_or_rotate_image()

The zoom_out method checks if an image is loaded. If no image is loaded, it returns. If the zoom level is already below 0.1, meaning the image is zoomed out to the limit, it returns. Otherwise, it decreases the zoom level by 10% and calls the zoom_or_rotate_image method to update the displayed image.

Implement the rotate method

Implement the rotate method:

    def rotate(self):
        if not self.current_image_path:  ## No image loaded
            return
        self.original_image = self.original_image.rotate(-90)
        self.zoom_or_rotate_image()

The rotate method checks if an image is loaded. If no image is loaded, it returns. Otherwise, it rotates the original image by -90 degrees using the rotate method from PIL and calls the zoom_or_rotate_image method to update the displayed image.

Implement the zoom_or_rotate_image method

Implement the zoom_or_rotate_image method:

    def zoom_or_rotate_image(self):
        ## Zoom and rotate original image, convert to Tk image, and display
        new_image = self.original_image.resize((int(self.original_image.width * self.zoom_level),
                                                int(self.original_image.height * self.zoom_level)))
        self.tk_image = ImageTk.PhotoImage(new_image)
        self.image_label.configure(image=self.tk_image)

The zoom_or_rotate_image method resizes the original image based on the current zoom level. It creates a new image with the updated size using the resize method from PIL. Then, it converts the new image to a Tkinter-compatible image using ImageTk.PhotoImage and updates the image label to display the updated image.

Create the main application loop

Add the following code at the end of the image_viewer.py file to create the main application loop:

if __name__ == '__main__':
    root = tk.Tk()
    app = ImageViewer(root)
    root.mainloop()

This code creates a Tkinter root window, initializes an instance of the ImageViewer class, and starts the main application loop.

Switch to the Desktop and run the image_viewer.py file to test the application. You should see the following window:

python image_viewer.py
Alt text

Summary

Congratulations! You have created an image viewer application using Python and Tkinter. The application allows you to open an image file, display it, and perform actions such as zooming in, zooming out, and rotating the image. You have learned how to use the PIL library for image processing and Tkinter for creating the graphical user interface. Feel free to customize the application further or explore additional features.

Other Python Tutorials you may like