web: add CLASSIC VIVIDIPES, spliced at the blue row

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.
This commit is contained in:
2026-09-18 16:09:09 +07:00
parent abaa980f93
commit d7d7be2c6b
4 changed files with 16 additions and 1 deletions
@@ -120,6 +120,17 @@ export function getSkiaColorMatrix(baseFilter: BaseFilter, adj: ColorAdjustments
0.0652, 0.3973, 0.5575, 0, -0.0100,
0, 0, 0, 1, 0,
];
} else if (baseFilter === 'classic-vivid') {
// Classic Vivid: the Classic Chrome blue row kept verbatim — skies stay the
// same muted teal/cyan — with the red and green rows taken from Velvia, so
// everything that is not blue reads loud. Two stocks spliced at the blue
// row, which is exactly the point: quiet skies over saturated colour.
matrix = [
1.3895, -0.2540, -0.0256, 0, -0.0550,
-0.0772, 1.2355, -0.0261, 0, -0.0661,
0.0652, 0.3973, 0.5575, 0, -0.0100,
0, 0, 0, 1, 0,
];
} else if (baseFilter === 'astia') {
// Astia (Soft): gentler than standard — contrast below neutral (shadows
// lift, highlights ease off) and colour held back, with a faint warm/pink
@@ -41,6 +41,7 @@ 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 } },
@@ -207,6 +207,9 @@ export interface ToneUniforms {
// without also moving the other.
const FILM_TONE: Partial<Record<BaseFilter, Partial<ToneUniforms>>> = {
'classic-chrome': { sh: -0.28 },
// Classic Vivid is Classic Chrome's sibling — the shadow crush belongs to the
// stock, not to the matrix rows, so it comes along.
'classic-vivid': { sh: -0.28 },
'classic-neg': { shT: [-0.018, 0.009, 0.013], hlT: [0.024, 0.008, -0.012] },
// Acros. A black-and-white stock IS its grey ramp, so this entry only shapes
// the two ENDS and leaves the middle an identity: a smooth shadow toe that