web: add the B&W HIGH CONTRAST film sim to the PRESETS rail
The chip lands after ACRIPES and is a mono stock of its own, so it gets its own
baseFilter ('mono-high-contrast') rather than borrowing Acros': the PHOTO STYLE
chips are keyed by baseFilter, and the two greys must sit side by side.
The look is the B&W MIX plus a push at both ends. The mix rides the matrix — a
non-BT.709 row set (0.38/0.56/0.06, identical rows, sum 1.00) so a red roof
reads bright, a blue sky deep, and the separation is contrast before any curve.
The push rides FILM_TONE (shadow -0.32, highlight +0.26) so the ends move
without touching the midtones, and the midtone slope is SIM_CONTRAST_BIAS (4
contrast units) next to the sim's own exposure bias. The knobs stay at neutral:
a sim is colour and tone only.
Both B&W stocks being mono is now asked once, through isMonochromeBase, so the
colour-only stages (saturation, white balance, R/B fine-tune, chrome, hue
mixer) and the MONO strip label can never half-apply to one of them.
This commit is contained in:
@@ -33,7 +33,7 @@ import {
|
||||
type HslBandId,
|
||||
type Recipe,
|
||||
} from '../shared/types';
|
||||
import { HSL_BANDS, nearestHslBand, rgbToHsl } from '../shared/utils/colorUtils';
|
||||
import { HSL_BANDS, isMonochromeBase, nearestHslBand, rgbToHsl } from '../shared/utils/colorUtils';
|
||||
import type { MsgKey } from './i18n/vi';
|
||||
|
||||
// Mirrors the API's MAX_PHOTOS_PER_USER: shown on SAVE PHOTO, enforced there.
|
||||
@@ -1140,7 +1140,7 @@ export function Workspace() {
|
||||
const slug = name.replace(/[^\p{L}\p{N}]+/gu, '_').replace(/^_+|_+$/g, '').toUpperCase();
|
||||
const grain = Math.max(0, Math.round(recipe.adjustments.grain ?? 0));
|
||||
const warmth = Math.round((recipe.adjustments.temperature - 5500) / 250);
|
||||
const tail = recipe.baseFilter === 'monochrome' ? 'MONO' : `WARMTH ${warmth >= 0 ? '+' : ''}${warmth}`;
|
||||
const tail = isMonochromeBase(recipe.baseFilter) ? 'MONO' : `WARMTH ${warmth >= 0 ? '+' : ''}${warmth}`;
|
||||
return { tag: `#${slug || 'RECIPE'}`, title: name, meta: `ISO ${iso ?? 'AUTO'} · GRAIN ${grain} · ${tail}` };
|
||||
}, [recipe.name, recipe.adjustments, recipe.baseFilter, iso]);
|
||||
|
||||
@@ -1960,7 +1960,7 @@ export function Workspace() {
|
||||
// FX's MONOCHROME switch is not a look of its own: it swaps the base filter
|
||||
// for the mono stock and swaps right back. Adjustments are never touched, so
|
||||
// a knob moved while the switch is on survives the trip back.
|
||||
const monoOn = recipe.baseFilter === 'monochrome';
|
||||
const monoOn = isMonochromeBase(recipe.baseFilter);
|
||||
const toggleMono = () => {
|
||||
remember();
|
||||
if (monoOn) {
|
||||
|
||||
Reference in New Issue
Block a user