#!/usr/bin/env python3 import clize import exif import json from datetime import datetime from enum import Enum from pathlib import Path from typing import Any def exif_content_to_json(tag, content): match content: case Enum() as e: return e.name case int() as i: return i case float() as f: return f case str() as s: if tag.startswith("datetime"): dt = datetime.strptime(s, "%Y:%m:%d %H:%M:%S") return dt.strftime("%Y-%m-%d %H:%M") return s case _: return {"pyType": str(type(content)), "stringified": str(content)} def extract_exif_data(image_path: Path) -> dict[str, Any]: with image_path.open("rb") as image_file: image = exif.Image(image_file) exif_data = {} for tag in image.list_all(): try: content = image[tag] except: # Some keys are in list_all() but can't be accessed for my camera :( # Skip them. continue exif_data[tag] = exif_content_to_json(tag, content) return exif_data def extract_stat_data(image_path: Path): FIELDS = ["st_size"] s = image_path.stat() stat_data = {} for field in FIELDS: stat_data[field] = getattr(s, field) return stat_data def extract_metadata(image_path: Path, *, root: Path): exif_data = extract_exif_data(image_path) stat_data = extract_stat_data(image_path) metadata = { "exif": exif_data, "stat": stat_data, "path": { "name": image_path.name, "relativeToRoot": str(image_path.relative_to(root)), }, } print(json.dumps(metadata, indent=2)) if __name__ == "__main__": clize.run(extract_metadata)