Skip to content

Commit 6360eb5

Browse files
committed
Improve image conversion
Preserve icc_profile convert image to RGBA or RGB
1 parent 5927c0e commit 6360eb5

File tree

2 files changed

+74
-52
lines changed

2 files changed

+74
-52
lines changed

ImageToWEBP.py

Lines changed: 63 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -6,69 +6,86 @@
66
import threading
77
import time
88

9+
VERSION = "1.0.1"
910

10-
def convert_to_webp():
11-
file_paths = filedialog.askopenfilenames(title="Select image files",
12-
filetypes=[("Image files", "*.png;*.jpg;*.jpeg;*.bmp;*.tiff")])
11+
class ImageConverterApp:
12+
def __init__(self, root):
13+
self.root = root
14+
self.root.title(f"Image to WebP Converter | V{VERSION}")
15+
self.root.geometry("300x150")
1316

14-
if not file_paths:
15-
return
17+
self.btn_select = tk.Button(root, text="Select Images & Convert", command=self.convert_to_webp, padx=10, pady=5)
18+
self.btn_select.pack(pady=10)
1619

17-
save_dir = filedialog.askdirectory(title="Select destination folder")
18-
if not save_dir:
19-
return
20+
self.progress_label = tk.Label(root, text="0/0 images processed", font=("Arial", 12))
21+
self.progress_label.pack(pady=5)
2022

21-
progress_label.config(text=f"0/{len(file_paths)} images processed")
22-
time_label.config(text="Elapsed time: 0 seconds")
23+
self.status_label = tk.Label(root, text="", font=("Arial", 10), fg="green")
24+
self.status_label.pack(pady=5)
2325

24-
remaining_files = list(file_paths)
26+
self.start_time = 0
27+
self.completed_count = 0
28+
self.num_files = 0
29+
self.lock = None
2530

26-
start_time = time.time()
31+
def convert_to_webp(self):
32+
file_paths = filedialog.askopenfilenames(title="Select image files",
33+
filetypes=[("Image files", "*.png;*.jpg;*.jpeg")])
34+
if not file_paths:
35+
return
2736

28-
def convert_image(file_path):
29-
try:
30-
img = Image.open(file_path)
31-
file_name = os.path.splitext(os.path.basename(file_path))[0] + ".webp"
32-
save_path = os.path.join(save_dir, file_name)
33-
if img.format == "JPEG":
34-
img.save(save_path, "webp", lossy=True)
35-
else:
36-
img.save(save_path, "webp", lossless=True)
37+
save_dir = filedialog.askdirectory(title="Select destination folder")
38+
if not save_dir:
39+
return
3740

38-
remaining_files.remove(file_path)
39-
progress_label.config(text=f"{len(file_paths) - len(remaining_files)}/{len(file_paths)} images processed")
41+
self.num_files = len(file_paths)
42+
self.progress_label.config(text=f"0/{self.num_files} images processed")
43+
self.status_label.config(text="", fg="green")
4044

41-
elapsed_time = time.time() - start_time
42-
time_label.config(text=f"Elapsed time: {int(elapsed_time)} seconds")
43-
root.update_idletasks()
44-
except Exception as e:
45-
messagebox.showerror("Error", f"Failed to convert {file_path}: {e}")
45+
self.start_time = time.time()
46+
self.completed_count = 0
47+
self.lock = None
4648

47-
def convert_images():
48-
max_workers = os.cpu_count() // 2
49+
def convert_image(file_path):
50+
try:
51+
img = Image.open(file_path)
52+
file_name = os.path.splitext(os.path.basename(file_path))[0] + ".webp"
53+
save_path = os.path.join(save_dir, file_name)
4954

50-
with ThreadPoolExecutor(max_workers=max_workers) as executor:
51-
futures = [executor.submit(convert_image, file_path) for file_path in file_paths]
52-
for future in futures:
53-
future.result()
55+
icc_profile = img.info.get("icc_profile")
5456

55-
total_time = time.time() - start_time
56-
messagebox.showinfo("Success", f"All images have been converted to WebP.\nTotal time: {int(total_time)} seconds.")
57+
if img.mode in ("P", "CMYK"):
58+
img = img.convert("RGBA" if img.mode == "P" else "RGB")
5759

58-
threading.Thread(target=convert_images, daemon=True).start()
60+
if img.format == "JPEG":
61+
img.save(save_path, "webp", lossy=True, icc_profile=icc_profile)
62+
else:
63+
img.save(save_path, "webp", lossless=True, icc_profile=icc_profile)
5964

65+
with self.lock:
66+
self.completed_count += 1
67+
self.update_progress()
6068

