78 lines
1.8 KiB
Python
Executable File
78 lines
1.8 KiB
Python
Executable File
#!/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)
|