Photo looks for rullino: each look is a recipe of ordinary filters (a colour grade baked once into a 3D LUT, plus vignette and grain), so there are no third-party LUT licences and a look is just a list of chain steps you can edit.
Pre-alpha (0.x): the API may change between minor versions.
API reference (generated from the sources)
npm install @rullino/core @rullino/filters @rullino/presets
import { createImage, runChainCpu } from '@rullino/core';
import { lookSteps, looks } from '@rullino/presets';
console.log(looks.map((look) => `${look.id}: ${look.description}`));
const steps = lookSteps(looks[0]!, { intensity: 0.8 }); // 0 = no effect, 1 = as designed
const out = runChainCpu(steps, createImage(16, 16));
console.log(out.width);
lookLut(look) returns the baked 33³ LUT, and bakeLut bakes any chain of pointwise filters into one. A baked grade clamps HDR values to [0, 1] and differs from the live chain by less than 1/255 on average.
A look is also an edit document (see @rullino/core's "Edits as JSON"): its LUT travels by name (look:<id>), so the document fits in a link and renders anywhere applyEdit runs.
import { applyEdit, type LinearImage } from '@rullino/core';
import { filters } from '@rullino/filters';
import { lookEdit, looks, resolveLookLut } from '@rullino/presets';
export async function withLook(image: LinearImage): Promise<LinearImage> {
const doc = JSON.parse(JSON.stringify(lookEdit(looks[0]!, { intensity: 0.8 }))); // e.g. stored or sent
return applyEdit(image, doc, { filters, resolveLut: resolveLookLut });
}
Pass lutRef: lookLutRef to serializeChain to save your own chains that use looks.
MIT.