Repository navigation
Expand file tree
/
Copy pathformat_icons.py
More file actions
120 lines (90 loc) · 3.37 KB
/
Copy pathformat_icons.py
File metadata and controls
120 lines (90 loc) · 3.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import logging
import os
import shutil
from pathlib import Path
from PIL import Image
from tqdm import tqdm
def same_pixels(a, b):
"""Compare decoded pixels, ignoring PNG compression differences."""
with Image.open(a) as ia, Image.open(b) as ib:
return ia.size == ib.size and ia.convert("RGBA").tobytes() == ib.convert("RGBA").tobytes()
def process_images(input_dir, quality, palette_colors):
total_files = 0
modified_files = 0
original_size = 0
new_size = 0
target_ext = ".png"
max_size = (144, 144)
# Create a temporary directory for processed images
temp_dir = os.path.join(input_dir, "temp_processed")
os.makedirs(temp_dir, exist_ok=True)
# Get list of files to process (excluding directories)
files_to_process = [
f
for f in os.listdir(input_dir)
if os.path.isfile(os.path.join(input_dir, f)) and not f.startswith("temp_processed")
]
# Initialize progress bar
progress_bar = tqdm(files_to_process, desc="Processing images", unit="file")
for filename in progress_bar:
filepath = os.path.join(input_dir, filename)
progress_bar.set_postfix(file=filename[:15] + "..." if len(filename) > 15 else filename)
try:
with Image.open(filepath) as img:
total_files += 1
original_size += os.path.getsize(filepath)
img.thumbnail(max_size, Image.LANCZOS)
if img.mode == "RGB":
img = img.convert("P", palette=Image.Palette.ADAPTIVE, colors=palette_colors)
# Remove metadata
img.info.pop("icc_profile", None)
# Prepare new filename
new_filename = Path(filename).stem + target_ext
temp_filepath = os.path.join(temp_dir, new_filename)
# Save with optimized settings
save_kwargs = {"compress_level": 9 - int((quality / 100) * 9), "optimize": True}
img.save(temp_filepath, "PNG", **save_kwargs)
# Keep the existing file if the pixels are identical (zlib output differs per platform)
existing = os.path.join(input_dir, new_filename)
if os.path.exists(existing) and same_pixels(temp_filepath, existing):
os.remove(temp_filepath)
new_size += os.path.getsize(existing)
continue
modified_files += 1
new_size += os.path.getsize(temp_filepath)
except Exception as e: # noqa: BLE001
logging.getLogger(__name__).warning(f"Could not process {filename}: {e!s}")
continue
# Replace original files with processed ones
if modified_files > 0:
for filename in os.listdir(temp_dir):
src = os.path.join(temp_dir, filename)
dst = os.path.join(input_dir, filename)
if os.path.exists(dst):
os.remove(dst)
shutil.move(src, dst)
# Clean up temporary directory
shutil.rmtree(temp_dir)
return total_files, modified_files, original_size, new_size
def main():
input_dir = "./icons"
if not os.path.exists(input_dir):
print(f"Error: Directory '{input_dir}' does not exist.")
return
total_files, modified_files, original_size, new_size = process_images(
input_dir=input_dir, quality=99, palette_colors=256
)
# Print results
print("\nProcessing complete.")
print(f"Total files processed: {total_files}")
print(f"Files modified: {modified_files}")
if modified_files > 0:
size_change = original_size - new_size
if size_change > 0:
print(f"Space saved: {size_change / 1024:.2f} KB ({size_change} bytes)")
elif size_change < 0:
print(f"Space increased: {-size_change / 1024:.2f} KB ({-size_change} bytes)")
else:
print("No change in total storage space")
if __name__ == "__main__":
main()