Skip to content

Commit 3fe8a9b

Browse files
committed
Annotate exposure/gain candidates and EXR docs
Add human-readable labels for standard EXIF exposure-program and gain-control numeric values in metadata concept candidates. Implemented helpers (double_to_u64_enum, exposure_exif_value_label, apply_exposure_display_text) and wire them into append_exposure_candidates; tests updated to assert candidate.text and value_key. Bump VERSION to 0.4.19 and add CHANGES entry. Add documentation clarifications and new guidance for a late-bound EXR fixed-size reservation/patch use case in writer/transfer docs and sphinx sources (notes that this should be a bounded patch API, not a general variable-length header rewrite).
1 parent ded5447 commit 3fe8a9b

11 files changed

Lines changed: 127 additions & 12 deletions

CHANGES.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
# OpenMeta Changes
22

3+
## 0.4.19 - 2026-05-21
4+
5+
Changes compared with `0.4.18`.
6+
7+
### Added
8+
9+
- Added a public writer/transfer use case for late-bound EXR metadata, where a
10+
streaming writer reserves a fixed-size attribute before pixel writes and
11+
patches the value bytes after the image is complete.
12+
- Exposure concept candidates now attach human-readable labels for standard
13+
EXIF exposure program and gain-control values.
14+
15+
### Changed
16+
17+
- Clarified that late-bound EXR metadata should be treated as a future bounded
18+
fixed-size patch API, not as a general variable-length EXR header rewrite.
19+
320
## 0.4.18 - 2026-05-20
421

522
Changes compared with `0.4.17`.

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.4.18
1+
0.4.19

