Files
planet/scripts/prepare_card_images.py
rayd1o 05377bf5c6
Some checks failed
ci / backend (push) Has been cancelled
ci / frontend (push) Has been cancelled
ci / delivery (push) Has been cancelled
release / images (push) Has been cancelled
release: bump version to 0.76.0
2026-09-30 17:49:29 +08:00

54 lines
2.0 KiB
Python

"""Generate card-sized previews while preserving licensed source images and credits."""
import hashlib
import json
import sys
from pathlib import Path
from PIL import Image, ImageOps
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "backend"))
def main() -> None:
from app.services.card_image_files import render_variants
directory = ROOT / "frontend/public/earth/assets/cards"
manifest_path = directory / "manifest.json"
manifest = json.loads(manifest_path.read_text())
previews = directory / "previews"
previews.mkdir(exist_ok=True)
for asset in manifest["assets"]:
if asset.get("redistribution_status") == "permission_not_verified" and not asset.get(
"enabled", False
):
continue
source = (directory / asset["file"]).resolve()
if source.parent != directory.resolve():
raise ValueError("Asset path must stay inside cards")
if hashlib.sha256(source.read_bytes()).hexdigest() != asset["sha256"]:
raise ValueError(f"Source checksum changed: {asset['id']}")
with Image.open(source) as original:
image = ImageOps.exif_transpose(original).convert(
"RGBA" if "A" in original.getbands() else "RGB"
)
variants = render_variants(image)
asset["variants"] = {}
asset["variant_metadata"] = {}
for size, content in variants.items():
checksum = hashlib.sha256(content).hexdigest()
name = f"{asset['id']}-{size}-{checksum[:12]}.webp"
(previews / name).write_bytes(content)
asset["variants"][size] = f"/earth/assets/cards/previews/{name}"
asset["variant_metadata"][size] = {
"sha256": checksum,
"byte_length": len(content),
"modifications": "Resized to fit the indicated pixel bound and encoded as WebP; no upscaling or cropping",
}
manifest_path.write_text(json.dumps(manifest, ensure_ascii=False, indent=2) + "\n")
if __name__ == "__main__":
main()