faceless-photolib

@faceless-photolib/color

Color science for faceless-photolib — transfer functions, RGB/XYZ primaries, Bradford chromatic adaptation, and OCIO-style hub-and-spoke conversions through an ACEScg (AP1) scene-linear connection space.

Color science for faceless-photolib — a headless, color-managed, GPU-accelerated image-editing engine.

Provides transfer functions (sRGB, Rec.709/2020, gamma, PQ, HLG, and the LogC3/LogC4/S-Log3/Log3G10/ACEScc/ACEScct log variants), pinned RGB primaries with Lindbloom RGB↔XYZ matrices, Bradford chromatic adaptation, and an OCIO-style hub-and-spoke color manager. Every conversion routes through a single fixed connection space — ACEScg / AP1 scene-linear — so spaces convert via the hub rather than pairwise.

Install

pnpm add @faceless-photolib/color

Usage

import {
  createStandardColorSpaceRegistry,
  conversionFromWorkingSpace,
  conversionToWorkingSpace,
  applyConversion,
  eotf,
  inverseEotf,
  PRIMARIES_SRGB,
} from "@faceless-photolib/color";
import { ColorSpaceIdSchema } from "@faceless-photolib/schemas";

// A registry seeded with the standard spaces (srgb, rec2020, display-p3, acescc, …).
const registry = createStandardColorSpaceRegistry();
const srgb = ColorSpaceIdSchema.parse("srgb");

// Build a conversion descriptor: sRGB → ACEScg connection space.
const toHub = conversionFromWorkingSpace(registry, srgb);
if (toHub.kind === "ok") {
  // input transfer (decode) → matrix → output transfer (encode)
  const linearAp1 = applyConversion(toHub.value, [0.5, 0.25, 0.75]);

  // …and back to sRGB.
  const fromHub = conversionToWorkingSpace(registry, srgb);
  if (fromHub.kind === "ok") {
    const roundTrip = applyConversion(fromHub.value, linearAp1);
  }
}

// Scalar transfer-function evaluation (EOTF and its inverse).
const linear = eotf({ kind: "sRGB" }, 0.5); // encoded → scene-linear
const encoded = inverseEotf({ kind: "sRGB" }, linear); // scene-linear → encoded

API

ExportDescription
createColorSpaceRegistry(spaces?)Build an immutable ColorSpaceRegistry; unknown ids resolve to a rejected Result plus a beacon, never identity.
createStandardColorSpaceRegistry()A registry seeded with the standard v1 spaces (srgb, srgb-linear, rec709, rec2020, rec2020-pq/hlg, display-p3, acescc, acescct) plus the ACEScg connection space.
makeColorSpace(id, primaries, transferFn)Build a ColorSpace, deriving its toReference/fromReference matrices (Bradford-adapted to the ACES white point).
conversionToWorkingSpace(registry, ws)Descriptor for connection → working-space (matrix + input/output transfers).
conversionFromWorkingSpace(registry, ws)Descriptor for working-space → connection (the inverse).
applyConversion(descriptor, rgb)CPU reference realization: decode → matrix → encode on an RGB triple.
outputTransform(version, display)Display + View output-transform descriptor (aces-1.x; aces-2.0 is gated and reports not-implemented).
eotf(fn, encoded) / inverseEotf(fn, linear)Evaluate a transfer function's EOTF / inverse EOTF on a scalar.
rgbToXyzMatrix(space)The 3x3 linear RGB→XYZ matrix, Bradford-adapted to the connection (ACES) white.
CONNECTION_SPACE_ID / REFERENCE_PRIMARIESThe connection space id ("acescg") and its primaries (AP1).
PRIMARIES_SRGB, PRIMARIES_REC2020, PRIMARIES_DISPLAY_P3, PRIMARIES_AP0, PRIMARIES_AP1, PRIMARIES_AWG4Pinned standard primaries tables.
ColorSpaceRegistry, ColorConversionDescriptor, OutputTransformDescriptorPublic interface/descriptor types.

All chromaticities and transfer-function constants are pinned to primary sources; conversions are exhaustively matched (no silent fallbacks) and route through the ACEScg / AP1 hub.

License

MIT

API reference

21 public exports · 21 documented · generated from source.

applyConversionfunction
applyConversion(descriptor: ColorConversionDescriptor, rgb: readonly [number, number, number]): readonly [number, number, number]

Apply a `ColorConversionDescriptor` to a linear-or-encoded RGB triple, following its declared order: input transfer (decode) → matrix → output transfer (encode). This is the CPU reference realization of the descriptor and is what the round-trip-stability requirement is tested against.

conversionFromWorkingSpacefunction
conversionFromWorkingSpace(registry: ColorSpaceRegistry, workingSpace: string & $brand<"ColorSpaceId">): Result<ColorConversionDescriptor>

Compose the workingSpace→connection conversion descriptor — the inverse of `conversionToWorkingSpace`, auto-inserted after a declared-workingSpace op. - the input transfer is the working space's encoding (decode before matrix); - the matrix rotates working primaries back into connection primaries; - the output transfer is linear (connection space is scene-linear).

