d7d7be2c6b
Classic Chrome's blue row, verbatim, with the red and green rows taken from VELVIPES: skies keep the muted teal/cyan lean while everything that is not blue reads loud. The shadow crush rides along from FILM_TONE, since it belongs to the stock rather than to a row. CLASSIC CHRIPES stays untouched beside it.
305 lines
8.6 KiB
TypeScript
305 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,
|
|
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,
|
|
},
|
|
];
|