Create initial fujifilm recipe type
This commit is contained in:
parent
d973b95d00
commit
8249e2929b
@ -2,9 +2,10 @@
|
||||
|
||||
import SiteGrid from '@/components/SiteGrid';
|
||||
import { clsx } from 'clsx/lite';
|
||||
import { FILM_SIMULATION_FORM_INPUT_OPTIONS } from '@/platforms/fujifilm';
|
||||
import PhotoFilmSimulation from
|
||||
'@/simulation/PhotoFilmSimulation';
|
||||
import {
|
||||
FILM_SIMULATION_FORM_INPUT_OPTIONS,
|
||||
} from '@/platforms/fujifilm/simulation';
|
||||
import PhotoFilmSimulation from '@/simulation/PhotoFilmSimulation';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export default function FilmPage() {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { FILM_SIMULATION_FORM_INPUT_OPTIONS } from '@/platforms/fujifilm';
|
||||
import PhotoFilmSimulation from
|
||||
'@/simulation/PhotoFilmSimulation';
|
||||
import {
|
||||
FILM_SIMULATION_FORM_INPUT_OPTIONS,
|
||||
} from '@/platforms/fujifilm/simulation';
|
||||
import PhotoFilmSimulation from '@/simulation/PhotoFilmSimulation';
|
||||
|
||||
export default function FilmPage() {
|
||||
return (
|
||||
|
||||
@ -18,7 +18,7 @@ import { formatCount, formatCountDescriptive } from '@/utility/string';
|
||||
import PhotoFilmSimulationIcon from '@/simulation/PhotoFilmSimulationIcon';
|
||||
import { IoMdCamera } from 'react-icons/io';
|
||||
import { ADMIN_DEBUG_TOOLS_ENABLED, SHOW_FILM_SIMULATIONS } from './config';
|
||||
import { labelForFilmSimulation } from '@/platforms/fujifilm';
|
||||
import { labelForFilmSimulation } from '@/platforms/fujifilm/simulation';
|
||||
import { getUniqueFocalLengths } from '@/photo/db/query';
|
||||
import { formatFocalLength } from '@/focal';
|
||||
import { TbCone } from 'react-icons/tb';
|
||||
|
||||
@ -4,7 +4,7 @@ import ImagePhotoGrid from './components/ImagePhotoGrid';
|
||||
import ImageContainer from './components/ImageContainer';
|
||||
import {
|
||||
labelForFilmSimulation,
|
||||
} from '@/platforms/fujifilm';
|
||||
} from '@/platforms/fujifilm/simulation';
|
||||
import PhotoFilmSimulationIcon from
|
||||
'@/simulation/PhotoFilmSimulationIcon';
|
||||
import { FilmSimulation } from '@/simulation';
|
||||
|
||||
@ -18,11 +18,11 @@ import { convertStringToArray } from '@/utility/string';
|
||||
import { generateNanoid } from '@/utility/nanoid';
|
||||
import {
|
||||
FILM_SIMULATION_FORM_INPUT_OPTIONS,
|
||||
MAKE_FUJIFILM,
|
||||
} from '@/platforms/fujifilm';
|
||||
} from '@/platforms/fujifilm/simulation';
|
||||
import { FilmSimulation } from '@/simulation';
|
||||
import { GEO_PRIVACY_ENABLED } from '@/app/config';
|
||||
import { TAG_FAVS, getValidationMessageForTags } from '@/tag';
|
||||
import { MAKE_FUJIFILM } from '@/platforms/fujifilm';
|
||||
|
||||
type VirtualFields = 'favorite';
|
||||
|
||||
|
||||
@ -5,8 +5,7 @@ import {
|
||||
import { convertExifToFormData } from '@/photo/form';
|
||||
import {
|
||||
getFujifilmSimulationFromMakerNote,
|
||||
isExifForFujifilm,
|
||||
} from '@/platforms/fujifilm';
|
||||
} from '@/platforms/fujifilm/simulation';
|
||||
import { ExifData, ExifParserFactory } from 'ts-exif-parser';
|
||||
import { PhotoFormData } from './form';
|
||||
import { FilmSimulation } from '@/simulation';
|
||||
@ -15,6 +14,7 @@ import {
|
||||
GEO_PRIVACY_ENABLED,
|
||||
PRESERVE_ORIGINAL_UPLOADS,
|
||||
} from '@/app/config';
|
||||
import { isExifForFujifilm } from '@/platforms/fujifilm';
|
||||
|
||||
const IMAGE_WIDTH_RESIZE = 200;
|
||||
const IMAGE_WIDTH_BLUR = 200;
|
||||
|
||||
48
src/platforms/fujifilm/index.ts
Normal file
48
src/platforms/fujifilm/index.ts
Normal file
@ -0,0 +1,48 @@
|
||||
// MakerNote tag IDs and values referenced from:
|
||||
// github.com/exiftool/exiftool/blob/master/lib/Image/ExifTool/FujiFilm.pm
|
||||
|
||||
import type { ExifData } from 'ts-exif-parser';
|
||||
|
||||
export const MAKE_FUJIFILM = 'FUJIFILM';
|
||||
|
||||
const BYTE_INDEX_TAG_COUNT = 12;
|
||||
const BYTE_INDEX_FIRST_TAG = 14;
|
||||
const BYTES_PER_TAG = 12;
|
||||
const BYTE_OFFSET_TAG_TYPE = 2;
|
||||
const BYTE_OFFSET_TAG_VALUE = 8;
|
||||
|
||||
export const TAG_ID_SATURATION = 0x1003;
|
||||
export const TAG_ID_FILM_MODE = 0x1401;
|
||||
|
||||
export const isExifForFujifilm = (data: ExifData) =>
|
||||
data.tags?.Make === MAKE_FUJIFILM;
|
||||
|
||||
export const parseFujifilmMakerNote = (
|
||||
bytes: Buffer,
|
||||
valueForTagUInt: (tagId: number, value: number) => void,
|
||||
) => {
|
||||
const tagCount = bytes.readUint16LE(BYTE_INDEX_TAG_COUNT);
|
||||
for (let i = 0; i < tagCount; i++) {
|
||||
const index = BYTE_INDEX_FIRST_TAG + i * BYTES_PER_TAG;
|
||||
if (index + BYTES_PER_TAG < bytes.length) {
|
||||
const tagId = bytes.readUInt16LE(index);
|
||||
const tagType = bytes.readUInt16LE(index + BYTE_OFFSET_TAG_TYPE);
|
||||
switch (tagType) {
|
||||
// UInt16
|
||||
case 3:
|
||||
valueForTagUInt(
|
||||
tagId,
|
||||
bytes.readUInt16LE(index + BYTE_OFFSET_TAG_VALUE),
|
||||
);
|
||||
break;
|
||||
// UInt32
|
||||
case 4:
|
||||
valueForTagUInt(
|
||||
tagId,
|
||||
bytes.readUInt32LE(index + BYTE_OFFSET_TAG_VALUE),
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
20
src/platforms/fujifilm/recipe.ts
Normal file
20
src/platforms/fujifilm/recipe.ts
Normal file
@ -0,0 +1,20 @@
|
||||
export interface FujifilmRecipe {
|
||||
dynamicRange: number
|
||||
highlight: number
|
||||
shadow: number
|
||||
color: number
|
||||
noiseReduction: number
|
||||
sharpening: number
|
||||
clarity: number
|
||||
grainEffect: {
|
||||
type: 'strong' | 'medium' | 'weak'
|
||||
size: 'small' | 'large'
|
||||
}
|
||||
colorChromeEffect: 'strong' | 'medium' | 'weak'
|
||||
colorChromeEffectBlue: 'off' | 'weak' | 'strong'
|
||||
whiteBalance: {
|
||||
type: string
|
||||
red: number
|
||||
blue: number
|
||||
}
|
||||
}
|
||||
@ -1,18 +1,8 @@
|
||||
// MakerNote tag IDs and values referenced from:
|
||||
// github.com/exiftool/exiftool/blob/master/lib/Image/ExifTool/FujiFilm.pm
|
||||
|
||||
import type { ExifData } from 'ts-exif-parser';
|
||||
|
||||
export const MAKE_FUJIFILM = 'FUJIFILM';
|
||||
|
||||
const BYTE_INDEX_TAG_COUNT = 12;
|
||||
const BYTE_INDEX_FIRST_TAG = 14;
|
||||
const BYTES_PER_TAG = 12;
|
||||
const BYTE_OFFSET_TAG_TYPE = 2;
|
||||
const BYTE_OFFSET_TAG_VALUE = 8;
|
||||
|
||||
const TAG_ID_SATURATION = 0x1003;
|
||||
const TAG_ID_FILM_MODE = 0x1401;
|
||||
import {
|
||||
TAG_ID_FILM_MODE,
|
||||
parseFujifilmMakerNote,
|
||||
TAG_ID_SATURATION,
|
||||
} from '.';
|
||||
|
||||
type FujifilmSimulationFromSaturation =
|
||||
'monochrome' |
|
||||
@ -46,9 +36,6 @@ export type FujifilmSimulation =
|
||||
FujifilmSimulationFromSaturation |
|
||||
FujifilmMode;
|
||||
|
||||
export const isExifForFujifilm = (data: ExifData) =>
|
||||
data.tags?.Make === MAKE_FUJIFILM;
|
||||
|
||||
const getFujifilmSimulationFromSaturation = (
|
||||
value?: number,
|
||||
): FujifilmSimulationFromSaturation | undefined => {
|
||||
@ -231,36 +218,6 @@ export const FILM_SIMULATION_FORM_INPUT_OPTIONS = Object
|
||||
export const labelForFilmSimulation = (simulation: FujifilmSimulation) =>
|
||||
FILM_SIMULATION_LABELS[simulation];
|
||||
|
||||
const parseFujifilmMakerNote = (
|
||||
bytes: Buffer,
|
||||
valueForTagUInt: (tagId: number, value: number) => void,
|
||||
) => {
|
||||
const tagCount = bytes.readUint16LE(BYTE_INDEX_TAG_COUNT);
|
||||
for (let i = 0; i < tagCount; i++) {
|
||||
const index = BYTE_INDEX_FIRST_TAG + i * BYTES_PER_TAG;
|
||||
if (index + BYTES_PER_TAG < bytes.length) {
|
||||
const tagId = bytes.readUInt16LE(index);
|
||||
const tagType = bytes.readUInt16LE(index + BYTE_OFFSET_TAG_TYPE);
|
||||
switch (tagType) {
|
||||
// UInt16
|
||||
case 3:
|
||||
valueForTagUInt(
|
||||
tagId,
|
||||
bytes.readUInt16LE(index + BYTE_OFFSET_TAG_VALUE),
|
||||
);
|
||||
break;
|
||||
// UInt32
|
||||
case 4:
|
||||
valueForTagUInt(
|
||||
tagId,
|
||||
bytes.readUInt32LE(index + BYTE_OFFSET_TAG_VALUE),
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const getFujifilmSimulationFromMakerNote = (
|
||||
bytes: Buffer,
|
||||
): FujifilmSimulation | undefined => {
|
||||
@ -1,4 +1,4 @@
|
||||
import { labelForFilmSimulation } from '@/platforms/fujifilm';
|
||||
import { labelForFilmSimulation } from '@/platforms/fujifilm/simulation';
|
||||
import PhotoFilmSimulationIcon from './PhotoFilmSimulationIcon';
|
||||
import { pathForFilmSimulation } from '@/app/paths';
|
||||
import { FilmSimulation } from '.';
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* eslint-disable max-len */
|
||||
import { labelForFilmSimulation } from '@/platforms/fujifilm';
|
||||
import { labelForFilmSimulation } from '@/platforms/fujifilm/simulation';
|
||||
import { CSSProperties } from 'react';
|
||||
import { FilmSimulation } from '.';
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ import {
|
||||
import {
|
||||
FujifilmSimulation,
|
||||
labelForFilmSimulation,
|
||||
} from '@/platforms/fujifilm';
|
||||
} from '@/platforms/fujifilm/simulation';
|
||||
|
||||
export type FilmSimulation = FujifilmSimulation;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user