Image resizer tool
This image resizer tool is highly powered by advanced GUI and can work efficiently.
source code :
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from PIL import Image
import os
from pathlib import Path
import math
import shutil
import threading
class ImageResizer:
def __init__(self, root):
self.root = root
self.root.title("π Futuristic Image Resizer v3.0 - ERROR FREE")
self.root.geometry("1200x800")
self.root.configure(bg='#0a0a0a')
self.colors = {
'bg': '#0a0a0a', 'panel': '#1a1a2e', 'accent': '#00d4ff',
'accent2': '#ff00ff', 'text': '#ffffff', 'glow': '#1a1a2e'
}
self.images = []
self.setup_ui()
def setup_ui(self):
# Title
title = tk.Label(self.root, text="π NEON IMAGE RESIZER v3.0",
font=('Arial', 24, 'bold'), bg=self.colors['bg'],
fg=self.colors['accent'])
title.pack(pady=20)
# Main frame
main_frame = tk.Frame(self.root, bg=self.colors['bg'])
main_frame.pack(fill='both', expand=True, padx=20, pady=10)
# Left panel - Images
left_panel = tk.LabelFrame(main_frame, text="π Image Queue",
font=('Arial', 12, 'bold'), bg=self.colors['panel'],
fg=self.colors['accent'])
left_panel.pack(side='left', fill='both', expand=True, padx=(0,10))
# Add button
btn_frame = tk.Frame(left_panel, bg=self.colors['panel'])
btn_frame.pack(fill='x', padx=20, pady=20)
tk.Button(btn_frame, text="➕ ADD IMAGES", command=self.add_images,
bg=self.colors['accent'], fg='black', font=('Arial', 12, 'bold'),
relief='flat', pady=10).pack(fill='x')
# Listbox
list_frame = tk.Frame(left_panel, bg=self.colors['panel'])
list_frame.pack(fill='both', expand=True, padx=20, pady=10)
scrollbar = tk.Scrollbar(list_frame)
scrollbar.pack(side='right', fill='y')
self.image_listbox = tk.Listbox(list_frame, yscrollcommand=scrollbar.set,
bg=self.colors['panel'], fg=self.colors['text'],
selectbackground=self.colors['accent'],
font=('Arial', 10))
self.image_listbox.pack(side='left', fill='both', expand=True)
scrollbar.config(command=self.image_listbox.yview)
self.image_listbox.bind('<Delete>', self.remove_selected)
# Right panel - Settings
right_panel = tk.LabelFrame(main_frame, text="⚙️ Settings",
font=('Arial', 12, 'bold'), bg=self.colors['panel'],
fg=self.colors['accent2'])
right_panel.pack(side='right', fill='both', expand=True)
# Size input
tk.Label(right_panel, text="Target Size:", font=('Arial', 12, 'bold'),
bg=self.colors['panel'], fg=self.colors['text']).pack(anchor='w', padx=20, pady=(20,5))
size_frame = tk.Frame(right_panel, bg=self.colors['panel'])
size_frame.pack(fill='x', padx=20, pady=5)
self.size_var = tk.StringVar(value="500")
tk.Entry(size_frame, textvariable=self.size_var, font=('Arial', 12),
bg='#2a2a3e', fg=self.colors['accent'], relief='flat').pack(side='left', fill='x', expand=True, padx=(0,10))
self.unit_var = tk.StringVar(value="KB")
ttk.Combobox(size_frame, textvariable=self.unit_var, values=["KB", "MB"],
state="readonly", font=('Arial', 10), width=8).pack(side='right')
# Quality
tk.Label(right_panel, text="Quality:", font=('Arial', 12, 'bold'),
bg=self.colors['panel'], fg=self.colors['text']).pack(anchor='w', padx=20, pady=(20,5))
self.quality_var = tk.IntVar(value=85)
tk.Scale(right_panel, from_=50, to=95, orient='horizontal', variable=self.quality_var,
bg=self.colors['panel'], fg=self.colors['accent'],
highlightthickness=0, troughcolor='#2a2a3e').pack(fill='x', padx=20, pady=5)
# Process button
self.process_btn = tk.Button(right_panel, text="π RESIZE ALL",
command=self.start_resize, state='disabled',
bg=self.colors['accent2'], fg='black',
font=('Arial', 14, 'bold'), relief='flat', pady=15)
self.process_btn.pack(fill='x', padx=20, pady=30)
# Progress
self.progress = ttk.Progressbar(right_panel, mode='determinate')
self.progress.pack(fill='x', padx=20, pady=10)
self.status_label = tk.Label(right_panel, text="Add images to start",
font=('Arial', 11), bg=self.colors['panel'],
fg=self.colors['text'])
self.status_label.pack(pady=10)
def add_images(self):
files = filedialog.askopenfilenames(
title="Select Images",
filetypes=[("Images", "*.jpg *.jpeg *.png *.bmp *.tiff *.webp *.gif")]
)
self.load_images(files)
def load_images(self, file_paths):
for path in file_paths:
if path not in [img['path'] for img in self.images]:
if os.path.exists(path):
try:
size = os.path.getsize(path)
self.images.append({
'path': path,
'name': os.path.basename(path),
'size': size
})
except:
pass
self.update_listbox()
def update_listbox(self):
self.image_listbox.delete(0, tk.END)
for img in self.images:
kb = img['size'] / 1024
size_str = f"{img['name']} ({kb:.1f} KB)"
self.image_listbox.insert(tk.END, size_str)
count = len(self.images)
self.process_btn.config(state='normal' if count > 0 else 'disabled')
self.status_label.config(text=f"Loaded {count} images ✓")
def remove_selected(self, event=None):
selection = list(self.image_listbox.curselection())
for i in reversed(selection):
del self.images[i]
self.update_listbox()
def parse_size(self):
try:
num = float(self.size_var.get())
unit = self.unit_var.get()
if unit == "KB": return int(num * 1024)
return int(num * 1024 * 1024) # MB
except:
return 500 * 1024 # 500KB default
def resize_image(self, img_path, target_size, quality=85):
try:
with Image.open(img_path) as img:
# Get original dimensions
orig_w, orig_h = img.size
# Try different scales to hit target size
for scale in [1.0, 0.8, 0.6, 0.5, 0.4, 0.3, 0.2]:
new_w = max(100, int(orig_w * scale))
new_h = max(100, int(orig_h * scale))
# Resize and test
test_img = img.resize((new_w, new_h), Image.Resampling.LANCZOS)
if test_img.mode != 'RGB':
test_img = test_img.convert('RGB')
temp_path = img_path + '.tmp'
test_img.save(temp_path, 'JPEG', quality=quality, optimize=True)
if os.path.getsize(temp_path) <= target_size:
os.rename(temp_path, img_path.rsplit('.', 1)[0] + '_resized.jpg')
return True
os.remove(temp_path)
# Fallback
final_img = img.resize((400, 400), Image.Resampling.LANCZOS).convert('RGB')
output_path = img_path.rsplit('.', 1)[0] + '_resized.jpg'
final_img.save(output_path, 'JPEG', quality=quality, optimize=True)
return True
except Exception as e:
print(f"Error processing {img_path}: {e}")
return False
def start_resize(self):
if not self.images:
return
target_size = self.parse_size()
quality = self.quality_var.get()
def process():
self.process_btn.config(state='disabled')
total = len(self.images)
self.progress['maximum'] = total
# Get output folder
output_dir = filedialog.askdirectory(title="Save Resized Images")
if not output_dir:
self.process_btn.config(state='normal')
return
success = 0
for i, img in enumerate(self.images):
# Update progress
self.root.after(0, lambda v=i+1: self.progress.config(value=v))
self.root.after(0, lambda t=f"Resizing {i+1}/{total}": setattr(self.status_label, 'text', t))
if self.resize_image(img['path'], target_size, quality):
# Copy to output folder
resized_path = img['path'].rsplit('.', 1)[0] + '_resized.jpg'
if os.path.exists(resized_path):
shutil.copy2(resized_path, os.path.join(output_dir, os.path.basename(resized_path)))
success += 1
# Final update
self.root.after(0, lambda: self.progress.config(value=0))
self.root.after(0, lambda: setattr(self.status_label, 'text', f"✅ Done! {success}/{total} resized"))
self.root.after(0, lambda: self.process_btn.config(state='normal'))
threading.Thread(target=process, daemon=True).start()
if __name__ == "__main__":
try:
root = tk.Tk()
app = ImageResizer(root)
root.mainloop()
except ImportError as e:
print("ERROR: Install Pillow first!")
print("Run: pip install Pillow")
input("Press Enter to exit...")
Comments
Post a Comment