diff --git a/imageEditor.py b/imageEditor.py index ff8010b..4876765 100644 --- a/imageEditor.py +++ b/imageEditor.py @@ -40,11 +40,11 @@ def __init__(self): self.image_editor_window = tk.Frame(self) wallpaper = Image.open('images_ie/splash_screen_ie.jpg') - wallpaper = wallpaper.resize((window_width, window_height - 30), Image.ANTIALIAS) + wallpaper = wallpaper.resize((window_width, window_height - 30), Image.Resampling.LANCZOS) wallpaper = ImageTk.PhotoImage(wallpaper) self.loading = Image.open('images_ie/loader_ie.png') - self.loading = self.loading.resize((19, 19), Image.ANTIALIAS) + self.loading = self.loading.resize((19, 19), Image.Resampling.LANCZOS) self.loading = ImageTk.PhotoImage(self.loading) self.wallpaper_label = tk.Label(self, image=wallpaper, bd=0) @@ -90,210 +90,284 @@ def __init__(self): self.error = None flip_icon = Image.open('images_ie/flip2_ie.png') - flip_icon = flip_icon.resize((25, 25), Image.ANTIALIAS) + flip_icon = flip_icon.resize((25, 25), Image.Resampling.LANCZOS) flip_icon = ImageTk.PhotoImage(flip_icon) rotate_icon = Image.open('images_ie/rotate_ie.png') - rotate_icon = rotate_icon.resize((25, 25), Image.ANTIALIAS) + rotate_icon = rotate_icon.resize((25, 25), Image.Resampling.LANCZOS) rotate_icon = ImageTk.PhotoImage(rotate_icon) next_icon = Image.open('images_ie/right_ie.png') - next_icon = next_icon.resize((25, 25), Image.ANTIALIAS) + next_icon = next_icon.resize((25, 25), Image.Resampling.LANCZOS) next_icon = ImageTk.PhotoImage(next_icon) previous_icon = Image.open('images_ie/left_ie.png') - previous_icon = previous_icon.resize((25, 25), Image.ANTIALIAS) + previous_icon = previous_icon.resize((25, 25), Image.Resampling.LANCZOS) previous_icon = ImageTk.PhotoImage(previous_icon) adjust_icon = Image.open('images_ie/adjust_ie.png') - adjust_icon = adjust_icon.resize((25, 25), Image.ANTIALIAS) + adjust_icon = adjust_icon.resize((25, 25), Image.Resampling.LANCZOS) adjust_icon = ImageTk.PhotoImage(adjust_icon) filter_icon = Image.open('images_ie/filter_ie.png') - filter_icon = filter_icon.resize((25, 25), Image.ANTIALIAS) + filter_icon = filter_icon.resize((25, 25), Image.Resampling.LANCZOS) filter_icon = ImageTk.PhotoImage(filter_icon) save_icon = Image.open('images_ie/save_ie.png') - save_icon = save_icon.resize((25, 25), Image.ANTIALIAS) + save_icon = save_icon.resize((25, 25), Image.Resampling.LANCZOS) save_icon = ImageTk.PhotoImage(save_icon) delete_icon = Image.open('images_ie/delete_ie.png') - delete_icon = delete_icon.resize((25, 25), Image.ANTIALIAS) + delete_icon = delete_icon.resize((25, 25), Image.Resampling.LANCZOS) delete_icon = ImageTk.PhotoImage(delete_icon) power_off_icon = Image.open('images_ie/power-button_ie.png') - power_off_icon = power_off_icon.resize((25, 25), Image.ANTIALIAS) + power_off_icon = power_off_icon.resize((25, 25), Image.Resampling.LANCZOS) power_off_icon = ImageTk.PhotoImage(power_off_icon) self.error_icon = Image.open('images_ie/error_ie.png') - self.error_icon = self.error_icon.resize((50, 50), Image.ANTIALIAS) + self.error_icon = self.error_icon.resize((50, 50), Image.Resampling.LANCZOS) self.error_icon = ImageTk.PhotoImage(self.error_icon) self.open_image_icon = Image.open('images_ie/open_image_ie.png') - self.open_image_icon = self.open_image_icon.resize((150, 120), Image.ANTIALIAS) + self.open_image_icon = self.open_image_icon.resize((150, 120), Image.Resampling.LANCZOS) self.open_image_icon = ImageTk.PhotoImage(self.open_image_icon) self.open_image_small_icon = Image.open('images_ie/open_image_ie.png') - self.open_image_small_icon = self.open_image_small_icon.resize((50, 40), Image.ANTIALIAS) + self.open_image_small_icon = self.open_image_small_icon.resize((50, 40), Image.Resampling.LANCZOS) self.open_image_small_icon = ImageTk.PhotoImage(self.open_image_small_icon) self.checked_icon = Image.open('images_ie/checked_ie.png') - self.checked_icon = self.checked_icon.resize((25, 25), Image.ANTIALIAS) + self.checked_icon = self.checked_icon.resize((25, 25), Image.Resampling.LANCZOS) self.checked_icon = ImageTk.PhotoImage(self.checked_icon) self.unchecked_icon = Image.open('images_ie/unchecked_ie.png') - self.unchecked_icon = self.unchecked_icon.resize((25, 25), Image.ANTIALIAS) + self.unchecked_icon = self.unchecked_icon.resize((25, 25), Image.Resampling.LANCZOS) self.unchecked_icon = ImageTk.PhotoImage(self.unchecked_icon) reset_icon = Image.open('images_ie/reset_ie.png') - reset_icon = reset_icon.resize((25, 25), Image.ANTIALIAS) + reset_icon = reset_icon.resize((25, 25), Image.Resampling.LANCZOS) reset_icon = ImageTk.PhotoImage(reset_icon) color_picker_icon = Image.open('images_ie/color_picker_ie.png') - color_picker_icon = color_picker_icon.resize((25, 25), Image.ANTIALIAS) + color_picker_icon = color_picker_icon.resize((25, 25), Image.Resampling.LANCZOS) color_picker_icon = ImageTk.PhotoImage(color_picker_icon) - heading = tk.Label(self.image_editor_window, text="Image Editor", background="sky blue", font="lucida 9 bold") - heading.pack(fill="x") + self.top_toolbar_color = "#2d3436" + self.bottom_toolbar_color = "#2d3436" + self.button_normal_color = "#ffffff" + self.button_hover_color = "#dfe6e9" + self.button_text_color = "#2d3436" + self.button_pressed_color = "#b2bec3" + self.button_border_width = 2 + self.button_relief = "raised" - self.image_canvas = tk.Canvas(self.image_editor_window, bd=0, highlightbackground="black", background="black") + self.top_toolbar = tk.Frame(self.image_editor_window, background=self.top_toolbar_color, height=50) + self.top_toolbar.pack(fill="x") + self.top_toolbar.pack_propagate(False) + + self.left_toolbar = tk.Frame(self.top_toolbar, background=self.top_toolbar_color) + self.left_toolbar.pack(side="left", padx=10) + + self.center_toolbar = tk.Frame(self.top_toolbar, background=self.top_toolbar_color) + self.center_toolbar.pack(side="left", padx=20, expand=True) + + self.right_toolbar = tk.Frame(self.top_toolbar, background=self.top_toolbar_color) + self.right_toolbar.pack(side="right", padx=10) + + self.image_canvas = tk.Canvas(self.image_editor_window, bd=0, highlightbackground="black", background="#1a1a2e") self.image_canvas.bind('', self.draw_crop) self.image_canvas.bind('', self.get_mouse_pos) self.image_canvas.bind('', self.button_release) self.image_canvas.pack(fill="both", expand=True) - self.button_frame_color = "#333331" - - self.button_frame2 = tk.Frame(self.image_editor_window, background=self.button_frame_color) - self.button_frame2.pack(fill="x") - - self.button_frame = tk.Frame(self.button_frame2, background=self.button_frame_color) - self.button_frame.pack() - - previous_b = tk.Button(self.button_frame, text="Previous", image=previous_icon, - background=self.button_frame_color, command=self.previous_image, - padx=5, bd=0, cursor="hand2") - previous_b.bind("", lambda e: mouse_hover(previous_b, color='#1c1c1b')) - previous_b.bind("", lambda e: mouse_not_hover(previous_b, color=self.button_frame_color)) - previous_b.pack(side="left", padx=2) - - rotate_b = tk.Button(self.button_frame, text="Rotate", image=rotate_icon, background=self.button_frame_color, - command=self.rotate, padx=5, bd=0, cursor="hand2") - rotate_b.bind("", lambda e: mouse_hover(rotate_b, color='#1c1c1b')) - rotate_b.bind("", lambda e: mouse_not_hover(rotate_b, color=self.button_frame_color)) - rotate_b.pack(side="left", padx=10) - - flip_b = tk.Button(self.button_frame, text="Flip", background=self.button_frame_color, - image=flip_icon, command=self.mirror, padx=5, bd=0, cursor="hand2") - flip_b.bind("", lambda e: mouse_hover(flip_b, color='#1c1c1b')) - flip_b.bind("", lambda e: mouse_not_hover(flip_b, color=self.button_frame_color)) - flip_b.pack(side="left", padx=10) - - self.delete_b = tk.Button(self.button_frame, text="Flip", background=self.button_frame_color, image=delete_icon, - command=self.delete, - padx=5, bd=0, cursor="hand2", state="disable") - self.delete_b.bind("", lambda e: mouse_hover(self.delete_b, color='#1c1c1b')) - self.delete_b.bind("", lambda e: mouse_not_hover(self.delete_b, color=self.button_frame_color)) - self.delete_b.pack(side="left", padx=10) - - next_b = tk.Button(self.button_frame, text="Next", image=next_icon, command=self.next_image, - background=self.button_frame_color, padx=5, bd=0, cursor="hand2") - next_b.bind("", lambda e: mouse_hover(next_b, color='#1c1c1b')) - next_b.bind("", lambda e: mouse_not_hover(next_b, color=self.button_frame_color)) - next_b.pack(side="left", padx=2) - - exit_window = tk.Button(self.image_editor_window, image=power_off_icon, compound="left", - text="Exit", font="lucida 9 bold", foreground='white', background="black", - command=self.exit_window, padx=12, cursor="hand2") - exit_window.bind("", lambda e: mouse_hover(exit_window)) - exit_window.bind("", lambda e: mouse_not_hover(exit_window)) - exit_window.place(x=1418, y=640) - - self.side_frame = tk.Frame(self.image_editor_window, background="black") - - adjust_b = tk.Button(self.side_frame, text="Adjust", foreground="white", compound="left", font="lucida 9 bold", - image=adjust_icon, background="black", cursor="hand2", - command=self.open_adjustment_window, padx=5) - adjust_b.bind("", lambda e: mouse_hover(adjust_b)) - adjust_b.bind("", lambda e: mouse_not_hover(adjust_b)) - adjust_b.pack(pady=2) - - filter_b = tk.Button(self.side_frame, text="Filters", foreground="white", compound="left", - font="lucida 9 bold", image=filter_icon, background="black", cursor="hand2", - command=self.open_filter_window, padx=5) - filter_b.bind("", lambda e: mouse_hover(filter_b)) - filter_b.bind("", lambda e: mouse_not_hover(filter_b)) - filter_b.pack(pady=2) - - self.reset_b = tk.Button(self.image_editor_window, text="Reset", foreground="white", compound="left", - font="lucida 9 bold", image=reset_icon, background="black", - command=self.reset, padx=6, cursor="hand2") - self.reset_b.bind("", lambda e: mouse_hover(self.reset_b)) - self.reset_b.bind("", lambda e: mouse_not_hover(self.reset_b)) - - self.draw_b = tk.Button(self.image_editor_window, text="Draw", image=self.unchecked_icon, foreground="white", - font="lucida 9 bold", compound="left", background="black", command=self.activate_draw, - padx=3, cursor="hand2") - self.draw_b.bind("", lambda e: mouse_hover(self.draw_b)) - self.draw_b.bind("", lambda e: mouse_not_hover(self.draw_b)) - - self.crop_b = tk.Button(self.image_editor_window, text="Crop", image=self.unchecked_icon, foreground="white", - font="lucida 9 bold", compound="left", background="black", - command=self.activate_crop, padx=4, cursor="hand2") - self.crop_b.bind("", lambda e: mouse_hover(self.crop_b)) - self.crop_b.bind("", lambda e: mouse_not_hover(self.crop_b)) - - self.crop_save = tk.Button(self.image_editor_window, image=save_icon, compound='left', text="Save", - foreground="white", font="lucida 9 bold", background="black", - command=self.crop_image, padx=4, cursor="hand2") - self.crop_save.bind("", lambda e: mouse_hover(self.crop_save)) - self.crop_save.bind("", lambda e: mouse_not_hover(self.crop_save)) - - self.save_b = tk.Button(self.image_editor_window, text="Save", foreground="white", compound="left", - font="lucida 9 bold", state='disabled', image=save_icon, background="black", - command=self.save, padx=10, cursor="hand2") - - self.draw_save = tk.Button(self.image_editor_window, image=save_icon, compound='left', text="Save", - foreground="white", font="lucida 10 bold", background="black", - command=self.image_after_draw, padx=3, cursor="hand2") - self.draw_save.bind("", lambda e: mouse_hover(self.draw_save)) - self.draw_save.bind("", lambda e: mouse_not_hover(self.draw_save)) - - version_label = tk.Label(self.button_frame2,text="v 1.0", background=self.button_frame_color, - foreground="white", font="lucida 9 bold") - version_label.place(x=20) - - self.status_bar = tk.Label(self.button_frame2, background=self.button_frame_color, - foreground="white", font="lucida 10 bold") - self.status_bar.place(x=1200) - - self.open_image_button = tk.Button(self.image_editor_window, command=self.open_image, cursor="hand2", - image=self.open_image_icon, compound='top', text="Click To Open Image", - font="lucida 12 bold", foreground="white", bd=0, background="black",) - self.open_image_button.bind("", lambda e: mouse_hover(self.open_image_button, color='#1c1c1b')) - self.open_image_button.bind("", lambda e: mouse_not_hover(self.open_image_button)) - self.open_image_button.place(x=685, y=350) + self.bottom_toolbar = tk.Frame(self.image_editor_window, background=self.bottom_toolbar_color, height=50) + self.bottom_toolbar.pack(fill="x", side="bottom") + self.bottom_toolbar.pack_propagate(False) + self.bottom_toolbar.winfo_toplevel().attributes('-alpha', 0.9) + + self.bottom_left = tk.Frame(self.bottom_toolbar, background=self.bottom_toolbar_color) + self.bottom_left.pack(side="left", padx=10) + + self.bottom_center = tk.Frame(self.bottom_toolbar, background=self.bottom_toolbar_color) + self.bottom_center.pack(side="left", padx=20, expand=True) + + self.bottom_right = tk.Frame(self.bottom_toolbar, background=self.bottom_toolbar_color) + self.bottom_right.pack(side="right", padx=10) + + self.open_image_button = tk.Button(self.left_toolbar, image=self.open_image_small_icon, compound="left", + text="Open", font="lucida 10 bold", foreground=self.button_text_color, + bd=0, background=self.button_normal_color, cursor="hand2", + activebackground=self.button_hover_color, + command=self.open_image, padx=10, pady=5) + self.open_image_button.bind("", lambda e: mouse_hover(self.open_image_button, color=self.button_hover_color)) + self.open_image_button.bind("", lambda e: mouse_not_hover(self.open_image_button, color=self.button_normal_color)) + self.open_image_button.pack(side="left", padx=5) + + self.save_b = tk.Button(self.left_toolbar, text="Save", foreground=self.button_text_color, compound="left", + font="lucida 10 bold", state='disabled', image=save_icon, background=self.button_normal_color, + command=self.save, padx=10, pady=5, bd=0, cursor="hand2", + activebackground=self.button_hover_color) + self.save_b.bind("", lambda e: mouse_hover(self.save_b, color=self.button_hover_color)) + self.save_b.bind("", lambda e: mouse_not_hover(self.save_b, color=self.button_normal_color)) + self.save_b.pack(side="left", padx=5) + + self.reset_b = tk.Button(self.left_toolbar, text="Reset", foreground=self.button_text_color, compound="left", + font="lucida 10 bold", image=reset_icon, background=self.button_normal_color, + command=self.reset, padx=10, pady=5, bd=0, cursor="hand2", + activebackground=self.button_hover_color) + self.reset_b.bind("", lambda e: mouse_hover(self.reset_b, color=self.button_hover_color)) + self.reset_b.bind("", lambda e: mouse_not_hover(self.reset_b, color=self.button_normal_color)) + self.reset_b.pack(side="left", padx=5) + + tk.Frame(self.left_toolbar, width=2, background="#1a252f").pack(side="left", fill="y", padx=10) + + self.adjust_b = tk.Button(self.center_toolbar, text="Adjust", foreground=self.button_text_color, compound="left", + font="lucida 10 bold", image=adjust_icon, background=self.button_normal_color, + cursor="hand2", command=self.open_adjustment_window, padx=10, pady=5, bd=0, + activebackground=self.button_hover_color) + self.adjust_b.bind("", lambda e: mouse_hover(self.adjust_b, color=self.button_hover_color)) + self.adjust_b.bind("", lambda e: mouse_not_hover(self.adjust_b, color=self.button_normal_color)) + self.adjust_b.pack(side="left", padx=5) + + self.filter_b = tk.Button(self.center_toolbar, text="Filters", foreground=self.button_text_color, compound="left", + font="lucida 10 bold", image=filter_icon, background=self.button_normal_color, + cursor="hand2", command=self.open_filter_window, padx=10, pady=5, bd=0, + activebackground=self.button_hover_color) + self.filter_b.bind("", lambda e: mouse_hover(self.filter_b, color=self.button_hover_color)) + self.filter_b.bind("", lambda e: mouse_not_hover(self.filter_b, color=self.button_normal_color)) + self.filter_b.pack(side="left", padx=5) + + self.draw_b = tk.Button(self.center_toolbar, text="Draw", image=self.unchecked_icon, foreground=self.button_text_color, + font="lucida 10 bold", compound="left", background=self.button_normal_color, + command=self.activate_draw, padx=10, pady=5, bd=0, cursor="hand2", + activebackground=self.button_hover_color) + self.draw_b.bind("", lambda e: mouse_hover(self.draw_b, color=self.button_hover_color)) + self.draw_b.bind("", lambda e: mouse_not_hover(self.draw_b, color=self.button_normal_color)) + self.draw_b.pack(side="left", padx=5) + + self.crop_b = tk.Button(self.center_toolbar, text="Crop", image=self.unchecked_icon, foreground=self.button_text_color, + font="lucida 10 bold", compound="left", background=self.button_normal_color, + command=self.activate_crop, padx=10, pady=5, bd=0, cursor="hand2", + activebackground=self.button_hover_color) + self.crop_b.bind("", lambda e: mouse_hover(self.crop_b, color=self.button_hover_color)) + self.crop_b.bind("", lambda e: mouse_not_hover(self.crop_b, color=self.button_normal_color)) + self.crop_b.pack(side="left", padx=5) + + tk.Frame(self.center_toolbar, width=2, background="#1a252f").pack(side="left", fill="y", padx=10) + + rotate_b = tk.Button(self.center_toolbar, text="Rotate", image=rotate_icon, background=self.button_normal_color, + command=self.rotate, padx=10, pady=5, bd=0, cursor="hand2", + foreground=self.button_text_color, font="lucida 10 bold", compound="left", + activebackground=self.button_hover_color) + rotate_b.bind("", lambda e: mouse_hover(rotate_b, color=self.button_hover_color)) + rotate_b.bind("", lambda e: mouse_not_hover(rotate_b, color=self.button_normal_color)) + rotate_b.pack(side="left", padx=5) + + flip_b = tk.Button(self.center_toolbar, text="Flip", background=self.button_normal_color, + image=flip_icon, command=self.mirror, padx=10, pady=5, bd=0, cursor="hand2", + foreground=self.button_text_color, font="lucida 10 bold", compound="left", + activebackground=self.button_hover_color) + flip_b.bind("", lambda e: mouse_hover(flip_b, color=self.button_hover_color)) + flip_b.bind("", lambda e: mouse_not_hover(flip_b, color=self.button_normal_color)) + flip_b.pack(side="left", padx=5) + + previous_b = tk.Button(self.bottom_center, text="Previous", image=previous_icon, + background=self.button_normal_color, command=self.previous_image, + padx=10, pady=5, bd=0, cursor="hand2", foreground=self.button_text_color, + font="lucida 10 bold", compound="left", activebackground=self.button_hover_color) + previous_b.bind("", lambda e: mouse_hover(previous_b, color=self.button_hover_color)) + previous_b.bind("", lambda e: mouse_not_hover(previous_b, color=self.button_normal_color)) + previous_b.pack(side="left", padx=5) + + self.delete_b = tk.Button(self.bottom_center, text="Delete", background=self.button_normal_color, image=delete_icon, + command=self.delete, padx=10, pady=5, bd=0, cursor="hand2", + state="disable", foreground=self.button_text_color, font="lucida 10 bold", + compound="left", activebackground=self.button_hover_color) + self.delete_b.bind("", lambda e: mouse_hover(self.delete_b, color=self.button_hover_color)) + self.delete_b.bind("", lambda e: mouse_not_hover(self.delete_b, color=self.button_normal_color)) + self.delete_b.pack(side="left", padx=5) + + next_b = tk.Button(self.bottom_center, text="Next", image=next_icon, command=self.next_image, + background=self.button_normal_color, padx=10, pady=5, bd=0, cursor="hand2", + foreground=self.button_text_color, font="lucida 10 bold", compound="left", + activebackground=self.button_hover_color) + next_b.bind("", lambda e: mouse_hover(next_b, color=self.button_hover_color)) + next_b.bind("", lambda e: mouse_not_hover(next_b, color=self.button_normal_color)) + next_b.pack(side="left", padx=5) + + exit_window = tk.Button(self.right_toolbar, image=power_off_icon, compound="left", + text="Exit", font="lucida 10 bold", foreground=self.button_text_color, + background="#e74c3c", command=self.exit_window, padx=10, pady=5, bd=0, + cursor="hand2", activebackground="#c0392b") + exit_window.bind("", lambda e: mouse_hover(exit_window, color="#c0392b")) + exit_window.bind("", lambda e: mouse_not_hover(exit_window, color="#e74c3c")) + exit_window.pack(side="right", padx=5) + + self.crop_save = tk.Button(self.image_editor_window, image=save_icon, compound='left', text="Apply Crop", + foreground=self.button_text_color, font="lucida 10 bold", background="#27ae60", + command=self.crop_image, padx=10, pady=5, bd=0, cursor="hand2", + activebackground="#229954") + self.crop_save.bind("", lambda e: mouse_hover(self.crop_save, color="#229954")) + self.crop_save.bind("", lambda e: mouse_not_hover(self.crop_save, color="#27ae60")) + + version_label = tk.Label(self.bottom_left, text="v 1.0", background=self.bottom_toolbar_color, + foreground="#bdc3c7", font="lucida 9 bold") + version_label.pack(side="left") + + self.status_bar = tk.Label(self.bottom_right, background=self.bottom_toolbar_color, + foreground="#ecf0f1", font="lucida 10 bold") + self.status_bar.pack(side="right") self.error_b = tk.Button(self.image_editor_window, text="It appears that we don't support this file format.", image=self.error_icon, compound="left", font="lucida 11 bold", - background="black", foreground="white", bd=0, padx=5) + background=self.button_normal_color, foreground=self.button_text_color, bd=0, padx=5) self.pencil_size = 2 self.pencil_color = 'red' - self.pencil_size_label = tk.Label(self.image_editor_window, text="Size", font="lucida 10 bold", - background='black', foreground="white") + self.draw_toolbar = tk.Frame(self.image_editor_window, background=self.top_toolbar_color, height=60) + self.draw_toolbar.pack_propagate(False) - self.pencil_size_scale = tk.Scale(self.image_editor_window, from_=1, to=15, sliderrelief='flat', - orient="horizontal", fg='white', highlightthickness=0, - command=self.change_pencil_size, cursor="hand2", background='black', - troughcolor='#73B5FA', activebackground='#1065BF') + self.pencil_size_label = tk.Label(self.draw_toolbar, text="Size", font="lucida 10 bold", + background=self.top_toolbar_color, foreground=self.button_text_color) + self.pencil_size_label.pack(side="left", padx=5) - self.color_chooser_button = tk.Button(self.image_editor_window, image=color_picker_icon, text="Color", - font="lucida 10 bold", cursor="hand2", background='black', - foreground="white", bd=0, command=self.choose_color) - self.color_chooser_button.bind("", lambda e: mouse_hover(self.color_chooser_button)) - self.color_chooser_button.bind("", lambda e: mouse_not_hover(self.color_chooser_button)) + self.pencil_size_scale = tk.Scale(self.draw_toolbar, from_=1, to=15, sliderrelief='flat', + orient="horizontal", fg=self.button_text_color, highlightthickness=0, + command=self.change_pencil_size, cursor="hand2", + background=self.top_toolbar_color, + troughcolor='#73B5FA', activebackground='#1065BF') + self.pencil_size_scale.pack(side="left", padx=5) + + self.color_chooser_button = tk.Button(self.draw_toolbar, image=color_picker_icon, text="Color", + font="lucida 10 bold", cursor="hand2", background=self.button_normal_color, + foreground=self.button_text_color, bd=2, command=self.choose_color, + compound="left", padx=10, pady=5, activebackground=self.button_hover_color, + relief="raised") + self.color_chooser_button.bind("", lambda e: mouse_hover(self.color_chooser_button, color=self.button_hover_color)) + self.color_chooser_button.bind("", lambda e: mouse_not_hover(self.color_chooser_button, color=self.button_normal_color)) + self.color_chooser_button.pack(side="left", padx=10) + + tk.Frame(self.draw_toolbar, width=2, background="#1a252f").pack(side="left", fill="y", padx=10) + + self.draw_cancel = tk.Button(self.draw_toolbar, text="Cancel", + font="Arial 12 bold", cursor="hand2", background="white", + foreground="#c0392b", bd=3, command=self.cancel_draw, + padx=20, pady=8, activebackground="#fadbd8", relief="raised", + highlightbackground="#c0392b") + self.draw_cancel.bind("", lambda e: mouse_hover(self.draw_cancel, color="#fadbd8")) + self.draw_cancel.bind("", lambda e: mouse_not_hover(self.draw_cancel, color="white")) + self.draw_cancel.pack(side="left", padx=5) + + self.draw_save = tk.Button(self.draw_toolbar, text="Apply", + font="Arial 12 bold", cursor="hand2", background="white", + foreground="#2980b9", bd=3, command=self.image_after_draw, + padx=20, pady=8, activebackground="#d4e6f1", relief="raised", + highlightbackground="#2980b9") + self.draw_save.bind("", lambda e: mouse_hover(self.draw_save, color="#d4e6f1")) + self.draw_save.bind("", lambda e: mouse_not_hover(self.draw_save, color="white")) + self.draw_save.pack(side="left", padx=5) self.img2 = None self.start_time = time.time() @@ -326,19 +400,9 @@ def choose_color(self): self.pencil_color = color[1] def open_image(self): - file_object = filedialog.askopenfile(filetype=(('jpg', '*.jpg'), ('png', '*.png'))) + file_object = filedialog.askopenfile(filetypes=(('jpg', '*.jpg'), ('png', '*.png'), ('jpeg', '*.jpeg'))) if file_object: - self.open_image_button.configure(image=self.open_image_small_icon, text="Open Image", compound="left", - font="lucida 9 bold") - self.open_image_button.place(x=1407, y=720) - - self.side_frame.place(x=1418, y=114) - self.save_b.place(x=1418, y=680) - self.draw_b.place(x=1465, y=232) - self.crop_b.place(x=1390, y=232) - self.reset_b.place(x=1418, y=190) - self.delete_b.configure(state="normal") filename = file_object.name @@ -398,12 +462,20 @@ def show_image(self, image=None, modified=None): elif modified: im = modified + canvas_width = self.image_canvas.winfo_width() + canvas_height = self.image_canvas.winfo_height() + + if canvas_width <= 1: + canvas_width = self.winfo_screenwidth() + if canvas_height <= 1: + canvas_height = self.winfo_screenheight() - 100 + image_width, image_height = self.current_resized_image_size[0], self.current_resized_image_size[1] - self.image_x_co, self.image_y_co = (self.winfo_screenwidth() / 2) - image_width / 2, ( - self.max_height / 2) - image_height / 2 + self.image_x_co = (canvas_width / 2) - image_width / 2 + self.image_y_co = (canvas_height / 2) - image_height / 2 self.image_canvas.image = im - if image_height < self.max_height: + if image_height < canvas_height: self.image_canvas.create_image(self.image_x_co, self.image_y_co, image=im, anchor="nw") else: self.image_canvas.create_image(self.image_x_co, 0, image=im, anchor="nw") @@ -476,30 +548,23 @@ def get_mouse_pos(self, event): def button_release(self, event): if self.crop_active: - self.crop_save.place(x=1464, y=232) + self.crop_save.pack(side="left", padx=10, in_=self.center_toolbar) def activate_draw(self): if self.original_image and not self.error: if not self.draw_active: - # if we write self.image_before_draw = self.image_copy , then drawing on self.image_before_draw changes - # self.image_copy too therefore create a new image and paste image_copy on it self.image_before_draw = Image.new('RGB', size=self.current_image_size) self.image_before_draw.paste(self.image_copy, (0, 0)) - self.pencil_size_label.place(x=1388, y=282) - self.pencil_size_scale.place(x=1425, y=267) - self.color_chooser_button.place(x=1450, y=312) - self.image_canvas.configure(cursor='pencil') - self.draw_save.place(x=1390, y=232) - self.draw_b.configure(image=self.checked_icon) - self.open_image_button.place_forget() - self.button_frame.pack_forget() - self.side_frame.place_forget() - self.crop_b.place_forget() - self.save_b.place_forget() + + self.draw_toolbar.pack(after=self.top_toolbar, fill="x") + + self.crop_b.configure(state="disabled") + self.adjust_b.configure(state="disabled") + self.filter_b.configure(state="disabled") print("draw activated..") self.draw_active = True @@ -515,22 +580,16 @@ def activate_draw(self): self.draw_b.configure(image=self.unchecked_icon) print("draw deactivated..") self.draw_active = False - self.button_frame.pack() - self.side_frame.place(x=1418, y=114) - self.save_b.place(x=1418, y=680) - self.crop_b.place(x=1390, y=232) - self.open_image_button.place(x=1407, y=720) + self.draw_toolbar.pack_forget() - self.pencil_size_label.place_forget() - self.pencil_size_scale.place_forget() - self.color_chooser_button.place_forget() - self.draw_save.place_forget() + self.crop_b.configure(state="normal") + self.adjust_b.configure(state="normal") + self.filter_b.configure(state="normal") def activate_crop(self): if self.original_image and not self.error: - # to deactivate draw when we switch from draw to crop as we don't want both to be active at the same time if self.draw_active: self.activate_draw() @@ -538,26 +597,23 @@ def activate_crop(self): self.crop_b.configure(image=self.checked_icon) self.image_canvas.configure(cursor='plus') self.crop_active = True - self.reset_b.place_forget() - self.button_frame.pack_forget() - self.side_frame.place_forget() - self.draw_b.place_forget() - self.save_b.place_forget() + + self.draw_b.configure(state="disabled") + self.adjust_b.configure(state="disabled") + self.filter_b.configure(state="disabled") else: self.image_canvas.configure(cursor='arrow') self.crop_b.configure(image=self.unchecked_icon) - self.crop_save.place_forget() + self.crop_save.pack_forget() if self.rect: self.image_canvas.delete(self.rect) self.crop_active = False - self.side_frame.place(x=1418, y=114) - self.save_b.place(x=1418, y=680) - self.draw_b.place(x=1465, y=232) - self.crop_b.place(x=1390, y=232) - self.reset_b.place(x=1418, y=190) - self.button_frame.pack() + + self.draw_b.configure(state="normal") + self.adjust_b.configure(state="normal") + self.filter_b.configure(state="normal") def draw_crop(self, event): if self.crop_active: @@ -565,9 +621,10 @@ def draw_crop(self, event): self.rectangles.append(self.rect) image_width, image_height = self.current_resized_image_size[0], self.current_resized_image_size[1] - x_co_1, x_co_2 = int((self.winfo_screenwidth() / 2) - image_width / 2), int( - (self.winfo_screenwidth() / 2) + image_width / 2) - y_co_1, y_co_2 = int(self.max_height / 2 - image_height / 2), int((self.max_height / 2) + image_height / 2) + x_co_1 = self.image_x_co + x_co_2 = self.image_x_co + image_width + y_co_1 = self.image_y_co + y_co_2 = self.image_y_co + image_height if x_co_2 > event.x > x_co_1 and y_co_1 + 2 < event.y < y_co_2: self.image_canvas.coords(self.rect, self.point_x, self.point_y, event.x, event.y) @@ -576,9 +633,10 @@ def draw_crop(self, event): elif self.draw_active: image_width, image_height = self.current_resized_image_size[0], self.current_resized_image_size[1] - x_co_1, x_co_2 = int((self.winfo_screenwidth() / 2) - image_width / 2), int( - (self.winfo_screenwidth() / 2) + image_width / 2) - y_co_1, y_co_2 = int(self.max_height / 2 - image_height / 2), int((self.max_height / 2) + image_height / 2) + x_co_1 = self.image_x_co + x_co_2 = self.image_x_co + image_width + y_co_1 = self.image_y_co + y_co_2 = self.image_y_co + image_height if x_co_2 > self.point_x > x_co_1 and y_co_1 < self.point_y < y_co_2: if x_co_2 > event.x > x_co_1 and y_co_1 < event.y < y_co_2: @@ -600,19 +658,81 @@ def crop_image(self): x_co_1, y_co_1, x_co_2, y_co2 = ((self.point_x - self.image_x_co) * self.current_image_size[0])/self.current_resized_image_size[0], ((self.point_y - self.image_y_co) * self.current_image_size[1]) / self.current_resized_image_size[1], ((self.event_x - self.image_x_co) * self.current_image_size[0]) / self.current_resized_image_size[0], ((self.event_y - self.image_y_co) * self.current_image_size[1]) / self.current_resized_image_size[1] self.image_copy = self.image_copy.crop((int(x_co_1), int(y_co_1), int(x_co_2), int(y_co2))) - x_co_1, y_co_1, x_co_2, y_co2 = self.point_x - self.image_x_co, self.point_y - self.image_y_co, self.event_x - self.image_x_co, self.event_y - self.image_y_co + self.image_copy_resized = self.image_copy_resized.crop(( + int(self.point_x - self.image_x_co), + int(self.point_y - self.image_y_co), + int(self.event_x - self.image_x_co), + int(self.event_y - self.image_y_co) + )) + + self.current_image_size = self.image_copy.size + self.current_resized_image_size = self.image_copy_resized.size + + self.image_canvas.delete(self.rect) + self.rect = None + self.rectangles = [] - self.save() + self.crop_save.pack_forget() + + im = ImageTk.PhotoImage(self.image_copy_resized) + self.show_image(modified=im) + + self.save_b.configure(state="normal") + + self.crop_b.configure(image=self.unchecked_icon) + self.image_canvas.configure(cursor='arrow') + self.crop_active = False + + self.draw_b.configure(state="normal") + self.adjust_b.configure(state="normal") + self.filter_b.configure(state="normal") else: messagebox.showinfo(title="Can't crop !", message="Please select the portion of the image," " you want to crop") def image_after_draw(self): if self.lines_drawn: - self.image_copy = self.image_before_draw - self.save() + self.image_copy = self.image_before_draw.copy() + + self.image_copy_resized = self.image_copy.resize(self.current_resized_image_size, Image.Resampling.LANCZOS) + + for line in self.lines_drawn: + self.image_canvas.delete(line) + self.lines_drawn = [] + + self.draw_toolbar.pack_forget() + + self.image_canvas.configure(cursor='arrow') + self.draw_b.configure(image=self.unchecked_icon) + self.draw_active = False + + self.crop_b.configure(state="normal") + self.adjust_b.configure(state="normal") + self.filter_b.configure(state="normal") + + im = ImageTk.PhotoImage(self.image_copy_resized) + self.show_image(modified=im) + + self.save_b.configure(state="normal") else: - messagebox.showinfo(title='Cannot save!', message='You have not drawn anything on the image.') + messagebox.showinfo(title='Cannot apply!', message='You have not drawn anything on the image.') + + def cancel_draw(self): + if self.lines_drawn: + for line in self.lines_drawn: + self.image_canvas.delete(line) + self.lines_drawn = [] + self.image_before_draw = None + + self.draw_toolbar.pack_forget() + + self.image_canvas.configure(cursor='arrow') + self.draw_b.configure(image=self.unchecked_icon) + self.draw_active = False + + self.crop_b.configure(state="normal") + self.adjust_b.configure(state="normal") + self.filter_b.configure(state="normal") def save(self): image_path_object = filedialog.asksaveasfile(defaultextension='.jpg') @@ -620,17 +740,27 @@ def save(self): if image_path_object: image_path = image_path_object.name if self.draw_active: + if self.lines_drawn: + self.image_copy = self.image_before_draw.copy() + self.image_copy_resized = self.image_copy.resize(self.current_resized_image_size, Image.Resampling.LANCZOS) + for line in self.lines_drawn: self.image_canvas.delete(line) self.lines_drawn = [] - # as crop is still active after cropping the image so on calling activate_crop, it will get deactivated - self.activate_draw() + self.draw_toolbar.pack_forget() + + self.image_canvas.configure(cursor='arrow') + self.draw_b.configure(image=self.unchecked_icon) + self.draw_active = False + + self.crop_b.configure(state="normal") + self.adjust_b.configure(state="normal") + self.filter_b.configure(state="normal") if self.crop_active: self.image_canvas.delete(self.rect) - # as crop is still active after cropping the image so on calling activate_crop, it will get deactivated self.activate_crop() self.image_copy.save(image_path) @@ -667,12 +797,9 @@ def open_filter_window(self): def delete(self): if self.image_paths: - import winshell self.original_image.close() - winshell.delete_file(self.image_paths[self.current_index]) - print(len(self.image_paths), self.current_index) + os.remove(self.image_paths[self.current_index]) - print(len(self.image_paths), self.current_index) if len(self.image_paths) - 1 == self.current_index: self.image_paths.remove(self.image_paths[self.current_index]) self.current_index = 0 @@ -680,16 +807,11 @@ def delete(self): self.image_paths.remove(self.image_paths[self.current_index]) if self.image_paths: - self.show_image(image=self.image_paths[self.current_index]) else: self.status_bar.configure(text="") self.image_canvas.image = '' - self.open_image_button.configure(image=self.open_image_icon, command=self.open_image, - text="Click To Open Image", font="lucida 12 bold") - self.open_image_button.place(x=685, y=350) - if self.error: self.error_b.place_forget() self.error = None @@ -721,11 +843,11 @@ def __init__(self, parent, image_copy, modified_img, image_copy_resized, modifie super().__init__(parent) self.parent = parent - self.configure(background="grey") - self.wm_overrideredirect(True) + self.configure(background="#ffffff") + self.geometry("400x400+600+200") + self.title("Adjustments") + self.transient(parent) self.grab_set() - self.winfo_parent() - self.geometry("260x280+1200+100") self.image_copy = image_copy self.modified_img = modified_img @@ -735,57 +857,81 @@ def __init__(self, parent, image_copy, modified_img, image_copy_resized, modifie self.modifications = {'contrast': 1.0, 'sharpness': 1.0, 'brightness': 1.0} - background_color1 = '#19191a' - background_color2 = 'black' + background_color1 = '#ffffff' + title_color = '#0984e3' + text_color = '#2d3436' + button_bg_cancel = 'white' + button_bg_apply = 'white' + button_fg_cancel = '#c0392b' + button_fg_apply = '#2980b9' + button_border_color_cancel = '#c0392b' + button_border_color_apply = '#2980b9' + button_font = "Arial 12 bold" f1 = tk.Frame(self, background=background_color1) - f1.pack(fill="both", expand=True, padx=5, pady=5) + f1.pack(fill="both", expand=True, padx=15, pady=15) - tk.Label(f1, text="Adjustments", background="black", foreground="white").pack(fill="x") + title_label = tk.Label(f1, text="Adjustments", background=title_color, foreground='white', + font="lucida 12 bold", pady=8) + title_label.pack(fill="x") - contrast_l = tk.Label(f1, text="Contrast", relief="solid", font="lucida 11 bold", background=background_color2, - foreground="red") - contrast_l.place(x=15, y=60) + controls_frame = tk.Frame(f1, background=background_color1) + controls_frame.pack(fill="both", expand=True, pady=15) - self.contrast_b = tk.Scale(f1, from_=0, to=20, sliderrelief='flat', + contrast_frame = tk.Frame(controls_frame, background=background_color1) + contrast_frame.pack(fill="x", pady=8) + contrast_l = tk.Label(contrast_frame, text="Contrast", font="lucida 10 bold", background=background_color1, + foreground=text_color, width=10, anchor="w") + contrast_l.pack(side="left", padx=5) + self.contrast_b = tk.Scale(contrast_frame, from_=0, to=100, sliderrelief='raised', command=lambda e: self.adjust(e, 'contrast'), - orient="horizontal", highlightthickness=0, background=background_color1, fg='white', - troughcolor='#73B5FA', activebackground='#1065BF') - self.contrast_b.place(x=120, y=40) - - sharpness_l = tk.Label(f1, text="Sharpness", font="lucida 11 bold", background=background_color2, - foreground="red") - sharpness_l.place(x=15, y=100) - - self.sharpness_b = tk.Scale(f1, from_=0, to=30, sliderrelief='flat', + orient="horizontal", highlightthickness=1, background=background_color1, fg=text_color, + troughcolor='#dfe6e9', activebackground='#74b9ff', length=200, bd=2) + self.contrast_b.set(50) + self.contrast_b.pack(side="left", padx=5) + + sharpness_frame = tk.Frame(controls_frame, background=background_color1) + sharpness_frame.pack(fill="x", pady=8) + sharpness_l = tk.Label(sharpness_frame, text="Sharpness", font="lucida 10 bold", background=background_color1, + foreground=text_color, width=10, anchor="w") + sharpness_l.pack(side="left", padx=5) + self.sharpness_b = tk.Scale(sharpness_frame, from_=0, to=100, sliderrelief='raised', command=lambda e: self.adjust(e, 'sharpness'), - orient="horizontal", highlightthickness=0, background=background_color1, fg='white', - troughcolor='#73B5FA', activebackground='#1065BF') - self.sharpness_b.place(x=120, y=80) - # - brightness_l = tk.Label(f1, text="Brightness", font="lucida 11 bold", background=background_color2, - foreground="red") - brightness_l.place(x=15, y=140) - - self.brightness_b = tk.Scale(f1, from_=0, to=20, sliderrelief='flat', + orient="horizontal", highlightthickness=1, background=background_color1, fg=text_color, + troughcolor='#dfe6e9', activebackground='#74b9ff', length=200, bd=2) + self.sharpness_b.set(50) + self.sharpness_b.pack(side="left", padx=5) + + brightness_frame = tk.Frame(controls_frame, background=background_color1) + brightness_frame.pack(fill="x", pady=8) + brightness_l = tk.Label(brightness_frame, text="Brightness", font="lucida 10 bold", background=background_color1, + foreground=text_color, width=10, anchor="w") + brightness_l.pack(side="left", padx=5) + self.brightness_b = tk.Scale(brightness_frame, from_=0, to=100, sliderrelief='raised', command=lambda e: self.adjust(e, 'brightness'), - orient="horizontal", highlightthickness=0, background=background_color1, - fg='white', - troughcolor='#73B5FA', activebackground='#1065BF') - self.brightness_b.place(x=120, y=120) - - cancel_b = tk.Button(f1, text="Cancel", command=self.cancel, relief="solid", background=background_color1, - foreground="red", font="lucida 12 bold", cursor="hand2") - cancel_b.bind("", lambda e: mouse_hover(cancel_b)) - cancel_b.bind("", lambda e: mouse_not_hover(cancel_b)) - cancel_b.place(x=45, y=220) - - apply_b = tk.Button(f1, text="Apply", command=self.apply, relief="solid", background=background_color1, - foreground="red", - font="lucida 12 bold", padx=8, cursor="hand2") - apply_b.bind("", lambda e: mouse_hover(apply_b)) - apply_b.bind("", lambda e: mouse_not_hover(apply_b)) - apply_b.place(x=130, y=220) + orient="horizontal", highlightthickness=1, background=background_color1, + fg=text_color, + troughcolor='#dfe6e9', activebackground='#74b9ff', length=200, bd=2) + self.brightness_b.set(50) + self.brightness_b.pack(side="left", padx=5) + + buttons_frame = tk.Frame(f1, background=background_color1) + buttons_frame.pack(fill="x", pady=15) + + cancel_b = tk.Button(buttons_frame, text="Cancel", command=self.cancel, relief="raised", background=button_bg_cancel, + foreground=button_fg_cancel, font=button_font, cursor="hand2", padx=30, pady=10, + activebackground='#fadbd8', bd=3, highlightbackground=button_border_color_cancel) + cancel_b.bind("", lambda e: mouse_hover(cancel_b, color='#fadbd8')) + cancel_b.bind("", lambda e: mouse_not_hover(cancel_b, color=button_bg_cancel)) + cancel_b.pack(side="left", padx=30, expand=True) + + apply_b = tk.Button(buttons_frame, text="Apply", command=self.apply, relief="raised", background=button_bg_apply, + foreground=button_fg_apply, + font=button_font, padx=30, pady=10, cursor="hand2", activebackground='#d4e6f1', bd=3, + highlightbackground=button_border_color_apply) + apply_b.bind("", lambda e: mouse_hover(apply_b, color='#d4e6f1')) + apply_b.bind("", lambda e: mouse_not_hover(apply_b, color=button_bg_apply)) + apply_b.pack(side="left", padx=30, expand=True) def adjust(self, e, changes): im2 = self.image_copy @@ -851,37 +997,37 @@ def adjust(self, e, changes): im2_resized = self.modified_img_resized if changes == 'sharpness': - self.modifications['sharpness'] = int(e) / 10 + self.modifications['sharpness'] = int(e) / 50.0 * 3.0 enhancer = ImageEnhance.Sharpness(self.modified_img) - self.modified_img = enhancer.enhance(int(e) / 10) + self.modified_img = enhancer.enhance(int(e) / 50.0 * 3.0) enhancer = ImageEnhance.Sharpness(self.modified_img_resized) - self.modified_img_resized = enhancer.enhance(int(e) / 10) + self.modified_img_resized = enhancer.enhance(int(e) / 50.0 * 3.0) im = ImageTk.PhotoImage(self.modified_img_resized) self.parent.show_image(modified=im) elif changes == 'contrast': - self.modifications['contrast'] = int(e) / 10 + self.modifications['contrast'] = int(e) / 50.0 enhancer = ImageEnhance.Contrast(self.modified_img) - self.modified_img = enhancer.enhance(int(e) / 10) + self.modified_img = enhancer.enhance(int(e) / 50.0) enhancer = ImageEnhance.Contrast(self.modified_img_resized) - self.modified_img_resized = enhancer.enhance(int(e) / 10) + self.modified_img_resized = enhancer.enhance(int(e) / 50.0) im = ImageTk.PhotoImage(self.modified_img_resized) self.parent.show_image(modified=im) elif changes == 'brightness': - self.modifications['brightness'] = int(e) / 10 + self.modifications['brightness'] = int(e) / 50.0 enhancer = ImageEnhance.Brightness(self.modified_img) - self.modified_img = enhancer.enhance(int(e) / 10) + self.modified_img = enhancer.enhance(int(e) / 50.0) enhancer = ImageEnhance.Brightness(self.modified_img_resized) - self.modified_img_resized = enhancer.enhance(int(e) / 10) + self.modified_img_resized = enhancer.enhance(int(e) / 50.0) im = ImageTk.PhotoImage(self.modified_img_resized) self.parent.show_image(modified=im) @@ -898,7 +1044,7 @@ def apply(self): self.grab_release() for i in (self.brightness_b, self.contrast_b, self.sharpness_b): - if i.get() != 10: + if i.get() != 50: self.parent.save_b.configure(state="normal") break @@ -914,12 +1060,17 @@ class Filters(tk.Toplevel): def __init__(self, parent, image_copy, modified_img, image_copy_resized, modified_img_resized): super().__init__(parent) - self.configure(background="grey") - self.wm_overrideredirect(True) + self.configure(background="#ffffff") + self.geometry("350x550+700+200") + self.title("Filters") + self.transient(parent) self.grab_set() - self.winfo_parent() - self.geometry("150x250+1328+100") self.filter_ = None + self.filter_intensity = 50 + self.full_filter_img = None + self.full_filter_img_resized = None + self.current_filter_button = None + self.filter_buttons = {} self.parent = parent @@ -929,88 +1080,206 @@ def __init__(self, parent, image_copy, modified_img, image_copy_resized, modifie self.image_copy_resized = image_copy_resized self.modified_img_resized = modified_img_resized - background_color1 = '#19191a' - foreground_color = 'sky blue' + background_color1 = '#ffffff' + title_color = '#0984e3' + text_color = '#2d3436' + button_normal_color = '#dfe6e9' + button_hover_color = '#b2bec3' + button_bg_cancel = 'white' + button_bg_apply = 'white' + button_fg_cancel = '#c0392b' + button_fg_apply = '#2980b9' + button_border_color_cancel = '#c0392b' + button_border_color_apply = '#2980b9' + button_font = "Arial 12 bold" f1 = tk.Frame(self, background=background_color1) - f1.pack(fill="both", expand=True, padx=5, pady=5) + f1.pack(fill="both", expand=True, padx=15, pady=15) - tk.Label(f1, text="Filters", background="black", foreground="#ba5a14", font="lucida 11 bold").pack(fill="x") + title_label = tk.Label(f1, text="Filters", background=title_color, foreground='white', + font="lucida 12 bold", pady=8) + title_label.pack(fill="x") filters_frame = tk.Frame(f1, background=background_color1) - filters_frame.pack(fill="both", expand=True) - - buttons_frame = tk.Frame(f1, background="black", pady=0) - buttons_frame.pack(fill="both", expand=True) - - emboss_b = tk.Button(filters_frame, text="Emboss", font="lucida 8 bold", command=lambda: self.filters(emboss_b), - foreground=foreground_color, background="black", padx=17, cursor="hand2") - emboss_b.bind("", lambda e: mouse_hover(button=emboss_b)) - emboss_b.bind("", lambda e: mouse_not_hover(button=emboss_b)) - emboss_b.pack(pady=9) - - grey_b = tk.Button(filters_frame, text="Grey", font="lucida 8 bold", command=lambda: self.filters(grey_b), - foreground=foreground_color, background="black", padx=8, cursor="hand2") - grey_b.bind("", lambda e: mouse_hover(button=grey_b)) - grey_b.bind("", lambda e: mouse_not_hover(button=grey_b)) - grey_b.pack(pady=9) - - negative_b = tk.Button(filters_frame, text="Negative", font="lucida 8 bold", - command=lambda: self.filters(negative_b), foreground=foreground_color, - background="black", padx=17, cursor="hand2") - negative_b.bind("", lambda e: mouse_hover(button=negative_b)) - negative_b.bind("", lambda e: mouse_not_hover(button=negative_b)) - negative_b.pack(pady=9) - - blur_b = tk.Button(filters_frame, text="Gaussian Blur", font="lucida 8 bold", - command=lambda: self.filters(blur_b), foreground=foreground_color, - background="black", padx=17, cursor="hand2") - blur_b.bind("", lambda e: mouse_hover(button=blur_b)) - blur_b.bind("", lambda e: mouse_not_hover(button=blur_b)) - blur_b.pack(pady=9) - - cancel_b = tk.Button(f1, text="Cancel", command=self.cancel, background='black', - foreground=foreground_color, font="lucida 12 bold", cursor="hand2") - cancel_b.bind("", lambda e: mouse_hover(button=cancel_b)) - cancel_b.bind("", lambda e: mouse_not_hover(button=cancel_b)) - cancel_b.pack(side="left") - - apply_b = tk.Button(f1, text="Apply", command=self.apply, background='black', foreground=foreground_color, - font="lucida 12 bold", padx=8, cursor="hand2") - apply_b.bind("", lambda e: mouse_hover(button=apply_b)) - apply_b.bind("", lambda e: mouse_not_hover(button=apply_b)) - apply_b.pack(side="left") + filters_frame.pack(fill="both", expand=True, pady=15) + + emboss_b = tk.Button(filters_frame, text="Emboss", font="lucida 10 bold", command=lambda: self.filters(emboss_b), + foreground=text_color, background=button_normal_color, padx=20, pady=8, + cursor="hand2", relief="raised", activebackground=button_hover_color, bd=2) + emboss_b.bind("", lambda e: mouse_hover(emboss_b, color=button_hover_color)) + emboss_b.bind("", lambda e: self.on_filter_button_leave(emboss_b)) + emboss_b.pack(fill="x", pady=5) + self.filter_buttons['emboss'] = emboss_b + + grey_b = tk.Button(filters_frame, text="Grey", font="lucida 10 bold", command=lambda: self.filters(grey_b), + foreground=text_color, background=button_normal_color, padx=20, pady=8, + cursor="hand2", relief="raised", activebackground=button_hover_color, bd=2) + grey_b.bind("", lambda e: mouse_hover(grey_b, color=button_hover_color)) + grey_b.bind("", lambda e: self.on_filter_button_leave(grey_b)) + grey_b.pack(fill="x", pady=5) + self.filter_buttons['grey'] = grey_b + + negative_b = tk.Button(filters_frame, text="Negative", font="lucida 10 bold", + command=lambda: self.filters(negative_b), foreground=text_color, + background=button_normal_color, padx=20, pady=8, + cursor="hand2", relief="raised", activebackground=button_hover_color, bd=2) + negative_b.bind("", lambda e: mouse_hover(negative_b, color=button_hover_color)) + negative_b.bind("", lambda e: self.on_filter_button_leave(negative_b)) + negative_b.pack(fill="x", pady=5) + self.filter_buttons['negative'] = negative_b + + blur_b = tk.Button(filters_frame, text="Gaussian Blur", font="lucida 10 bold", + command=lambda: self.filters(blur_b), foreground=text_color, + background=button_normal_color, padx=20, pady=8, + cursor="hand2", relief="raised", activebackground=button_hover_color, bd=2) + blur_b.bind("", lambda e: mouse_hover(blur_b, color=button_hover_color)) + blur_b.bind("", lambda e: self.on_filter_button_leave(blur_b)) + blur_b.pack(fill="x", pady=5) + self.filter_buttons['gaussian blur'] = blur_b + + intensity_frame = tk.Frame(f1, background=background_color1) + intensity_frame.pack(fill="x", pady=10) + + intensity_header = tk.Frame(intensity_frame, background=background_color1) + intensity_header.pack(fill="x") + + intensity_label = tk.Label(intensity_header, text="Intensity", font="lucida 10 bold", + background=background_color1, foreground=text_color) + intensity_label.pack(side="left", padx=5) + + self.intensity_value_label = tk.Label(intensity_header, text="50%", font="lucida 10 bold", + background=background_color1, foreground=text_color) + self.intensity_value_label.pack(side="right", padx=5) + + self.intensity_scale = tk.Scale(intensity_frame, from_=0, to=100, sliderrelief='raised', + command=self.adjust_intensity, + orient="horizontal", highlightthickness=1, + background=background_color1, fg=text_color, + troughcolor='#dfe6e9', activebackground='#74b9ff', + length=280, bd=2, state='disabled', showvalue=False) + self.intensity_scale.set(50) + self.intensity_scale.pack(fill="x", padx=5, pady=5) + + clear_frame = tk.Frame(f1, background=background_color1) + clear_frame.pack(fill="x", pady=5) + + clear_b = tk.Button(clear_frame, text="Clear Filter", font="lucida 10 bold", + command=self.clear_filter, foreground=button_fg_cancel, + background=button_bg_cancel, padx=20, pady=8, + cursor="hand2", relief="raised", activebackground='#fadbd8', bd=3, + highlightbackground=button_border_color_cancel) + clear_b.bind("", lambda e: mouse_hover(clear_b, color='#fadbd8')) + clear_b.bind("", lambda e: mouse_not_hover(clear_b, color=button_bg_cancel)) + clear_b.pack(fill="x", pady=5) + + buttons_frame = tk.Frame(f1, background=background_color1) + buttons_frame.pack(fill="x", pady=15) + + cancel_b = tk.Button(buttons_frame, text="Cancel", command=self.cancel, background=button_bg_cancel, + foreground=button_fg_cancel, font=button_font, cursor="hand2", + padx=25, pady=10, relief="raised", activebackground='#fadbd8', bd=3, + highlightbackground=button_border_color_cancel) + cancel_b.bind("", lambda e: mouse_hover(cancel_b, color='#fadbd8')) + cancel_b.bind("", lambda e: mouse_not_hover(cancel_b, color=button_bg_cancel)) + cancel_b.pack(side="left", expand=True) + + apply_b = tk.Button(buttons_frame, text="Apply", command=self.apply, background=button_bg_apply, + foreground=button_fg_apply, font=button_font, padx=25, pady=10, + cursor="hand2", relief="raised", activebackground='#d4e6f1', bd=3, + highlightbackground=button_border_color_apply) + apply_b.bind("", lambda e: mouse_hover(apply_b, color='#d4e6f1')) + apply_b.bind("", lambda e: mouse_not_hover(apply_b, color=button_bg_apply)) + apply_b.pack(side="left", expand=True) def filters(self, button): + if self.current_filter_button is not None: + self.current_filter_button.configure(highlightbackground='#dfe6e9', relief='raised') + self.filter_ = button['text'].lower() + self.current_filter_button = button + self.filter_intensity = 50 + + button.configure(highlightbackground='#74b9ff', relief='sunken') - if self.filter_ == 'emboss': - self.modified_img = self.image_copy.filter(ImageFilter.EMBOSS) + self.intensity_scale.configure(state='normal') + self.intensity_scale.set(50) - self.modified_img_resized = self.image_copy_resized.filter(ImageFilter.EMBOSS) - im = ImageTk.PhotoImage(self.modified_img_resized) - self.parent.show_image(modified=im) + if self.filter_ == 'emboss': + self.full_filter_img = self.image_copy.filter(ImageFilter.EMBOSS) + self.full_filter_img_resized = self.image_copy_resized.filter(ImageFilter.EMBOSS) elif self.filter_ == 'negative': - self.modified_img = ImageOps.invert(self.image_copy) - - self.modified_img_resized = ImageOps.invert(self.image_copy_resized) - im = ImageTk.PhotoImage(self.modified_img_resized) - self.parent.show_image(modified=im) + self.full_filter_img = ImageOps.invert(self.image_copy.convert('RGB')) + self.full_filter_img_resized = ImageOps.invert(self.image_copy_resized.convert('RGB')) elif self.filter_ == 'grey': - self.modified_img = ImageOps.grayscale(self.image_copy) - - self.modified_img_resized = ImageOps.grayscale(self.image_copy_resized) - im = ImageTk.PhotoImage(self.modified_img_resized) - self.parent.show_image(modified=im) + self.full_filter_img = ImageOps.grayscale(self.image_copy) + self.full_filter_img_resized = ImageOps.grayscale(self.image_copy_resized) elif self.filter_ == 'gaussian blur': - self.modified_img = self.image_copy.filter(ImageFilter.GaussianBlur) + self.full_filter_img = self.image_copy.filter(ImageFilter.GaussianBlur) + self.full_filter_img_resized = self.image_copy_resized.filter(ImageFilter.GaussianBlur) - self.modified_img_resized = self.image_copy_resized.filter(ImageFilter.GaussianBlur) - im = ImageTk.PhotoImage(self.modified_img_resized) - self.parent.show_image(modified=im) + self.apply_filter_with_intensity() + + def apply_filter_with_intensity(self): + if self.full_filter_img is None or self.full_filter_img_resized is None: + return + + intensity = self.filter_intensity + self.intensity_value_label.configure(text=f"{intensity}%") + + if intensity == 0: + self.modified_img = self.image_copy + self.modified_img_resized = self.image_copy_resized + elif intensity == 100: + self.modified_img = self.full_filter_img + self.modified_img_resized = self.full_filter_img_resized + else: + alpha = intensity / 100.0 + + original_img_rgb = self.image_copy.convert('RGB') + filtered_img_rgb = self.full_filter_img.convert('RGB') + + original_img_resized_rgb = self.image_copy_resized.convert('RGB') + filtered_img_resized_rgb = self.full_filter_img_resized.convert('RGB') + + self.modified_img = Image.blend(original_img_rgb, filtered_img_rgb, alpha) + self.modified_img_resized = Image.blend(original_img_resized_rgb, filtered_img_resized_rgb, alpha) + + im = ImageTk.PhotoImage(self.modified_img_resized) + self.parent.show_image(modified=im) + + def adjust_intensity(self, value): + if self.full_filter_img is not None: + self.filter_intensity = int(value) + self.apply_filter_with_intensity() + + def clear_filter(self): + self.filter_ = None + self.full_filter_img = None + self.full_filter_img_resized = None + self.filter_intensity = 50 + + if self.current_filter_button is not None: + self.current_filter_button.configure(highlightbackground='#dfe6e9', relief='raised') + self.current_filter_button = None + + self.intensity_scale.set(50) + self.intensity_scale.configure(state='disabled') + self.intensity_value_label.configure(text="50%") + + self.modified_img = self.image_copy + self.modified_img_resized = self.image_copy_resized + + im = ImageTk.PhotoImage(self.image_copy_resized) + self.parent.show_image(modified=im) + + def on_filter_button_leave(self, button): + if self.current_filter_button == button: + button.configure(highlightbackground='#74b9ff') + else: + button.configure(highlightbackground='#dfe6e9') def cancel(self): self.grab_release()