Created
April 17, 2023 22:48
-
-
Save markrmiller/80f1c2c8e759eb2c34ba6f2b35ed011e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import tkinter as tk | |
import os | |
import glob | |
from pathlib import Path | |
from tkinter import filedialog | |
from PIL import Image, ImageTk | |
class ImageManager: | |
def __init__(self): | |
self.image_sets = [] | |
self.edit_mode = False | |
def add_image_set(self, image_set): | |
self.image_sets.append(image_set) | |
def remove_image_set(self, index): | |
del self.image_sets[index] | |
def add_image_to_set(self, set_index, image_path): | |
self.image_sets[set_index].images.append(image_path) | |
def move_image_within_set(self, set_index, old_index, new_index): | |
self.image_sets[set_index].images.insert(new_index, self.image_sets[set_index].images.pop(old_index)) | |
def get_image_sets(self): | |
return self.image_sets | |
class ImageSet: | |
def __init__(self, images): | |
self.images = images | |
self.current_image_index = 0 | |
class ImageManagerApp: | |
def __init__(self, image_manager): | |
self.image_manager = image_manager | |
self.root = tk.Tk() | |
self.root.title("Image Manager") | |
self.root.geometry("800x600") | |
self.images = [] | |
# create a sample image set with a sample image | |
# image_set = ImageSet("Sample Set") | |
# image_set.images.append("sample.jpg") | |
# self.image_manager.add_image_set(image_set) | |
# self.update_image_set_listbox() | |
self.edit_mode_button = tk.Button(self.root, text="Edit Mode", command=self.toggle_edit_mode) | |
self.edit_mode_button.pack() | |
self.image_set_listbox = tk.Listbox(self.root) | |
self.image_set_listbox.pack(side=tk.LEFT, fill=tk.Y) | |
self.image_set_scrollbar = tk.Scrollbar(self.root) | |
self.image_set_scrollbar.pack(side=tk.LEFT, fill=tk.Y) | |
self.image_set_listbox.config(yscrollcommand=self.image_set_scrollbar.set) | |
self.image_set_scrollbar.config(command=self.image_set_listbox.yview) | |
self.image_set_listbox.bind("<<ListboxSelect>>", self.update_image_listbox) | |
self.image_listbox = tk.Listbox(self.root) | |
self.image_listbox.pack(side=tk.LEFT, fill=tk.Y) | |
self.image_scrollbar = tk.Scrollbar(self.root) | |
self.image_scrollbar.pack(side=tk.LEFT, fill=tk.Y) | |
self.image_listbox.config(yscrollcommand=self.image_scrollbar.set) | |
self.image_scrollbar.config(command=self.image_listbox.yview) | |
self.image_listbox.bind("<<ListboxSelect>>", self.update_current_image) | |
self.image_canvas = tk.Canvas(self.root) | |
self.image_canvas.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True) | |
self.image_canvas.bind("<Configure>", self.update_image_grid) | |
self.next_button = tk.Button(self.root, text="Next Image", command=self.show_next_image) | |
self.next_button.pack(side=tk.BOTTOM) | |
self.prev_button = tk.Button(self.root, text="Previous Image", command=self.show_prev_image) | |
self.prev_button.pack(side=tk.BOTTOM) | |
self.add_imageset_button = tk.Button(self.root, text="Add ImageSet", command=self.add_image_set) | |
self.add_imageset_button.pack(side=tk.BOTTOM) | |
self.add_image_button = tk.Button(self.root, text="Add Image", command=self.add_image_to_set) | |
self.add_image_button.pack(side=tk.BOTTOM) | |
self.remove_image_button = tk.Button(self.root, text="Remove Image", command=self.remove_image_from_set) | |
self.remove_image_button.pack(side=tk.BOTTOM) | |
self.remove_imageset_button = tk.Button(self.root, text="Remove ImageSet", command=self.remove_image_set) | |
self.remove_imageset_button.pack(side=tk.BOTTOM) | |
self.image_listbox.pack_forget() | |
self.root.bind("<space>", self.show_next_image) | |
self.update_image_set_listbox() | |
image_set = ImageSet([]) | |
image_manager.add_image_set(image_set) | |
self.root.bind("<Configure>", self.update_image_grid) | |
def on_image_set_listbox_select(self, event): | |
if self.image_manager.edit_mode: | |
self.update_image_set_listbox() | |
def remove_image_set(self): | |
set_index = self.image_set_listbox.curselection()[0] | |
self.image_manager.remove_image_set(set_index) | |
self.update_image_set_listbox() | |
def remove_image_from_set(self): | |
if not self.image_manager.edit_mode: | |
return | |
if not self.image_set_listbox.curselection() or not self.image_listbox.curselection(): | |
return | |
set_index = self.image_set_listbox.curselection()[0] | |
image_index = self.image_listbox.curselection()[0] | |
self.image_manager.remove_image_from_set(set_index, image_index) | |
self.update_image_listbox() | |
def add_image_set(self): | |
self.image_manager.add_image_set(ImageSet([])) | |
self.update_image_set_listbox() | |
def toggle_edit_mode(self): | |
self.image_manager.edit_mode = not self.image_manager.edit_mode | |
if self.image_manager.edit_mode: | |
self.edit_mode_button.config(text="View Mode") | |
self.remove_imageset_button.config(state=tk.NORMAL) | |
self.remove_image_button.config(state=tk.NORMAL) | |
self.image_listbox.pack(side=tk.LEFT, fill=tk.Y) | |
else: | |
self.edit_mode_button.config(text="Edit Mode") | |
self.remove_imageset_button.config(state=tk.DISABLED) | |
self.remove_image_button.config(state=tk.DISABLED) | |
self.image_listbox.pack_forget() | |
self.update_image_set_listbox() | |
self.update_image_listbox() | |
def add_image_to_set(self): | |
if not self.image_manager.edit_mode: | |
return | |
if not self.image_set_listbox.curselection(): | |
return | |
set_index = self.image_set_listbox.curselection()[0] | |
filetypes = (("JPEG files", "*.jpg"), ("PNG files", "*.png")) | |
filenames = filedialog.askopenfilenames(filetypes=filetypes) | |
for filename in filenames: | |
self.image_manager.add_image_to_set(set_index, filename) | |
self.update_image_set_listbox() | |
def update_image_listbox(self, event=None): | |
if not self.image_manager.edit_mode: | |
return | |
set_index = self.image_set_listbox.curselection()[0] if self.image_set_listbox.curselection() else 0 | |
image_set = self.image_manager.get_image_sets()[set_index] | |
self.image_listbox.delete(0, tk.END) | |
for j, image_path in enumerate(image_set.images): | |
self.image_listbox.insert(tk.END, f"{j + 1}. {image_path}") | |
if self.image_manager.edit_mode: | |
self.update_image_set_listbox() | |
def update_image_set_listbox(self): | |
self.image_set_listbox.delete(0, tk.END) | |
for i, image_set in enumerate(self.image_manager.get_image_sets()): | |
self.image_set_listbox.insert(tk.END, f"Image Set {i + 1}") | |
if self.image_manager.edit_mode: | |
set_index = self.image_set_listbox.curselection()[0] if self.image_set_listbox.curselection() else 0 | |
image_set = self.image_manager.get_image_sets()[set_index] | |
self.image_listbox.delete(0, tk.END) | |
for j, image_path in enumerate(image_set.images): | |
self.image_listbox.insert(tk.END, f"{j + 1}. {image_path}") | |
def update_current_image(self, event): | |
if self.image_manager.edit_mode: | |
return | |
selection = event.widget.curselection() | |
if len(selection) == 0: | |
return | |
if len(self.image_manager.get_image_sets()) == 0: | |
return | |
self.update_image_grid() | |
def update_image_grid(self, event=None): | |
if self.image_manager.edit_mode: | |
return | |
self.image_canvas.delete(tk.ALL) | |
image_sets = self.image_manager.get_image_sets() | |
num_image_sets = len(image_sets) | |
# Determine the number of columns and rows based on the current window size | |
window_width = self.image_canvas.winfo_width() | |
window_height = self.image_canvas.winfo_height() | |
cell_size = 200 # You can adjust this value to change the size of the grid cells | |
cols = window_width // cell_size | |
rows = (num_image_sets + cols - 1) // cols | |
if cols > 0: | |
max_width = window_width // cols | |
max_height = window_height // rows | |
for i, image_set in enumerate(image_sets): | |
if len(image_set.images) > 0: | |
row = i // cols | |
col = i % cols | |
img = Image.open(image_set.images[image_set.current_image_index]) | |
img_width, img_height = img.size | |
# Calculate new width and height while maintaining aspect ratio | |
aspect_ratio = float(img_width) / float(img_height) | |
if img_width > max_width or img_height > max_height: | |
if (max_width / img_width) < (max_height / img_height): | |
new_width = max_width | |
new_height = int(new_width / aspect_ratio) | |
else: | |
new_height = max_height | |
new_width = int(new_height * aspect_ratio) | |
else: | |
new_width = img_width | |
new_height = img_height | |
img = img.resize((new_width, new_height), Image.ANTIALIAS) | |
img = ImageTk.PhotoImage(img) | |
x_offset = (max_width - new_width) // 2 | |
y_offset = (max_height - new_height) // 2 | |
self.image_canvas.create_image(col * max_width + x_offset, row * max_height + y_offset, | |
anchor=tk.NW, image=img) | |
self.images.append(img) # Store the image in the list | |
def show_current_image(self): | |
image_path = self.image_manager.get_current_image() | |
img = Image.open(image_path) | |
img = img.resize((self.image_canvas.winfo_width(), self.image_canvas.winfo_height()), Image.ANTIALIAS) | |
img = ImageTk.PhotoImage(img) | |
self.image_canvas.create_image(0, 0, anchor=tk.NW, image=img) | |
self.image_canvas.image = img | |
def show_next_image(self, event=None): | |
for image_set in self.image_manager.get_image_sets(): | |
image_set.current_image_index = (image_set.current_image_index + 1) % len(image_set.images) if len( | |
image_set.images) > 0 else 0 | |
self.update_image_grid() | |
def show_prev_image(self): | |
for image_set in self.image_manager.get_image_sets(): | |
image_set.current_image_index = (image_set.current_image_index - 1) % len(image_set.images) if len( | |
image_set.images) > 0 else 0 | |
self.update_image_grid() | |
def load_image_sets(): | |
image_manager = ImageManager() | |
for image_set_path in glob.glob("image_sets/*.txt"): | |
with open(image_set_path) as f: | |
image_paths = f.read().splitlines() | |
image_set = ImageSet(image_paths) | |
image_manager.add_image_set(image_set) | |
return image_manager | |
def save_image_sets(image_manager): | |
Path("image_sets").mkdir(parents=True, exist_ok=True) | |
for i, image_set in enumerate(image_manager.get_image_sets()): | |
with open(f"image_sets/image_set_{i + 1}.txt", "w") as f: | |
f.write("\n".join(image_set.images)) | |
def main(): | |
image_manager = load_image_sets() | |
app = ImageManagerApp(image_manager) | |
app.root.mainloop() | |
save_image_sets(image_manager) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment