← back to Japan Enrich
make_sangetsu_swatches.py
47 lines
#!/usr/bin/env python3
"""
Downscale the full-res Sangetsu colorway images (images/sangetsu/, ~2.1 GB, fetched
by enrich_sangetsu.py for hex accuracy) into small 256px card swatches
(images/sangetsu-sw/) so the viewer can serve /img/sangetsu/<sku> self-contained
and ship disk-safe to Kamatera — same pattern as the Greenland swatches.
$0 local (Pillow). Skip-existing + concurrency. Originals are left untouched.
"""
import os, concurrent.futures as cf
from PIL import Image
SRC = "images/sangetsu"
DST = "images/sangetsu-sw"
MAX = 256
os.makedirs(DST, exist_ok=True)
def one(fn):
if not fn.lower().endswith((".jpg", ".jpeg")):
return 0
dst = os.path.join(DST, fn)
if os.path.exists(dst) and os.path.getsize(dst) > 0:
return 0
try:
with Image.open(os.path.join(SRC, fn)) as im:
im = im.convert("RGB")
im.thumbnail((MAX, MAX))
im.save(dst, "JPEG", quality=82, optimize=True)
return 1
except Exception:
return 0
def main():
files = [f for f in os.listdir(SRC) if f.lower().endswith((".jpg", ".jpeg"))]
print(f"sangetsu swatches: {len(files)} source images -> {DST} (max {MAX}px)", flush=True)
made = skipped = 0
with cf.ThreadPoolExecutor(max_workers=8) as ex:
for i, r in enumerate(ex.map(one, files), 1):
made += r; skipped += (1 - r)
if i % 2000 == 0:
print(f" {i}/{len(files)} ({made} made)", flush=True)
total = len([f for f in os.listdir(DST) if f.lower().endswith((".jpg", ".jpeg"))])
print(f"DONE: {made} made this run; {total} swatches in {DST}", flush=True)
if __name__ == "__main__":
main()