docs/api_stability.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ different status.
2626
| EXIF/TIFF/DNG numeric value names: `exif_tag_numeric_value_name(...)` and focused helpers | `openmeta/exif_value_names.h` | Stable | Small helper contract for common enum-like TIFF/EXIF/DNG numeric values such as compression, photometric interpretation, planar configuration, exposure program, metering mode, light source, flash, color space, white balance, scene capture type, gain control, CFA layout, and DNG calibration illuminants. Unknown values return an empty string and remain lossless numeric metadata. |
2727
| Semantic metadata query: `query_metadata(...)`, `query_crop_metadata(...)`, focused query helpers, and `metadata_query_fuzzy_search_available()` | `openmeta/metadata_query.h` | Experimental | Query contract for inspection matches plus normalized candidates. Current coverage includes crop/active-area/border margins, exposure/gain, white balance, color, lens correction, orientation, and RAW/source-processing metadata across standard tags, selected DNG tags, Fujifilm RAF raw crop/zoom rectangles, Canon aspect/crop metadata, Nikon Capture crop bounds, Sony panorama crop margins, fuzzy XMP paths, and vendor RAW-processing classification. Matches report `exact_match`, `fuzzy_match`, and `fuzzy_score` so tools can label exact results separately from RapidFuzz near-miss hits. `OPENMETA_ENABLE_RAPIDFUZZ=ON` adds optional near-miss XMP/property-path scoring. Grouped candidates include `matrix_set`, `vector_set`, and `table` shapes for related non-crop metadata, including RAW black/white levels, linearization, CFA/sensor layout, source geometry, raw-storage identifiers, source-processing buckets, and per-family vendor MakerNote/RAW white-balance, color, raw-storage, sensor, and source-processing groups. Matrix/vector/table groups are promoted only when the available numeric payloads meet conservative minimum shapes, so malformed color matrices, white-balance vectors, and lens-correction records remain per-entry inspection data instead of becoming normalized groups. Long-tail source color/style aliases such as camera-to-XYZ/RGB matrices, creative/picture style, film simulation, dynamic-range, optical-correction, and raw-development terms are classified for query and transfer-policy inspection. Python `Document` and `TransferSourceSnapshot` mirror this as thin dictionary-returning wrappers. |
2828
| Structured metadata interpretation records: `interpret_metadata(...)`, `interpret_metadata_query(...)` | `openmeta/metadata_interpretation.h` | Experimental | Thin structured projection over semantic query candidates. Records carry query class, semantic kind, normalized shape, confidence, source entry ids, and normalized origin/size/rect/margins/value arrays where available. Current scope covers orientation, geometry/crop/border including Fujifilm RAF, Canon, Nikon Capture, and Sony panorama geometry patterns, exposure/gain, color/white-balance, lens-correction, RAW/source-processing records, and grouped vendor-family table/vector records where classification supports them. Python `Document` and `TransferSourceSnapshot` expose matching dictionary wrappers. |
29-
| Cross-family concept resolution: `resolve_metadata_concepts(...)`, `resolve_metadata_concept(...)` | `openmeta/metadata_concepts.h` | Experimental | First bounded resolver for duplicated host-facing concepts. Current scope reports candidates, candidate source entries, source families, preferred entries, normalized numeric/text keys, full normalized value vectors, transfer hints, normalized date/time fields, date/time precision, timezone kind, normalized geometry fields, normalized exposure values, and same-role conflicts for orientation, date/time, exposure/gain, color/profile, GPS, geometry, lens-correction, and RAW-processing evidence across EXIF, XMP, IPTC, ICC, PNG text, and query-backed interpretation records where applicable. Exposure candidates cover exposure time, aperture, ISO sensitivity, exposure bias, exposure program, gain, and raw exposure-adjustment roles; capture exposure facts are safe, while raw/DNG exposure adjustments stay rendered-unsafe. Geometry candidates cover crop, active area, border, and sensor geometry with canonical origin, size, rect, and margin fields when available, including normalized DNG, Phase One/Leaf, Fujifilm RAF, Canon, Nikon Capture, and Sony panorama geometry patterns. Candidate transfer hints distinguish `safe`, `source_bound`, `rendered_unsafe`, and `requires_target_image_spec` evidence, with compatible-file and rendered-image safety booleans. Color/white-balance, lens-correction, and RAW-processing concepts preserve grouped matrix/vector/table values for host inspection; they do not make source-bound values safe to serialize into rendered targets. GPS date/time is combined from `GPSDateStamp` plus `GPSTimeStamp` when both entries exist, and GPS altitude candidates expose altitude-reference code plus below-sea-level state when reference metadata is present; `metadata_concept_gps_altitude_reference_name(...)` provides a stable display token for the reference code. It is intended for inspection UI and host policy decisions; it does not rewrite metadata or hide ambiguity. Python `Document` and `TransferSourceSnapshot` expose matching dictionary wrappers. |
29+
| Cross-family concept resolution: `resolve_metadata_concepts(...)`, `resolve_metadata_concept(...)` | `openmeta/metadata_concepts.h` | Experimental | First bounded resolver for duplicated host-facing concepts. Current scope reports candidates, candidate source entries, source families, preferred entries, normalized numeric/text keys, full normalized value vectors, transfer hints, normalized date/time fields, date/time precision, timezone kind, normalized geometry fields, normalized exposure values, and same-role conflicts for orientation, date/time, exposure/gain, color/profile, GPS, geometry, lens-correction, and RAW-processing evidence across EXIF, XMP, IPTC, ICC, PNG text, and query-backed interpretation records where applicable. Exposure candidates cover exposure time, aperture, ISO sensitivity, exposure bias, exposure program, gain, and raw exposure-adjustment roles; standard EXIF exposure program and gain-control values include human-readable labels; capture exposure facts are safe, while raw/DNG exposure adjustments stay rendered-unsafe. Geometry candidates cover crop, active area, border, and sensor geometry with canonical origin, size, rect, and margin fields when available, including normalized DNG, Phase One/Leaf, Fujifilm RAF, Canon, Nikon Capture, and Sony panorama geometry patterns. Candidate transfer hints distinguish `safe`, `source_bound`, `rendered_unsafe`, and `requires_target_image_spec` evidence, with compatible-file and rendered-image safety booleans. Color/white-balance, lens-correction, and RAW-processing concepts preserve grouped matrix/vector/table values for host inspection; they do not make source-bound values safe to serialize into rendered targets. GPS date/time is combined from `GPSDateStamp` plus `GPSTimeStamp` when both entries exist, and GPS altitude candidates expose altitude-reference code plus below-sea-level state when reference metadata is present; `metadata_concept_gps_altitude_reference_name(...)` provides a stable display token for the reference code. It is intended for inspection UI and host policy decisions; it does not rewrite metadata or hide ambiguity. Python `Document` and `TransferSourceSnapshot` expose matching dictionary wrappers. |
3030
| Transfer concept diagnostics: `transfer_concept_diagnostics_from_store(...)`, `transfer_concept_diagnostic_message(...)` | `openmeta/metadata_transfer.h` | Experimental | Preflight view over concept candidates for `TransferSafetyMode`. Each diagnostic reports concept kind/role, transfer hint, keep/drop/requires-target-image-spec action, reason token, severity token, default message text, conflict flag, source entries, compatible/rendered safety booleans, and GPS altitude-reference presentation fields. Rendered-transfer drop messages distinguish source color transforms, white balance, and lens-correction records from generic source-processing metadata. Intended for UI previews and host policy messages before calling `prepare_metadata_for_target(...)`; it does not replace the actual transfer filter. Python `Document` and `TransferSourceSnapshot` expose `transfer_concept_diagnostics(...)` dictionaries with `severity_name` and `message` fields. |
3131
| Vendor RAW-processing summaries: `vendor_raw_processing_from_store(...)`, `classify_vendor_raw_processing_field(...)` | `openmeta/vendor_raw_processing.h` | Experimental | Conservative grouped source-RAW/source-processing field summaries for decoded Sony, Canon, Nikon, Fujifilm, Pentax, Panasonic, Olympus, Kodak, Minolta, Sigma, Samsung, Ricoh, Apple, DJI, Google, FLIR, Casio, Sanyo, KyoceraRaw, Reconyx, HP, JVC, GE, Motorola, Nintendo, and Microsoft MakerNotes, including vendor-private, computational, thermal, preview, face-geometry, stitch/panorama, Apple computational capture/HDR/motion, DJI pose/thermal, Google HDR+/shot-log, pixel-shift/multi-shot/composite/auto-lighting/source-style processing, and FLIR radiometric/raw-value buckets. Long-tail aliases cover source color/style, camera-to-XYZ/RGB matrix, white-balance gain, optical/lens correction, dynamic-range, and raw-development terms. Direct field classification also recognizes decoded Phase One/Leaf RAW-processing tags; use the dedicated Phase One/Leaf helpers for normalized geometry and processing summaries. Intended for audit/UI and rendered-transfer safety decisions, not for writing vendor RAW/source-processing values into rendered targets. |
3232
| Transfer safety audit: `transfer_safety_audit_from_store(...)` | `openmeta/metadata_transfer.h` | Experimental | Preflight summary of source entries and entries filtered or invalidated by `TransferSafetyMode`, including Sony/Canon/Nikon/Fujifilm/Pentax/Panasonic/Olympus/Kodak/Minolta/Sigma/Samsung/Ricoh/Apple/DJI/Google/FLIR/Casio/Sanyo/KyoceraRaw/Reconyx/HP/JVC/GE/Motorola/Nintendo/Microsoft RAW/source-processing buckets. Intended for diagnostics and host UI before preparing rendered-image transfers. |

