Luminous Weaver Python GUI
👤 Sharing: AI
import tkinter as tk
from tkinter import ttk, colorchooser, filedialog
from PIL import Image, ImageDraw, ImageTk
import random
class ImageEditor:
def __init__(self, master):
self.master = master
master.title("Luminous Weaver: Creative Image Editor")
self.image = None
self.image_tk = None
self.draw = None
self.filename = None
# --- UI Elements ---
self.canvas_width = 600
self.canvas_height = 400
self.canvas = tk.Canvas(master, width=self.canvas_width, height=self.canvas_height, bg='white')
self.canvas.pack(pady=10)
self.toolbar = ttk.Frame(master)
self.toolbar.pack(pady=5)
# Open Button
self.open_button = ttk.Button(self.toolbar, text="Open Image", command=self.open_image)
self.open_button.grid(row=0, column=0, padx=5)
# Save Button
self.save_button = ttk.Button(self.toolbar, text="Save Image", command=self.save_image, state=tk.DISABLED)
self.save_button.grid(row=0, column=1, padx=5)
# Color Picker
self.color_button = ttk.Button(self.toolbar, text="Choose Color", command=self.choose_color)
self.color_button.grid(row=0, column=2, padx=5)
self.current_color = 'black'
# Brush Size
self.brush_size_label = ttk.Label(self.toolbar, text="Brush Size:")
self.brush_size_label.grid(row=0, column=3, padx=5)
self.brush_size = tk.IntVar(value=5)
self.brush_size_scale = tk.Scale(self.toolbar, from_=1, to=20, orient=tk.HORIZONTAL, variable=self.brush_size, command=self.update_brush_size, width=10, length=100)
self.brush_size_scale.grid(row=0, column=4, padx=5)
# Draw Button
self.draw_button = ttk.Button(self.toolbar, text="Draw", command=self.activate_draw)
self.draw_button.grid(row=0, column=5, padx=5)
self.drawing = False
self.last_x = None
self.last_y = None
# Clear Button
self.clear_button = ttk.Button(self.toolbar, text="Clear", command=self.clear_canvas)
self.clear_button.grid(row=0, column=6, padx=5)
# Effects Menu
self.effects_menu_button = ttk.Menubutton(self.toolbar, text="Effects")
self.effects_menu_button.grid(row=0, column=7, padx=5)
self.effects_menu = tk.Menu(self.effects_menu_button, tearoff=0)
self.effects_menu_button["menu"] = self.effects_menu
self.effects_menu.add_command(label="Grayscale", command=self.apply_grayscale)
self.effects_menu.add_command(label="Blur", command=self.apply_blur)
self.effects_menu.add_command(label="Invert Colors", command=self.apply_invert)
self.effects_menu.add_command(label="Pixelate", command=self.apply_pixelate)
# Details Button
self.details_button = ttk.Button(master, text="Details", command=self.show_details)
self.details_button.pack(pady=5)
# --- Event Binding ---
self.canvas.bind("<B1-Motion>", self.paint)
self.canvas.bind("<ButtonRelease-1>", self.reset)
def open_image(self):
self.filename = filedialog.askopenfilename(initialdir=".", title="Select an Image", filetypes=(("Image Files", "*.png;*.jpg;*.jpeg;*.bmp"), ("all files", "*.*")))
if self.filename:
self.image = Image.open(self.filename)
self.image_tk = ImageTk.PhotoImage(self.image)
self.canvas_width = self.image.width
self.canvas_height = self.image.height
self.canvas.config(width=self.canvas_width, height=self.canvas_height)
self.canvas.create_image(0, 0, anchor=tk.NW, image=self.image_tk)
self.draw = ImageDraw.Draw(self.image)
self.save_button['state'] = tk.NORMAL
def save_image(self):
if self.filename:
file_extension = self.filename.split(".")[-1].lower()
if file_extension in ["jpg", "jpeg"]
save_file_extension = "jpeg"
else:
save_file_extension = "png"
save_filename = filedialog.asksaveasfilename(defaultextension=f".{save_file_extension}", filetypes=(("PNG files", "*.png"), ("JPEG files", "*.jpg"), ("All files", "*.*")))
if save_filename:
self.image.save(save_filename)
def choose_color(self):
color_code = colorchooser.askcolor(title="Choose a color")[1]
if color_code:
self.current_color = color_code
def update_brush_size(self, event=None):
pass # Brush size is already handled by the self.brush_size variable
def activate_draw(self):
self.drawing = True
def paint(self, event):
if self.drawing and self.image:
x, y = event.x, event.y
if self.last_x is not None and self.last_y is not None:
self.canvas.create_line((self.last_x, self.last_y, x, y), width=self.brush_size.get(), fill=self.current_color, capstyle=tk.ROUND, smooth=tk.TRUE)
self.draw.line((self.last_x, self.last_y, x, y), width=self.brush_size.get(), fill=self.current_color, joint='curve')
self.last_x = x
self.last_y = y
def reset(self, event):
self.last_x = None
self.last_y = None
def clear_canvas(self):
if self.image:
self.image = Image.new("RGB", (self.canvas_width, self.canvas_height), "white")
self.image_tk = ImageTk.PhotoImage(self.image)
self.canvas.create_image(0, 0, anchor=tk.NW, image=self.image_tk)
self.draw = ImageDraw.Draw(self.image)
self.save_button['state'] = tk.NORMAL
else:
self.canvas.delete("all") # Clear canvas even if no image is loaded
def apply_grayscale(self):
if self.image:
self.image = self.image.convert('L').convert('RGB') # Convert to grayscale then back to RGB to ensure compatibility with drawing
self.image_tk = ImageTk.PhotoImage(self.image)
self.canvas.create_image(0, 0, anchor=tk.NW, image=self.image_tk)
self.draw = ImageDraw.Draw(self.image)
def apply_blur(self):
if self.image:
from PIL import ImageFilter
self.image = self.image.filter(ImageFilter.BLUR)
self.image_tk = ImageTk.PhotoImage(self.image)
self.canvas.create_image(0, 0, anchor=tk.NW, image=self.image_tk)
self.draw = ImageDraw.Draw(self.image)
def apply_invert(self):
if self.image:
self.image = Image.eval(self.image, lambda x: 255 - x)
self.image_tk = ImageTk.PhotoImage(self.image)
self.canvas.create_image(0, 0, anchor=tk.NW, image=self.image_tk)
self.draw = ImageDraw.Draw(self.image)
def apply_pixelate(self):
if self.image:
# Reduce image size
small_size = (self.image.width // 10, self.image.height // 10)
img = self.image.resize(small_size, Image.NEAREST)
# Scale it back up
self.image = img.resize(self.image.size, Image.NEAREST)
self.image_tk = ImageTk.PhotoImage(self.image)
self.canvas.create_image(0, 0, anchor=tk.NW, image=self.image_tk)
self.draw = ImageDraw.Draw(self.image)
def show_details(self):
details_window = tk.Toplevel(self.master)
details_window.title("Program Details")
details_text = tk.Text(details_window, wrap=tk.WORD)
details_text.pack(padx=10, pady=10)
details_text.insert(tk.END, "Luminous Weaver is a versatile image editor designed for both beginners and experienced users. It allows you to open, edit, and save images in various formats. Key features include: drawing with customizable colors and brush sizes, applying various image effects (grayscale, blur, invert colors, pixelate), and a user-friendly interface. You can easily load an image, apply modifications using the provided tools, and save the result. The effects are designed to be quick and easy to apply, enhancing your workflow.")
details_text.config(state=tk.DISABLED)
root = tk.Tk()
editor = ImageEditor(root)
root.mainloop()
👁️ Viewed: 7
Comments