Spaces:
Running on Zero
Running on Zero
Download make_thumbs.py from SharpMeow/lasagna-fields: direct link, hf CLI and curl.
- Browser
- Download file 2.87 kB
-
https://huggingface.co/spaces/SharpMeow/lasagna-fields/resolve/main/make_thumbs.py
- Command line
-
hf download hf://spaces/SharpMeow/lasagna-fields/make_thumbs.py
-
curl -L -o make_thumbs.py https://huggingface.co/spaces/SharpMeow/lasagna-fields/resolve/main/make_thumbs.py
2.87 kB
| """Card pictures for the Every field tab: each field's xy preview (cos | normals; preview_xy in fields.json, a | |
| dataset's preview-xy.png or, for villa's fields in the open data, the picture make_previews.py wrote) as a small 2:1 | |
| WebP (fitted whole, on black) under assets/thumbs/SCROLL-VOLUME.webp. The guide falls back to the preview itself when | |
| a thumb is missing. Like the rest of assets/, the thumbs live on the Space, not in git. | |
| python3 spaces/lasagna-fields/make_thumbs.py OUT_DIR [PREVIEWS_DIR] (then upload OUT_DIR as assets/thumbs/) | |
| PREVIEWS_DIR, make_previews.py's output, is read before the Space has the open-data previews. | |
| """ | |
| import io | |
| import json | |
| import sys | |
| import urllib.request | |
| from pathlib import Path | |
| HERE = Path(__file__).resolve().parent | |
| W, H = 720, 360 | |
| def trim(im): | |
| """The picture without its title bar and empty margins: the panels are pure black where the field is empty, the | |
| title bar and labels sit on a dark gray canvas around them, so keep the black panels' box, then the content in it.""" | |
| import numpy as np | |
| a = np.asarray(im).astype(int) | |
| canvas = a[0, 0].copy() | |
| black = (a.max(axis=2) <= 3) | |
| ys, xs = np.nonzero(black) | |
| if len(ys) and (ys.max() - ys.min()) * (xs.max() - xs.min()) > 0.3 * a.shape[0] * a.shape[1]: | |
| a = a[ys.min():ys.max() + 1, xs.min():xs.max() + 1] | |
| if canvas.max() > 3: # the canvas strip between the panels turns black too | |
| a = a.copy() | |
| a[np.abs(a - canvas).max(axis=2) <= 4] = 0 | |
| ys, xs = np.nonzero(a.max(axis=2) > 24) | |
| if len(ys): | |
| pad = 8 | |
| a = a[max(0, ys.min() - pad):ys.max() + 1 + pad, max(0, xs.min() - pad):xs.max() + 1 + pad] | |
| from PIL import Image | |
| return Image.fromarray(a.astype("uint8")) | |
| def main(argv=None): | |
| from PIL import Image | |
| args = argv or sys.argv[1:] | |
| out = Path(args[0]) | |
| local = Path(args[1]) if len(args) > 1 else None | |
| out.mkdir(parents=True, exist_ok=True) | |
| doc = json.loads((HERE / "fields.json").read_text()) | |
| for f in doc["fields"]: | |
| name = f"{f['scroll']}-{f['volume']}" | |
| url = f["preview_xy"] | |
| here = local / url.rsplit("/", 1)[1] if local else None | |
| raw = here.read_bytes() if here and here.is_file() else urllib.request.urlopen(url, timeout=120).read() | |
| im = trim(Image.open(io.BytesIO(raw)).convert("RGB")) | |
| r = min(W / im.width, H / im.height) # contain, centered on black like the panels | |
| im = im.resize((round(im.width * r), round(im.height * r)), Image.LANCZOS) | |
| canvas = Image.new("RGB", (W, H)) | |
| canvas.paste(im, ((W - im.width) // 2, (H - im.height) // 2)) | |
| canvas.save(out / f"{name}.webp", "WEBP", quality=82, method=6) | |
| print(name, (out / f"{name}.webp").stat().st_size) | |
| return 0 | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |