Standardize on one recipe layout
This commit is contained in:
parent
d404aeede3
commit
dbb743468d
@ -2,9 +2,25 @@ import { FujifilmRecipe } from '@/platforms/fujifilm/recipe';
|
|||||||
import { FilmSimulation } from '@/simulation';
|
import { FilmSimulation } from '@/simulation';
|
||||||
import PhotoFilmSimulation from '@/simulation/PhotoFilmSimulation';
|
import PhotoFilmSimulation from '@/simulation/PhotoFilmSimulation';
|
||||||
import clsx from 'clsx/lite';
|
import clsx from 'clsx/lite';
|
||||||
|
import { IoCloseCircle } from 'react-icons/io5';
|
||||||
|
|
||||||
const addSign = (value = 0) => value < 0 ? value : `+${value}`;
|
const addSign = (value = 0) => value < 0 ? value : `+${value}`;
|
||||||
|
|
||||||
|
const getRandomInt = () => {
|
||||||
|
const randomInt = Math.floor(Math.random() * 4) + 1;
|
||||||
|
return Math.random() >= 0.5 ? randomInt : -randomInt;
|
||||||
|
};
|
||||||
|
|
||||||
|
const random = {
|
||||||
|
highlight: getRandomInt(),
|
||||||
|
shadow: getRandomInt(),
|
||||||
|
color: getRandomInt(),
|
||||||
|
sharpness: getRandomInt(),
|
||||||
|
clarity: getRandomInt(),
|
||||||
|
colorChromeEffect: getRandomInt(),
|
||||||
|
colorChromeFXBlue: getRandomInt(),
|
||||||
|
};
|
||||||
|
|
||||||
export default function PhotoRecipe({
|
export default function PhotoRecipe({
|
||||||
recipe: {
|
recipe: {
|
||||||
dynamicRange,
|
dynamicRange,
|
||||||
@ -23,29 +39,31 @@ export default function PhotoRecipe({
|
|||||||
bwMagentaGreen,
|
bwMagentaGreen,
|
||||||
},
|
},
|
||||||
simulation,
|
simulation,
|
||||||
|
exposure,
|
||||||
|
iso,
|
||||||
}: {
|
}: {
|
||||||
recipe: FujifilmRecipe
|
recipe: FujifilmRecipe
|
||||||
simulation: FilmSimulation
|
simulation: FilmSimulation
|
||||||
|
exposure: string
|
||||||
|
iso: string
|
||||||
}) {
|
}) {
|
||||||
const whiteBalanceFormatted = (whiteBalance?.type ?? 'auto')
|
const whiteBalanceFormatted = (whiteBalance?.type ?? 'auto')
|
||||||
.replaceAll('auto', ' ')
|
.replaceAll('auto', ' ')
|
||||||
.replaceAll('-', ' ');
|
.replaceAll('-', ' ');
|
||||||
|
|
||||||
const hasCustomizedWhiteBalance =
|
|
||||||
Boolean(whiteBalance?.red) ||
|
|
||||||
Boolean(whiteBalance?.blue);
|
|
||||||
|
|
||||||
const hasBWAdjustments =
|
const hasBWAdjustments =
|
||||||
Boolean(bwAdjustment) ||
|
Boolean(bwAdjustment) ||
|
||||||
Boolean(bwMagentaGreen);
|
Boolean(bwMagentaGreen);
|
||||||
|
|
||||||
const renderDataSquare = (label: string, value: string | number = '0') => (
|
const renderDataSquare = (label: string, value: string | number = '0') => (
|
||||||
<div className={clsx(
|
<div className={clsx(
|
||||||
'flex flex-col items-center justify-center',
|
'flex flex-col items-center justify-center gap-0.5',
|
||||||
'bg-dim border-medium rounded-md p-0.5',
|
'bg-white/25 border border-white/20 rounded-md p-1',
|
||||||
)}>
|
)}>
|
||||||
<div>{typeof value === 'number' ? addSign(value) : value}</div>
|
<div>{typeof value === 'number' ? addSign(value) : value}</div>
|
||||||
<div className="text-xs tracking-wide text-dim">
|
<div className={clsx(
|
||||||
|
'text-[10px] leading-none tracking-wide font-medium text-black/50',
|
||||||
|
)}>
|
||||||
{label}
|
{label}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -53,72 +71,84 @@ export default function PhotoRecipe({
|
|||||||
|
|
||||||
return <div className="flex gap-8">
|
return <div className="flex gap-8">
|
||||||
<div className={clsx(
|
<div className={clsx(
|
||||||
'w-[20rem] self-start',
|
'w-[17rem] self-start',
|
||||||
'p-3',
|
'p-3',
|
||||||
'component-surface shadow-xs',
|
'rounded-lg shadow-2xl',
|
||||||
|
'bg-white/60 backdrop-blur-xl border border-white/30',
|
||||||
'space-y-3',
|
'space-y-3',
|
||||||
|
'text-[13px] text-black',
|
||||||
|
'saturate-200',
|
||||||
)}>
|
)}>
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-2">
|
||||||
<PhotoFilmSimulation {...{ simulation, className: 'grow' }} />
|
<PhotoFilmSimulation
|
||||||
<div className="bg-dim border-medium rounded-md px-1">
|
contrast="frost"
|
||||||
<span>DR</span>
|
className="grow"
|
||||||
<span>{dynamicRange ?? 100}</span>
|
simulation={simulation}
|
||||||
</div>
|
/>
|
||||||
|
<IoCloseCircle
|
||||||
|
size={20}
|
||||||
|
className="text-black/25"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div className="uppercase space-y-2">
|
||||||
className="uppercase space-y-2"
|
<div className="flex gap-2 *:grow">
|
||||||
>
|
<div className={clsx(
|
||||||
<div>
|
'inline-flex justify-center',
|
||||||
{whiteBalanceFormatted.length <= 8 && 'AWB: '}
|
'bg-white/25 border border-white/20 rounded-md px-1',
|
||||||
{whiteBalanceFormatted}
|
)}>
|
||||||
{hasCustomizedWhiteBalance && <>
|
DR{dynamicRange ?? 100}
|
||||||
{' '}
|
</div>
|
||||||
<span className="text-extra-dim">{'('}</span>
|
<div className={clsx(
|
||||||
R {addSign(whiteBalance?.red ?? 0)}
|
'inline-flex justify-center',
|
||||||
<span className="text-extra-dim">/</span>
|
'bg-white/25 border border-white/20 rounded-md px-1',
|
||||||
B {addSign(whiteBalance?.blue ?? 0)}
|
)}>
|
||||||
<span className="text-extra-dim">{')'}</span>
|
{iso}
|
||||||
</>}
|
</div>
|
||||||
|
<div className={clsx(
|
||||||
|
'inline-flex justify-center',
|
||||||
|
'bg-white/25 border border-white/20 rounded-md px-1',
|
||||||
|
)}>
|
||||||
|
{exposure}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2 *:w-full">
|
<div className="flex gap-2 *:w-full">
|
||||||
{renderDataSquare('Highlight', highlight)}
|
{renderDataSquare(
|
||||||
{renderDataSquare('Shadow', shadow)}
|
`R${addSign(whiteBalance?.red)} / B${addSign(whiteBalance?.blue)}`,
|
||||||
|
whiteBalanceFormatted,
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-2 *:w-full">
|
||||||
|
{renderDataSquare('Highlight', highlight || random.highlight)}
|
||||||
|
{renderDataSquare('Shadow', shadow || random.shadow)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2 *:w-full">
|
<div className="flex gap-2 *:w-full">
|
||||||
{/* TODO: Confirm color vs saturation label */}
|
{/* TODO: Confirm color vs saturation label */}
|
||||||
{renderDataSquare('Color', color)}
|
{renderDataSquare('Color', color || random.color)}
|
||||||
{renderDataSquare('Sharp', sharpness)}
|
{renderDataSquare('Sharpness', sharpness || random.sharpness)}
|
||||||
{renderDataSquare('Clarity', clarity)}
|
{renderDataSquare('Clarity', clarity || random.clarity)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2 *:w-full">
|
<div className="flex gap-2 *:w-full">
|
||||||
{renderDataSquare('Chrome', colorChromeEffect)}
|
{renderDataSquare('Color Chrome', colorChromeEffect)}
|
||||||
{renderDataSquare('FX Blue', colorChromeFXBlue)}
|
{renderDataSquare('FX Blue', colorChromeFXBlue)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
{highISONoiseReduction !== undefined
|
|
||||||
? <>
|
|
||||||
<span>High ISO NR: </span>
|
|
||||||
<span>{addSign(highISONoiseReduction)}</span>
|
|
||||||
</>
|
|
||||||
: <>
|
|
||||||
<span>Noise Reduction: </span>
|
|
||||||
<span>{noiseReductionBasic}</span>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
{grainEffect &&
|
{grainEffect &&
|
||||||
<div>
|
<div className="flex gap-2 *:w-full">
|
||||||
Grain:
|
{renderDataSquare(
|
||||||
{' '}
|
highISONoiseReduction !== undefined
|
||||||
{grainEffect.roughness}
|
? 'High ISO NR'
|
||||||
<span className="text-extra-dim">{' / '}</span>
|
: 'Noise Reduction',
|
||||||
{grainEffect.size}
|
highISONoiseReduction ?? noiseReductionBasic,
|
||||||
|
)}
|
||||||
|
{renderDataSquare(
|
||||||
|
'Grain',
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
|
`${grainEffect.roughness} / ${grainEffect.size === 'large' ? 'LG' : grainEffect.size === 'small' ? 'SM' : 'OFF'}`,
|
||||||
|
)}
|
||||||
</div>}
|
</div>}
|
||||||
{hasBWAdjustments &&
|
{hasBWAdjustments &&
|
||||||
<div>
|
<div className="flex gap-2 *:w-full">
|
||||||
BW Adjustment: {addSign(bwAdjustment)}
|
{renderDataSquare('BW Adjustment', bwAdjustment)}
|
||||||
<span className="text-extra-dim">{' / '}</span>
|
{renderDataSquare('BW Magenta Green', bwMagentaGreen)}
|
||||||
MG: {addSign(bwMagentaGreen)}
|
|
||||||
</div>}
|
</div>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,132 +0,0 @@
|
|||||||
import { FujifilmRecipe } from '@/platforms/fujifilm/recipe';
|
|
||||||
import { FilmSimulation } from '@/simulation';
|
|
||||||
import PhotoFilmSimulation from '@/simulation/PhotoFilmSimulation';
|
|
||||||
import clsx from 'clsx/lite';
|
|
||||||
|
|
||||||
const addSign = (value = 0) => value < 0 ? value : `+${value}`;
|
|
||||||
|
|
||||||
export default function PhotoRecipeFrostDark({
|
|
||||||
recipe: {
|
|
||||||
dynamicRange,
|
|
||||||
whiteBalance,
|
|
||||||
highISONoiseReduction,
|
|
||||||
noiseReductionBasic,
|
|
||||||
highlight,
|
|
||||||
shadow,
|
|
||||||
color,
|
|
||||||
sharpness,
|
|
||||||
clarity,
|
|
||||||
colorChromeEffect,
|
|
||||||
colorChromeFXBlue,
|
|
||||||
grainEffect,
|
|
||||||
bwAdjustment,
|
|
||||||
bwMagentaGreen,
|
|
||||||
},
|
|
||||||
simulation,
|
|
||||||
}: {
|
|
||||||
recipe: FujifilmRecipe
|
|
||||||
simulation: FilmSimulation
|
|
||||||
}) {
|
|
||||||
const whiteBalanceFormatted = (whiteBalance?.type ?? 'auto')
|
|
||||||
.replaceAll('auto', ' ')
|
|
||||||
.replaceAll('-', ' ');
|
|
||||||
|
|
||||||
const hasCustomizedWhiteBalance =
|
|
||||||
Boolean(whiteBalance?.red) ||
|
|
||||||
Boolean(whiteBalance?.blue);
|
|
||||||
|
|
||||||
const hasBWAdjustments =
|
|
||||||
Boolean(bwAdjustment) ||
|
|
||||||
Boolean(bwMagentaGreen);
|
|
||||||
|
|
||||||
const renderDataSquare = (label: string, value: string | number = '0') => (
|
|
||||||
<div className={clsx(
|
|
||||||
'flex flex-col items-center justify-center',
|
|
||||||
'bg-black/30 border border-white/20 rounded-md p-1',
|
|
||||||
)}>
|
|
||||||
<div>{typeof value === 'number' ? addSign(value) : value}</div>
|
|
||||||
<div className="text-xs tracking-wide text-white/40">
|
|
||||||
{label}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
return <div className="flex gap-8">
|
|
||||||
<div className={clsx(
|
|
||||||
'w-[20rem] self-start',
|
|
||||||
'p-3',
|
|
||||||
'rounded-lg shadow-2xl',
|
|
||||||
'bg-black/10 backdrop-blur-xl border border-white/20',
|
|
||||||
'space-y-3',
|
|
||||||
'text-main',
|
|
||||||
)}>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<PhotoFilmSimulation
|
|
||||||
contrast="high"
|
|
||||||
className="grow"
|
|
||||||
simulation={simulation}
|
|
||||||
/>
|
|
||||||
<div className="bg-black/15 border border-white/20 rounded-md px-1">
|
|
||||||
<span>DR</span>
|
|
||||||
<span>{dynamicRange ?? 100}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="uppercase space-y-3"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
{whiteBalanceFormatted.length <= 8 && 'AWB: '}
|
|
||||||
{whiteBalanceFormatted}
|
|
||||||
{hasCustomizedWhiteBalance && <>
|
|
||||||
{' '}
|
|
||||||
<span className="text-extra-dim">{'('}</span>
|
|
||||||
R {addSign(whiteBalance?.red ?? 0)}
|
|
||||||
<span className="text-extra-dim">/</span>
|
|
||||||
B {addSign(whiteBalance?.blue ?? 0)}
|
|
||||||
<span className="text-extra-dim">{')'}</span>
|
|
||||||
</>}
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-3 *:w-full">
|
|
||||||
{renderDataSquare('Highlight', highlight)}
|
|
||||||
{renderDataSquare('Shadow', shadow)}
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-3 *:w-full">
|
|
||||||
{/* TODO: Confirm color vs saturation label */}
|
|
||||||
{renderDataSquare('Color', color)}
|
|
||||||
{renderDataSquare('Sharp', sharpness)}
|
|
||||||
{renderDataSquare('Clarity', clarity)}
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-3 *:w-full">
|
|
||||||
{renderDataSquare('Chrome', colorChromeEffect)}
|
|
||||||
{renderDataSquare('FX Blue', colorChromeFXBlue)}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{highISONoiseReduction !== undefined
|
|
||||||
? <>
|
|
||||||
<span>High ISO NR: </span>
|
|
||||||
<span>{addSign(highISONoiseReduction)}</span>
|
|
||||||
</>
|
|
||||||
: <>
|
|
||||||
<span>Noise Reduction: </span>
|
|
||||||
<span>{noiseReductionBasic}</span>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
{grainEffect &&
|
|
||||||
<div>
|
|
||||||
Grain:
|
|
||||||
{' '}
|
|
||||||
{grainEffect.roughness}
|
|
||||||
<span className="text-extra-dim">{' / '}</span>
|
|
||||||
{grainEffect.size}
|
|
||||||
</div>}
|
|
||||||
{hasBWAdjustments &&
|
|
||||||
<div>
|
|
||||||
BW Adjustment: {addSign(bwAdjustment)}
|
|
||||||
<span className="text-extra-dim">{' / '}</span>
|
|
||||||
MG: {addSign(bwMagentaGreen)}
|
|
||||||
</div>}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
@ -1,156 +0,0 @@
|
|||||||
import { FujifilmRecipe } from '@/platforms/fujifilm/recipe';
|
|
||||||
import { FilmSimulation } from '@/simulation';
|
|
||||||
import PhotoFilmSimulation from '@/simulation/PhotoFilmSimulation';
|
|
||||||
import clsx from 'clsx/lite';
|
|
||||||
import { IoCloseCircle } from 'react-icons/io5';
|
|
||||||
|
|
||||||
const addSign = (value = 0) => value < 0 ? value : `+${value}`;
|
|
||||||
|
|
||||||
const getRandomInt = () => {
|
|
||||||
const randomInt = Math.floor(Math.random() * 4) + 1;
|
|
||||||
return Math.random() >= 0.5 ? randomInt : -randomInt;
|
|
||||||
};
|
|
||||||
|
|
||||||
const random = {
|
|
||||||
highlight: getRandomInt(),
|
|
||||||
shadow: getRandomInt(),
|
|
||||||
color: getRandomInt(),
|
|
||||||
sharpness: getRandomInt(),
|
|
||||||
clarity: getRandomInt(),
|
|
||||||
colorChromeEffect: getRandomInt(),
|
|
||||||
colorChromeFXBlue: getRandomInt(),
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function PhotoRecipeFrostLight({
|
|
||||||
recipe: {
|
|
||||||
dynamicRange,
|
|
||||||
whiteBalance,
|
|
||||||
highISONoiseReduction,
|
|
||||||
noiseReductionBasic,
|
|
||||||
highlight,
|
|
||||||
shadow,
|
|
||||||
color,
|
|
||||||
sharpness,
|
|
||||||
clarity,
|
|
||||||
colorChromeEffect,
|
|
||||||
colorChromeFXBlue,
|
|
||||||
grainEffect,
|
|
||||||
bwAdjustment,
|
|
||||||
bwMagentaGreen,
|
|
||||||
},
|
|
||||||
simulation,
|
|
||||||
exposure,
|
|
||||||
iso,
|
|
||||||
}: {
|
|
||||||
recipe: FujifilmRecipe
|
|
||||||
simulation: FilmSimulation
|
|
||||||
exposure: string
|
|
||||||
iso: string
|
|
||||||
}) {
|
|
||||||
const whiteBalanceFormatted = (whiteBalance?.type ?? 'auto')
|
|
||||||
.replaceAll('auto', ' ')
|
|
||||||
.replaceAll('-', ' ');
|
|
||||||
|
|
||||||
const hasBWAdjustments =
|
|
||||||
Boolean(bwAdjustment) ||
|
|
||||||
Boolean(bwMagentaGreen);
|
|
||||||
|
|
||||||
const renderDataSquare = (label: string, value: string | number = '0') => (
|
|
||||||
<div className={clsx(
|
|
||||||
'flex flex-col items-center justify-center gap-0.5',
|
|
||||||
'bg-white/25 border border-white/20 rounded-md p-1',
|
|
||||||
)}>
|
|
||||||
<div>{typeof value === 'number' ? addSign(value) : value}</div>
|
|
||||||
<div className={clsx(
|
|
||||||
'text-[10px] leading-none tracking-wide font-medium text-black/50',
|
|
||||||
)}>
|
|
||||||
{label}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
return <div className="flex gap-8">
|
|
||||||
<div className={clsx(
|
|
||||||
'w-[17rem] self-start',
|
|
||||||
'p-3',
|
|
||||||
'rounded-lg shadow-2xl',
|
|
||||||
'bg-white/60 backdrop-blur-xl border border-white/30',
|
|
||||||
'space-y-3',
|
|
||||||
'text-[13px] text-black',
|
|
||||||
'saturate-200',
|
|
||||||
)}>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<PhotoFilmSimulation
|
|
||||||
contrast="frost"
|
|
||||||
className="grow"
|
|
||||||
simulation={simulation}
|
|
||||||
/>
|
|
||||||
<IoCloseCircle
|
|
||||||
size={20}
|
|
||||||
className="text-black/25"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="uppercase space-y-2">
|
|
||||||
<div className="flex gap-2 *:grow">
|
|
||||||
<div className={clsx(
|
|
||||||
'inline-flex justify-center',
|
|
||||||
'bg-white/25 border border-white/20 rounded-md px-1',
|
|
||||||
)}>
|
|
||||||
DR{dynamicRange ?? 100}
|
|
||||||
</div>
|
|
||||||
<div className={clsx(
|
|
||||||
'inline-flex justify-center',
|
|
||||||
'bg-white/25 border border-white/20 rounded-md px-1',
|
|
||||||
)}>
|
|
||||||
{iso}
|
|
||||||
</div>
|
|
||||||
<div className={clsx(
|
|
||||||
'inline-flex justify-center',
|
|
||||||
'bg-white/25 border border-white/20 rounded-md px-1',
|
|
||||||
)}>
|
|
||||||
{exposure}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-2 *:w-full">
|
|
||||||
{renderDataSquare(
|
|
||||||
`R${addSign(whiteBalance?.red)} / B${addSign(whiteBalance?.blue)}`,
|
|
||||||
whiteBalanceFormatted,
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-2 *:w-full">
|
|
||||||
{renderDataSquare('Highlight', highlight || random.highlight)}
|
|
||||||
{renderDataSquare('Shadow', shadow || random.shadow)}
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-2 *:w-full">
|
|
||||||
{/* TODO: Confirm color vs saturation label */}
|
|
||||||
{renderDataSquare('Color', color || random.color)}
|
|
||||||
{renderDataSquare('Sharpness', sharpness || random.sharpness)}
|
|
||||||
{renderDataSquare('Clarity', clarity || random.clarity)}
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-2 *:w-full">
|
|
||||||
{renderDataSquare('Color Chrome', colorChromeEffect)}
|
|
||||||
{renderDataSquare('FX Blue', colorChromeFXBlue)}
|
|
||||||
</div>
|
|
||||||
{grainEffect &&
|
|
||||||
<div className="flex gap-2 *:w-full">
|
|
||||||
{renderDataSquare(
|
|
||||||
highISONoiseReduction !== undefined
|
|
||||||
? 'High ISO NR'
|
|
||||||
: 'Noise Reduction',
|
|
||||||
highISONoiseReduction ?? noiseReductionBasic,
|
|
||||||
)}
|
|
||||||
{renderDataSquare(
|
|
||||||
'Grain',
|
|
||||||
// eslint-disable-next-line max-len
|
|
||||||
`${grainEffect.roughness} / ${grainEffect.size === 'large' ? 'LG' : grainEffect.size === 'small' ? 'SM' : 'OFF'}`,
|
|
||||||
)}
|
|
||||||
</div>}
|
|
||||||
{hasBWAdjustments &&
|
|
||||||
<div className="flex gap-2 *:w-full">
|
|
||||||
{renderDataSquare('BW Adjustment', bwAdjustment)}
|
|
||||||
{renderDataSquare('BW Magenta Green', bwMagentaGreen)}
|
|
||||||
</div>}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
@ -1,156 +0,0 @@
|
|||||||
import { FujifilmRecipe } from '@/platforms/fujifilm/recipe';
|
|
||||||
import { FilmSimulation } from '@/simulation';
|
|
||||||
import PhotoFilmSimulation from '@/simulation/PhotoFilmSimulation';
|
|
||||||
import clsx from 'clsx/lite';
|
|
||||||
import { IoCloseCircle } from 'react-icons/io5';
|
|
||||||
|
|
||||||
const addSign = (value = 0) => value < 0 ? value : `+${value}`;
|
|
||||||
|
|
||||||
const getRandomInt = () => {
|
|
||||||
const randomInt = Math.floor(Math.random() * 4) + 1;
|
|
||||||
return Math.random() >= 0.5 ? randomInt : -randomInt;
|
|
||||||
};
|
|
||||||
|
|
||||||
const random = {
|
|
||||||
highlight: getRandomInt(),
|
|
||||||
shadow: getRandomInt(),
|
|
||||||
color: getRandomInt(),
|
|
||||||
sharpness: getRandomInt(),
|
|
||||||
clarity: getRandomInt(),
|
|
||||||
colorChromeEffect: getRandomInt(),
|
|
||||||
colorChromeFXBlue: getRandomInt(),
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function PhotoRecipeFrostLightV2({
|
|
||||||
recipe: {
|
|
||||||
dynamicRange,
|
|
||||||
whiteBalance,
|
|
||||||
highISONoiseReduction,
|
|
||||||
noiseReductionBasic,
|
|
||||||
highlight,
|
|
||||||
shadow,
|
|
||||||
color,
|
|
||||||
sharpness,
|
|
||||||
clarity,
|
|
||||||
colorChromeEffect,
|
|
||||||
colorChromeFXBlue,
|
|
||||||
grainEffect,
|
|
||||||
bwAdjustment,
|
|
||||||
bwMagentaGreen,
|
|
||||||
},
|
|
||||||
simulation,
|
|
||||||
exposure,
|
|
||||||
iso,
|
|
||||||
}: {
|
|
||||||
recipe: FujifilmRecipe
|
|
||||||
simulation: FilmSimulation
|
|
||||||
exposure: string
|
|
||||||
iso: string
|
|
||||||
}) {
|
|
||||||
const whiteBalanceFormatted = (whiteBalance?.type ?? 'auto')
|
|
||||||
.replaceAll('auto', ' ')
|
|
||||||
.replaceAll('-', ' ');
|
|
||||||
|
|
||||||
const hasBWAdjustments =
|
|
||||||
Boolean(bwAdjustment) ||
|
|
||||||
Boolean(bwMagentaGreen);
|
|
||||||
|
|
||||||
const renderDataSquare = (label: string, value: string | number = '0') => (
|
|
||||||
<div className={clsx(
|
|
||||||
'flex flex-col items-center justify-center gap-0.5',
|
|
||||||
'bg-white/25 border border-white/20 rounded-md p-1',
|
|
||||||
)}>
|
|
||||||
<div>{typeof value === 'number' ? addSign(value) : value}</div>
|
|
||||||
<div className={clsx(
|
|
||||||
'text-[10px] leading-none tracking-wide font-medium text-black/50',
|
|
||||||
)}>
|
|
||||||
{label}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
return <div className="flex gap-8">
|
|
||||||
<div className={clsx(
|
|
||||||
'w-[17rem] self-start',
|
|
||||||
'p-3',
|
|
||||||
'rounded-lg shadow-2xl',
|
|
||||||
'bg-white/60 backdrop-blur-xl border border-white/30',
|
|
||||||
'space-y-3',
|
|
||||||
'text-[13px] text-black',
|
|
||||||
'saturate-200',
|
|
||||||
)}>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<PhotoFilmSimulation
|
|
||||||
contrast="frost"
|
|
||||||
className="grow"
|
|
||||||
simulation={simulation}
|
|
||||||
/>
|
|
||||||
<IoCloseCircle
|
|
||||||
size={20}
|
|
||||||
className="text-black/25"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="uppercase space-y-2">
|
|
||||||
<div className="flex gap-2 *:grow">
|
|
||||||
<div className={clsx(
|
|
||||||
'inline-flex justify-center',
|
|
||||||
'bg-white/25 border border-white/20 rounded-md px-1',
|
|
||||||
)}>
|
|
||||||
DR{dynamicRange ?? 100}
|
|
||||||
</div>
|
|
||||||
<div className={clsx(
|
|
||||||
'inline-flex justify-center',
|
|
||||||
'bg-white/25 border border-white/20 rounded-md px-1',
|
|
||||||
)}>
|
|
||||||
{iso}
|
|
||||||
</div>
|
|
||||||
<div className={clsx(
|
|
||||||
'inline-flex justify-center',
|
|
||||||
'bg-white/25 border border-white/20 rounded-md px-1',
|
|
||||||
)}>
|
|
||||||
{exposure}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-2 *:w-full">
|
|
||||||
{renderDataSquare(
|
|
||||||
`R${addSign(whiteBalance?.red)} / B${addSign(whiteBalance?.blue)}`,
|
|
||||||
whiteBalanceFormatted,
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-2 *:w-full">
|
|
||||||
{renderDataSquare('Highlight', highlight || random.highlight)}
|
|
||||||
{renderDataSquare('Shadow', shadow || random.shadow)}
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-2 *:w-full">
|
|
||||||
{/* TODO: Confirm color vs saturation label */}
|
|
||||||
{renderDataSquare('Color', color || random.color)}
|
|
||||||
{renderDataSquare('Sharpness', sharpness || random.sharpness)}
|
|
||||||
{renderDataSquare('Clarity', clarity || random.clarity)}
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-2 *:w-full">
|
|
||||||
{renderDataSquare('Color Chrome', colorChromeEffect)}
|
|
||||||
{renderDataSquare('FX Blue', colorChromeFXBlue)}
|
|
||||||
</div>
|
|
||||||
{grainEffect &&
|
|
||||||
<div className="flex gap-2 *:w-full">
|
|
||||||
{renderDataSquare(
|
|
||||||
highISONoiseReduction !== undefined
|
|
||||||
? 'High ISO NR'
|
|
||||||
: 'Noise Reduction',
|
|
||||||
highISONoiseReduction ?? noiseReductionBasic,
|
|
||||||
)}
|
|
||||||
{renderDataSquare(
|
|
||||||
'Grain',
|
|
||||||
// eslint-disable-next-line max-len
|
|
||||||
`${grainEffect.roughness} / ${grainEffect.size === 'large' ? 'LG' : grainEffect.size === 'small' ? 'SM' : 'OFF'}`,
|
|
||||||
)}
|
|
||||||
</div>}
|
|
||||||
{hasBWAdjustments &&
|
|
||||||
<div className="flex gap-2 *:w-full">
|
|
||||||
{renderDataSquare('BW Adjustment', bwAdjustment)}
|
|
||||||
{renderDataSquare('BW Magenta Green', bwMagentaGreen)}
|
|
||||||
</div>}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
@ -2,7 +2,7 @@ import { FujifilmRecipe } from '@/platforms/fujifilm/recipe';
|
|||||||
import { FilmSimulation } from '@/simulation';
|
import { FilmSimulation } from '@/simulation';
|
||||||
import clsx from 'clsx/lite';
|
import clsx from 'clsx/lite';
|
||||||
import ImageLarge from '@/components/image/ImageLarge';
|
import ImageLarge from '@/components/image/ImageLarge';
|
||||||
import PhotoRecipeFrostLightV2 from './PhotoRecipeFrostLightV2';
|
import PhotoRecipe from './PhotoRecipe';
|
||||||
|
|
||||||
export default function PhotoRecipeOverlay({
|
export default function PhotoRecipeOverlay({
|
||||||
backgroundImageUrl,
|
backgroundImageUrl,
|
||||||
@ -31,7 +31,7 @@ export default function PhotoRecipeOverlay({
|
|||||||
'absolute inset-0',
|
'absolute inset-0',
|
||||||
'flex items-center justify-center',
|
'flex items-center justify-center',
|
||||||
)}>
|
)}>
|
||||||
<PhotoRecipeFrostLightV2 {...{
|
<PhotoRecipe {...{
|
||||||
recipe,
|
recipe,
|
||||||
simulation,
|
simulation,
|
||||||
exposure,
|
exposure,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user