docs/interpretation_status.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ explicit outcome:
3535
| IPTC-IIM and portable XMP | IPTC datasets and XMP properties decode into typed entries, and bounded EXIF/IPTC-to-XMP projection exists for transfer/writeback. | Medium-high, about 75-85%. | Full MWG-style reconciliation of duplicated EXIF/XMP/IPTC concepts is still bounded. |
3636
| Orientation | EXIF/TIFF orientation query, LibRaw flip mapping, generic orientation helpers for index, rotation degrees, mirrored state, dimension swap, rotation-only fallback, human-readable labels, and EXIF-vs-XMP conflict reporting in the LibRaw bridge. | High, about 90-95%. | Higher-level policy for resolving container and host pixel-orientation state remains host-specific. |
3737
| Geometry, crop, active area, and borders | DNG crop/active-area/masked-area tags, Phase One/Leaf geometry, Fujifilm RAF raw crop/zoom rectangles, Canon aspect/crop metadata, Nikon Capture crop bounds, Sony panorama crop margins, canonical border margins, vendor RAW-processing geometry buckets, and fuzzy crop/border-style paths are queryable. | High, about 88-92%. | More vendor-specific normalized rectangles and stronger output contracts for ambiguous multi-tag geometry. |
38-
| Exposure and gain | Standard EXIF exposure time, f-number, exposure program, photographic sensitivity, exposure bias, exposure index, gain control, selected DNG baseline/raw-preview gain fields, and matching XMP paths are queryable and promoted into cross-family exposure roles. Capture exposure facts are marked safe, while raw/DNG exposure adjustments are marked unsafe for rendered-image transfer. | Medium-high, about 84-90%. | More vendor MakerNote exposure print conversions and richer human-readable exposure-program/gain labels. |
38+
| Exposure and gain | Standard EXIF exposure time, f-number, exposure program, photographic sensitivity, exposure bias, exposure index, gain control, selected DNG baseline/raw-preview gain fields, and matching XMP paths are queryable and promoted into cross-family exposure roles. Standard EXIF exposure program and gain-control values carry human-readable labels in concept candidates. Capture exposure facts are marked safe, while raw/DNG exposure adjustments are marked unsafe for rendered-image transfer. | Medium-high, about 85-90%. | More vendor MakerNote exposure print conversions and richer per-vendor exposure/gain labels. |
3939
| Color, white balance, and matrices | DNG color/calibration/reduction/forward matrix groups, white-balance vector groups, ICC metadata, RAW color/source-processing safety buckets, transfer hints, per-family grouped vendor color/WB candidates, long-tail camera-to-XYZ/RGB, style/color, and white-balance gain aliases, and cross-family concept candidates with full grouped value vectors are identified. Matrix/vector groups require numeric payloads with conservative minimum shapes before promotion. | Medium-high, about 82-90%. | Deeper camera/vendor color science interpretation is intentionally conservative, especially for rendered-image transfer. |
4040
| Lens correction and RAW processing | Lens-correction groups, black/white levels, linearization, CFA/sensor layout, raw-storage identifiers, vendor RAW/source-processing buckets, creative/picture style, film simulation, dynamic-range, optical correction, and raw-development aliases, per-family vendor raw-storage/sensor/source-processing table candidates, transfer hints, transfer diagnostics, and concept candidates with grouped table/vector values are classified for query and transfer safety. Lens-correction grouped tables require numeric payloads before promotion. | Medium-high, about 82-89%. | Long-tail per-model correction tables and richer numeric normalization. |
4141
| Vendor MakerNotes | Broad MakerNote naming and source-processing classification exists for common vendors and several live computational/thermal vendors. Unknown entries remain lossless and source-private subgroups distinguish preview, face geometry, computational, thermal, stitch/panorama, pixel-shift, multi-shot, composite, auto-lighting, RAW crop/active-area, source color-transform, source style/rendering aliases, lens-correction, raw-level processing data, and Phase One/Leaf RAW-processing fields handled by direct classification plus dedicated normalized helpers. Classified multi-field vendor groups now surface as grouped query/interpretation candidates where safe to expose structurally. | Medium-high, about 83-90%. | ExifTool-style long-tail print conversions, encrypted/custom settings, and per-model private tables. |

