You can find the full script here: Image_Convert_BUSINESS_PRO_v2.py
In this tutorial, we’ll build SnapConvert BUSINESS PRO, a professional image converter with a GUI, drag-and-drop support, license validation, history logging, and CSV export.
1️⃣ Importing Libraries
We start by importing all the necessary modules. This includes Python built-ins, GUI libraries, image processing, encryption, and threading.
import os
import sys
import csv
import time
import sqlite3 # for database storage
import hashlib
import base64
from threading import Thread
from PIL import Image, ImageTk
We also handle the resampling library, which is used for resizing images with high quality:
try:
from PIL import ImageResampling
RESAMPLE = ImageResampling.LANCZOS
except:
RESAMPLE = Image.LANCZOS
Finally, we import GUI frameworks and encryption tools:
import ttkbootstrap as tb
from ttkbootstrap.constants import *
from tkinter import filedialog, messagebox, Listbox, Canvas, Scrollbar, simpledialog
from tkinterdnd2 import TkinterDnD, DND_FILES
from cryptography.fernet import Fernet
Tip: ttkbootstrap is like a modern theme for Tkinter, and tkinterdnd2 enables drag-and-drop support.
2️⃣ Application Info and Paths
Define basic app info and important paths:
APP_NAME = "SnapConvert BUSINESS PRO"
APP_VERSION = "2.1"
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")
Why: Keeping paths centralized makes it easier to manage files and database locations.
3️⃣ License Management
We protect the app with a license system. Valid licenses are encrypted with Fernet.
SECRET_KEY = base64.urlsafe_b64encode(hashlib.sha256(b"MySuperSecretBusinessKey2026").digest())
fernet = Fernet(SECRET_KEY)
VALID_LICENSES = ["PRO-2026-XYZ123", "PRO-2026-ABC789"]
def encrypt_license(key: str) -> str:
return fernet.encrypt(key.encode()).decode()
def decrypt_license(enc: str) -> str:
try:
return fernet.decrypt(enc.encode()).decode()
except:
return None
The app checks for a valid license file or prompts the user to enter one:
def check_license():
if os.path.exists(LICENSE_FILE):
with open(LICENSE_FILE,"r") as f:
encrypted = f.read().strip()
key = decrypt_license(encrypted)
if key in VALID_LICENSES:
return True
key = simpledialog.askstring("License Required","Enter your license key:")
if key in VALID_LICENSES:
with open(LICENSE_FILE,"w") as f:
f.write(encrypt_license(key))
messagebox.showinfo("License Activated","License activated successfully!")
return True
else:
messagebox.showerror("Invalid License","License key is invalid. Exiting application.")
return False
4️⃣ Database for Conversion History
We use SQLite to store the history of converted images:
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()
Insert, fetch, and clear history functions:
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
def clear_history():
conn = sqlite3.connect(DB_NAME)
c = conn.cursor()
c.execute("DELETE FROM history")
conn.commit()
conn.close()
Tip: Logging all conversions helps users track what they’ve done and export history to CSV.
5️⃣ Logging and Exporting History
We log events to a file:
def log_event(msg):
with open(LOG_FILE,"a") as f:
f.write(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] {msg}\n")
And provide a way to export conversion history:
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")
6️⃣ Image Conversion Worker
We process images in a separate thread for smooth UI responsiveness:
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()}")
c=1
while os.path.exists(out_path):
out_path=os.path.join(out,f"{name}_{c}.{fmt.lower()}")
c+=1
params={"quality":quality} if fmt=="JPEG" else {}
img.save(out_path, fmt, **params)
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)
Tip: This ensures the UI doesn’t freeze when converting large batches.
7️⃣ Building the GUI
We use ttkbootstrap for a modern look and TkinterDnD for drag-and-drop:
Left panel: File list and buttons to add/remove images
Center panel: Thumbnail gallery of images
Right panel: Settings like format, quality, resize, and conversion button
Bottom: Conversion history table
class App:
def __init__(self):
if not check_license(): sys.exit()
self.root = TkinterDnD.Tk()
self.root.title(APP_NAME)
self.root.geometry("1250x750")
self.style = tb.Style("darkly")
self.images=[]
self.thumbs=[]
self.create_menu()
self.build_ui()
self.load_history()
We register the drop target:
self.root.drop_target_register(DND_FILES)
self.root.dnd_bind("<<Drop>>", self.drop)
8️⃣ Running the App
Finally, initialize the database and start the app:
if __name__=="__main__":
init_db()
App().run()
✅ That’s it! You now have a fully functional image converter with GUI, drag-and-drop, database history, and licensing.
You can explore the full working version here: Image_Convert_BUSINESS_PRO_v2.py
Top comments (0)