diff --git a/images/goal/MC_queen.png b/images/goal/MC_queen.png new file mode 100644 index 0000000..042b832 Binary files /dev/null and b/images/goal/MC_queen.png differ diff --git a/images/goal/horse_sit.png b/images/goal/horse_sit.png new file mode 100644 index 0000000..c2b311c Binary files /dev/null and b/images/goal/horse_sit.png differ diff --git a/images/source/horse_ballin.png b/images/source/horse_ballin.png new file mode 100644 index 0000000..404f6ea Binary files /dev/null and b/images/source/horse_ballin.png differ diff --git a/images/source/milk_shake.png b/images/source/milk_shake.png new file mode 100644 index 0000000..93027f0 Binary files /dev/null and b/images/source/milk_shake.png differ diff --git a/images/source/teach.png b/images/source/teach.png new file mode 100644 index 0000000..1971efb Binary files /dev/null and b/images/source/teach.png differ diff --git a/images/source/water_slide.png b/images/source/water_slide.png new file mode 100644 index 0000000..b6061bb Binary files /dev/null and b/images/source/water_slide.png differ diff --git a/python/__pycache__/image_preparing.cpython-313.pyc b/python/__pycache__/image_preparing.cpython-313.pyc new file mode 100644 index 0000000..82550fe Binary files /dev/null and b/python/__pycache__/image_preparing.cpython-313.pyc differ diff --git a/python/__pycache__/interface.cpython-313.pyc b/python/__pycache__/interface.cpython-313.pyc new file mode 100644 index 0000000..3af6629 Binary files /dev/null and b/python/__pycache__/interface.cpython-313.pyc differ diff --git a/python/__pycache__/main.cpython-313.pyc b/python/__pycache__/main.cpython-313.pyc new file mode 100644 index 0000000..f6b90e4 Binary files /dev/null and b/python/__pycache__/main.cpython-313.pyc differ diff --git a/python/image_preparing.py b/python/image_preparing.py new file mode 100644 index 0000000..db0a4b4 --- /dev/null +++ b/python/image_preparing.py @@ -0,0 +1,31 @@ +from pathlib import Path + +from PIL import Image +import matplotlib.pylab as plt + + +def fix_image_resolution(image_path): + figure, axis = plt.subplots(figsize=(8, 6), dpi=100) + figure.patch.set_facecolor("#111111") + axis.set_facecolor("#1a1a1a") + axis.axis("off") + axis.set_title("Source Image", color="#f2f2f2") + + def close_on_key(event): + if event.key in ("escape", "q"): + plt.close(figure) + + figure.canvas.mpl_connect("key_press_event", close_on_key) + + if image_path is None: + axis.text(0.5, 0.5, "No source image selected", ha="center", va="center", color="#f2f2f2") + plt.show() + return + + image = Image.open(image_path).resize((800, 600)) + axis.imshow(image) + if isinstance(image_path, Path): + axis.set_title(f"Source Image - {image_path.name}", color="#f2f2f2") + else: + axis.set_title(f"Source Image - {Path(image_path).name}", color="#f2f2f2") + plt.show() diff --git a/python/interface.py b/python/interface.py new file mode 100644 index 0000000..44d7d2b --- /dev/null +++ b/python/interface.py @@ -0,0 +1,180 @@ +from pathlib import Path +from glob import glob + +from PIL import Image +import matplotlib.pylab as plt +from matplotlib.widgets import Button + +from image_preparing import fix_image_resolution + + +class ImageInterface: + def __init__(self, base_dir=None): + self.base_dir = Path(base_dir or Path(__file__).resolve().parent.parent) + self.image_sets = { + "source": self._load_images(str(self.base_dir / "images" / "source" / "*.png")), + "goal": self._load_images(str(self.base_dir / "images" / "goal" / "*.png")), + "shenanigans": self._load_images(str(self.base_dir / "images" / "shenanigans" / "*.png")), + } + self.current_category = None + self.current_index = 0 + self.selected_indices = {"source": None, "goal": None} + self.figure = None + self.image_axis = None + self.list_axis = None + self.buttons = [] + self.key_connection_id = None + self.colors = { + "figure": "#111111", + "panel": "#1a1a1a", + "text": "#f2f2f2", + "button": "#2b2b2b", + "button_hover": "#3a3a3a", + } + def _load_images(self, pattern): + return sorted(glob(pattern)) + def _ensure_figure(self): + if self.figure is None: + self.figure = plt.figure(figsize=(10, 6)) + self.key_connection_id = self.figure.canvas.mpl_connect("key_press_event", self._on_key_press) + def _clear_layout(self): + self._ensure_figure() + self.figure.clf() + self.image_axis = None + self.list_axis = None + self.buttons = [] + def _make_button(self, rect, label, callback): + button_axis = self.figure.add_axes(rect) + button_axis.set_facecolor(self.colors["button"]) + button_axis.tick_params(left=False, labelleft=False, bottom=False, labelbottom=False) + button = Button(button_axis, label, color=self.colors["button"], hovercolor=self.colors["button_hover"]) + button.label.set_color(self.colors["text"]) + button.on_clicked(callback) + self.buttons.append(button) + return button + def _open_image(self, image_paths, index): + if not image_paths: + return None + safe_index = max(0, min(index, len(image_paths) - 1)) + return Image.open(image_paths[safe_index]) + def _draw_image_panel(self, axis, image, title): + axis.clear() + axis.set_title(title) + axis.set_facecolor(self.colors["panel"]) + axis.axis("off") + axis.title.set_color(self.colors["text"]) + if image is not None: + axis.imshow(image) + else: + axis.text(0.5, 0.5, "No images found", ha="center", va="center", color=self.colors["text"]) + def _draw_list_panel(self, axis, image_paths, current_index): + axis.clear() + axis.set_facecolor(self.colors["panel"]) + axis.axis("off") + axis.set_title("Images") + axis.title.set_color(self.colors["text"]) + if not image_paths: + axis.text(0.5, 0.5, "No images found", ha="center", va="center", color=self.colors["text"]) + return + lines = [] + for index, image_path in enumerate(image_paths): + name = Path(image_path).name + prefix = "> " if index == current_index else " " + lines.append(f"{prefix}{name}") + axis.text(0.02, 0.98, "\n".join(lines), ha="left", va="top", family="monospace", color=self.colors["text"]) + axis.title.set_color(self.colors["text"]) + def _show_menu(self): + self.current_category = None + self._clear_layout() + self.figure.patch.set_facecolor(self.colors["figure"]) + self._menu_row(0.66, "Source Images", "source", lambda event: self._open_category("source")) + self._menu_row(0.50, "Goal Images", "goal", lambda event: self._open_category("goal")) + self._make_button([0.08, 0.34, 0.32, 0.12], "Shenanigans Image", lambda event: self._open_shenanigans()) + self.figure.canvas.draw_idle() + def _open_category(self, category): + self.current_category = category + self.current_index = 0 + self._show_browser() + def _open_shenanigans(self): + image_paths = self.image_sets.get("source", []) + selected_index = self.selected_indices.get("source") + if selected_index is None: + selected_index = self.current_index if self.current_category == "source" else 0 + selected_path = None + if image_paths: + safe_index = max(0, min(selected_index, len(image_paths) - 1)) + selected_path = image_paths[safe_index] + fix_image_resolution(selected_path) + def _selected_image_name(self, category): + selected_index = self.selected_indices.get(category) + image_paths = self.image_sets.get(category, []) + if selected_index is None or not image_paths: + return None + safe_index = max(0, min(selected_index, len(image_paths) - 1)) + return Path(image_paths[safe_index]).name + def _menu_label(self, base_label, category=None): + if category is None: + return base_label + selected_name = self._selected_image_name(category) + if selected_name is None: + return base_label + return f"{base_label} - {selected_name}" + def _menu_row(self, y, label, category, callback): + self._make_button([0.08, y, 0.32, 0.12], label, callback) + selected_name = self._selected_image_name(category) + if selected_name is not None: + self.figure.text(0.44, y + 0.055, f"- {selected_name}", color=self.colors["text"], va="center", ha="left", fontsize=11) + def _select_current_image(self): + if self.current_category in ("source", "goal"): + self.selected_indices[self.current_category] = self.current_index + self._show_menu() + def _close_interface(self): + if self.figure is not None: + plt.close(self.figure) + def _show_browser(self): + self._clear_layout() + self.figure.patch.set_facecolor(self.colors["figure"]) + self.figure.suptitle(self.current_category.replace("_", " ").title(), fontsize=16, color=self.colors["text"]) + self.image_axis, self.list_axis = self.figure.subplots(1, 2, gridspec_kw={"width_ratios": [3, 1]}) + self._refresh_browser_view() + self._make_button([0.02, 0.02, 0.12, 0.06], "Back", lambda event: self._show_menu()) + if self.current_category in ("source", "goal"): + self._make_button([0.76, 0.10, 0.18, 0.06], "Select", lambda event: self._select_current_image()) + self._make_button([0.76, 0.02, 0.08, 0.06], "<", lambda event: self.previous_image()) + self._make_button([0.86, 0.02, 0.08, 0.06], ">", lambda event: self.next_image()) + self.figure.subplots_adjust(left=0.05, right=0.95, bottom=0.12, top=0.90, wspace=0.22) + self.figure.canvas.draw_idle() + def _refresh_browser_view(self): + images = self.image_sets.get(self.current_category, []) + current_image = self._open_image(images, self.current_index) + category_title = self.current_category.replace("_", " ").title() if self.current_category else "Images" + self._draw_image_panel(self.image_axis, current_image, f"{category_title} {self.current_index + 1}/{max(len(images), 1)}") + self._draw_list_panel(self.list_axis, images, self.current_index) + self.figure.canvas.draw_idle() + def _step_image(self, delta): + images = self.image_sets.get(self.current_category, []) + if images: + self.current_index = (self.current_index + delta) % len(images) + self._refresh_browser_view() + def next_image(self): + self._step_image(1) + def previous_image(self): + self._step_image(-1) + def _on_key_press(self, event): + if self.current_category is None: + if event.key in ("escape", "q"): + self._close_interface() + return + if event.key in ("right", "d"): + self.next_image() + elif event.key in ("left", "a"): + self.previous_image() + elif event.key == "escape": + self._show_menu() + def render(self): + self._show_menu() + plt.show() + +def launch_interface(): + interface = ImageInterface() + interface.render() diff --git a/python/main.py b/python/main.py new file mode 100644 index 0000000..7575fa0 --- /dev/null +++ b/python/main.py @@ -0,0 +1,6 @@ +from interface import launch_interface + + + +if __name__ == "__main__": + launch_interface() \ No newline at end of file diff --git a/python/test.py b/python/test.py new file mode 100644 index 0000000..ac89b68 --- /dev/null +++ b/python/test.py @@ -0,0 +1,14 @@ +from PIL import Image +from glob import glob +import matplotlib.pylab as plt + +source_path = r"./images/source/*.png" + +source_images = glob(source_path) + +selected_source_image = Image.open(source_images[0]) + +fig, ax = plt.subplots(1, 1, figsize=(5, 5)) +ax.imshow(selected_source_image) +ax.axis("off") +plt.show() \ No newline at end of file