faceless-photolib

@faceless-photolib/color-transform

ACES CLF reader and a constrained DCTL subset compiled to the faceless-photolib render IR — the DaVinci-Resolve-style color-transform layer.

The DaVinci-Resolve-style color-transform layer for faceless-photolib — a headless, color-managed, GPU-accelerated image-editing engine.

It reads an ACES Common LUT Format (CLF, S-2014-006) <ProcessList> and lowers its fixed node set (Matrix, LUT1D, LUT3D, Range, ASC_CDL, Log/Exponent) onto the engine's adjustment and 3D-LUT layers as an ordered chain. Adobe .cube files lower to a single 3D-LUT node, and a constrained DCTL expression subset is phased in later. Unsupported or unknown constructs fail loudly with a named rejected("not-implemented", …) result and a diagnostic beacon — never a silent identity passthrough.

Install

pnpm add @faceless-photolib/color-transform

Usage

import { match } from "ts-pattern";
import { parseClf, parseCubeTransform } from "@faceless-photolib/color-transform";
import type { ColorTransformProgram } from "@faceless-photolib/color-transform";

// Lower a CLF document into an ordered chain of adjustment / LUT nodes.
const result = parseClf(clfXmlString);

match(result)
  .with({ kind: "ok" }, ({ value }: { value: ColorTransformProgram }) => {
    // value.source === "clf"; value.chain is the ordered list of lowered nodes.
    for (const node of value.chain) {
      console.log(node.kind); // "adjustment" | "lut3d"
    }
  })
  .otherwise((failure) => {
    // validation-error (malformed CLF) or rejected:not-implemented (unsupported node).
    console.warn(`color-transform parse failed: ${failure.kind}`);
  });

// An Adobe .cube file lowers to a single 3D-LUT node (reusing the lut package's parser).
const cube = parseCubeTransform(cubeText, "tetrahedral");

API

ExportDescription
parseClf(xml)Parses an ACES CLF <ProcessList> XML document into a Result<ColorTransformProgram> — an ordered chain of lowered adjustment / LUT nodes.
parseDctlSubset(source)Entry point for the constrained DCTL expression-subset transpiler; phased to v1.x, so it currently returns rejected("not-implemented", …) with a beacon.
parseCubeTransform(text, interpolation?)Parses an Adobe .cube LUT into a single lut3d ColorTransformNode (interpolation defaults to "tetrahedral").
ColorTransformProgramA compiled transform: { node: "colorTransform"; source: "clf" | "dctl"; chain }.
ColorTransformNodeOne lowered node: an { kind: "adjustment" } op or an { kind: "lut3d" } op.

Every parser returns the engine's shared Result<T> discriminated union ({ kind: "ok", value } on success), so failures carry an explicit reason and are matched exhaustively with ts-pattern.

License

MIT

API reference

5 public exports · 5 documented · generated from source.

parseClffunction
parseClf(xml: string): Result<ColorTransformProgram>

Parse an ACES CLF (S-2014-006) `<ProcessList>` XML document into a lowered program: an ordered chain of adjustment/LUT nodes. Each fixed node is lowered by the exact-or-reject rules in `clf-nodes` (Matrix→channelMixer, clamped in-[0,1] Range→levels, LUT1D→curves, LUT3D→lut3d, restricted ASC_CDL→diagonal channelMixer); an unsupported or unknown construct is rejected by name with a `warnNotImplemented` beacon, never a silent identity.

parseCubeTransformfunction
parseCubeTransform(text: string, interpolation?: LutInterpolation): Result<ColorTransformNode>

`.cube` integration for the color-transform layer (design D7: the Adobe `.cube` reader lowers onto the 3D-LUT layer). An Adobe `.cube` file IS a single 3D LUT, so it lowers to a single `lut3d` `ColorTransformNode` — the SAME node shape a CLF `<LUT3D>` ProcessNode produces. That shared node type is the `.cube` integration: a `.cube` is not its own color-transform *grammar* (the frozen `ColorTransformProgram.source` is only `"clf" | "dctl"`), it is a LUT asset, so we never mislabel it as a CLF/DCTL program — we lower it to the honest 3D-LUT node. The parse reuses the `lut` package's real `.cube` parser (never a re-impl, never a silent identity): a malformed `.cube` forwards its `validation-error`, and a 1D-only `.cube` forwards its `rejected:not-implemented`.

parseDctlSubsetfunction
parseDctlSubset(_source: string): Result<ColorTransformProgram>

Parse the supported DCTL expression subset (v1.x; design D7 — phased later). The constrained DCTL grammar (scalar/`float3` arithmetic, `_xxxf` intrinsics, `__CONSTANT__` literals, `if`/`else`, statically-bounded `for`, `DEFINE_UI_PARAMS` → typed uniforms) is transpiled to the working pipeline. Unsupported constructs (pointers/structs/recursion/dynamic loops, `#include`, ACES built-ins, encrypted `.dctle`, `_tex2D`/`DEFINE_LUT`/`APPLY_LUT`, OCIO import) return `rejected("not-implemented", …)` with a beacon. v1.x not yet implemented: the whole subset transpiler is phased to a later version (see `notImplementedRemaining`). It fails loudly rather than guessing.

ColorTransformPrograminterface
interface ColorTransformProgram

A compiled color-transform: an ordered chain of lowered nodes.

ColorTransformNodetype
type ColorTransformNode

One lowered CLF/DCTL node: either an adjustment-style op or a LUT op.

On this page