Files
RecipesCam/docker/frontend/shared/utils/defaultRecipes.ts
T
3dtours 4057566a14 web: the three mixer knobs move the whole image, a frame chip toggles itself, ROTATE lets go when STRAIGHTEN steers
HUE, SAT and LUM leave the colour row: behind an IMAGE divider they are
hslHue/hslSat/hslLum, seeded into the shader's band accumulator at full
weight for every hue, while the eight band chips keep picking which colour
the panel on the photo edits. The image lightness term stays ungated so a
frame drained to grey by -SAT still answers +LUM.

FRAME loses its NO FRAME chip: pressing the frame already on the photo
takes it off.

ROTATE's quarter turns stop lighting the moment the fine angle leaves 0,
so the strip shows which of the two is steering the photo.
2026-09-18 18:45:41 +07:00

308 lines
8.6 KiB
TypeScript

import { Recipe, ColorAdjustments } from '../types';
// Fallback values for every adjustable knob. Old recipes/sessions persisted in
// AsyncStorage lack the newer fields — merge this under stored JSON to keep
// every adjustment well-defined (see storageUtils.getAllRecipes / App session).
export const DEFAULT_ADJUSTMENTS: ColorAdjustments = {
exposure: 0,
contrast: 0,
saturation: 0,
temperature: 5500,
tint: 0,
wbRed: 0,
wbBlue: 0,
highlight: 0,
shadow: 0,
denoise: 0,
clarity: 0,
grain: 0,
colorChrome: 'none',
colorChromeBlue: 'none',
dynamicRange: 'auto',
sharpening: 0,
hslHue: 0,
hslSat: 0,
hslLum: 0,
exposureCompensation: 0,
};
// Standard Fuji film simulations. These are the fixed "look" presets shown at
// the front of the PRESETS chip row: tapping one applies the simulation — its
// baseFilter colour matrix plus whatever the stock itself carries outside the
// matrix (its FILM_TONE curve, and a grain amount when the grain IS the look,
// as on Acros). Every other knob still resets to its neutral default (0 /
// auto), so a sim is a clean starting point, never a baked recipe; any further
// look (DR, CC, contrast, more grain) is added by the user afterwards.
export interface FilmSim {
id: string; // Recipe-like id used only while the sim is the current selection
name: string;
baseFilter: Recipe['baseFilter'];
adjustments: ColorAdjustments;
}
export const FILM_SIMS: FilmSim[] = [
{ id: 'sim-provia', name: 'PROVIPES', baseFilter: 'provia', adjustments: { ...DEFAULT_ADJUSTMENTS } },
{ id: 'sim-velvia', name: 'VELVIPES', baseFilter: 'velvia', adjustments: { ...DEFAULT_ADJUSTMENTS } },
{ id: 'sim-classic-chrome', name: 'CLASSIC CHRIPES', baseFilter: 'classic-chrome', adjustments: { ...DEFAULT_ADJUSTMENTS } },
{ id: 'sim-classic-vivid', name: 'CLASSIC VIVIDIPES', baseFilter: 'classic-vivid', adjustments: { ...DEFAULT_ADJUSTMENTS } },
{ id: 'sim-classic-neg', name: 'CLASSIC NEGIPES', baseFilter: 'classic-neg', adjustments: { ...DEFAULT_ADJUSTMENTS } },
{ id: 'sim-astia', name: 'ASTIPES', baseFilter: 'astia', adjustments: { ...DEFAULT_ADJUSTMENTS } },
{ id: 'sim-eterna', name: 'ETERNIPES', baseFilter: 'eterna', adjustments: { ...DEFAULT_ADJUSTMENTS } },
{ id: 'sim-acros', name: 'ACRIPES', baseFilter: 'monochrome', adjustments: { ...DEFAULT_ADJUSTMENTS, grain: 3 } },
// The rangefinder digital look (M/Q/SL) is not a film stock, so it ships as its own
// pair instead of one look that has to compromise:
// CLASSIC — the stock character: deep solid darks, natural shadows, rich but
// quiet colour. Its micro-contrast is CLARITY (a local unsharp mask in both
// renderers), never a global saturation boost, and a whisker of grain
// keeps it feeling like film rather than digital sharpness.
// VIVID — the same channel separation opened up for the digital era: lifted
// exposure, lifted shadows, a little colour. It reads bright and flattering
// straight off the shutter, no editing pass needed.
// Both share the 'leica'/'leica-vivid' matrices; the tonal half is the sim's
// own adjustments, which every apply path now carries into the panel.
{ id: 'sim-leica', name: 'LC STREETLIFE CLASSIC', baseFilter: 'leica', adjustments: { ...DEFAULT_ADJUSTMENTS, clarity: 2, grain: 1 } },
{ id: 'sim-leica-vivid', name: 'LC STREETLIFE VIVID', baseFilter: 'leica-vivid', adjustments: { ...DEFAULT_ADJUSTMENTS, exposure: 2, saturation: 2, clarity: 2, shadow: 1, highlight: -1 } },
];
// Film sim → full Recipe (never persisted; sims are applied on the fly).
export function filmSimToRecipe(sim: FilmSim): Recipe {
return {
id: sim.id,
name: sim.name,
baseFilter: sim.baseFilter,
adjustments: { ...sim.adjustments },
frameId: 'none',
useGeotag: true,
};
}
export const DEFAULT_RECIPES: Recipe[] = [
{
id: 'classic-neg-default',
name: 'CLASSIC NEGIPES.',
baseFilter: 'classic-neg',
adjustments: {
exposure: 2,
contrast: 1,
saturation: -1,
temperature: 6300,
tint: 2,
highlight: -2,
shadow: 1,
denoise: 1,
clarity: 2,
grain: 4,
colorChrome: 'weak',
colorChromeBlue: 'none',
dynamicRange: 'auto',
sharpening: 0,
exposureCompensation: 0,
},
frameId: 'none',
useGeotag: true,
},
{
id: 'velvia-default',
name: 'VELVIPES VIVID',
baseFilter: 'velvia',
adjustments: {
exposure: 0,
contrast: 2,
saturation: 3,
temperature: 5500,
tint: 0,
highlight: 1,
shadow: -1,
denoise: 2,
clarity: 4,
grain: 1,
colorChrome: 'strong',
colorChromeBlue: 'none',
dynamicRange: 'auto',
sharpening: 0,
exposureCompensation: 0,
},
frameId: 'none',
useGeotag: true,
},
{
id: 'provia-default',
name: 'PROVIPES STD',
baseFilter: 'provia',
adjustments: {
exposure: 1,
contrast: 0,
saturation: 0,
temperature: 5000,
tint: 0,
highlight: 0,
shadow: 0,
denoise: 2,
clarity: 1,
grain: 2,
colorChrome: 'none',
colorChromeBlue: 'none',
dynamicRange: 'auto',
sharpening: 0,
exposureCompensation: 0,
},
frameId: 'none',
useGeotag: true,
},
{
id: 'acros-default',
name: 'ACRIPES MONO',
baseFilter: 'monochrome',
adjustments: {
exposure: 0,
// Low: the deep black comes from FILM_TONE's toe and the micro-contrast
// from CLARITY, both of which add separation WITHOUT flattening the grey
// ramp. The old 4 / highlight 3 / shadow -2 stack was three global
// contrast moves on top of a matrix that was already clipping — it
// bought its deep black by throwing away every step below 9% and every
// one above 91%.
contrast: 2,
saturation: 0,
temperature: 5000,
tint: 0,
highlight: 0,
shadow: 0,
denoise: 0,
clarity: 3,
grain: 5,
colorChrome: 'none',
colorChromeBlue: 'none',
dynamicRange: 'auto',
sharpening: 0,
exposureCompensation: 0,
},
frameId: 'none',
useGeotag: true,
},
{
id: 'retro-amber-default',
name: 'RETRO AMBER 🏮',
baseFilter: 'classic-neg',
adjustments: {
exposure: 3,
contrast: 2,
saturation: 1,
temperature: 7500,
tint: -2,
highlight: -3,
shadow: 2,
denoise: 3,
clarity: -2,
grain: 5,
colorChrome: 'strong',
colorChromeBlue: 'none',
dynamicRange: 'auto',
sharpening: 0,
exposureCompensation: 0,
},
frameId: 'classic-white',
useGeotag: true,
},
{
id: 'cinema-spring-default',
name: 'CINEMA SPRING',
baseFilter: 'none',
adjustments: {
exposure: 0,
contrast: 1,
saturation: 1,
temperature: 5800,
tint: 0,
highlight: -1,
shadow: 1,
denoise: 2,
clarity: 1,
grain: 3,
colorChrome: 'none',
colorChromeBlue: 'none',
dynamicRange: 'auto',
sharpening: 0,
exposureCompensation: 0,
},
frameId: 'none',
cinema: 'spring',
useGeotag: true,
},
{
id: 'cinema-summer-default',
name: 'CINEMA SUMMER',
baseFilter: 'none',
adjustments: {
exposure: 0,
contrast: 2,
saturation: 2,
temperature: 6000,
tint: -1,
highlight: 1,
shadow: -1,
denoise: 1,
clarity: 2,
grain: 2,
colorChrome: 'weak',
colorChromeBlue: 'none',
dynamicRange: 'auto',
sharpening: 0,
exposureCompensation: 0,
},
frameId: 'none',
cinema: 'summer',
useGeotag: true,
},
{
id: 'cinema-autumn-default',
name: 'CINEMA AUTUMN',
baseFilter: 'none',
adjustments: {
exposure: 0,
contrast: 1,
saturation: 2,
temperature: 7200,
tint: -2,
highlight: -2,
shadow: 1,
denoise: 2,
clarity: 0,
grain: 4,
colorChrome: 'weak',
colorChromeBlue: 'none',
dynamicRange: 'auto',
sharpening: 0,
exposureCompensation: 0,
},
frameId: 'none',
cinema: 'autumn',
useGeotag: true,
},
{
id: 'cinema-winter-default',
name: 'CINEMA WINTER',
baseFilter: 'none',
adjustments: {
exposure: 1,
contrast: -1,
saturation: -2,
temperature: 4500,
tint: 2,
highlight: -2,
shadow: 2,
denoise: 3,
clarity: -2,
grain: 3,
colorChrome: 'none',
colorChromeBlue: 'weak',
dynamicRange: 'auto',
sharpening: 0,
exposureCompensation: 0,
},
frameId: 'none',
cinema: 'winter',
useGeotag: true,
},
];