| """Write the protected image plus a reproducibility manifest.""" |
|
|
| from __future__ import annotations |
|
|
| import json |
| from dataclasses import asdict |
| from datetime import datetime, timezone |
| from pathlib import Path |
|
|
| from PIL import Image |
|
|
| from veil_pgd.config import get_settings |
| from veil_pgd.types import Candidate |
|
|
|
|
| def save_result( |
| original_path: str, |
| protected: Image.Image, |
| candidate: Candidate, |
| truth: str, |
| out_dir: str | None = None, |
| ) -> dict: |
| out = Path(out_dir or get_settings().artifacts_dir) |
| out.mkdir(parents=True, exist_ok=True) |
| stem = Path(original_path).stem |
| img_path = out / f"{stem}.protected.png" |
| protected.save(img_path) |
|
|
| manifest = { |
| "created": datetime.now(timezone.utc).isoformat(), |
| "original": original_path, |
| "protected_image": str(img_path), |
| "truth": truth, |
| "spec": asdict(candidate.spec), |
| "surrogate_fitness": candidate.surrogate_fitness, |
| "blackbox_fitness": candidate.blackbox_fitness, |
| "per_model_distance": candidate.per_model_distance, |
| "reachability": candidate.reachability, |
| "stealth": asdict(candidate.stealth) if candidate.stealth else None, |
| "notes": candidate.notes, |
| } |
| man_path = out / f"{stem}.manifest.json" |
| man_path.write_text(json.dumps(manifest, indent=2)) |
| manifest["manifest_path"] = str(man_path) |
| return manifest |
|
|