#!/usr/bin/env python3 """ DR-Image-Magic - FULL FEATURED GUI All features, no database needed! """ import tkinter as tk from tkinter import filedialog, messagebox, ttk, scrolledtext from PIL import Image, ImageTk, ImageEnhance, ImageFilter, ImageOps, ImageDraw, ImageFont import os from pathlib import Path import numpy as np from datetime import datetime class DrImageMagicFull: def __init__(self, root): self.root = root self.root.title("DR-Image-Magic - FULL EDITION") self.root.geometry("1200x900") self.root.configure(bg='#0a0a0a') self.current_image = None self.original_image = None self.image_path = None self.history = [] # Undo history self.setup_ui() def setup_ui(self): # Main container with scrollbar main_canvas = tk.Canvas(self.root, bg='#0a0a0a', highlightthickness=0) scrollbar = ttk.Scrollbar(self.root, orient="vertical", command=main_canvas.yview) scrollable_frame = tk.Frame(main_canvas, bg='#0a0a0a') scrollable_frame.bind( "", lambda e: main_canvas.configure(scrollregion=main_canvas.bbox("all")) ) main_canvas.create_window((0, 0), window=scrollable_frame, anchor="nw") main_canvas.configure(yscrollcommand=scrollbar.set) main_canvas.pack(side="left", fill="both", expand=True) scrollbar.pack(side="right", fill="y") # Enable mousewheel scrolling def _on_mousewheel(event): main_canvas.yview_scroll(int(-1*(event.delta/120)), "units") main_canvas.bind_all("", _on_mousewheel) # Header header = tk.Label( scrollable_frame, text="🎨 DR-IMAGE-MAGIC", font=("Arial", 32, "bold"), bg='#0a0a0a', fg='#ff6600' ) header.pack(pady=15) subtitle = tk.Label( scrollable_frame, text="FULL FEATURED EDITION - All Tools, No Limits", font=("Arial", 12), bg='#0a0a0a', fg='#888' ) subtitle.pack() # Upload Section upload_frame = tk.Frame(scrollable_frame, bg='#0a0a0a') upload_frame.pack(pady=15) upload_btn = tk.Button( upload_frame, text="📁 UPLOAD IMAGE", command=self.upload_image, font=("Arial", 16, "bold"), bg='#ff6600', fg='white', padx=30, pady=12, cursor='hand2', relief=tk.FLAT ) upload_btn.pack() # Image Preview preview_frame = tk.Frame(scrollable_frame, bg='#1a1a1a', relief=tk.SUNKEN, bd=2) preview_frame.pack(pady=10, padx=20, fill=tk.BOTH) self.image_label = tk.Label( preview_frame, bg='#1a1a1a', text="No Image Loaded\n\nDrag & Drop or Click Upload", fg='#666', font=("Arial", 14) ) self.image_label.pack(pady=40, padx=20) # Quick Actions quick_frame = tk.Frame(scrollable_frame, bg='#0a0a0a') quick_frame.pack(pady=10) quick_btns = [ ("🔄 UNDO", self.undo_last, '#ff9900'), ("↺ RESET", self.reset_image, '#cc0000'), ("💾 SAVE", self.save_image, '#00cc00'), ("📦 BATCH SAVE", self.batch_save, '#0066cc'), ] for text, cmd, color in quick_btns: btn = tk.Button( quick_frame, text=text, command=cmd, font=("Arial", 11, "bold"), bg=color, fg='white', padx=15, pady=8, cursor='hand2', relief=tk.FLAT ) btn.pack(side=tk.LEFT, padx=5) # EFFECTS SECTIONS self.create_effects_section(scrollable_frame) def create_effects_section(self, parent): # Section 1: ESSENTIAL ENHANCEMENTS self.create_section(parent, "⚡ ESSENTIAL ENHANCEMENTS", [ ("✨ Auto Enhance", self.auto_enhance, "Smart enhancement"), ("💎 Super Sharpen", self.super_sharpen, "Crystal clear"), ("🌈 Color Pop", self.color_pop, "Vibrant colors"), ("🔥 HDR Effect", self.hdr_effect, "High dynamic range"), ]) # Section 2: ARTISTIC STYLES self.create_section(parent, "🎨 ARTISTIC STYLES", [ ("🖼️ Oil Painting", self.oil_painting, "Classic art"), ("📸 Film Noir", self.film_noir, "Black & white drama"), ("🌅 Golden Hour", self.golden_hour, "Warm sunset glow"), ("❄️ Ice Cold", self.ice_cold, "Cool blue tones"), ("🔴 Infrared", self.infrared, "IR photography"), ("⚫ High Key B&W", self.high_key_bw, "Bright grayscale"), ]) # Section 3: DRAMATIC EFFECTS self.create_section(parent, "💥 DRAMATIC EFFECTS", [ ("🌙 Dark Fantasy", self.dark_fantasy, "Gothic mood"), ("☀️ Sunburst", self.sunburst, "Intense brightness"), ("🎭 Vignette Drama", self.vignette_drama, "Dark edges"), ("✨ Glow", self.glow_effect, "Soft luminous"), ("🔆 Cross Process", self.cross_process, "Film effect"), ]) # Section 4: VINTAGE & RETRO self.create_section(parent, "📷 VINTAGE & RETRO", [ ("📼 VHS Glitch", self.vhs_glitch, "80s video"), ("📺 CRT Monitor", self.crt_effect, "Old screen"), ("🎞️ 70s Film", self.seventies_film, "Retro warm"), ("📟 Polaroid", self.polaroid, "Instant camera"), ("🌄 Faded Memory", self.faded_memory, "Old photo"), ]) # Section 5: MODERN & DIGITAL self.create_section(parent, "🚀 MODERN & DIGITAL", [ ("💻 Cyberpunk", self.cyberpunk, "Neon future"), ("🌐 Glitch Art", self.glitch_art, "Digital chaos"), ("🎮 Pixel Art", self.pixel_art, "8-bit style"), ("🌌 Vaporwave", self.vaporwave, "A E S T H E T I C"), ("⚡ Neon Lights", self.neon_lights, "Bright neon"), ]) # Section 6: PRO PRESETS self.create_section(parent, "🏆 PRO PRESETS", [ ("📱 Instagram Pro", self.instagram_pro, "Social ready"), ("🖼️ Gallery Print", self.gallery_print, "Museum quality"), ("💼 Professional", self.professional, "Business look"), ("🎪 Artistic Bold", self.artistic_bold, "Creative statement"), ("🕯️ Candlelight Sketch", self.candlelight_sketch, "Pencil + warm glow"), ]) # Section 7: IMAGE TOOLS self.create_section(parent, "🔧 IMAGE TOOLS", [ ("🔲 Expand Canvas", self.expand_canvas, "Extend image"), ("📐 Upscale 2x", self.upscale_image, "Make bigger"), ("🎨 Style Transfer", self.style_transfer, "Apply style"), ("🔄 Rotate 90°", self.rotate_90, "Quick rotate"), ("↔️ Flip Horizontal", self.flip_horizontal, "Mirror"), ("↕️ Flip Vertical", self.flip_vertical, "Flip"), ]) def create_section(self, parent, title, effects): section = tk.LabelFrame( parent, text=title, font=("Arial", 14, "bold"), bg='#0a0a0a', fg='#ff6600', relief=tk.GROOVE, bd=2 ) section.pack(pady=15, padx=20, fill=tk.X) grid_frame = tk.Frame(section, bg='#0a0a0a') grid_frame.pack(pady=10, padx=10) row, col = 0, 0 for name, cmd, desc in effects: btn_frame = tk.Frame(grid_frame, bg='#1a1a1a', relief=tk.RAISED, bd=1) btn_frame.grid(row=row, column=col, padx=5, pady=5, sticky='ew') btn = tk.Button( btn_frame, text=name, command=cmd, font=("Arial", 10, "bold"), bg='#1a1a1a', fg='#ff6600', padx=12, pady=8, cursor='hand2', relief=tk.FLAT ) btn.pack(fill=tk.X) desc_label = tk.Label( btn_frame, text=desc, font=("Arial", 8), bg='#1a1a1a', fg='#666' ) desc_label.pack() col += 1 if col > 3: # 4 columns col = 0 row += 1 def upload_image(self): file_path = filedialog.askopenfilename( title="Select Image", filetypes=[("Images", "*.png *.jpg *.jpeg *.webp *.bmp"), ("All", "*.*")] ) if file_path: try: self.image_path = file_path self.original_image = Image.open(file_path).convert('RGB') self.current_image = self.original_image.copy() self.history = [self.current_image.copy()] self.display_image(self.current_image) except Exception as e: messagebox.showerror("Error", f"Failed to load: {e}") def display_image(self, image): display_img = image.copy() display_img.thumbnail((600, 400), Image.Resampling.LANCZOS) photo = ImageTk.PhotoImage(display_img) self.image_label.configure(image=photo, text="") self.image_label.image = photo def save_to_history(self): if self.current_image: self.history.append(self.current_image.copy()) if len(self.history) > 20: # Keep last 20 self.history.pop(0) def check_image(self): if not self.current_image: messagebox.showwarning("No Image", "Upload an image first!") return False return True def apply_effect(self, effect_func): if not self.check_image(): return self.save_to_history() try: self.current_image = effect_func(self.current_image) self.display_image(self.current_image) except Exception as e: messagebox.showerror("Effect Error", str(e)) # === ESSENTIAL ENHANCEMENTS === def auto_enhance(self): if not self.check_image(): return self.save_to_history() img = self.current_image img = ImageEnhance.Contrast(img).enhance(1.2) img = ImageEnhance.Sharpness(img).enhance(1.3) img = ImageEnhance.Color(img).enhance(1.1) self.current_image = img self.display_image(img) def super_sharpen(self): self.apply_effect(lambda img: img.filter(ImageFilter.UnsharpMask(radius=2, percent=150, threshold=3))) def color_pop(self): self.apply_effect(lambda img: ImageEnhance.Color(img).enhance(1.8)) def hdr_effect(self): if not self.check_image(): return self.save_to_history() img = self.current_image img = ImageEnhance.Contrast(img).enhance(1.5) img = ImageEnhance.Brightness(img).enhance(0.95) img = ImageEnhance.Color(img).enhance(1.3) self.current_image = img self.display_image(img) # === ARTISTIC STYLES === def oil_painting(self): self.apply_effect(lambda img: img.filter(ImageFilter.SMOOTH_MORE).filter(ImageFilter.EDGE_ENHANCE)) def film_noir(self): if not self.check_image(): return self.save_to_history() img = self.current_image.convert('L').convert('RGB') img = ImageEnhance.Contrast(img).enhance(1.6) self.current_image = img self.display_image(img) def golden_hour(self): if not self.check_image(): return self.save_to_history() img = self.current_image r, g, b = img.split() r = r.point(lambda i: min(255, int(i * 1.15))) g = g.point(lambda i: min(255, int(i * 1.08))) b = b.point(lambda i: int(i * 0.88)) img = Image.merge('RGB', (r, g, b)) img = ImageEnhance.Brightness(img).enhance(1.05) self.current_image = img self.display_image(img) def ice_cold(self): if not self.check_image(): return self.save_to_history() img = self.current_image r, g, b = img.split() r = r.point(lambda i: int(i * 0.85)) g = g.point(lambda i: int(i * 0.92)) b = b.point(lambda i: min(255, int(i * 1.15))) self.current_image = Image.merge('RGB', (r, g, b)) self.display_image(self.current_image) def infrared(self): if not self.check_image(): return self.save_to_history() img = self.current_image.convert('L') img = ImageOps.invert(img) img = ImageEnhance.Contrast(img).enhance(1.3) r = img g = img b = img.point(lambda i: int(i * 0.7)) self.current_image = Image.merge('RGB', (r, g, b)) self.display_image(self.current_image) def high_key_bw(self): if not self.check_image(): return self.save_to_history() img = self.current_image.convert('L').convert('RGB') img = ImageEnhance.Brightness(img).enhance(1.2) img = ImageEnhance.Contrast(img).enhance(0.8) self.current_image = img self.display_image(img) # === DRAMATIC EFFECTS === def dark_fantasy(self): if not self.check_image(): return self.save_to_history() img = self.current_image img = ImageEnhance.Brightness(img).enhance(0.6) img = ImageEnhance.Contrast(img).enhance(1.6) img = ImageEnhance.Color(img).enhance(0.8) self.current_image = img self.display_image(img) def sunburst(self): self.apply_effect(lambda img: ImageEnhance.Brightness(img).enhance(1.4)) def vignette_drama(self): if not self.check_image(): return self.save_to_history() img = self.current_image width, height = img.size mask = Image.new('L', (width, height), 0) draw = ImageDraw.Draw(mask) for i in range(min(width, height) // 4): alpha = int(255 * (i / (min(width, height) // 4))) draw.ellipse( [i, i, width-i, height-i], fill=alpha ) dark = Image.new('RGB', img.size, (0, 0, 0)) self.current_image = Image.composite(img, dark, mask) self.display_image(self.current_image) def glow_effect(self): if not self.check_image(): return self.save_to_history() img = self.current_image glow = img.filter(ImageFilter.GaussianBlur(15)) glow = ImageEnhance.Brightness(glow).enhance(1.5) self.current_image = Image.blend(img, glow, 0.3) self.display_image(self.current_image) def cross_process(self): if not self.check_image(): return self.save_to_history() img = self.current_image r, g, b = img.split() r = r.point(lambda i: min(255, int(i * 1.1))) g = g.point(lambda i: int(i * 0.95)) b = b.point(lambda i: min(255, int(i * 1.15))) img = Image.merge('RGB', (r, g, b)) img = ImageEnhance.Contrast(img).enhance(1.3) self.current_image = img self.display_image(img) # === VINTAGE & RETRO === def vhs_glitch(self): if not self.check_image(): return self.save_to_history() img = self.current_image img = ImageEnhance.Contrast(img).enhance(1.2) img = ImageEnhance.Color(img).enhance(0.8) self.current_image = img self.display_image(img) def crt_effect(self): self.apply_effect(lambda img: ImageEnhance.Brightness(img).enhance(1.1)) def seventies_film(self): if not self.check_image(): return self.save_to_history() img = self.current_image r, g, b = img.split() r = r.point(lambda i: min(255, int(i * 1.12))) g = g.point(lambda i: min(255, int(i * 1.05))) b = b.point(lambda i: int(i * 0.9)) img = Image.merge('RGB', (r, g, b)) img = ImageEnhance.Contrast(img).enhance(0.9) self.current_image = img self.display_image(img) def polaroid(self): if not self.check_image(): return self.save_to_history() img = self.current_image img = ImageEnhance.Brightness(img).enhance(1.1) img = ImageEnhance.Color(img).enhance(0.85) img = ImageEnhance.Contrast(img).enhance(0.95) self.current_image = img self.display_image(img) def faded_memory(self): if not self.check_image(): return self.save_to_history() img = self.current_image img = ImageEnhance.Color(img).enhance(0.6) img = ImageEnhance.Brightness(img).enhance(1.15) img = ImageEnhance.Contrast(img).enhance(0.8) self.current_image = img self.display_image(img) # === MODERN & DIGITAL === def cyberpunk(self): if not self.check_image(): return self.save_to_history() img = self.current_image r, g, b = img.split() r = r.point(lambda i: min(255, int(i * 1.2))) g = g.point(lambda i: int(i * 0.9)) b = b.point(lambda i: min(255, int(i * 1.3))) img = Image.merge('RGB', (r, g, b)) img = ImageEnhance.Contrast(img).enhance(1.4) self.current_image = img self.display_image(img) def glitch_art(self): self.apply_effect(lambda img: img.filter(ImageFilter.EDGE_ENHANCE_MORE)) def pixel_art(self): if not self.check_image(): return self.save_to_history() img = self.current_image small = img.resize((img.width // 16, img.height // 16), Image.Resampling.NEAREST) self.current_image = small.resize(img.size, Image.Resampling.NEAREST) self.display_image(self.current_image) def vaporwave(self): if not self.check_image(): return self.save_to_history() img = self.current_image r, g, b = img.split() r = r.point(lambda i: min(255, int(i * 1.2))) g = g.point(lambda i: min(255, int(i * 0.95))) b = b.point(lambda i: min(255, int(i * 1.25))) img = Image.merge('RGB', (r, g, b)) img = ImageEnhance.Color(img).enhance(1.5) self.current_image = img self.display_image(img) def neon_lights(self): if not self.check_image(): return self.save_to_history() img = self.current_image img = ImageEnhance.Color(img).enhance(2.0) img = ImageEnhance.Contrast(img).enhance(1.3) img = ImageEnhance.Brightness(img).enhance(1.2) self.current_image = img self.display_image(img) # === PRO PRESETS === def instagram_pro(self): if not self.check_image(): return self.save_to_history() img = self.current_image img = ImageEnhance.Contrast(img).enhance(1.15) img = ImageEnhance.Color(img).enhance(1.2) img = ImageEnhance.Sharpness(img).enhance(1.1) self.current_image = img self.display_image(img) def gallery_print(self): if not self.check_image(): return self.save_to_history() img = self.current_image img = ImageEnhance.Contrast(img).enhance(1.1) img = ImageEnhance.Sharpness(img).enhance(1.3) img = ImageEnhance.Color(img).enhance(1.05) self.current_image = img self.display_image(img) def professional(self): self.apply_effect(lambda img: ImageEnhance.Contrast(img).enhance(1.1)) def artistic_bold(self): if not self.check_image(): return self.save_to_history() img = self.current_image img = ImageEnhance.Color(img).enhance(1.6) img = ImageEnhance.Contrast(img).enhance(1.4) self.current_image = img self.display_image(img) def candlelight_sketch(self): """Pencil sketch with warm candlelight - mimics the style Dave showed""" if not self.check_image(): return self.save_to_history() img = self.current_image # Step 1: Reduce color saturation (pencil sketch base) img = ImageEnhance.Color(img).enhance(0.3) # Step 2: Add warm candlelight glow (orange/golden tones) r, g, b = img.split() # Boost reds/oranges (candlelight) r = r.point(lambda i: min(255, int(i * 1.3))) g = g.point(lambda i: min(255, int(i * 1.15))) b = b.point(lambda i: int(i * 0.75)) # Reduce blue for warmth img = Image.merge('RGB', (r, g, b)) # Step 3: High contrast (dramatic lighting) img = ImageEnhance.Contrast(img).enhance(1.8) # Step 4: Darken overall (dark shadows) img = ImageEnhance.Brightness(img).enhance(0.7) # Step 5: Add slight blur to mimic soft pencil texture img = img.filter(ImageFilter.GaussianBlur(radius=0.5)) # Step 6: Edge enhance for sketch lines img = img.filter(ImageFilter.EDGE_ENHANCE) self.current_image = img self.display_image(img) # === ACTIONS === def undo_last(self): if len(self.history) > 1: self.history.pop() self.current_image = self.history[-1].copy() self.display_image(self.current_image) else: messagebox.showinfo("Undo", "No more undo history!") def reset_image(self): if self.original_image: self.current_image = self.original_image.copy() self.history = [self.current_image.copy()] self.display_image(self.current_image) def save_image(self): if not self.check_image(): return file_path = filedialog.asksaveasfilename( defaultextension=".png", filetypes=[("PNG", "*.png"), ("JPEG", "*.jpg"), ("WebP", "*.webp")] ) if file_path: try: self.current_image.save(file_path, quality=95) messagebox.showinfo("Saved!", f"Saved to:\n{file_path}") except Exception as e: messagebox.showerror("Error", f"Save failed: {e}") def batch_save(self): if not self.check_image(): return folder = filedialog.askdirectory(title="Select Output Folder") if folder: try: timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"dr_magic_{timestamp}.png" path = os.path.join(folder, filename) self.current_image.save(path, quality=95) messagebox.showinfo("Batch Saved!", f"Saved to:\n{path}") except Exception as e: messagebox.showerror("Error", str(e)) # === IMAGE TOOLS === def expand_canvas(self): if not self.check_image(): return self.save_to_history() # Ask for expansion amount expansion = 100 # pixels on each side img = self.current_image width, height = img.size new_width = width + (expansion * 2) new_height = height + (expansion * 2) # Create new canvas expanded = Image.new('RGB', (new_width, new_height), (20, 20, 20)) # Paste original in center expanded.paste(img, (expansion, expansion)) self.current_image = expanded self.display_image(self.current_image) messagebox.showinfo("Expanded!", f"Canvas expanded by {expansion}px on each side") def upscale_image(self): if not self.check_image(): return self.save_to_history() img = self.current_image new_size = (img.width * 2, img.height * 2) # Use LANCZOS for quality upscaling upscaled = img.resize(new_size, Image.Resampling.LANCZOS) self.current_image = upscaled self.display_image(self.current_image) messagebox.showinfo("Upscaled!", f"Image doubled to {new_size[0]}x{new_size[1]}") def style_transfer(self): if not self.check_image(): return style_path = filedialog.askopenfilename( title="Select Style Reference Image", filetypes=[("Images", "*.png *.jpg *.jpeg"), ("All", "*.*")] ) if not style_path: return self.save_to_history() try: style_img = Image.open(style_path).convert('RGB') # Simple style transfer using color statistics content = self.current_image # Get color statistics from style image style_array = np.array(style_img) content_array = np.array(content) # Match mean and std of each channel for i in range(3): # RGB channels content_mean = content_array[:,:,i].mean() content_std = content_array[:,:,i].std() style_mean = style_array[:,:,i].mean() style_std = style_array[:,:,i].std() # Transfer statistics content_array[:,:,i] = (content_array[:,:,i] - content_mean) / (content_std + 1e-5) content_array[:,:,i] = content_array[:,:,i] * style_std + style_mean # Clip to valid range content_array = np.clip(content_array, 0, 255).astype(np.uint8) self.current_image = Image.fromarray(content_array) self.display_image(self.current_image) messagebox.showinfo("Style Applied!", "Style transfer complete!") except Exception as e: messagebox.showerror("Error", f"Style transfer failed: {e}") def rotate_90(self): if not self.check_image(): return self.save_to_history() self.current_image = self.current_image.rotate(-90, expand=True) self.display_image(self.current_image) def flip_horizontal(self): if not self.check_image(): return self.save_to_history() self.current_image = self.current_image.transpose(Image.FLIP_LEFT_RIGHT) self.display_image(self.current_image) def flip_vertical(self): if not self.check_image(): return self.save_to_history() self.current_image = self.current_image.transpose(Image.FLIP_TOP_BOTTOM) self.display_image(self.current_image) if __name__ == "__main__": root = tk.Tk() app = DrImageMagicFull(root) root.mainloop()