Skip to content

Commit c6c6410

Browse files
feat(utils): conv2web -imgs w/ dir spec
1 parent 5f6ba5d commit c6c6410

1 file changed

Lines changed: 82 additions & 0 deletions

File tree

utils/conv2webp.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import sys
2+
from pathlib import Path
3+
from PIL import Image, ImageSequence
4+
5+
SUPPORTED_EXTS = {".png", ".jpg", ".jpeg", ".gif"}
6+
7+
def convert_image(image_path: Path):
8+
output_path = image_path.with_suffix(".webp")
9+
10+
if output_path.exists():
11+
print(f"[SKIP] {output_path.relative_to(ROOT_DIR)}")
12+
return False
13+
14+
try:
15+
with Image.open(image_path) as img:
16+
is_animated = getattr(img, "is_animated", False)
17+
18+
if is_animated:
19+
frames = []
20+
durations = []
21+
22+
for frame in ImageSequence.Iterator(img):
23+
frames.append(frame.convert("RGBA"))
24+
durations.append(frame.info.get("duration", 100))
25+
26+
frames[0].save(
27+
output_path,
28+
format="WEBP",
29+
save_all=True,
30+
append_images=frames[1:],
31+
duration=durations,
32+
loop=img.info.get("loop", 0),
33+
lossless=True
34+
)
35+
else:
36+
img.save(output_path, format="WEBP", lossless=True)
37+
38+
print(f"[OK] {image_path.relative_to(ROOT_DIR)}")
39+
return True
40+
41+
except Exception as e:
42+
print(f"[ERR] {image_path}: {e}")
43+
return False
44+
45+
46+
def main():
47+
if len(sys.argv) < 2:
48+
print("Usage: python utils/conv2webp.py <folder_from_root> [--recursive]")
49+
sys.exit(1)
50+
51+
folder_arg = sys.argv[1]
52+
recursive = "--recursive" in sys.argv
53+
54+
global ROOT_DIR
55+
ROOT_DIR = Path(__file__).resolve().parent.parent
56+
target_dir = ROOT_DIR / folder_arg
57+
58+
if not target_dir.exists() or not target_dir.is_dir():
59+
print(f"[ERROR] Folder does not exist: {target_dir}")
60+
sys.exit(1)
61+
62+
if recursive:
63+
files = [p for p in target_dir.rglob("*") if p.suffix.lower() in SUPPORTED_EXTS]
64+
else:
65+
files = [p for p in target_dir.iterdir() if p.is_file() and p.suffix.lower() in SUPPORTED_EXTS]
66+
67+
if not files:
68+
print("[INFO] No supported images found.")
69+
return
70+
71+
print(f"[INFO] Found {len(files)} image(s)")
72+
converted = 0
73+
74+
for img in files:
75+
if convert_image(img):
76+
converted += 1
77+
78+
print(f"[DONE] Converted {converted}/{len(files)} images")
79+
80+
81+
if __name__ == "__main__":
82+
main()

0 commit comments

Comments
 (0)