DEV Community

Mate Technologies
Mate Technologies

Posted on

Step-by-Step Guide: Building a Professional Image Converter in Python

In this tutorial, we’ll walk through building a desktop image converter in Python using Tkinter, Pillow, and ttkbootstrap. The full script is available here: GitHub link
.

We’ll cover:

Project setup

Database logging

Image conversion logic

GUI creation with drag-and-drop support

License verification system

1️⃣ Project Setup and Dependencies

First, install the required packages:

pip install pillow ttkbootstrap tkinterdnd2

Enter fullscreen mode Exit fullscreen mode

Then, import the required modules:

import os, sys, sqlite3, csv, time
from threading import Thread
from PIL import Image, ImageTk
Enter fullscreen mode Exit fullscreen mode

Optional for better resizing quality

try:
    from PIL import ImageResampling
    RESAMPLE = ImageResampling.LANCZOS
except:
    RESAMPLE = Image.LANCZOS

import ttkbootstrap as tb
from ttkbootstrap.constants import *
from tkinter import filedialog, messagebox, Listbox, Canvas, Scrollbar, simpledialog
from tkinterdnd2 import TkinterDnD, DND_FILES
Enter fullscreen mode Exit fullscreen mode

Explanation:

Pillow handles image processing.

ttkbootstrap provides modern Tkinter themes.

tkinterdnd2 adds drag-and-drop file support.

We try to use ImageResampling.LANCZOS for better resizing but fallback if unavailable.

2️⃣ App Info and Paths

Define your app metadata and file paths:

APP_NAME = "Image Convert BUSINESS PRO"
APP_VERSION = "2.0"

BASE_DIR = os.path.dirname(sys.argv[0])
DB_NAME = os.path.join(BASE_DIR, "snapconvert.db")
OUTPUT_DIR = os.path.join(BASE_DIR, "converted")
LOG_FILE = os.path.join(BASE_DIR, "conversion.log")
LICENSE_FILE = os.path.join(BASE_DIR, "license.key")
Enter fullscreen mode Exit fullscreen mode

Explanation:
This section sets up paths for your database, output folder, log file, and license file.

3️⃣ Database for Conversion History

We will log converted images into a SQLite database:

def init_db():
    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    c.execute("""CREATE TABLE IF NOT EXISTS history(
        id INTEGER PRIMARY KEY,
        name TEXT,
        original TEXT,
        converted TEXT
    )""")
    conn.commit()
    conn.close()
Enter fullscreen mode Exit fullscreen mode

To insert and fetch history:

def insert_db(name, orig, conv):
    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    c.execute("INSERT INTO history(name, original, converted) VALUES(?,?,?)", (name, orig, conv))
    conn.commit()
    conn.close()

def fetch_db():
    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    c.execute("SELECT name, original, converted FROM history ORDER BY id DESC")
    rows = c.fetchall()
    conn.close()
    return rows
Enter fullscreen mode Exit fullscreen mode

Explanation:

Every converted image is logged in the database with its original and converted paths.

History is fetched in descending order to show the latest conversions first.

4️⃣ Logging and Exporting History

Keep a log file of events:

def log_event(msg):
    with open(LOG_FILE, "a") as f:
        f.write(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] {msg}\n")
Enter fullscreen mode Exit fullscreen mode

Export history as a CSV:

def export_history_csv():
    rows = fetch_db()
    if not rows:
        messagebox.showinfo("Export History","No history to export")
        return
    path = filedialog.asksaveasfilename(defaultextension=".csv", filetypes=[("CSV file","*.csv")])
    if path:
        with open(path,"w", newline="", encoding="utf-8") as f:
            writer = csv.writer(f)
            writer.writerow(["Name","Original Path","Converted Path"])
            writer.writerows(rows)
        messagebox.showinfo("Export History", f"Exported {len(rows)} records")
Enter fullscreen mode Exit fullscreen mode

Explanation:

Every event is logged in a conversion.log file.

Users can export their history to a CSV for reference.

5️⃣ License System

You can secure your app using a simple license check:

VALID_LICENSES = ["PRO-2026-XYZ123", "PRO-2026-ABC789"]

def check_license():
    if os.path.exists(LICENSE_FILE):
        with open(LICENSE_FILE,"r") as f:
            key = f.read().strip()
        if key in VALID_LICENSES:
            return True
    key = simpledialog.askstring("License Required","Enter your license key:")
    if key and key in VALID_LICENSES:
        with open(LICENSE_FILE,"w") as f:
            f.write(key)
        messagebox.showinfo("License Activated","License activated successfully!")
        return True
    else:
        messagebox.showerror("Invalid License","The license key is invalid. App will exit.")
        return False
Enter fullscreen mode Exit fullscreen mode

Explanation:

Checks for an existing license file.

Prompts the user if no valid license is found.

6️⃣ Image Conversion Worker

Core function to resize, convert, and save images:

def worker(images, fmt, out, quality, resize, keep, progress, finish):
    os.makedirs(out, exist_ok=True)
    total = len(images)
    count = 0

    for i, path in enumerate(images):
        try:
            with Image.open(path) as img:
                if resize>0:
                    img = img.resize((resize,resize), RESAMPLE)
                if fmt=="JPEG" and img.mode in ("RGBA","P"):
                    img = img.convert("RGB")
                name = os.path.splitext(os.path.basename(path))[0]
                if not keep:
                    name += f"_{i+1}"
                out_path = os.path.join(out, f"{name}.{fmt.lower()}")
                img.save(out_path, fmt, quality=quality if fmt=="JPEG" else None)
                insert_db(name, path, out_path)
                count += 1
        except Exception as e:
            log_event(f"Error converting {path}: {e}")
        progress(int((i+1)/total*100))
    finish(count)
Enter fullscreen mode Exit fullscreen mode

Explanation:

Supports resizing and format conversion.

Handles JPEG transparency by converting to RGB.

Updates a progress bar and logs every conversion.

7️⃣ GUI Setup with Tkinter and ttkbootstrap

We’ll build a drag-and-drop GUI with a left file list, center gallery, and right settings panel. Example of adding files:

def add_files(self):
    self.add_images(filedialog.askopenfilenames())

def add_folder(self):
    folder = filedialog.askdirectory()
    imgs = []
    for r, _, f in os.walk(folder):
        for x in f:
            if x.lower().endswith(("png","jpg","jpeg","bmp","gif")):
                imgs.append(os.path.join(r, x))
    self.add_images(imgs)
Enter fullscreen mode Exit fullscreen mode

Explanation:

Users can add single files or entire folders.

Only valid image extensions are accepted.

8️⃣ Run the App

Initialize the database and start the GUI:

if __name__=="__main__":
    init_db()
    App().run()
Enter fullscreen mode Exit fullscreen mode

Explanation:

init_db() ensures the database exists.

App().run() launches the GUI.

✅ Full Script Reference

You can access the complete script here:
Image Convert BUSINESS PRO on GitHub

Top comments (0)