Skip to content

ADR-016 — L1 empty by default; opt-in per camera+lens

Status · Accepted Date · 2026-04-27 TA anchor ·/components/synthesizer Related RFC · RFC-015 (EXIF auto-binding rules)

Context

L1 (technical correction) covers lens correction, profiled denoise, hot pixel removal, and similar fixes that depend on camera + lens combination. A fisheye lens shouldn't be lens-corrected (the projection is the point). A clean low-ISO image doesn't need denoise. Defaulting L1 on for all images would over-process; defaulting it off for all images would force every photographer to opt in repeatedly.

Decision

L1 is empty by default for any image. Photographers opt in via per-camera+lens bindings declared in ~/.chemigram/config.toml:

[[layers.L1.bindings]]
camera = "NIKON D850"
lens = "AF-S Nikkor 24-70mm f/2.8E ED VR"
template = "lens_correct_full + denoise_auto"

[[layers.L1.bindings]]
camera = "NIKON D850"
lens = "AF-S Fisheye Nikkor 8-15mm f/3.5-4.5E ED"
template = "denoise_auto"   # NO lens correction — preserve fisheye projection

Auto-resolution by EXIF picks the right binding per image: exact match (camera + lens), then camera-only fallback, then nothing.

Rationale

  • Safety. A surprised photographer (e.g., fisheye over-corrected by default) is worse than a mildly inconvenienced one (had to add a binding once).
  • Per-camera+lens granularity. Lens correction has to be lens-specific; embedding the granularity in the binding pattern matches the actual problem shape.
  • Templates. The starter vocabulary provides a small set of templates (lens_correct_full, lens_correct_distortion_only, denoise_auto, chromatic_aberration_only); the photographer composes bindings from these.
  • One-time setup. Once the photographer's gear list is bound in config.toml, they don't think about L1 again.

Alternatives considered

  • Always-on L1 with per-image override: rejected — produces surprising over-processing for edge cases (fisheye, low-ISO, intentional lens character).
  • Camera-only bindings (ignore lens): rejected — loses the fisheye exception case and similar lens-specific decisions.
  • GUI-based binding management: out of scope (Chemigram has no UI). TOML is hand-edited; this is acceptable for a per-photographer one-time setup.

Consequences

Positive: - No surprising default processing applied to images - Per-lens granularity supports edge cases naturally - Setup cost is one-time per camera+lens combination - EXIF auto-resolution removes per-image decisions once bindings exist

Negative: - Photographers without bindings get no L1 (they must notice this and configure) - TOML editing is a setup friction (mitigated: small file, well-documented)

Implementation notes

src/chemigram_core/bind.py implements EXIF reading and binding resolution. Resolution rules: exact (camera+lens) → camera-only → nothing. Resolution result is stored in the per-image metadata.json as auto_binding.l1. RFC-015 specifies the resolution algorithm in detail.