chemigram.core.exif¶
chemigram.core.exif
¶
Read camera/lens metadata from raw files for L1 vocabulary binding + camera-default WB coefficients for camera-aware parametric apply.
Two readers:
- :func:
read_exif(exifread) — extractsMake,Model,LensModel,FocalLength. Per RFC-015 / ADR-053, downstream binding (:mod:chemigram.core.binding) is exact-match on(make, model, lens_model). - :func:
read_camera_daylight_wb(rawpy) — extracts the raw's camera-default daylight WB coefficients as RGB multipliers. Used by RFC-039 to make parametric temperature camera-aware: atkelvin_delta=0the parametric primitive emits these coefficients (preserves camera default); at non-zero delta it shifts relative to this base.
Both libraries are pure-Python or wheel-distributed (no exiftool
binary required). PyExifTool (faster, more complete) is rejected for
v1 because it requires the exiftool binary as an external dep.
Public API
- :func:
read_exif— extract EXIF identity fields from a raw - :func:
read_camera_daylight_wb— read camera daylight WB coefficients - :class:
ExifData— frozen dataclass with the four identity fields - :class:
ExifReadError— raised on unreadable input
ExifReadError
¶
Bases: Exception
Raised when EXIF cannot be read from a file.
ExifData
dataclass
¶
The EXIF fields chemigram cares about for L1 binding.
String fields are whitespace- and null-stripped. Missing string
fields become empty strings (not None) so callers don't need
to special-case absence vs. presence-of-empty.
read_exif
¶
Read relevant EXIF tags from a raw file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
path to a raw (NEF, ARW, RAF, CR2, ...). |
required |
Returns:
| Type | Description |
|---|---|
ExifData
|
class: |
ExifData
|
string fields become |
ExifData
|
becomes |
Raises:
| Type | Description |
|---|---|
ExifReadError
|
corrupt or unreadable file. |
FileNotFoundError
|
|
Source code in src/chemigram/core/exif.py
read_filmic_auto_points
¶
Compute filmic-friendly black_point_source / white_point_source in log2-EV space from the raw's actual histogram.
Returns (black_ev, white_ev) where both values are relative to
the camera's mid-gray reference (18.45% of white_level). Mirrors
darktable's "Auto-tune levels" button on the filmic module.
Used by camera-aware filmic (#135 / RFC-039): at apply time, the parametric primitive substitutes these auto-tuned points for the dtstyle's authored defaults (typically -8.0 / +4.0), producing a tone curve fitted to the actual scene's dynamic range.
Returns None if rawpy can't read the file or compute valid
percentiles (very dark / completely clipped raw). Callers treat
None as "skip auto-tune, use source coefficients."
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
|
ExifReadError
|
rawpy can't parse the raw. |
Source code in src/chemigram/core/exif.py
read_camera_iso
¶
Read the raw's ISO speed rating from EXIF.
Returns the ISO as an integer (typically 100..51200 range), or
None if the tag is missing. Used by camera-aware denoise (#134
/ RFC-039): noise floor scales with ISO, so the parametric apply
path scales the denoise threshold relative to the raw's ISO at
apply time.
Uses exifread.process_file (no rawpy needed for this field; ISO
is in standard EXIF). Returns None rather than raising on missing
tag — callers (parametric denoise.patch) treat absence as "skip
auto-scaling, use source coefficients."
Source code in src/chemigram/core/exif.py
read_camera_daylight_wb
¶
Read the camera-default daylight WB coefficients from a raw file.
Returns (red_coeff, green_coeff, blue_coeff) as float multipliers
matching darktable's temperature module struct layout, normalized
to green_coeff == 1.0. This is the form darktable uses internally
when it auto-inserts a temperature op for a raw with no explicit
history.
The values come from libraw's camera_whitebalance field (the
raw's as-shot WB metadata, divided by the green coefficient to
normalize). Using camera_whitebalance (rather than
daylight_whitebalance) matches darktable's behavior: darktable reads
the as-shot multipliers from EXIF / MakerNote and applies them at
raw-prepare time, before the chromatic-adaptation channelmixerrgb
step. Using daylight_whitebalance instead would interact differently
with the chromatic-adaptation chain and produce a visible cast.
Used by camera-aware parametric apply (RFC-039 / #131 Step 2): at
kelvin_delta=0 the parametric temperature primitive emits these
coefficients (preserves camera default); at non-zero delta the
primitive shifts relative to this base.
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
|
ExifReadError
|
rawpy can't parse the raw (corrupt / unsupported format / DNG without WB). |