54 lines
2.0 KiB
Python
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()
|