61-
root = tk.Tk()
62-
root.title("Image to WebP Converter")
63-
root.geometry("300x150")
69+
except Exception as e:
70+
print(f"Error converting {file_path}: {e}")
71+
72+
def run_conversion():
73+
self.lock = threading.Lock()
74+
max_workers = max(1, os.cpu_count() // 2)
75+
with ThreadPoolExecutor(max_workers=max_workers) as executor:
76+
executor.map(convert_image, file_paths)
6477

65-
btn_select = tk.Button(root, text="Select Images & Convert", command=convert_to_webp, padx=10, pady=5)
66-
btn_select.pack(pady=10)
78+
self.show_completion_message()
6779

68-
progress_label = tk.Label(root, text="0/0 images processed", font=("Arial", 12))
69-
progress_label.pack(pady=5)
80+
threading.Thread(target=run_conversion, daemon=True).start()
7081

71-
time_label = tk.Label(root, text="Elapsed time: 0 seconds", font=("Arial", 10))
72-
time_label.pack(pady=5)
82+
def update_progress(self):
83+
self.progress_label.config(text=f"{self.completed_count}/{self.num_files} images processed")
7384

85+
def show_completion_message(self):
86+
total_time = int(time.time() - self.start_time)
87+
self.root.after(0, lambda: self.status_label.config(text=f"Conversion completed in {total_time} seconds!", fg="blue"))
88+
89+
root = tk.Tk()
90+
app = ImageConverterApp(root)
7491
root.mainloop()

MapArtsMerger.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from tkinter import filedialog, messagebox
44
from PIL import Image, ImageTk
55

6-
VERSION = "1.0.0"
6+
VERSION = "1.0.1"
77

88
class ImageMerger:
99
def __init__(self, root):
@@ -77,7 +77,7 @@ def select_images(self):
7777
self.blank_image = ImageTk.PhotoImage(Image.new("RGB", (self.preview_size, self.preview_size), "white"))
7878

7979
max_images = self.row_count * self.col_count
80-
files = sorted(filedialog.askopenfilenames(filetypes=[("Image Files", "*.png;*.jpg;*.jpeg;*.webp")]),
80+
files = sorted(filedialog.askopenfilenames(filetypes=[("Image Files", "*.png;*.webp")]),
8181
key=self.extract_number)
8282

8383
if len(files) > max_images:
@@ -94,7 +94,9 @@ def load_image(self, img_path, size):
9494
return self.image_cache[img_path]
9595

9696
if img_path:
97-
img = Image.open(img_path).resize((size, size))
97+
img = Image.open(img_path)
98+
img = img.convert("RGBA" if img.mode in ("P", "CMYK") else "RGB")
99+
img = img.resize((size, size))
98100
img_tk = ImageTk.PhotoImage(img)
99101
self.image_cache[img_path] = img_tk
100102
return img_tk
@@ -129,7 +131,7 @@ def handle_image_click(self, idx):
129131
self.replace_image(idx)
130132

131133
def replace_image(self, idx):
132-
file_path = filedialog.askopenfilename(filetypes=[("Image Files", "*.png;*.jpg;*.jpeg;*.webp")])
134+
file_path = filedialog.askopenfilename(filetypes=[("Image Files", "*.png;*.webp")])
133135
if file_path:
134136
self.image_cache.pop(self.images[idx], None)
135137
self.images[idx] = file_path
@@ -171,14 +173,17 @@ def merge_images(self):
171173

172174
merged = Image.new("RGB", (self.col_count * 128, self.row_count * 128))
173175
for i, img_path in enumerate(self.images):
174-
img = Image.open(img_path).resize((128, 128)) if img_path else Image.new("RGB", (128, 128), "white")
176+
img = Image.open(img_path) if img_path else Image.new("RGB", (128, 128), "white")
177+
img = img.convert("RGBA" if img.mode in ("P", "CMYK") else "RGB")
178+
img = img.resize((128, 128))
175179
merged.paste(img, ((i % self.col_count) * 128, (i // self.col_count) * 128))
176180

177181
save_path = filedialog.asksaveasfilename(defaultextension=".webp",
178182
filetypes=[("WEBP files", "*.webp")],
179183
initialfile=f"[{map_id}]-{map_name}")
180184
if save_path:
181-
merged.save(save_path, "WEBP", lossless=True)
185+
icc_profile = merged.info.get("icc_profile")
186+
merged.save(save_path, "WEBP", lossless=True, icc_profile=icc_profile)
182187
messagebox.showinfo("Success", "Image merged successfully!")
183188

184189
def on_closing():

0 commit comments

Comments
 (0)