@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-transformUsage
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
| Export | Description |
|---|---|
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"). |
ColorTransformProgram | A compiled transform: { node: "colorTransform"; source: "clf" | "dctl"; chain }. |
ColorTransformNode | One 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.
parseClffunctionparseClf(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.
parseCubeTransformfunctionparseCubeTransform(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`.
parseDctlSubsetfunctionparseDctlSubset(_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.
ColorTransformPrograminterfaceinterface ColorTransformProgramA compiled color-transform: an ordered chain of lowered nodes.
ColorTransformNodetypetype ColorTransformNodeOne lowered CLF/DCTL node: either an adjustment-style op or a LUT op.
@faceless-photolib/lut
3D LUT parsing (.cube / .3dl / ACES .clf) and CPU-reference tetrahedral/trilinear interpolation, lowering every format to one rgba16float-shaped cube descriptor for the faceless-photolib engine.
@faceless-photolib/interaction
Headless crop / resize / rotate / straighten / free-transform interaction controllers — pure state-machine reducers that emit committed transforms and crop rects, replicating Photoshop and Lightroom crop+transform controls without any UI.