diff --git a/api/image_get.go b/api/image_get.go index d1ff4d2a31783d36bf9b063cb07b173304b61e22..eefc6fd6463d94da9145d6973abcae24c3dc4f52 100644 --- a/api/image_get.go +++ b/api/image_get.go @@ -26,6 +26,11 @@ func GetImage(env environment.FrontendEnvironment) http.Handler { http.Error(writer, err.Error(), http.StatusInternalServerError) return } + image.Metadata, err = env.Repositories.ImageMetadata.List(image) + if err != nil { + http.Error(writer, err.Error(), http.StatusInternalServerError) + return + } util.ReturnJson(writer, image) }) diff --git a/api/image_list.go b/api/image_list.go index eef39a53edfd41ce29ad34320189b0da02e7e50f..755aa9c99842e56c59f88647fecc8ebf98f9fff8 100644 --- a/api/image_list.go +++ b/api/image_list.go @@ -20,6 +20,11 @@ func ListImages(env environment.FrontendEnvironment) http.Handler { http.Error(writer, err.Error(), http.StatusInternalServerError) return } + image.Metadata, err = env.Repositories.ImageMetadata.List(image) + if err != nil { + http.Error(writer, err.Error(), http.StatusInternalServerError) + return + } images[idx] = image } diff --git a/docs/EXIF.md b/docs/EXIF.md new file mode 100644 index 0000000000000000000000000000000000000000..768be2124745efdf4d7909eb1271edd3782796e8 --- /dev/null +++ b/docs/EXIF.md @@ -0,0 +1,119 @@ +# EXIF metadata format + +* `Make` + Manufacturer +* `Model` + Device +* `DateTime` +* `DateTimeDigitized` +* `DateTimeOriginal` +* `DigitalZoomRatio` + Zoom + - 0 unused +* `ExposureBiasValue` + Exposure + -100.0 to +100.0 +* `ExposureMode` + Exposure Mode + - 0 = auto + - 1 = manual + - 2 = bracket +* `ExposureProgram` + Exposure Program + - 0 undefined + - 1 manual + - 2 normal + - 3 aperture priority + - 4 shutter priority + - 5 creative (depth of field priority) + - 6 action (fast shutter priority) + - 7 portrait (object separation priority) + - 8 landscape (background in focus priority) +* `ExposureTime` + Shutter in seconds +* `FNumber` + Aperture +* `Flash` + Bitfield of Flash metadata (bits counted from LSB to MSB) + - bit 0: flashFired + - bit 1: flashStrobeDetectionAvailable + - bit 2: flashStrobeDetected + - bit 3-4 + - 0 undefined + - 1 always on + - 2 always off + - 3 auto + - bit 5: flashAvailable + - bit 6: redEyeReductionAvailable +* `FlashEnergy` + Strobe energy in BCPS +* `FocalLength` + Focal Length in mm +* `FocalLengthIn35mmFilm` + Focal Length in mm compared to a 35mm Film equivalent +* `ISOSpeedRatings` + ISO exposure/speed rating +* `LightSource` + Type of lightsource for white balance + - 0 undefined + - 1 daylight + - 2 fluorescent + - 3 tungsten / incandescent + - 4 flash + - 9 fine weather + - 10 cloudy weather + - 11 shade + - 12 daylight fluorescent 5700-7100K + - 13 day white fluorescent 4600-5400K + - 14 cool white fluorescent 3900-4500K + - 15 white fluorescent 3200-3700K + - 17 standard light A + - 18 standard light B + - 19 standard light C + - 20 D55 + - 21 D65 + - 22 D75 + - 23 D50 + - 24 ISO studio tungsten + - 255 other +* `MeteringMode` + exposure metering mode + - 0 undefined + - 1 average + - 2 center weighted average + - 3 spot + - 4 multispot + - 5 pattern + - 6 partial + - 255 other +* `WhiteBalance` + White balance + - 0 auto + - 1 manual +* `SceneCaptureType` + Scene Mode + - 0 standard + - 1 landscape + - 2 portrait + - 3 night scene +* `Contrast` Contrast Processing + - 0 normal + - 1 soft + - 2 hard +* `Sharpness` + Sharpness Processing + - 0 normal + - 1 soft + - 2 hard +* `SubjectDistance` + Distance in meters +* `SubjectDistanceRange` + Distance Type + - 0 unknown + - 1 macro + - 2 close + - 3 distant +* `Software` + Application and version used to generate the image +* `Copyright` + copyright information diff --git a/model/image.go b/model/image.go index 79c204acfd131b4bd31c907ab7b02b2058f2c7ba..b43c7fd68cf621d4ce4d180b9d6b869b5711dd65 100644 --- a/model/image.go +++ b/model/image.go @@ -8,16 +8,17 @@ import ( ) type Image struct { - Id string `json:"id" db:"id"` - Owner string `json:"owner" db:"owner"` - Title string `json:"title" db:"title"` - Description string `json:"description" db:"description"` - CreatedAt time.Time `json:"created_at" db:"created_at"` - UpdatedAt time.Time `json:"updated_at" db:"updated_at"` - OriginalName string `json:"original_name" db:"original_name"` - MimeType string `json:"mime_type" db:"type"` - State string `json:"state" db:"state"` - Url string `json:"url"` + Id string `json:"id" db:"id"` + Owner string `json:"owner" db:"owner"` + Title string `json:"title" db:"title"` + Description string `json:"description" db:"description"` + CreatedAt time.Time `json:"created_at" db:"created_at"` + UpdatedAt time.Time `json:"updated_at" db:"updated_at"` + OriginalName string `json:"original_name" db:"original_name"` + MimeType string `json:"mime_type" db:"type"` + State string `json:"state" db:"state"` + Metadata map[string]string `json:"metadata,omitempty"` + Url string `json:"url"` } func (image Image) VerifyOwner(user User) error { diff --git a/task/image_resize_processor.go b/task/image_resize_processor.go index 414478ee6332cd6c89d7f29933deaf7eee082104..515244396dfb8e66667c31f4ab16ce74e53de760 100644 --- a/task/image_resize_processor.go +++ b/task/image_resize_processor.go @@ -75,12 +75,43 @@ func (processor *ImageProcessor) ProcessTask(ctx context.Context, task *asynq.Ta return } + supportedMetadata := map[string]bool{ + "Make": true, + "Model": true, + "DateTime": true, + "DateTimeDigitized": true, + "DateTimeOriginal": true, + "DigitalZoomRatio": true, + "ExposureBiasValue": true, + "ExposureMode": true, + "ExposureProgram": true, + "ExposureTime": true, + "FNumber": true, + "Flash": true, + "FlashEnergy": true, + "FocalLength": true, + "FocalLengthIn35mmFilm": true, + "ISOSpeedRatings": true, + "LightSource": true, + "MeteringMode": true, + "WhiteBalance": true, + "Contrast": true, + "Sharpness": true, + "SubjectDistance": true, + "SubjectDistanceRange": true, + "Software": true, + "Copyright": true, + } metadata := make(map[string]string) for _, key := range wand.GetImageProperties("exif:*") { if strings.HasPrefix(key, "exif:thumbnail:") { continue } - metadata[strings.TrimPrefix(key, "exif:")] = wand.GetImageProperty(key) + trimmedKey := strings.TrimPrefix(key, "exif:") + if !supportedMetadata[trimmedKey] { + continue + } + metadata[trimmedKey] = wand.GetImageProperty(key) } err = processor.env.Repositories.ImageMetadata.Update(payload.ImageId, metadata) if err != nil { diff --git a/ui/src/api/model/Image.ts b/ui/src/api/model/Image.ts index e944e649414ef3856b46f3d82bd0885006916405..16683c3fc246c123665c6bf403aeb49f5d2ab33b 100644 --- a/ui/src/api/model/Image.ts +++ b/ui/src/api/model/Image.ts @@ -8,5 +8,8 @@ export interface Image { original_name: string, mime_type: string, state: string, + metadata: { + [key: string]: string + }, url: string, } diff --git a/ui/src/components/ImageView.tsx b/ui/src/components/ImageView.tsx index e6e62e62b15b3a24336a3d581210e842d94cf0da..9d57bc6f32a9ed88c09cbf0fc444a8aaddb44ee7 100644 --- a/ui/src/components/ImageView.tsx +++ b/ui/src/components/ImageView.tsx @@ -1,7 +1,18 @@ import {Image} from "../api/model/Image"; -import React, {useState} from "react"; +import React, {useMemo, useState} from "react"; import {useUpdateImage} from "../api/useUpdateImage"; import {useDeleteImage} from "../api/useDeleteImage"; +import {parseMetadata, ratioToTime} from "../metadata/ImageMetadata"; +import {ratioToFloat} from "../metadata/Ratio"; +import {ExposureMode} from "../metadata/ExposureMode"; +import {ExposureProgram} from "../metadata/ExposureProgram"; +import {LightSource} from "../metadata/LightSource"; +import {MeteringMode} from "../metadata/MeteringMode"; +import {WhiteBalance} from "../metadata/WhiteBalance"; +import {SceneMode} from "../metadata/SceneMode"; +import {ContrastProcessing} from "../metadata/ContrastProcessing"; +import {SharpnessProcessing} from "../metadata/SharpnessProcessing"; +import {SubjectDistanceRange} from "../metadata/SubjectDistanceRange"; export interface ImageProps { image: Image @@ -13,6 +24,10 @@ export default function ImageView({image}: ImageProps) { const [title, setTitle] = useState<string>(image.title); const [description, setDescription] = useState<string>(image.description); + const metadata = useMemo(() => + parseMetadata(image.metadata), + [image]); + return ( <div> <p>UpdateError: {JSON.stringify(updateError, null, 2)}</p> @@ -45,6 +60,40 @@ export default function ImageView({image}: ImageProps) { <p>{image.created_at}</p> <p>{image.updated_at}</p> <p>{image.state}</p> + <h3>Metadata</h3> + <p><b>Make</b>: {metadata.make}</p> + <p><b>Model</b>: {metadata.model}</p> + <p><b>Software</b>: {metadata.software}</p> + <p><b>Copyright</b>: {metadata.copyright}</p> + <p><b>DateTime Created</b>: {metadata.dateTimeCreated?.toISOString()}</p> + <p><b>DateTime Digitized</b>: {metadata.dateTimeDigitized?.toISOString()}</p> + <p><b>DateTime Original</b>: {metadata.dateTimeOriginal?.toISOString()}</p> + <p><b>Digital Zoom</b>: {ratioToFloat(metadata.digitalZoomRatio)}</p> + <p><b>Exposure</b>: {ratioToFloat(metadata.exposure)}</p> + <p><b>Exposure Mode</b>: {metadata.exposureMode !== undefined ? + ExposureMode[metadata.exposureMode] : "null"}</p> + <p><b>Exposure Program</b>: {metadata.exposureProgram !== undefined ? + ExposureProgram[metadata.exposureProgram] : "null"}</p> + <p><b>Exposure Time</b>: {ratioToTime(metadata.exposureTime)}</p> + <p><b>Aperture</b>: {ratioToFloat(metadata.aperture)}</p> + <p><b>Focal Length</b>: {ratioToFloat(metadata.focalLength)}</p> + <p><b>Focal Length (35mm equivalent)</b>: {ratioToFloat(metadata.focalLength35mm)}</p> + <p><b>ISO</b>: {metadata.isoSpeedRating}</p> + <p><b>Light source</b>: {metadata.lightSource !== undefined ? + LightSource[metadata.lightSource] : "null"}</p> + <p><b>Metering mode</b>: {metadata.meteringMode !== undefined ? + MeteringMode[metadata.meteringMode] : "null"}</p> + <p><b>White balance</b>: {metadata.whiteBalance !== undefined ? + WhiteBalance[metadata.whiteBalance] : "null"}</p> + <p><b>Scene Mode</b>: {metadata.sceneMode !== undefined ? + SceneMode[metadata.sceneMode] : "null"}</p> + <p><b>Contrast Processing</b>: {metadata.contrast !== undefined ? + ContrastProcessing[metadata.contrast] : "null"}</p> + <p><b>Sharpness Processing</b>: {metadata.sharpness !== undefined ? + SharpnessProcessing[metadata.sharpness] : "null"}</p> + <p><b>Subject Distance</b>: {metadata.subjectDistance}</p> + <p><b>Subject Distance Range</b>: {metadata.subjectDistanceRange !== undefined ? + SubjectDistanceRange[metadata.subjectDistanceRange] : "null"}</p> <img src={image.url + "t"} alt=""/> <br/> <input diff --git a/ui/src/metadata/ContrastProcessing.ts b/ui/src/metadata/ContrastProcessing.ts new file mode 100644 index 0000000000000000000000000000000000000000..91405fb701cdbb9500ba8a3fb38df3edd87330b3 --- /dev/null +++ b/ui/src/metadata/ContrastProcessing.ts @@ -0,0 +1,5 @@ +export enum ContrastProcessing { + NORMAL = 0, + SOFT = 1, + HARD = 2, +} diff --git a/ui/src/metadata/ExposureMode.ts b/ui/src/metadata/ExposureMode.ts new file mode 100644 index 0000000000000000000000000000000000000000..2518b99022f968eb336e1d0cf0dfb4c2c82b1508 --- /dev/null +++ b/ui/src/metadata/ExposureMode.ts @@ -0,0 +1,5 @@ +export enum ExposureMode { + AUTO = 0, + MANUAL = 1, + BRACKET = 2, +} diff --git a/ui/src/metadata/ExposureProgram.ts b/ui/src/metadata/ExposureProgram.ts new file mode 100644 index 0000000000000000000000000000000000000000..c0569270344e88f9fa4b204b4dff1aa690613529 --- /dev/null +++ b/ui/src/metadata/ExposureProgram.ts @@ -0,0 +1,10 @@ +export enum ExposureProgram { + MANUAL = 1, + NORMAL = 2, + APERTURE_PRIORITY = 3, + SHUTTER_PRIORITY = 4, + CREATIVE = 5, + ACTION = 6, + PORTRAIT = 7, + LANDSCAPE = 8, +} diff --git a/ui/src/metadata/Flash.ts b/ui/src/metadata/Flash.ts new file mode 100644 index 0000000000000000000000000000000000000000..2a966779caefecf93428f0b2bd6883a630d0eb49 --- /dev/null +++ b/ui/src/metadata/Flash.ts @@ -0,0 +1,12 @@ +import {FlashMode} from "./FlashMode"; + +export interface Flash { + available: boolean, + fired: boolean, + strobeDetection: { + available: boolean, + detected: boolean, + }, + mode: FlashMode | null, + redEyeReduction: boolean, +} diff --git a/ui/src/metadata/FlashMode.ts b/ui/src/metadata/FlashMode.ts new file mode 100644 index 0000000000000000000000000000000000000000..02f73791c3a43e45ca9004f6f7a2637509e96831 --- /dev/null +++ b/ui/src/metadata/FlashMode.ts @@ -0,0 +1,5 @@ +export enum FlashMode { + ALWAYS_ON = 1, + ALWAYS_OFF = 2, + AUTO = 3 +} diff --git a/ui/src/metadata/ImageMetadata.ts b/ui/src/metadata/ImageMetadata.ts new file mode 100644 index 0000000000000000000000000000000000000000..12ff5d23c6b30d4dcd9f8b9dad4c4f2a6d8d3763 --- /dev/null +++ b/ui/src/metadata/ImageMetadata.ts @@ -0,0 +1,204 @@ +import {parseRatio, Ratio} from "./Ratio"; +import {Flash} from "./Flash"; +import {ExposureMode} from "./ExposureMode"; +import {ExposureProgram} from "./ExposureProgram"; +import {LightSource} from "./LightSource"; +import {MeteringMode} from "./MeteringMode"; +import {WhiteBalance} from "./WhiteBalance"; +import {SceneMode} from "./SceneMode"; +import {ContrastProcessing} from "./ContrastProcessing"; +import {SharpnessProcessing} from "./SharpnessProcessing"; +import {SubjectDistanceRange} from "./SubjectDistanceRange"; + +export interface ImageMetadata { + make?: string, + model?: string, + software?: string, + copyright?: string, + dateTimeCreated?: Date, + dateTimeDigitized?: Date, + dateTimeOriginal?: Date, + digitalZoomRatio?: Ratio, + exposure?: Ratio, + exposureMode?: ExposureMode, + exposureProgram?: ExposureProgram, + exposureTime?: Ratio, + aperture?: Ratio, + flash?: Flash, + focalLength?: Ratio, + focalLength35mm?: Ratio, + isoSpeedRating?: number, + lightSource?: LightSource, + meteringMode?: MeteringMode, + whiteBalance?: WhiteBalance, + sceneMode?: SceneMode, + contrast?: ContrastProcessing, + sharpness?: SharpnessProcessing, + subjectDistance?: number, + subjectDistanceRange?: SubjectDistanceRange, +} + +export function parseMetadata(metadata: { [key: string]: string }): ImageMetadata { + return { + make: metadata["Make"], + model: metadata["Model"], + software: metadata["Software"], + copyright: metadata["Copyright"], + dateTimeCreated: parseDate(metadata["DateTime"]), + dateTimeDigitized: parseDate(metadata["DateTimeDigitized"]), + dateTimeOriginal: parseDate(metadata["DateTimeOriginal"]), + digitalZoomRatio: parseRatio(metadata["DigitalZoomRatio"]), + exposure: parseRatio(metadata["ExposureBiasValue"]), + exposureMode: parseExposureMode(metadata["ExposureMode"]), + exposureProgram: parseExposureProgram(metadata["ExposureProgram"]), + exposureTime: parseRatio(metadata["ExposureTime"]), + aperture: parseRatio(metadata["FNumber"]), + flash: undefined, + focalLength: parseRatio(metadata["FocalLength"]), + focalLength35mm: parseRatio(metadata["FocalLengthIn35mmFilm"]), + isoSpeedRating: parseNumber(metadata["ISOSpeedRatings"]), + lightSource: parseLightSource(metadata["LightSource"]), + meteringMode: parseMeteringMode(metadata["MeteringMode"]), + whiteBalance: parseWhiteBalance(metadata["WhiteBalance"]), + sceneMode: parseSceneMode(metadata["SceneMode"]), + contrast: parseContrastProcessing(metadata["Contrast"]), + sharpness: parseSharpnessProcessing(metadata["Sharpness"]), + subjectDistance: parseNumber(metadata["SubjectDistance"]), + subjectDistanceRange: parseSubjectDistanceRange(metadata["SubjectDistanceRange"]), + } +} + +export function parseDate(value: string): Date | undefined { + const split = value.split(" "); + if (split.length !== 2) { + return undefined; + } + const [date, time] = split; + try { + const parsed = new Date( + date.replaceAll(":", "-") + " " + time + ); + parsed.toISOString(); + return parsed; + } catch (e) { + return undefined; + } +} + +export function parseNumber(value: string): number | undefined { + const number = parseInt(value); + if (isNaN(number) || number === Infinity || number === -Infinity) { + return undefined; + } + return number; +} + +export function parseExposureMode(value: string): ExposureMode | undefined { + const numericValue = parseNumber(value) + if (numericValue === undefined) { + return undefined; + } + if (numericValue in Object.values(ExposureMode)) { + return numericValue as ExposureMode; + } + return undefined; +} + +export function parseExposureProgram(value: string): ExposureProgram | undefined { + const numericValue = parseNumber(value); + if (numericValue === undefined) { + return undefined; + } + if (numericValue in Object.values(ExposureProgram)) { + return numericValue as ExposureProgram; + } + return undefined; +} + +export function parseLightSource(value: string): LightSource | undefined { + const numericValue = parseNumber(value); + if (numericValue === undefined) { + return undefined; + } + if (numericValue in Object.values(LightSource)) { + return numericValue as LightSource; + } + return undefined; +} + +export function parseMeteringMode(value: string): MeteringMode | undefined { + const numericValue = parseNumber(value); + if (numericValue === undefined) { + return undefined; + } + if (numericValue in Object.values(MeteringMode)) { + return numericValue as MeteringMode; + } + return undefined; +} + +export function parseWhiteBalance(value: string): WhiteBalance | undefined { + const numericValue = parseNumber(value); + if (numericValue === undefined) { + return undefined; + } + if (numericValue in Object.values(WhiteBalance)) { + return numericValue as WhiteBalance; + } + return undefined; +} + +export function parseSceneMode(value: string): SceneMode | undefined { + const numericValue = parseNumber(value); + if (numericValue === undefined) { + return undefined; + } + if (numericValue in Object.values(SceneMode)) { + return numericValue as SceneMode; + } + return undefined; +} + +export function parseContrastProcessing(value: string): ContrastProcessing | undefined { + const numericValue = parseNumber(value); + if (numericValue === undefined) { + return undefined; + } + if (numericValue in Object.values(ContrastProcessing)) { + return numericValue as ContrastProcessing; + } + return undefined; +} + +export function parseSharpnessProcessing(value: string): SharpnessProcessing | undefined { + const numericValue = parseNumber(value); + if (numericValue === undefined) { + return undefined; + } + if (numericValue in Object.values(SharpnessProcessing)) { + return numericValue as SharpnessProcessing; + } + return undefined; +} + +export function parseSubjectDistanceRange(value: string): SubjectDistanceRange | undefined { + const numericValue = parseNumber(value); + if (numericValue === undefined) { + return undefined; + } + if (numericValue in Object.values(SubjectDistanceRange)) { + return numericValue as SubjectDistanceRange; + } + return undefined; +} + +export function ratioToTime(value: Ratio | undefined): string | undefined { + if (value === undefined) { + return undefined; + } + if (value.numerator > value.denominator) { + return (value.numerator / value.denominator).toFixed(0) + "s"; + } else { + return "1/" + (value.denominator / value.numerator) + "s"; + } +} diff --git a/ui/src/metadata/LightSource.ts b/ui/src/metadata/LightSource.ts new file mode 100644 index 0000000000000000000000000000000000000000..46d3c65bd6f85046cccc392b73e9e9e1e32f971f --- /dev/null +++ b/ui/src/metadata/LightSource.ts @@ -0,0 +1,21 @@ +export enum LightSource { + DAYLIGHT = 1, + FLUORESCENT = 2, + INCANDESCENT = 3, + FLASH = 4, + FINE_WEATHER = 9, + CLOUDY_WEATHER = 10, + SHADE = 11, + FLUORESCENT_6400K = 12, + FLUORESCENT_5000K = 13, + FLUORESCENT_4200K = 14, + FLUORESCENT_3450K = 15, + STANDARD_LIGHT_A = 17, + STANDARD_LIGHT_B = 18, + STANDARD_LIGHT_C = 10, + D55 = 20, + D65 = 21, + D75 = 22, + D50 = 23, + ISO_STUDIO_INCANDESCENT = 24, +} diff --git a/ui/src/metadata/MeteringMode.ts b/ui/src/metadata/MeteringMode.ts new file mode 100644 index 0000000000000000000000000000000000000000..38572e86564c9815a7deccb94de441b3c11a2f4f --- /dev/null +++ b/ui/src/metadata/MeteringMode.ts @@ -0,0 +1,8 @@ +export enum MeteringMode { + AVERAGE = 1, + CENTER_WEIGHTED_AVERAGE = 2, + SPOT = 3, + MULTI_SPOT = 4, + PATTERN = 5, + PARTIAL = 6, +} diff --git a/ui/src/metadata/Ratio.ts b/ui/src/metadata/Ratio.ts new file mode 100644 index 0000000000000000000000000000000000000000..f5a3c5e4594e27ddbb607d0a13043fd1247068ac --- /dev/null +++ b/ui/src/metadata/Ratio.ts @@ -0,0 +1,33 @@ +export interface Ratio { + numerator: number, + denominator: number +} + +export function parseRatio(value: string): Ratio | undefined { + const splitValues = value.split("/"); + if (splitValues.length < 1) { + return undefined; + } + const numerator = parseInt(splitValues[0]); + if (isNaN(numerator)) { + return undefined; + } + let denominator; + if (splitValues.length === 1) { + denominator = 1; + } else { + denominator = parseInt(splitValues[1]); + if (isNaN(denominator) || denominator === 0) { + return undefined; + } + } + + return {numerator, denominator}; +} + +export function ratioToFloat(ratio: Ratio | undefined): number | undefined { + if (ratio === undefined) { + return undefined; + } + return ratio.numerator / ratio.denominator; +} diff --git a/ui/src/metadata/SceneMode.ts b/ui/src/metadata/SceneMode.ts new file mode 100644 index 0000000000000000000000000000000000000000..9c04599239fd45be6d5418e5873fe349d1e20dfc --- /dev/null +++ b/ui/src/metadata/SceneMode.ts @@ -0,0 +1,6 @@ +export enum SceneMode { + STANDARD = 0, + LANDSCAPE = 1, + PORTRAIT = 2, + NIGHT_SCENE = 3, +} diff --git a/ui/src/metadata/SharpnessProcessing.ts b/ui/src/metadata/SharpnessProcessing.ts new file mode 100644 index 0000000000000000000000000000000000000000..f8d0a5fd96c3e0418fc98c0dd4ca1e5eb8db9ad6 --- /dev/null +++ b/ui/src/metadata/SharpnessProcessing.ts @@ -0,0 +1,5 @@ +export enum SharpnessProcessing { + NORMAL = 0, + SOFT = 1, + HARD = 2, +} diff --git a/ui/src/metadata/SubjectDistanceRange.ts b/ui/src/metadata/SubjectDistanceRange.ts new file mode 100644 index 0000000000000000000000000000000000000000..f28a4b7a9b97e0987fad2b7783a60458eb3de425 --- /dev/null +++ b/ui/src/metadata/SubjectDistanceRange.ts @@ -0,0 +1,5 @@ +export enum SubjectDistanceRange { + MACRO = 1, + CLOSE = 2, + DISTANT = 3, +} diff --git a/ui/src/metadata/WhiteBalance.ts b/ui/src/metadata/WhiteBalance.ts new file mode 100644 index 0000000000000000000000000000000000000000..7b13f42f16a531bb7b88dc225c3bed79068809d4 --- /dev/null +++ b/ui/src/metadata/WhiteBalance.ts @@ -0,0 +1,4 @@ +export enum WhiteBalance { + AUTO = 0, + MANUAL = 1, +}