Add parsing for remaining fujifilm recipe fields
This commit is contained in:
parent
c9ffb96082
commit
64a49c85a3
16
__tests__/fujifilm.test.ts
Normal file
16
__tests__/fujifilm.test.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { processTone } from '@/platforms/fujifilm/recipe';
|
||||||
|
|
||||||
|
describe('Fujifilm', () => {
|
||||||
|
describe('recipes', () => {
|
||||||
|
it('process tone', () => {
|
||||||
|
expect(processTone(0)).toBe(0);
|
||||||
|
expect(processTone(8)).toBe(-0.5);
|
||||||
|
expect(processTone(16)).toBe(-1);
|
||||||
|
expect(processTone(32)).toBe(-2);
|
||||||
|
expect(processTone(-16)).toBe(1);
|
||||||
|
expect(processTone(-32)).toBe(2);
|
||||||
|
expect(processTone(-48)).toBe(3);
|
||||||
|
expect(processTone(-64)).toBe(4);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -31,7 +31,7 @@ export default function Container({
|
|||||||
case 'blue': return [
|
case 'blue': return [
|
||||||
'text-blue-900 dark:text-blue-300',
|
'text-blue-900 dark:text-blue-300',
|
||||||
'bg-blue-50/50 dark:bg-blue-950/30',
|
'bg-blue-50/50 dark:bg-blue-950/30',
|
||||||
'border-blue-200 dark:border-blue-600/20',
|
'border-blue-200 dark:border-blue-500/40',
|
||||||
];
|
];
|
||||||
case 'red': return [
|
case 'red': return [
|
||||||
'text-red-600 dark:text-red-500/90',
|
'text-red-600 dark:text-red-500/90',
|
||||||
|
|||||||
@ -101,12 +101,19 @@ export default function PhotoForm({
|
|||||||
|
|
||||||
if (changedKeys.length > 0) {
|
if (changedKeys.length > 0) {
|
||||||
const fields = convertFormKeysToLabels(changedKeys);
|
const fields = convertFormKeysToLabels(changedKeys);
|
||||||
toastSuccess(
|
// Delay toasts to avoid render sync issue
|
||||||
`Updated EXIF fields: ${fields.join(', ')}`,
|
const timeout = setTimeout(
|
||||||
8000,
|
() => toastSuccess(`Updated EXIF fields: ${fields.join(', ')}`, 8000),
|
||||||
|
100,
|
||||||
);
|
);
|
||||||
|
return () => clearTimeout(timeout);
|
||||||
} else {
|
} else {
|
||||||
toastWarning('No new EXIF data found');
|
// Delay toasts to avoid render sync issue
|
||||||
|
const timeout = setTimeout(
|
||||||
|
() => toastWarning('No new EXIF data found'),
|
||||||
|
100,
|
||||||
|
);
|
||||||
|
return () => clearTimeout(timeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [updatedExifData]);
|
}, [updatedExifData]);
|
||||||
|
|||||||
@ -15,8 +15,10 @@ import {
|
|||||||
PRESERVE_ORIGINAL_UPLOADS,
|
PRESERVE_ORIGINAL_UPLOADS,
|
||||||
} from '@/app/config';
|
} from '@/app/config';
|
||||||
import { isExifForFujifilm } from '@/platforms/fujifilm';
|
import { isExifForFujifilm } from '@/platforms/fujifilm';
|
||||||
import { getFujifilmRecipeFromMakerNote } from '@/platforms/fujifilm/recipe';
|
import {
|
||||||
|
FujifilmRecipe,
|
||||||
|
getFujifilmRecipeFromMakerNote,
|
||||||
|
} from '@/platforms/fujifilm/recipe';
|
||||||
const IMAGE_WIDTH_RESIZE = 200;
|
const IMAGE_WIDTH_RESIZE = 200;
|
||||||
const IMAGE_WIDTH_BLUR = 200;
|
const IMAGE_WIDTH_BLUR = 200;
|
||||||
|
|
||||||
@ -49,6 +51,7 @@ export const extractImageDataFromBlobPath = async (
|
|||||||
|
|
||||||
let exifData: ExifData | undefined;
|
let exifData: ExifData | undefined;
|
||||||
let filmSimulation: FilmSimulation | undefined;
|
let filmSimulation: FilmSimulation | undefined;
|
||||||
|
let recipe: Partial<FujifilmRecipe> | undefined;
|
||||||
let blurData: string | undefined;
|
let blurData: string | undefined;
|
||||||
let imageResizedBase64: string | undefined;
|
let imageResizedBase64: string | undefined;
|
||||||
let shouldStripGpsData = false;
|
let shouldStripGpsData = false;
|
||||||
@ -79,9 +82,8 @@ export const extractImageDataFromBlobPath = async (
|
|||||||
const makerNote = exifDataBinary.tags?.MakerNote;
|
const makerNote = exifDataBinary.tags?.MakerNote;
|
||||||
if (Buffer.isBuffer(makerNote)) {
|
if (Buffer.isBuffer(makerNote)) {
|
||||||
filmSimulation = getFujifilmSimulationFromMakerNote(makerNote);
|
filmSimulation = getFujifilmSimulationFromMakerNote(makerNote);
|
||||||
console.log({
|
recipe = getFujifilmRecipeFromMakerNote(makerNote);
|
||||||
recipe: getFujifilmRecipeFromMakerNote(makerNote),
|
console.log(recipe);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
// MakerNote tag IDs and values referenced from:
|
// MakerNote tag IDs and values referenced from:
|
||||||
// github.com/exiftool/exiftool/blob/master/lib/Image/ExifTool/FujiFilm.pm
|
// - github.com/exiftool/exiftool/blob/master/lib/Image/ExifTool/FujiFilm.pm
|
||||||
|
// - exiftool.org/TagNames/FujiFilm.html
|
||||||
|
|
||||||
import type { ExifData } from 'ts-exif-parser';
|
import type { ExifData } from 'ts-exif-parser';
|
||||||
|
|
||||||
@ -9,6 +10,7 @@ const BYTE_INDEX_TAG_COUNT = 12;
|
|||||||
const BYTE_INDEX_FIRST_TAG = 14;
|
const BYTE_INDEX_FIRST_TAG = 14;
|
||||||
const BYTES_PER_TAG = 12;
|
const BYTES_PER_TAG = 12;
|
||||||
const BYTE_OFFSET_TAG_TYPE = 2;
|
const BYTE_OFFSET_TAG_TYPE = 2;
|
||||||
|
const BYTE_OFFSET_TAG_SIZE = 4;
|
||||||
const BYTE_OFFSET_TAG_VALUE = 8;
|
const BYTE_OFFSET_TAG_VALUE = 8;
|
||||||
|
|
||||||
export const isExifForFujifilm = (data: ExifData) =>
|
export const isExifForFujifilm = (data: ExifData) =>
|
||||||
@ -16,7 +18,7 @@ export const isExifForFujifilm = (data: ExifData) =>
|
|||||||
|
|
||||||
export const parseFujifilmMakerNote = (
|
export const parseFujifilmMakerNote = (
|
||||||
bytes: Buffer,
|
bytes: Buffer,
|
||||||
valueForTagUInt: (tagId: number, value: number) => void,
|
valueForTagNumbers: (tagId: number, numbers: number[]) => void,
|
||||||
) => {
|
) => {
|
||||||
const tagCount = bytes.readUint16LE(BYTE_INDEX_TAG_COUNT);
|
const tagCount = bytes.readUint16LE(BYTE_INDEX_TAG_COUNT);
|
||||||
for (let i = 0; i < tagCount; i++) {
|
for (let i = 0; i < tagCount; i++) {
|
||||||
@ -24,22 +26,46 @@ export const parseFujifilmMakerNote = (
|
|||||||
if (index + BYTES_PER_TAG < bytes.length) {
|
if (index + BYTES_PER_TAG < bytes.length) {
|
||||||
const tagId = bytes.readUInt16LE(index);
|
const tagId = bytes.readUInt16LE(index);
|
||||||
const tagType = bytes.readUInt16LE(index + BYTE_OFFSET_TAG_TYPE);
|
const tagType = bytes.readUInt16LE(index + BYTE_OFFSET_TAG_TYPE);
|
||||||
|
const tagValueSize = bytes.readUInt16LE(index + BYTE_OFFSET_TAG_SIZE);
|
||||||
switch (tagType) {
|
switch (tagType) {
|
||||||
|
// Int8 (UInt8 read as Int8)
|
||||||
|
case 1:
|
||||||
|
valueForTagNumbers(
|
||||||
|
tagId,
|
||||||
|
[bytes.readInt8(index + BYTE_OFFSET_TAG_VALUE)],
|
||||||
|
);
|
||||||
|
break;
|
||||||
// UInt16
|
// UInt16
|
||||||
case 3:
|
case 3:
|
||||||
valueForTagUInt(
|
valueForTagNumbers(
|
||||||
tagId,
|
tagId,
|
||||||
bytes.readUInt16LE(index + BYTE_OFFSET_TAG_VALUE),
|
[bytes.readUInt16LE(index + BYTE_OFFSET_TAG_VALUE)],
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
// UInt32
|
// UInt32
|
||||||
case 4:
|
case 4:
|
||||||
valueForTagUInt(
|
valueForTagNumbers(
|
||||||
tagId,
|
tagId,
|
||||||
bytes.readUInt32LE(index + BYTE_OFFSET_TAG_VALUE),
|
[bytes.readUInt32LE(index + BYTE_OFFSET_TAG_VALUE)],
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
// Int32
|
||||||
|
case 9:
|
||||||
|
if (tagValueSize === 1) {
|
||||||
|
valueForTagNumbers(
|
||||||
|
tagId,
|
||||||
|
[bytes.readInt32LE(index + BYTE_OFFSET_TAG_VALUE)],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
const offset = bytes.readInt32LE(index + BYTE_OFFSET_TAG_VALUE);
|
||||||
|
const values: number[] = [];
|
||||||
|
for (let i = 0; i < tagValueSize; i++) {
|
||||||
|
values.push(bytes.readInt32LE(offset + i * 4));
|
||||||
|
}
|
||||||
|
valueForTagNumbers(tagId, values);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,46 +1,158 @@
|
|||||||
import { parseFujifilmMakerNote } from '.';
|
import { parseFujifilmMakerNote } from '.';
|
||||||
|
|
||||||
// const TAG_ID_DYNAMIC_RANGE = 0x1400;
|
|
||||||
// const TAG_ID_DYNAMIC_RANGE_SETTING = 0x1402;
|
|
||||||
const TAG_ID_DEVELOPMENT_DYNAMIC_RANGE = 0x1403;
|
const TAG_ID_DEVELOPMENT_DYNAMIC_RANGE = 0x1403;
|
||||||
// const TAG_ID_AUTO_DYNAMIC_RANGE = 0x140b;
|
const TAG_ID_HIGHLIGHT = 0x1041;
|
||||||
// const TAG_ID_HIGHLIGHT = 0x1041;
|
const TAG_ID_SHADOW = 0x1040;
|
||||||
// const TAG_ID_SHADOW = 0x1040;
|
const TAG_ID_SATURATION = 0x1003;
|
||||||
// const TAG_ID_COLOR = 0x1003;
|
const TAG_ID_NOISE_REDUCTION = 0x100e;
|
||||||
// const TAG_ID_NOISE_REDUCTION = 0x100b;
|
const TAG_ID_NOISE_REDUCTION_LEGACY = 0x100b;
|
||||||
// const TAG_ID_SHARPNESS = 0x1001;
|
const TAG_ID_SHARPNESS = 0x1001;
|
||||||
// const TAG_ID_CLARITY = 0x100f;
|
const TAG_ID_CLARITY = 0x100f;
|
||||||
// const TAG_ID_GRAIN_EFFECT_ROUGHNESS = 0x1047;
|
const TAG_ID_GRAIN_EFFECT_ROUGHNESS = 0x1047;
|
||||||
// const TAG_ID_GRAIN_EFFECT_SIZE = 0x104c;
|
const TAG_ID_GRAIN_EFFECT_SIZE = 0x104c;
|
||||||
// const TAG_ID_COLOR_CHROME_EFFECT = 0x1048;
|
const TAG_ID_COLOR_CHROME_EFFECT = 0x1048;
|
||||||
// const TAG_ID_COLOR_CHROME_FX_BLUE = 0x104e;
|
const TAG_ID_COLOR_CHROME_FX_BLUE = 0x104e;
|
||||||
// const TAG_ID_WHITE_BALANCE = 0x1002;
|
const TAG_ID_WHITE_BALANCE = 0x1002;
|
||||||
// const TAG_ID_WHITE_BALANCE_FINE_TUNE = 0x1003;
|
const TAG_ID_WHITE_BALANCE_FINE_TUNE = 0x100a;
|
||||||
// TBD
|
const TAG_ID_BW_ADJUSTMENT = 0x1049;
|
||||||
// const TAG_ID_TONE = 0x1004;
|
const TAG_ID_BW_MAGENTA_GREEN = 0x104b;
|
||||||
// const TAG_ID_CONTRAST = 0x1006;
|
|
||||||
|
type WeakStrong = 'off' | 'weak' | 'strong';
|
||||||
|
|
||||||
export interface FujifilmRecipe {
|
export interface FujifilmRecipe {
|
||||||
dynamicRange: number
|
dynamicRange: number
|
||||||
highlight: number
|
highlight: number
|
||||||
shadow: number
|
shadow: number
|
||||||
color: number
|
color: number
|
||||||
noiseReduction: number
|
highISONoiseReduction: number
|
||||||
|
noiseReductionLegacy: string
|
||||||
sharpness: number
|
sharpness: number
|
||||||
clarity: number
|
clarity: number
|
||||||
grainEffect: {
|
grainEffect: {
|
||||||
roughness: 'strong' | 'medium' | 'weak'
|
roughness: WeakStrong
|
||||||
size: 'small' | 'large'
|
size: 'off' | 'small' | 'large'
|
||||||
}
|
}
|
||||||
colorChromeEffect: 'strong' | 'medium' | 'weak'
|
colorChromeEffect: WeakStrong
|
||||||
colorChromeFXBlue: 'off' | 'weak' | 'strong'
|
colorChromeFXBlue: WeakStrong
|
||||||
whiteBalance: {
|
whiteBalance: {
|
||||||
type: string
|
type: string
|
||||||
red: number
|
red: number
|
||||||
blue: number
|
blue: number
|
||||||
}
|
}
|
||||||
|
bwAdjustment: number
|
||||||
|
bwMagentaGreen: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DEFAULT_GRAIN_EFFECT = {
|
||||||
|
roughness: 'off',
|
||||||
|
size: 'off',
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
const DEFAULT_WHITE_BALANCE = {
|
||||||
|
type: 'auto',
|
||||||
|
red: 0,
|
||||||
|
blue: 0,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const processTone = (value: number) =>
|
||||||
|
value === 0 ? 0 : -(value / 16);
|
||||||
|
|
||||||
|
export const processSaturation = (value: number) => {
|
||||||
|
switch (value) {
|
||||||
|
case 0x4e0: return -4;
|
||||||
|
case 0x4c0: return -3;
|
||||||
|
case 0x400: return -2;
|
||||||
|
case 0x180: return -1;
|
||||||
|
case 0x80: return 1;
|
||||||
|
case 0x100: return 2;
|
||||||
|
case 0xc0: return 3;
|
||||||
|
case 0xe0: return 4;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const processNoiseReductionLegacy = (value: number) => {
|
||||||
|
switch (value) {
|
||||||
|
case 0x40: return 'low';
|
||||||
|
case 0x80: return 'normal';
|
||||||
|
default: return 'n/a';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const processNoiseReduction = (value: number) => {
|
||||||
|
switch (value) {
|
||||||
|
case 0x2e0: return -4;
|
||||||
|
case 0x2c0: return -3;
|
||||||
|
case 0x200: return -2;
|
||||||
|
case 0x280: return -1;
|
||||||
|
case 0x180: return 1;
|
||||||
|
case 0x100: return 2;
|
||||||
|
case 0x1c0: return 3;
|
||||||
|
case 0x1e0: return 4;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const processSharpness = (value: number) => {
|
||||||
|
switch (value) {
|
||||||
|
case 0x0: return -4;
|
||||||
|
case 0x1: return -3;
|
||||||
|
case 0x2: return -2;
|
||||||
|
case 0x82: return -1;
|
||||||
|
case 0x84: return 1;
|
||||||
|
case 0x4: return 2;
|
||||||
|
case 0x5: return 3;
|
||||||
|
case 0x6: return 4;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const processClarity = (value: number) => value / 1000;
|
||||||
|
|
||||||
|
export const processWeakStrong = (value: number): WeakStrong => {
|
||||||
|
switch (value) {
|
||||||
|
case 32: return 'weak';
|
||||||
|
case 64: return 'strong';
|
||||||
|
default: return 'off';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const processGrainEffectSize = (
|
||||||
|
value: number,
|
||||||
|
): FujifilmRecipe['grainEffect']['size'] => {
|
||||||
|
switch (value) {
|
||||||
|
case 16: return 'small';
|
||||||
|
case 32: return 'large';
|
||||||
|
default: return 'off';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const processWhiteBalanceType = (value: number) => {
|
||||||
|
switch (value) {
|
||||||
|
case 0x1: return 'auto-white-priority';
|
||||||
|
case 0x2: return 'auto-ambiance-priority';
|
||||||
|
case 0x100: return 'daylight';
|
||||||
|
case 0x200: return 'cloudy';
|
||||||
|
case 0x300: return 'daylight-fluorescent';
|
||||||
|
case 0x301: return 'day-white-fluorescent';
|
||||||
|
case 0x302: return 'white-fluorescent';
|
||||||
|
case 0x303: return 'warm-white-fluorescent';
|
||||||
|
case 0x304: return 'living-room-warm-white-fluorescent';
|
||||||
|
case 0x400: return 'incandescent';
|
||||||
|
case 0x500: return 'flash';
|
||||||
|
case 0x600: return 'underwater';
|
||||||
|
case 0xf00: return 'custom';
|
||||||
|
case 0xf01: return 'custom-2';
|
||||||
|
case 0xf02: return 'custom-3';
|
||||||
|
case 0xf03: return 'custom-4';
|
||||||
|
case 0xf04: return 'custom-5';
|
||||||
|
case 0xff0: return 'kelvin';
|
||||||
|
default: return 'auto';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const processWhiteBalanceComponent = (value: number) => value / 20;
|
||||||
|
|
||||||
export const getFujifilmRecipeFromMakerNote = (
|
export const getFujifilmRecipeFromMakerNote = (
|
||||||
bytes: Buffer,
|
bytes: Buffer,
|
||||||
): Partial<FujifilmRecipe> => {
|
): Partial<FujifilmRecipe> => {
|
||||||
@ -48,10 +160,65 @@ export const getFujifilmRecipeFromMakerNote = (
|
|||||||
|
|
||||||
parseFujifilmMakerNote(
|
parseFujifilmMakerNote(
|
||||||
bytes,
|
bytes,
|
||||||
(tag, value) => {
|
(tag, numbers) => {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case TAG_ID_DEVELOPMENT_DYNAMIC_RANGE:
|
case TAG_ID_DEVELOPMENT_DYNAMIC_RANGE:
|
||||||
recipe.dynamicRange = value;
|
recipe.dynamicRange = numbers[0];
|
||||||
|
break;
|
||||||
|
case TAG_ID_HIGHLIGHT:
|
||||||
|
recipe.highlight = processTone(numbers[0]);
|
||||||
|
break;
|
||||||
|
case TAG_ID_SHADOW:
|
||||||
|
recipe.shadow = processTone(numbers[0]);
|
||||||
|
break;
|
||||||
|
case TAG_ID_SATURATION:
|
||||||
|
recipe.color = processSaturation(numbers[0]);
|
||||||
|
break;
|
||||||
|
case TAG_ID_NOISE_REDUCTION:
|
||||||
|
recipe.highISONoiseReduction = processNoiseReduction(numbers[0]);
|
||||||
|
break;
|
||||||
|
case TAG_ID_NOISE_REDUCTION_LEGACY:
|
||||||
|
recipe.noiseReductionLegacy =
|
||||||
|
processNoiseReductionLegacy(numbers[0]);
|
||||||
|
break;
|
||||||
|
case TAG_ID_SHARPNESS:
|
||||||
|
recipe.sharpness = processSharpness(numbers[0]);
|
||||||
|
break;
|
||||||
|
case TAG_ID_CLARITY:
|
||||||
|
recipe.clarity = processClarity(numbers[0]);
|
||||||
|
break;
|
||||||
|
case TAG_ID_GRAIN_EFFECT_ROUGHNESS:
|
||||||
|
if (!recipe.grainEffect) { recipe.grainEffect = DEFAULT_GRAIN_EFFECT; }
|
||||||
|
recipe.grainEffect.roughness = processWeakStrong(numbers[0]);
|
||||||
|
break;
|
||||||
|
case TAG_ID_GRAIN_EFFECT_SIZE:
|
||||||
|
if (!recipe.grainEffect) { recipe.grainEffect = DEFAULT_GRAIN_EFFECT; }
|
||||||
|
recipe.grainEffect.size = processGrainEffectSize(numbers[0]);
|
||||||
|
break;
|
||||||
|
case TAG_ID_COLOR_CHROME_EFFECT:
|
||||||
|
recipe.colorChromeEffect = processWeakStrong(numbers[0]);
|
||||||
|
break;
|
||||||
|
case TAG_ID_COLOR_CHROME_FX_BLUE:
|
||||||
|
recipe.colorChromeFXBlue = processWeakStrong(numbers[0]);
|
||||||
|
break;
|
||||||
|
case TAG_ID_WHITE_BALANCE:
|
||||||
|
if (!recipe.whiteBalance) {
|
||||||
|
recipe.whiteBalance = DEFAULT_WHITE_BALANCE;
|
||||||
|
}
|
||||||
|
recipe.whiteBalance.type = processWhiteBalanceType(numbers[0]);
|
||||||
|
break;
|
||||||
|
case TAG_ID_WHITE_BALANCE_FINE_TUNE:
|
||||||
|
if (!recipe.whiteBalance) {
|
||||||
|
recipe.whiteBalance = DEFAULT_WHITE_BALANCE;
|
||||||
|
}
|
||||||
|
recipe.whiteBalance.red = processWhiteBalanceComponent(numbers[0]);
|
||||||
|
recipe.whiteBalance.blue = processWhiteBalanceComponent(numbers[1]);
|
||||||
|
break;
|
||||||
|
case TAG_ID_BW_ADJUSTMENT:
|
||||||
|
recipe.bwAdjustment = numbers[0];
|
||||||
|
break;
|
||||||
|
case TAG_ID_BW_MAGENTA_GREEN:
|
||||||
|
recipe.bwMagentaGreen = numbers[0];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -225,13 +225,15 @@ export const getFujifilmSimulationFromMakerNote = (
|
|||||||
|
|
||||||
parseFujifilmMakerNote(
|
parseFujifilmMakerNote(
|
||||||
bytes,
|
bytes,
|
||||||
(tag, value) => {
|
(tag, numbers) => {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case TAG_ID_SATURATION:
|
case TAG_ID_SATURATION:
|
||||||
filmModeFromSaturation = getFujifilmSimulationFromSaturation(value);
|
filmModeFromSaturation =
|
||||||
|
getFujifilmSimulationFromSaturation(numbers[0]);
|
||||||
break;
|
break;
|
||||||
case TAG_ID_FILM_MODE:
|
case TAG_ID_FILM_MODE:
|
||||||
filmMode = getFujifilmMode(value);
|
filmMode =
|
||||||
|
getFujifilmMode(numbers[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user