Skip to content

Proposal: a bypass Color Interop ID #15

Description

@zachlewis

Proposal: a bypass Color Interop ID

Revised 2026-06-12 — handling simplified and clarified per the discussion below; the
original text is preserved in this issue's edit history.

Problem Statement

A real color interop ID is one deterministic endpoint: everything known, the image
handled correctly everywhere that recognizes it. data is the other: heuristics off,
held as-is, identical behavior in every application. Everything between — unknown,
absent, partial container metadata — is the middle ground where each application guesses
differently, by design.

The catch: today the OFF switch asserts the image isn't color. To hold real color as-is
— a vendor passthrough, a deferred grading decision, reference media in an editorial
timeline — a writer has to lie. unknown is the honest alternative to guessing; there
is no honest alternative to misusing data: a deliberate hold has no spelling that
doesn't either claim "not color" or invite exactly the guess it means to forbid. The
practice is already common ("set it to raw so the app doesn't touch it"); the only real
question is whether its spelling lies.

Nothing here changes the meaning of unknown (≡ absent) or data.

CIID The writer means Reader may guess a space? Other color metadata
data not color — don't manage it No — no-op not used
unknown no reliable value (incl. absent) Yes — file rules / metadata / hints used to resolve
bypass color, deliberately unidentified — hold as-is No — held until re-tagged not used for resolution while tagged

Proposal

Reserve bypass: this is color, deliberately left unidentified — hold it as-is,
don't guess, carry the tag until someone re-tags it. data and bypass are two faces
of the same no-op routing: identical reader behavior, differing only in the content
claim — data says "not color"; bypass says "color, encoding deliberately withheld."

  • Readers: exactly data's obligations. Wherever an implementation already has a
    data behavior — including format conversion, ICC handling, transcoding — apply it
    unchanged. The complete ask of a non-participating implementation: persist the string,
    never volunteer it, don't extend unknown's fallback handling to it.
  • Precedence is positional. bypass governs only the machinery downstream of the
    CIID in the reading order
    : mechanisms that resolve before the ID is consulted
    (acesImageContainer, reading step 1) win exactly as today — a reader MAY warn;
    mechanisms that resolve after it (file rules, chromaticities/CICP fallback, step 4)
    are suppressed while the tag is present. Writers must never emit acesImageContainer
    together with bypass. bypass adds no new preservation requirement on other color
    metadata — per-format conventions apply unchanged; while tagged, that metadata is
    simply not used for resolution.
  • Writers: the one hard rule. Applications MUST NOT emit bypass on their own
    initiative; it is set only at the explicit direction of a user, a config, or a
    pipeline step a person configured. This is what keeps the tag meaningful — its
    presence always reflects a decision.
  • Persistence. bypass asserts intent, not fidelity: "this is color, no encoding
    is asserted, do not guess."
    Any derived output for which that remains true
    (re-encodes, crops, pixel operations on the held image) keeps the tag, by the same
    convention any CIID persists through a non-color-converting write. The tag clears only
    on a deliberate act: re-tag to a real ID; re-tag to data if found non-color; or
    downgrade to unknown/unset to re-enable resolution from other metadata.
  • The user override. bypass binds automatic behavior, never a user: an explicit
    re-tag or conversion decision always wins — it is the tag's intended exit. An explicit
    request to convert to a space supplies a destination, not a source; while tagged, a
    tool shouldn't substitute its untagged-input assumption — ask for the source.
    Supplying one is the re-tag.
  • Scope of the guarantee. bypass rides colorInteropID and inherits its carriage;
    per-format carriage is each format rec's existing job for all CIIDs. The hold is
    guaranteed across hops that preserve colorInteropID and degrades to today's status
    quo at any hop that doesn't — never worse than the present baseline.
  • Multi-part EXR: the same first-part / per-part convention as data; specifics
    belong to the OpenEXR rec.

Transition

Today a legacy reader treats bypass as an unrecognized ID — per the existing rec,
surfaced rather than silently guessed. Behavior converges to hold-everywhere as readers
adopt, and is never worse than the status quo meanwhile. The interim is also the
urgency: until an honest spelling exists, the dishonest one keeps accumulating — every
year deepens the installed base of data-tagged color, and installed bases fossilize.

What OCIO would need

  • Recognize bypass as a reserved un-namespaced interop ID alongside data and
    unknown (the character grammar already accepts the string).
  • Resolvers that already special-case data/unknown as non-resolvable sentinels add
    bypass to the same guard.

Suggested patches to existing documents

Color Interop ID rec — one definition alongside data/unknown:

bypass — color whose encoding is deliberately withheld. On read, handle exactly like
data (do not color manage; do not auto-assign a color space); persist the ID until a
user or pipeline step explicitly re-tags the image.

OpenEXR rec, Writing steps — insert after step 1:

1a. If the image is color but is deliberately being left unidentified for a later step
to resolve, set the colorInteropID to "bypass". Unlike "unknown", readers will not
auto-assign a color space to it. Applications must not set "bypass" on their own
initiative.

OpenEXR rec, Reading steps — extend step 2's first sentence:

If the colorInteropID is "data" or "bypass", the images should not be color
managed.

Figure 2 (read): E{Is InteropID _data_?}E{Is InteropID _data_ or _bypass_?}

Figure 1 (write): split node C's False edge:
C--False-->W{Deliberately holding as-is?} · W--True-->X["Set InteropID to _bypass_"]-->M · W--False-->F[…unchanged…]

An executable demo exists — a loadable OCIO config plus an OpenImageIO notebook showing
the held/managed/unknown cases side by side in one timeline — happy to share.

Decision requested

Reserve one ID whose reading rule is data's, for color. The proposal is refuted iff
the forum holds either (a) that data may legitimately be applied to color
encodings to elicit unmanaged behavior — in which case bypass is redundant, and data
now officially means "don't touch" rather than "not color"; or (b) that a deliberate
hold should not ride in image metadata at all. If neither, the proposal follows.

Open question: the name

bypass is proposed — it reads as the instruction it is ("bypass attempts to
automatically manage color"). A naming review also shortlisted passthrough (strong
broadcast precedent; hyphenation instability) and hold_color (carries the is-color
claim in the string; compound form). Alternatives welcome — we avoided raw (already an
alias of Data in common configs) and "un-" words (they read as absence, not intent).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    Later

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions