diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..b9b9c4d --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +*.jpg filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.jpeg filter=lfs diff=lfs merge=lfs -text diff --git a/.idea/assignment_2_improved.iml b/.idea/assignment_2_improved.iml index 9b772b7..e96f306 100644 --- a/.idea/assignment_2_improved.iml +++ b/.idea/assignment_2_improved.iml @@ -1,7 +1,9 @@ - + + + diff --git a/.idea/runConfigurations/Run_project.xml b/.idea/runConfigurations/Run_Project.xml similarity index 84% rename from .idea/runConfigurations/Run_project.xml rename to .idea/runConfigurations/Run_Project.xml index 7b2c8e5..140ddae 100644 --- a/.idea/runConfigurations/Run_project.xml +++ b/.idea/runConfigurations/Run_Project.xml @@ -1,5 +1,5 @@ - + + + - + + - - + + \ No newline at end of file diff --git a/f512418272.png b/f512418272.png index 0c69c1e..113325f 100644 Binary files a/f512418272.png and b/f512418272.png differ diff --git a/icon.png b/icon.png deleted file mode 100644 index 61e007f..0000000 Binary files a/icon.png and /dev/null differ diff --git a/lena.jpg b/lena.jpg index 6697e0e..7fad66a 100644 Binary files a/lena.jpg and b/lena.jpg differ diff --git a/main.py b/main.py deleted file mode 100644 index 5281843..0000000 --- a/main.py +++ /dev/null @@ -1,217 +0,0 @@ - -import os -import cv2 -import numpy as np -import tkinter as tk -from tkinter import filedialog -from PIL import Image, ImageTk - -OPENED_IMAGE = None - -def padding(file_path, border_width): - image = cv2.imread(file_path) - if image is None: - print("Failed to load the image.") - return - padded_image = cv2.copyMakeBorder( - image, - top=border_width, - bottom=border_width, - left=border_width, - right=border_width, - borderType=cv2.BORDER_REFLECT - ) - _cache_image(padded_image, file_path) - -def crop(file_path): - image = cv2.imread(file_path) - height, width = image.shape[:2] - # crop 80 px from top & left, 130 px from bottom & right - x_0 = 80 - x_1 = width - 130 - y_0 = 80 - y_1 = height - 130 - cropped_image = image[y_0:y_1, x_0:x_1] - - _cache_image(cropped_image, file_path) - -def resize(file_path): - width = 200 - height = 200 - image = cv2.imread(file_path) - resized_image = cv2.resize(image, (width, height)) - _cache_image(resized_image, file_path) - - -def copy(file_path): - image = cv2.imread(file_path) - - height, width, channels = image.shape - emptyPictureArray = np.zeros((height, width, 3), dtype=np.uint8) - - for y in range(height): - for x in range(width): - for c in range(channels): - emptyPictureArray[y, x, c] = image[y, x, c] - _cache_image(emptyPictureArray, file_path) - - -def grayscale(file_path): - image = cv2.imread(file_path) - gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) - _cache_image(gray_image, file_path) - -def hsv(file_path): - image = cv2.imread(file_path) - hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) - _cache_image(hsv_image, file_path) - - - -def hue_shifted(file_path, hue=50): - image = cv2.imread(file_path) - height, width, channels = image.shape - emptyPictureArray = np.zeros((height, width, 3), dtype=np.uint8) - for y in range(height): - for x in range(width): - for c in range(channels): - new_value = image[y, x, c] + hue - # Clip the value to stay within [0, 255] - emptyPictureArray[y, x, c] = np.clip(new_value, 0, 255) - _cache_image(emptyPictureArray, file_path) - -def smoothing(file_path): - image = cv2.imread(file_path) - smoothed_image = cv2.blur(image, ksize=(15, 15)) - _cache_image(smoothed_image, file_path) - - -def rotation(file_path, rotation_angle=90): - image = cv2.imread(file_path) - if rotation_angle == 90: - rotated_image = cv2.rotate(image, cv2.ROTATE_90_CLOCKWISE) - elif rotation_angle == 180: - rotated_image = cv2.rotate(image, cv2.ROTATE_180) - else: - print("Invalid angle. Use 90 or 180.") - return - _cache_image(rotated_image, file_path) - -def open_image(): - """ - Function called from the menu to open an image. - """ - # Ask user to choose an image file - file_path = filedialog.askopenfilename( - filetypes=[("Image files", "*.jpg *.jpeg *.png *.gif *.bmp")] - ) - if file_path: - _open_image(file_path) - -def _cache_image(image, file_path): - opened_image_basename = os.path.basename(file_path) - opened_image_path = os.path.dirname(file_path) - newfname = "cache/" + opened_image_basename - cv2.imwrite(newfname, image) - print(f"Image cached as '{newfname}'.") - _open_image(newfname) - - -def _save_image(file_path): - image = cv2.imread(file_path) - opened_image_basename = os.path.basename(file_path) - opened_image_path = os.path.dirname(file_path) - newfname = opened_image_path + '/../' + opened_image_basename - cv2.imwrite(newfname, image) - print(f"Image saved as '{newfname}'.") - _open_image(newfname) - - -def _open_image(file_path): - """ - Open and display an image in the GUI. - Params: - - file_path: Path to the image file. - """ - # Open with cv2 to get dimensions - imgcv2 = cv2.imread(file_path) - height, width, channels = imgcv2.shape - - # Open and resize image (optional) - img = Image.open(file_path) - img = img.resize((height, width), Image.LANCZOS) # Resize to fit frame - tk_img = ImageTk.PhotoImage(img) - - # Update label inside frame with the correct dimensions - image_label.config(image=tk_img, height=height, width=width) - - global OPENED_IMAGE - OPENED_IMAGE = file_path # Store opened image in global variable, to access later if needed - - print("Opened image:", file_path) - - -if __name__ == "__main__": - -# Main window - root = tk.Tk() - root.title("Image Viewer") - root.geometry("800x600") - root.config(bg="white") - icon = tk.PhotoImage(file='icon.png') - root.tk.call('wm', 'iconphoto', root._w, icon) - root.minsize(800, 600) - -# Menus - menu = tk.Menu(root) - root.config(menu=menu) - file_menu = tk.Menu(menu, tearoff=0) - menu.add_cascade(label="File", menu=file_menu) - file_menu.add_command(label="Open Image", command=open_image) - file_menu.add_command(label="Save Image", command=lambda: _save_image(OPENED_IMAGE)) - file_menu.add_command(label="Exit", command=root.quit) - - test_menu = tk.Menu(menu, tearoff=0) - menu.add_cascade(label="Test", menu=test_menu) - test_menu.add_command(label="Padding", command=lambda: padding(OPENED_IMAGE, border_width=50) if OPENED_IMAGE is not None else print("No image opened.")) - test_menu.add_command(label="Crop", command=lambda: crop(OPENED_IMAGE) if OPENED_IMAGE is not None else print("No image opened.")) - test_menu.add_command(label="Resize", command=lambda: resize(OPENED_IMAGE) if OPENED_IMAGE is not None else print("No image opened.")) - test_menu.add_command(label="Copy", command=lambda: copy(OPENED_IMAGE) if OPENED_IMAGE is not None else print("No image opened.")) - test_menu.add_command(label="Greyscale", command=lambda: grayscale(OPENED_IMAGE) if OPENED_IMAGE is not None else print("No image opened.")) - test_menu.add_command(label="Hsv", command=lambda: hsv(OPENED_IMAGE) if OPENED_IMAGE is not None else print("No image opened.")) - test_menu.add_command(label="Hue Shifted", command=lambda: hue_shifted(OPENED_IMAGE, hue=50) if OPENED_IMAGE is not None else print("No image opened.")) - test_menu.add_command(label="Smoothed", command=lambda: smoothing(OPENED_IMAGE) if OPENED_IMAGE is not None else print("No image opened.")) - test_menu.add_command(label="Rotated", command=lambda: rotation(OPENED_IMAGE, rotation_angle=90) if OPENED_IMAGE is not None else print("No image opened.")) - - - clipboard_menu = tk.Menu(menu, tearoff=0) - menu.add_cascade(label="Clipboard", menu=clipboard_menu) - - image_menu = tk.Menu(menu, tearoff=0) - menu.add_cascade(label="Image", menu=image_menu) - - tools_menu = tk.Menu(menu, tearoff=0) - menu.add_cascade(label="Tools", menu=tools_menu) - - shapes_menu = tk.Menu(menu, tearoff=0) - menu.add_cascade(label="Shapes", menu=shapes_menu) - - colors_menu = tk.Menu(menu, tearoff=0) - menu.add_cascade(label="Colors", menu=colors_menu) - - layer_menu = tk.Menu(menu, tearoff=0) - menu.add_cascade(label="Layer", menu=layer_menu) - - filter_menu = tk.Menu(menu, tearoff=0) - menu.add_cascade(label="Filter", menu=filter_menu) -# - -# Frame to hold image - imgframe = tk.Frame(root, width=500, height=500, bg="lightgray", relief="sunken", bd=2) - imgframe.pack(side="top", pady=10) - -# Label to display image - image_label = tk.Label(imgframe, width=500, height=500, bg="white") - image_label.pack(expand=True) - - root.mainloop() diff --git a/src/icon.png b/src/icon.png new file mode 100644 index 0000000..d4ad82b --- /dev/null +++ b/src/icon.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6eed3c9619d01b38005e4aec35623f40dffd930d15764fe54552ffb0f77c38a5 +size 1331