diff --git a/src/photo/PhotoLarge.tsx b/src/photo/PhotoLarge.tsx index 95cfd16e..9a8de663 100644 --- a/src/photo/PhotoLarge.tsx +++ b/src/photo/PhotoLarge.tsx @@ -40,6 +40,7 @@ import { LuExpand } from 'react-icons/lu'; import LoaderButton from '@/components/primitives/LoaderButton'; import Tooltip from '@/components/Tooltip'; import ZoomControls, { ZoomControlsRef } from '@/components/image/ZoomControls'; +import PhotoRecipe from './PhotoRecipe'; export default function PhotoLarge({ photo, @@ -142,6 +143,7 @@ export default function PhotoLarge({ const largePhotoContent =
+ {photo.fujifilmRecipe && photo.filmSimulation && +
+ +
}
; const largePhotoContainerClassName = clsx(arePhotosMatted && diff --git a/src/photo/PhotoRecipe.tsx b/src/photo/PhotoRecipe.tsx index 7f10dd95..7147d155 100644 --- a/src/photo/PhotoRecipe.tsx +++ b/src/photo/PhotoRecipe.tsx @@ -1,4 +1,8 @@ -import { FujifilmRecipe } from '@/platforms/fujifilm/recipe'; +import { + FujifilmRecipe, + DEFAULT_GRAIN_EFFECT, + DEFAULT_WHITE_BALANCE, +} from '@/platforms/fujifilm/recipe'; import { FilmSimulation } from '@/simulation'; import PhotoFilmSimulation from '@/simulation/PhotoFilmSimulation'; import clsx from 'clsx/lite'; @@ -25,7 +29,7 @@ const random = { export default function PhotoRecipe({ recipe: { dynamicRange, - whiteBalance, + whiteBalance = DEFAULT_WHITE_BALANCE, highISONoiseReduction, noiseReductionBasic, highlight, @@ -35,21 +39,21 @@ export default function PhotoRecipe({ clarity, colorChromeEffect, colorChromeFXBlue, - grainEffect, + grainEffect = DEFAULT_GRAIN_EFFECT, bwAdjustment, bwMagentaGreen, - }, + } = {}, simulation, - exposure, iso, + exposure, }: { recipe: FujifilmRecipe simulation: FilmSimulation - exposure?: string iso?: string + exposure?: string }) { - const whiteBalanceFormatted = (whiteBalance?.type ?? 'auto') - .replaceAll('auto', ' ') + const whiteBalanceTypeFormatted = whiteBalance.type + .replace(/auto./i, '') .replaceAll('-', ' '); const renderRow = (children: ReactNode) => @@ -61,15 +65,18 @@ export default function PhotoRecipe({ className?: string, ) => (
-
{typeof value === 'number' ? addSign(value) : value}
+
+ {typeof value === 'number' ? addSign(value) : value} +
{label &&
{label}
} @@ -97,20 +104,20 @@ export default function PhotoRecipe({ className="text-black/25" />
-
+
{renderRow(<> {renderDataSquare(`DR${dynamicRange ?? 100}`)} {renderDataSquare(iso)} - {renderDataSquare(exposure)} + {renderDataSquare(exposure ?? '0ev')} )} {renderRow(<> {renderDataSquare( - whiteBalanceFormatted, + whiteBalanceTypeFormatted.toUpperCase(), `R${addSign(whiteBalance?.red)} / B${addSign(whiteBalance?.blue)}`, 'basis-2/3', )} {renderDataSquare( - highISONoiseReduction ?? noiseReductionBasic, + highISONoiseReduction ?? noiseReductionBasic ?? 'OFF', 'ISO NR', 'basis-1/3', )} @@ -125,27 +132,35 @@ export default function PhotoRecipe({ {renderDataSquare(clarity || random.clarity, 'Clarity')} )} {renderRow(<> - {renderDataSquare(colorChromeEffect, 'Color Chrome')} - {renderDataSquare(colorChromeFXBlue, 'FX Blue')} + {renderDataSquare( + colorChromeEffect?.toLocaleUpperCase() ?? 'N/A', + 'Color Chrome', + )} + {renderDataSquare( + colorChromeFXBlue?.toLocaleUpperCase() ?? 'N/A', + 'FX Blue', + )} )} {renderRow(<> {renderDataSquare( - <> - {grainEffect?.roughness === 'strong' - ? 'Str' - : grainEffect?.roughness === 'weak' - ? 'Wk' - : 'OFF'} - {'/'} - {grainEffect?.size === 'large' - ? 'LG' - : grainEffect?.size === 'small' - ? 'SM' : 'OFF'} - , + grainEffect.roughness === 'off' + ? 'NONE' + : <> + {grainEffect.roughness === 'strong' + ? 'STR' + : grainEffect.roughness === 'weak' + ? 'WK' + : 'OFF'} + {'/'} + {grainEffect.size === 'large' + ? 'LG' + : grainEffect.size === 'small' + ? 'SM' : 'OFF'} + , 'Grain', )} - {renderDataSquare(bwAdjustment, 'BW ADJ')} - {renderDataSquare(bwMagentaGreen, 'BW M/G')} + {renderDataSquare(bwAdjustment ?? 0, 'BW ADJ')} + {renderDataSquare(bwMagentaGreen ?? 0, 'BW M/G')} )}
diff --git a/src/platforms/fujifilm/index.ts b/src/platforms/fujifilm/index.ts index aab37fa6..1fe6ad9c 100644 --- a/src/platforms/fujifilm/index.ts +++ b/src/platforms/fujifilm/index.ts @@ -37,23 +37,22 @@ export const parseFujifilmMakerNote = ( const tagValueSize = bytes.readUInt16LE(index + BYTE_OFFSET_TAG_SIZE); const sendNumbersForDataType = ( - calculateNumberForOffset: (offset: number) => number, + parseNumberAtOffset: (offset: number) => number, sizeInBytes: number, ) => { let values: number[] = []; if (tagValueSize * sizeInBytes <= BYTES_PER_TAG_VALUE) { // Retrieve values if they fit in tag block values = Array.from({ length: tagValueSize }, (_, i) => - calculateNumberForOffset( + parseNumberAtOffset( index + BYTE_OFFSET_TAG_VALUE + i * sizeInBytes, ), ); } else { // Retrieve outside values if they don't fit in tag block const offset = bytes.readUint16LE(index + BYTE_OFFSET_TAG_VALUE); - values = []; for (let i = 0; i < tagValueSize; i++) { - values.push(calculateNumberForOffset(offset + i * sizeInBytes)); + values.push(parseNumberAtOffset(offset + i * sizeInBytes)); } } sendTagNumbers(tagId, values); diff --git a/src/platforms/fujifilm/recipe.ts b/src/platforms/fujifilm/recipe.ts index 527eb0e5..e763f316 100644 --- a/src/platforms/fujifilm/recipe.ts +++ b/src/platforms/fujifilm/recipe.ts @@ -43,13 +43,13 @@ export type FujifilmRecipe = Partial<{ bwMagentaGreen: number }>; -const DEFAULT_WHITE_BALANCE = { +export const DEFAULT_WHITE_BALANCE = { type: 'auto', red: 0, blue: 0, } as const; -const DEFAULT_GRAIN_EFFECT = { +export const DEFAULT_GRAIN_EFFECT = { roughness: 'off', size: 'off', } as const;