|
4 | 4 | # Copyright (c) 2016 dn0z
|
5 | 5 | # https://github.com/dn0z/Batch-Image-Resize
|
6 | 6 |
|
| 7 | +import imgedit |
7 | 8 | import os
|
8 |
| -import PIL.Image |
| 9 | + |
| 10 | +from enum import Enum |
9 | 11 | from tkinter import *
|
10 | 12 | from tkinter import ttk
|
11 | 13 | from tkinter import filedialog
|
12 | 14 | from tkinter import messagebox
|
13 | 15 |
|
14 | 16 |
|
| 17 | +class SettingsStatus(Enum): |
| 18 | + """ |
| 19 | + An enumeration of the settings statuses |
| 20 | + """ |
| 21 | + |
| 22 | + # valid settings |
| 23 | + valid_settings = 1 |
| 24 | + |
| 25 | + # invalid settings |
| 26 | + directory_not_selected = 2 |
| 27 | + directory_does_not_exist = 3 |
| 28 | + invalid_dimensions = 4 |
| 29 | + |
| 30 | + |
15 | 31 | class Application(Frame):
|
16 | 32 | def set_properties_defaults(self):
|
17 | 33 | """
|
@@ -46,111 +62,70 @@ def confirm_settings(self):
|
46 | 62 |
|
47 | 63 | return messagebox.askyesno("Export confirmation", confirm_msg)
|
48 | 64 |
|
49 |
| - def is_image(self, filename): |
| 65 | + def get_settings_status(self): |
50 | 66 | """
|
51 |
| - Checks if a filename is an image (png, jpg or jpeg, case insensitive) |
| 67 | + Check if our settings are valid (directory exists, width and height are digits etc) |
52 | 68 |
|
53 |
| - :param filename: The filename (as a string) |
54 |
| - :return: `True` if the given filename is an image, or `False` if it's not |
| 69 | + :return: The settings status as an enumeration member of the |
| 70 | + `SettingsStatus` enumeration (e.g. `SettingsStatus.valid_settings`) |
55 | 71 | """
|
56 | 72 |
|
57 |
| - file = filename.lower() |
58 |
| - return file.endswith(".png") or file.endswith(".jpg") or file.endswith(".jpeg") |
59 |
| - |
60 |
| - def get_filename_with_type(self, filename, file_type, suffix=""): |
61 |
| - """ |
62 |
| - Get a filename and return it with the given suffix and the correct file extension for the given type |
63 |
| -
|
64 |
| - :param filename: The filename (e.g. "image_file.jpg") |
65 |
| - :param file_type: The file type (e.g. "PNG") |
66 |
| - :param suffix: An optional string to place between the name and the extension of the file (default is "") |
67 |
| - :return: the filename with the correct extension for the given type (e.g. "image_file.png") |
68 |
| - """ |
69 |
| - |
70 |
| - extension = filename.split(".")[-1] |
71 |
| - return filename[:-(len(extension) + 1)] + suffix + "." + file_type.lower() |
72 |
| - |
73 |
| - def export_file(self, path, name, width, height, export_type, overwrite): |
74 |
| - """ |
75 |
| - Open, resize and save an image with the given properties |
76 |
| -
|
77 |
| - :param path: The path to the directory where the image is located (without the image filename) |
78 |
| - :param name: The filename of the image we want to export |
79 |
| - :param width: The new width we want to resize to |
80 |
| - :param height: The new height we want to resize to |
81 |
| - :param export_type: The file type we want to save to (we ignore it if `overwrite` is `True`) |
82 |
| - :param overwrite: Whether we want to overwrite the original files or not |
83 |
| - """ |
84 |
| - |
85 |
| - img_path = os.path.join(path, name) |
86 |
| - |
87 |
| - # open the given image and resize it |
88 |
| - img = PIL.Image.open(img_path) |
89 |
| - img = img.resize((width, height), PIL.Image.ANTIALIAS) |
90 |
| - |
91 |
| - # set the destination image file we want to save |
92 |
| - dest_img_name = self.get_filename_with_type(name, export_type, "_resized") |
93 |
| - if overwrite: |
94 |
| - dest_img_name = name |
95 |
| - |
96 |
| - # save the resized/converted image |
97 |
| - img.save(os.path.join(path, dest_img_name)) |
98 |
| - |
99 |
| - def init_export(self): |
100 |
| - """ |
101 |
| - Export all the images in the selected directory |
| 73 | + selected_directory = self.selected_directory.get() |
102 | 74 |
|
103 |
| - When `self.init_export()` is called, everything is ready to resize and export images |
104 |
| - This loops through all the files in the given directory and calls `self.export_file()` |
105 |
| - for the actual opening, resizing and saving of the files |
106 |
| - """ |
| 75 | + # Check if a directory is selected |
| 76 | + if selected_directory == "No directory selected": |
| 77 | + return SettingsStatus.directory_not_selected |
107 | 78 |
|
108 |
| - # final export settings |
109 |
| - directory_path = self.selected_directory.get() |
110 |
| - width = int(self.export_properties["width"].get()) |
111 |
| - height = int(self.export_properties["height"].get()) |
112 |
| - export_type = self.export_properties["type"].get() |
113 |
| - overwrite = self.overwrite_original.get() |
| 79 | + # Check if the selected directory exists |
| 80 | + if not os.path.isdir(selected_directory): |
| 81 | + return SettingsStatus.directory_does_not_exist |
114 | 82 |
|
115 |
| - # loop through the files in the given directory and export any image files |
116 |
| - for path, subdirs, files in os.walk(directory_path): |
117 |
| - for name in files: |
118 |
| - if self.is_image(name): |
119 |
| - # TODO: Add a new window with a progress bar while exporting images |
120 |
| - self.export_file(path, name, width, height, export_type, overwrite) |
| 83 | + # Check if width and height are digits |
| 84 | + if (not self.export_properties["width"].get().isdigit()) or \ |
| 85 | + (not self.export_properties["height"].get().isdigit()): |
| 86 | + return SettingsStatus.invalid_dimensions |
121 | 87 |
|
122 |
| - # at this point, we are done with our exports, display a success message |
123 |
| - messagebox.showinfo("Exports completed", "All images were exported successfully") |
| 88 | + return SettingsStatus.valid_settings |
124 | 89 |
|
125 | 90 | def export_button_handler(self):
|
126 | 91 | """
|
127 | 92 | The handler of the Export button
|
128 | 93 | """
|
129 | 94 |
|
130 |
| - selected_directory = self.selected_directory.get() |
131 |
| - |
132 |
| - # Check if we are ready to export |
133 |
| - if selected_directory == "No directory selected": |
134 |
| - # No directory selected |
135 |
| - messagebox.showerror("Invalid directory", "You have to select a directory first") |
| 95 | + settings_status = self.get_settings_status() |
| 96 | + |
| 97 | + if settings_status is not SettingsStatus.valid_settings: |
| 98 | + # Invalid settings, display an error message |
| 99 | + error_messages = { |
| 100 | + SettingsStatus.directory_not_selected: [ |
| 101 | + "Invalid directory", |
| 102 | + "You have to select a directory first" |
| 103 | + ], |
| 104 | + SettingsStatus.directory_does_not_exist: [ |
| 105 | + "Invalid directory", |
| 106 | + "The directory \"" + self.selected_directory.get() + "\" does not exist" |
| 107 | + ], |
| 108 | + SettingsStatus.invalid_dimensions: [ |
| 109 | + "Invalid dimensions", |
| 110 | + "Width and height must be integers" |
| 111 | + ], |
| 112 | + } |
| 113 | + messagebox.showerror(*error_messages[settings_status]) |
136 | 114 | else:
|
137 |
| - # Directory selected |
138 |
| - if not os.path.isdir(selected_directory): |
139 |
| - # Directory does not exist |
140 |
| - messagebox.showerror("Invalid directory", |
141 |
| - "The directory \"" + selected_directory + "\" does not exist") |
142 |
| - else: |
143 |
| - # Directory exists |
144 |
| - if (not self.export_properties["width"].get().isdigit()) or \ |
145 |
| - (not self.export_properties["height"].get().isdigit()): |
146 |
| - # Dimensions are not digits |
147 |
| - messagebox.showerror("Invalid dimensions", |
148 |
| - "Width and height must be integers") |
149 |
| - else: |
150 |
| - # Dimensions are digits |
151 |
| - if self.confirm_settings(): |
152 |
| - # Settings confirmed, we are ready to export |
153 |
| - self.init_export() |
| 115 | + # Valid settings, confirm settings with the user and export |
| 116 | + if self.confirm_settings(): |
| 117 | + result = imgedit.export_all_in_dir( |
| 118 | + self.selected_directory.get(), |
| 119 | + int(self.export_properties["width"].get()), |
| 120 | + int(self.export_properties["height"].get()), |
| 121 | + self.export_properties["type"].get(), |
| 122 | + self.overwrite_original.get() |
| 123 | + ) |
| 124 | + |
| 125 | + if result: |
| 126 | + # at this point, we are done with our exports, display a success message |
| 127 | + messagebox.showinfo("Exports completed", |
| 128 | + "All images were exported successfully") |
154 | 129 |
|
155 | 130 | def browse_for_directory(self):
|
156 | 131 | """
|
@@ -212,10 +187,10 @@ def create_widgets(self):
|
212 | 187 | save_as_label.grid(row=3, column=0, sticky="e")
|
213 | 188 |
|
214 | 189 | self.save_as_dropdown = ttk.OptionMenu(main_container,
|
215 |
| - self.export_properties["type"], |
216 |
| - self.export_properties["type"].get(), |
217 |
| - "PNG", |
218 |
| - "JPEG") |
| 190 | + self.export_properties["type"], |
| 191 | + self.export_properties["type"].get(), |
| 192 | + "PNG", |
| 193 | + "JPEG") |
219 | 194 | self.save_as_dropdown.grid(row=3, column=1, sticky="we", padx=2)
|
220 | 195 |
|
221 | 196 | # Overwrite original
|
|
0 commit comments