import tkinter as tk
from tkinter import filedialog, colorchooser
from PIL import Image, ImageTk
class PixelEditor:
def __init__(self, root):
self.root = root
self.scale = 20
self.image = Image.new("RGBA", (16, 16), (0,0,0,0))
self.history = []
self.future = []
self.color = (0,0,0,255)
self.tool = "pen"
self.dark = True
self.canvas = tk.Canvas(root, width=320, height=320, highlightthickness=0)
self.canvas.pack()
self.canvas.bind("<B1-Motion>", self.paint)
self.canvas.bind("<Button-1>", self.paint)
self.canvas.bind("<Button-3>", self.pick_from_canvas)
self.setup_ui()
self.apply_theme()
self.draw()
def setup_ui(self):
self.frame = tk.Frame(self.root)
self.frame.pack(fill="x")
tk.Button(self.frame, text="Load", command=self.load).pack(side="left")
tk.Button(self.frame, text="Save", command=self.save).pack(side="left")
tk.Button(self.frame, text="Color", command=self.pick_color).pack(side="left")
tk.Button(self.frame, text="Pen", command=lambda: self.set_tool("pen")).pack(side="left")
tk.Button(self.frame, text="Eraser", command=lambda: self.set_tool("eraser")).pack(side="left")
tk.Button(self.frame, text="Undo", command=self.undo).pack(side="left")
tk.Button(self.frame, text="Redo", command=self.redo).pack(side="left")
tk.Button(self.frame, text="Theme", command=self.toggle_theme).pack(side="left")
def apply_theme(self):
bg = "#1e1e1e" if self.dark else "#eeeeee"
fg = "#ffffff" if self.dark else "#000000"
self.root.configure(bg=bg)
self.frame.configure(bg=bg)
for w in self.frame.winfo_children():
w.configure(bg=bg, fg=fg, activebackground=bg, activeforeground=fg)
self.canvas.configure(bg="#2b2b2b" if self.dark else "#ffffff")
def toggle_theme(self):
self.dark = not self.dark
self.apply_theme()
def set_tool(self, tool):
self.tool = tool
def pick_color(self):
c = colorchooser.askcolor()[0]
if c:
self.color = (int(c[0]), int(c[1]), int(c[2]), 255)
def pick_from_canvas(self, event):
x = event.x // self.scale
y = event.y // self.scale
if 0 <= x < self.image.width and 0 <= y < self.image.height:
self.color = self.image.getpixel((x, y))
def paint(self, event):
x = event.x // self.scale
y = event.y // self.scale
if 0 <= x < self.image.width and 0 <= y < self.image.height:
self.history.append(self.image.copy())
self.future.clear()
if self.tool == "pen":
self.image.putpixel((x, y), self.color)
else:
self.image.putpixel((x, y), (0,0,0,0))
self.draw()
def draw(self):
preview = self.image.resize(
(self.image.width*self.scale, self.image.height*self.scale),
Image.NEAREST
)
self.tk_img = ImageTk.PhotoImage(preview)
self.canvas.delete("all")
self.canvas.create_image(0,0,anchor="nw",image=self.tk_img)
def load(self):
path = filedialog.askopenfilename(filetypes=[("PNG","*.png")])
if path:
self.image = Image.open(path).convert("RGBA")
self.draw()
def save(self):
path = filedialog.asksaveasfilename(defaultextension=".png")
if path:
self.image.save(path, "PNG")
def undo(self):
if self.history:
self.future.append(self.image.copy())
self.image = self.history.pop()
self.draw()
def redo(self):
if self.future:
self.history.append(self.image.copy())
self.image = self.future.pop()
self.draw()
root = tk.Tk()
root.title("Pixel Editor")
PixelEditor(root)
root.mainloop()