docs/metadata_transfer_plan.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,19 @@ Current EXR transfer scope is intentionally conservative:
396396
- no general file-based EXR metadata rewrite/edit path yet
397397
- no typed EXR attribute synthesis beyond the current safe string projection
398398

399+
Important user use case to keep visible:
400+
- A tile/region streaming EXR writer may know some metadata only after all
401+
pixel chunks are written, for example `total_compute_time`.
402+
- The practical fast path for that use case is not a general variable-length
403+
header rewrite. It is a fixed-size reservation/patch contract: declare a
404+
fixed-width attribute, such as a `double`, before opening the EXR writer,
405+
write pixel chunks normally, then patch only the reserved value bytes after
406+
close.
407+
- OpenMeta does not expose that late-bound EXR patch plan yet. If EXR depth is
408+
expanded, the first useful scope should be a bounded fixed-size patch API
409+
with offset discovery, type/size validation, and a decode-after-patch
410+
verification gate.
411+
399412
## Transfer Policies
400413

401414
The public transfer contract now models five policy subjects:

docs/sphinx/api_stability.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,10 @@ Host-facing API map
149149
RAW-processing evidence across EXIF, XMP, IPTC, ICC, PNG text, and
150150
query-backed interpretation records where applicable. Exposure
151151
candidates cover exposure time, aperture, ISO sensitivity, exposure
152-
bias, exposure program, gain, and raw exposure-adjustment roles; capture
153-
exposure facts are safe, while raw/DNG exposure adjustments stay
154-
rendered-unsafe. Geometry
152+
bias, exposure program, gain, and raw exposure-adjustment roles.
153+
Standard EXIF exposure program and gain-control values include
154+
human-readable labels. Capture exposure facts are safe, while raw/DNG
155+
exposure adjustments stay rendered-unsafe. Geometry
155156
candidates cover crop, active area, border, and sensor geometry with
156157
canonical origin, size, rect, and margin fields when available,
157158
including normalized DNG, Phase One/Leaf, Fujifilm RAF, Canon, Nikon