conversionToWorkingSpacefunction
conversionToWorkingSpace(registry: ColorSpaceRegistry, workingSpace: string & $brand<"ColorSpaceId">): Result<ColorConversionDescriptor>

Compose the connection→workingSpace conversion descriptor for auto-insertion.

createColorSpaceRegistryfunction
createColorSpaceRegistry(spaces?: readonly { id: string & $brand<"ColorSpaceId">; primaries: { red: { x: number; y: number; }; green: { x: number; y: number; }; blue: { x: number; y: number; }; white: { x: number; y: number; }; }; transferFn: { ...; } | ... 11 more ... | { ...; }; toReference: [...]; fromReference: [...]; }[]): ColorSpaceRegistry

Build a registry seeded with the given color spaces (resolution is real; entries are seeded by implementers).

createStandardColorSpaceRegistryfunction
createStandardColorSpaceRegistry(): ColorSpaceRegistry

A registry seeded with the standard v1 color spaces. The connection space (`acescg`/AP1) carries identity reference matrices; every other space's matrices are Bradford-adapted to the ACES white point.

eotffunction
eotf(fn: { kind: "linear"; } | { kind: "gamma"; exponent: number; } | { kind: "sRGB"; } | { kind: "rec709"; } | { kind: "rec2020"; } | { kind: "pq"; } | { kind: "hlg"; } | { kind: "logC3"; } | { kind: "logC4"; } | { ...; } | { ...; } | { ...; } | { ...; }, encoded: number): number

Evaluate a transfer function's EOTF (encoded → linear) on a scalar.

inverseEotffunction
inverseEotf(fn: { kind: "linear"; } | { kind: "gamma"; exponent: number; } | { kind: "sRGB"; } | { kind: "rec709"; } | { kind: "rec2020"; } | { kind: "pq"; } | { kind: "hlg"; } | { kind: "logC3"; } | { kind: "logC4"; } | { ...; } | { ...; } | { ...; } | { ...; }, linear: number): number

Evaluate a transfer function's inverse EOTF (linear → encoded) on a scalar.

makeColorSpacefunction
makeColorSpace(id: string, primaries: { red: { x: number; y: number; }; green: { x: number; y: number; }; blue: { x: number; y: number; }; white: { x: number; y: number; }; }, transferFn: { kind: "linear"; } | { kind: "gamma"; exponent: number; } | ... 10 more ... | { ...; }): { ...; }

Build a `ColorSpace` entry from its primaries + transfer function, deriving the `toReference`/`fromReference` matrices (RGB↔reference-RGB with Bradford CAT) at config-load time. The connection space (`acescg`) resolves to identity matrices.

outputTransformfunction
outputTransform(version: "aces-1.x" | "aces-2.0", display: string & $brand<"ColorSpaceId">): Result<OutputTransformDescriptor>

Build the Display + View output-transform descriptor (ACES 1.x default). ACES 2.0 is gated behind its explicit flag: the engine builds an `aces-1.x` descriptor by default, and only when `aces-2.0` is requested does it report `not-implemented` (the ACES 2.0 RRT/ODT is a later phase; D3).

rgbToXyzMatrixfunction
rgbToXyzMatrix(space: { id: string & $brand<"ColorSpaceId">; primaries: { red: { x: number; y: number; }; green: { x: number; y: number; }; blue: { x: number; y: number; }; white: { x: number; y: number; }; }; transferFn: { ...; } | ... 11 more ... | { ...; }; toReference: [...]; fromReference: [...]; }): [...]

Build the 3x3 RGB→XYZ matrix from primaries + white using Bradford chromatic adaptation to the connection white point. The matrix maps this space's linear RGB into CIE XYZ adapted to the reference (ACES) white.

ColorConversionDescriptorinterface
interface ColorConversionDescriptor

A backend-agnostic descriptor for a reference↔workingSpace conversion (Shader IR node).

ColorSpaceRegistryinterface
interface ColorSpaceRegistry

A registry of resolvable color spaces keyed by id.

OutputTransformDescriptorinterface
interface OutputTransformDescriptor

A backend-agnostic Display + View output-transform descriptor.

CONNECTION_SPACE_IDconst
CONNECTION_SPACE_ID: "acescg"

The id of the fixed connection (working/reference) space.

PRIMARIES_AP0const
const PRIMARIES_AP0

ACES AP0 (ACES2065-1) primaries, ACES white (findings.json:479).

PRIMARIES_AP1const
const PRIMARIES_AP1

ACES AP1 (ACEScg) primaries, ACES white (findings.json:479).

PRIMARIES_AWG4const
const PRIMARIES_AWG4

ARRI Wide Gamut 4 (AWG4) primaries, D65 white (findings.json:455).

PRIMARIES_DISPLAY_P3const
const PRIMARIES_DISPLAY_P3

Display-P3 primaries, D65 white (SMPTE EG 432-1; standard display gamut).

PRIMARIES_REC2020const
const PRIMARIES_REC2020

Rec.2020 primaries, D65 white.

PRIMARIES_SRGBconst
const PRIMARIES_SRGB

sRGB / Rec.709 primaries, D65 white.

REFERENCE_PRIMARIESconst
const REFERENCE_PRIMARIES

The reference-space primaries (ACEScg / AP1).

On this page