Files
matrix-screen-controller/核桃派软件源代码/app/mobile/preview_cache.py
T

49 lines
1.6 KiB
Python

"""Regenerable BLE library previews, isolated from user-owned media."""
from __future__ import annotations
import hashlib
import re
from io import BytesIO
from pathlib import Path
from PIL import Image
from app.persistence import atomic_write_bytes
_PREVIEW_FILE = re.compile(r"[0-9a-f]{64}\.png\Z")
class PreviewCache:
def __init__(self, data_dir: Path):
self.root = Path(data_dir) / "mobile" / "previews"
self.root.mkdir(parents=True, exist_ok=True)
@staticmethod
def name(item: dict) -> str:
identity = "\0".join(str(item[key]) for key in ("type", "id", "revision"))
return hashlib.sha256(identity.encode("utf-8")).hexdigest() + ".png"
def reconcile(self, items: list[dict]) -> None:
expected = {self.name(item) for item in items}
for path in self.root.iterdir():
if path.is_file() and _PREVIEW_FILE.fullmatch(path.name) and path.name not in expected:
path.unlink(missing_ok=True)
def get(self, item: dict, image: Image.Image) -> bytes:
path = self.root / self.name(item)
if path.exists():
try:
data = path.read_bytes()
with Image.open(BytesIO(data)) as cached:
cached.verify()
if cached.format == "PNG" and cached.size == (16, 16):
return data
except (OSError, ValueError):
pass
output = BytesIO()
image.convert("RGB").resize((16, 16), Image.Resampling.LANCZOS).save(output, format="PNG", optimize=True)
data = output.getvalue()
atomic_write_bytes(path, data)
return data