docs/sphinx/interpretation_status.rst

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,13 @@ Coverage matrix
106106
- Standard EXIF exposure time, f-number, exposure program, photographic
107107
sensitivity, exposure bias, exposure index, gain control, selected DNG
108108
baseline/raw-preview gain fields, and matching XMP paths are queryable
109-
and promoted into cross-family exposure roles. Capture exposure facts
110-
are marked safe, while raw/DNG exposure adjustments are marked unsafe
111-
for rendered-image transfer.
112-
- Medium-high, about 84-90%.
113-
- More vendor MakerNote exposure print conversions and richer
114-
human-readable exposure-program/gain labels.
109+
and promoted into cross-family exposure roles. Standard EXIF exposure
110+
program and gain-control values carry human-readable labels in concept
111+
candidates. Capture exposure facts are marked safe, while raw/DNG
112+
exposure adjustments are marked unsafe for rendered-image transfer.
113+
- Medium-high, about 85-90%.
114+
- More vendor MakerNote exposure print conversions and richer per-vendor
115+
exposure/gain labels.
115116
* - Color, white balance, and matrices
116117
- DNG color/calibration/reduction/forward matrix groups, white-balance
117118
vector groups, ICC metadata, RAW color/source-processing safety

docs/sphinx/writer_target_contract.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,15 @@ the EXR attribute batch helpers for host-owned EXR writers. Existing EXR file
479479
metadata preservation is therefore owned by the host writer, not by an
480480
OpenMeta file edit helper.
481481

482+
One important pending use case is late-bound EXR metadata. Streaming tile or
483+
scanline writers sometimes only know a value after pixel data is finished,
484+
for example ``total_compute_time``. The safe fast design is a fixed-size
485+
reservation/patch contract: reserve a typed attribute, such as a ``double``,
486+
before writer construction, then patch exactly those value bytes after close.
487+
OpenMeta does not provide this patch API yet; it should remain separate from
488+
general EXR file rewrite because variable-length header changes would require
489+
moving later file structures.
490+
482491
Non-Goals
483492
---------
484493

docs/writer_target_contract.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,15 @@ the EXR attribute batch helpers for host-owned EXR writers. Existing EXR file
285285
metadata preservation is therefore owned by the host writer, not by an
286286
OpenMeta file edit helper.
287287

288+
One important pending use case is late-bound EXR metadata. Streaming tile or
289+
scanline writers sometimes only know a value after pixel data is finished,
290+
for example `total_compute_time`. The safe fast design is a fixed-size
291+
reservation/patch contract: reserve a typed attribute, such as a `double`,
292+
before writer construction, then patch exactly those value bytes after close.
293+
OpenMeta does not provide this patch API yet; it should remain separate from
294+
general EXR file rewrite because variable-length header changes would require
295+
moving later file structures.
296+
288297
## Non-Goals
289298

290299
The writer contract does not promise:

0 commit comments

Comments
 (0)