Interop API

Goal

Define a small export interface from MetaStore that is easy to adapt to:

  • OpenImageIO ImageSpec metadata conventions.

  • OpenEXR header attributes.

  • OpenColorIO FormatMetadata trees.

Stable API (v1)

Contract constant: kInteropExportContractVersion == 1.

enum class ExportNameStyle : uint8_t {
    Canonical,   // exif:ifd0:0x010F
    XmpPortable, // tiff:Make, exif:ExposureTime
    Oiio         // Make, Exif:ExposureTime, GPS:Latitude
};

struct ExportOptions final {
    ExportNameStyle style = ExportNameStyle::Canonical;
    bool include_origin = false;
    bool include_flags = false;
    bool include_makernotes = true;
};

struct ExportItem final {
    std::string_view name;
    const Entry* entry = nullptr;
    const Origin* origin = nullptr; // only when include_origin=true
    EntryFlags flags = EntryFlags::None; // only when include_flags=true
};

class MetadataSink {
public:
    virtual ~MetadataSink() = default;
    virtual void on_item(const ExportItem& item) = 0;
};

void visit_metadata(const MetaStore& store, const ExportOptions& options,
                    MetadataSink& sink) noexcept;

Naming Contract

  • Canonical: stable key-space-aware names for lossless workflows.

  • XmpPortable: normalized names intended for cross-tool interchange.

  • Oiio: OIIO-friendly names for drop-in metadata attribute use. EXR attributes map common OpenEXR names to OIIO-style names where practical (for example owner -> Copyright, capDate -> DateTime), while non-standard EXR attributes remain under openexr:*.

Adapters

  • OIIO adapter: collect_oiio_attributes(...) in openmeta/oiio_adapter.h. Stable request model: OiioAdapterRequest. Typed variant: collect_oiio_attributes_typed(...). OiioTypedValue keeps original MetaValue typing (scalar/array/bytes/text) for host integrations that need non-string metadata values. Strict safe variants: collect_oiio_attributes_safe(...) and collect_oiio_attributes_typed_safe(...) with InteropSafetyError.

  • OCIO adapter: build_ocio_metadata_tree(...) in openmeta/ocio_adapter.h. Stable request model: OcioAdapterRequest. Strict safe variant: build_ocio_metadata_tree_safe(...) with InteropSafetyError.

  • EXR adapter: build_exr_attribute_batch(...) in openmeta/exr_adapter.h. It exports one owned EXR-native attribute batch from MetaStore for OpenEXR/OIIO header workflows. build_exr_attribute_part_spans(...) groups that batch by part, and build_exr_attribute_part_views(...) exposes zero-copy grouped per-part views, replay_exr_attribute_batch(...) replays the grouped batch through explicit host callbacks. Unknown/custom attrs remain opaque only when the original EXR type name is preserved in Origin::wire_type_name.

Reference Tests

  • tests/interop_export_test.cc

  • tests/oiio_adapter_test.cc

  • tests/ocio_adapter_test.cc

  • tests/exr_adapter_test.cc

Python Entry Points

  • Document.export_names(style=..., include_makernotes=...)

  • Document.oiio_attributes(...)

  • Document.unsafe_oiio_attributes(...)

  • Document.oiio_attributes_typed(...)

  • Document.unsafe_oiio_attributes_typed(...)

  • Document.ocio_metadata_tree(...)

  • Document.unsafe_ocio_metadata_tree(...)

  • Document.dump_xmp_sidecar(format=...)

XMP Sidecar Export API

openmeta/xmp_dump.h exposes a stable flat request model for wrappers and adapters:

  • XmpSidecarRequest (format + limits + portable/lossless switches)

  • dump_xmp_sidecar(const MetaStore&, std::vector<std::byte>*, const XmpSidecarRequest&)

The nested XmpSidecarOptions API remains available for advanced callers.