Update config and settings etc

This commit is contained in:
Alexander Wainwright
2025-04-20 23:53:04 +10:00
parent 38ca9cb817
commit 73e6318640

View File

@@ -6,7 +6,6 @@ import datetime
import toml
from alive_progress import alive_bar
CONFIG_PATH = os.path.expanduser("~/.config/emulsion/config.toml")
@@ -27,8 +26,15 @@ def parse_args(config):
nargs='*',
help='Image files to process (e.g. *.jpg *.tif).'
)
# Configurable fields
parser.add_argument('--author', default=None, help='Name of the photographer.')
parser.add_argument('--lab', default=None, help='Name of the lab to store in XMP:DevelopedBy.')
parser.add_argument('--lab', default=None, help='Name of the lab who developed the film.')
parser.add_argument('--make', default=None, help='Camera make (stored in EXIF:Make).')
parser.add_argument('--model', default=None, help='Camera model (stored in EXIF:Model).')
parser.add_argument('--film', default=None, help='Film stock (stored in EXIF:UserComment and XMP:Description).')
# Time settings
parser.add_argument('--base-date', default=None, help='Base date or date/time (e.g. 2023-04-10 or 2023-04-10 12:00:00).')
parser.add_argument('--time-increment', type=int, default=None, help='Time increment in seconds between images.')
parser.add_argument('--dry-run', action='store_true', help='Show what would be changed without modifying files.')
@@ -36,10 +42,22 @@ def parse_args(config):
args = parser.parse_args()
# Merge from config
if args.author is None and 'author' in config:
args.author = config['author']
if args.lab is None and 'lab' in config:
args.lab = config['lab']
if args.make is None and 'make' in config:
args.make = config['make']
if args.model is None and 'model' in config:
args.model = config['model']
if args.film is None and 'film' in config:
args.film = config['film']
if args.time_increment is None and 'time_increment' in config:
args.time_increment = config['time_increment']
@@ -47,6 +65,10 @@ def parse_args(config):
def prompt_for_config(args):
"""
Prompt for config-only fields before creating a config file.
(Base date is ephemeral, not stored in config.)
"""
try:
if not args.author:
args.author = input("Photographer's name (Author)? ").strip()
@@ -55,6 +77,18 @@ def prompt_for_config(args):
resp = input("Lab name (optional, enter to skip)? ").strip()
args.lab = resp if resp else ""
if args.make is None:
resp = input("Camera make (optional, enter to skip)? ").strip()
args.make = resp if resp else ""
if args.model is None:
resp = input("Camera model (optional, enter to skip)? ").strip()
args.model = resp if resp else ""
if args.film is None:
resp = input("Film stock (optional, enter to skip)? ").strip()
args.film = resp if resp else ""
if not args.time_increment:
dflt = "60"
resp = input(f"Time increment in seconds [{dflt}]: ").strip()
@@ -66,6 +100,10 @@ def prompt_for_config(args):
def prompt_if_missing(args):
"""
Prompt for ephemeral fields like base_date if missing,
and also fill in other fields if user didn't supply them.
"""
try:
if not args.author:
args.author = input("Photographer's name (Author)? ").strip()
@@ -74,8 +112,20 @@ def prompt_if_missing(args):
resp = input("Lab name (optional, enter to skip)? ").strip()
args.lab = resp if resp else ""
if args.make is None:
resp = input("Camera make (optional, enter to skip)? ").strip()
args.make = resp if resp else ""
if args.model is None:
resp = input("Camera model (optional, enter to skip)? ").strip()
args.model = resp if resp else ""
if args.film is None:
resp = input("Film stock (optional, enter to skip)? ").strip()
args.film = resp if resp else ""
if not args.base_date:
dflt = "2023-01-01"
dflt = datetime.datetime.now().strftime("%Y-%m-%d")
resp = input(f"Base date/time for first image [{dflt}]: ").strip()
args.base_date = resp if resp else dflt
@@ -97,28 +147,56 @@ def parse_user_date(dt_str):
return datetime.datetime.strptime(dt_str, "%Y-%m-%d")
def build_exiftool_cmd(file_path, author, lab, timestamp, dry_run=False):
def build_exiftool_cmd(file_path, author, lab, make, model, film, timestamp, dry_run=False):
"""
Use standard EXIF fields:
- EXIF:Make (args.make)
- EXIF:Model (args.model)
- EXIF:UserComment (args.film)
Also store film in XMP:Description for better compatibility.
"""
current_year = datetime.datetime.now().year
cmd = [
"exiftool",
"-overwrite_original",
# Photographer info
f"-Artist={author}",
f"-Creator={author}",
f"-By-line={author}",
f"-Credit={author}",
f"-CopyrightNotice={author}",
f"-Copyright={author}",
f"-CopyrightNotice=© {current_year} {author}",
f"-Copyright=© {current_year} {author}",
# Timestamps
f"-DateTimeOriginal={timestamp}",
# Clear out some lab fields
"-WebStatement=",
"-CreatorWorkURL=",
f"-DateTimeOriginal={timestamp}"
"-CreatorWorkURL="
]
# Lab in XMP:DevelopedBy
if lab:
cmd.append(f"-XMP:DevelopedBy={lab}")
# If user gave a make, store it in EXIF:Make
if make:
cmd.append(f"-Make={make}")
# If user gave a model, store it in EXIF:Model
if model:
cmd.append(f"-Model={model}")
# If user gave a film stock, store it in EXIF:UserComment AND XMP:Description
if film:
cmd.append(f"-UserComment={film}")
cmd.append(f"-XMP:Description={film}")
cmd.append(file_path)
if dry_run:
# Return a string for printing only
return " ".join(cmd)
return cmd
@@ -130,9 +208,21 @@ def create_config_file(args):
defaults = {
"author": args.author or "Your Name",
"lab": args.lab or "",
"make": args.make or "",
"model": args.model or "",
"film": args.film or "",
"time_increment": args.time_increment if args.time_increment else 60
}
# Remove empty values so user is prompted next time if they left something blank
keys_to_remove = []
for k, v in defaults.items():
if isinstance(v, str) and not v.strip():
keys_to_remove.append(k)
for k in keys_to_remove:
del defaults[k]
os.makedirs(os.path.dirname(CONFIG_PATH), exist_ok=True)
with open(CONFIG_PATH, "w", encoding="utf-8") as f:
@@ -183,6 +273,9 @@ def main():
file_path=f,
author=args.author,
lab=args.lab,
make=args.make,
model=args.model,
film=args.film,
timestamp=timestamp_str,
dry_run=args.dry_run
)
@@ -194,8 +287,8 @@ def main():
subprocess.run(
cmd,
check=True,
stdout=subprocess.DEVNULL, # Hide exiftool normal output
stderr=subprocess.DEVNULL # Hide exiftool error output
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL
)
bar.text(f"Updated {f} => {timestamp_str}")
except subprocess.CalledProcessError as e: