Merge pull request #106 from sambecker/lens-make-model

Add camera lenses to model
This commit is contained in:
Sam Becker 2024-06-06 21:34:27 -05:00 committed by GitHub
commit 701055a35b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 119 additions and 1 deletions

47
src/lens/index.ts Normal file
View File

@ -0,0 +1,47 @@
import { Photo } from '@/photo';
import { parameterize } from '@/utility/string';
const LENS_PLACEHOLDER: Lens = { make: 'Lens', model: 'Model' };
export type Lens = {
make: string
model: string
};
export interface LensProps {
params: Lens
}
export interface PhotoLensProps {
params: Lens & { photoId: string }
}
export type LensWithCount = {
lensKey: string
lens: Lens
count: number
}
export type Lenses = LensWithCount[];
export const createLensKey = ({ make, model }: Lens) =>
parameterize(`${make}-${model}`, true);
export const getLensFromParams = ({
make,
model,
}: {
make: string,
model: string,
}): Lens => ({
make: parameterize(make, true),
model: parameterize(model, true),
});
export const lensFromPhoto = (
photo: Photo | undefined,
fallback?: Lens,
): Lens =>
photo?.lensMake && photo?.lensModel
? { make: photo.lensMake, model: photo.lensModel }
: fallback ?? LENS_PLACEHOLDER;

View File

@ -15,6 +15,7 @@ import {
getPhotosMostRecentUpdate,
getPhotosMeta,
getUniqueFocalLengths,
getUniqueLenses,
} from '@/photo/db/query';
import { GetPhotosOptions } from './db';
import { parseCachedPhotoDates, parseCachedPhotosDates } from '@/photo';
@ -30,6 +31,7 @@ import {
PREFIX_TAG,
pathForPhoto,
} from '@/site/paths';
import { createLensKey } from '@/lens';
// Table key
const KEY_PHOTOS = 'photos';
@ -37,6 +39,7 @@ const KEY_PHOTO = 'photo';
// Field keys
const KEY_TAGS = 'tags';
const KEY_CAMERAS = 'cameras';
const KEY_LENSES = 'lenses';
const KEY_FILM_SIMULATIONS = 'film-simulations';
const KEY_FOCAL_LENGTHS = 'focal-lengths';
// Type keys
@ -54,6 +57,10 @@ const getPhotosCacheKeyForOption = (
const value = options[option];
return value ? `${option}-${createCameraKey(value)}` : null;
}
case 'lens': {
const value = options[option];
return value ? `${option}-${createLensKey(value)}` : null;
}
case 'takenBefore':
case 'takenAfterInclusive': {
const value = options[option];
@ -192,6 +199,12 @@ export const getUniqueCamerasCached =
[KEY_PHOTOS, KEY_CAMERAS]
);
export const getUniqueLensesCached =
unstable_cache(
getUniqueLenses,
[KEY_PHOTOS, KEY_LENSES]
);
export const getUniqueFilmSimulationsCached =
unstable_cache(
getUniqueFilmSimulations,

View File

@ -1,4 +1,5 @@
import { Camera } from '@/camera';
import { Lens } from '@/lens';
import { FilmSimulation } from '@/simulation';
import { PRIORITY_ORDER_ENABLED } from '@/site/config';
import { parameterize } from '@/utility/string';
@ -13,6 +14,7 @@ export type GetPhotosOptions = {
query?: string
tag?: string
camera?: Camera
lens?: Lens
simulation?: FilmSimulation
focal?: number
takenBefore?: Date
@ -31,6 +33,7 @@ export const getWheresFromOptions = (
query,
tag,
camera,
lens,
simulation,
focal,
} = options;
@ -71,6 +74,12 @@ export const getWheresFromOptions = (
wheresValues.push(parameterize(camera.make, true));
wheresValues.push(parameterize(camera.model, true));
}
if (lens) {
wheres.push(`LOWER(REPLACE(lens_make, ' ', '-'))=$${valuesIndex++}`);
wheres.push(`LOWER(REPLACE(lens_model, ' ', '-'))=$${valuesIndex++}`);
wheresValues.push(parameterize(lens.make, true));
wheresValues.push(parameterize(lens.model, true));
}
if (simulation) {
wheres.push(`film_simulation=$${valuesIndex++}`);
wheresValues.push(simulation);

View File

@ -22,6 +22,7 @@ import {
} from '.';
import { getWheresFromOptions } from '.';
import { FocalLengths } from '@/focal';
import { Lenses, createLensKey } from '@/lens';
const createPhotosTable = () =>
sql`
@ -39,6 +40,8 @@ const createPhotosTable = () =>
model VARCHAR(255),
focal_length SMALLINT,
focal_length_in_35mm_format SMALLINT,
lens_make VARCHAR(255),
lens_model VARCHAR(255),
f_number REAL,
iso SMALLINT,
exposure_time DOUBLE PRECISION,
@ -65,6 +68,15 @@ const runMigration01 = () =>
ADD COLUMN IF NOT EXISTS semantic_description TEXT
`;
// Migration 02
const MIGRATION_FIELDS_02 = ['lens_make', 'lens_model'];
const runMigration02 = () =>
sql`
ALTER TABLE photos
ADD COLUMN IF NOT EXISTS lens_make VARCHAR(255),
ADD COLUMN IF NOT EXISTS lens_model VARCHAR(255)
`;
// Wrapper for most queries for JIT table creation/migration running
const safelyQueryPhotos = async <T>(
callback: () => Promise<T>,
@ -84,6 +96,13 @@ const safelyQueryPhotos = async <T>(
console.log('Running migration 01 ...');
await runMigration01();
result = await callback();
} else if (MIGRATION_FIELDS_02.some(field => new RegExp(
`column "${field}" of relation "photos" does not exist`,
'i',
).test(e.message))) {
console.log('Running migration 02 ...');
await runMigration02();
result = await callback();
} else if (/relation "photos" does not exist/i.test(e.message)) {
// If the table does not exist, create it
console.log('Creating photos table ...');
@ -131,6 +150,8 @@ export const insertPhoto = (photo: PhotoDbInsert) =>
model,
focal_length,
focal_length_in_35mm_format,
lens_make,
lens_model,
f_number,
iso,
exposure_time,
@ -158,6 +179,8 @@ export const insertPhoto = (photo: PhotoDbInsert) =>
${photo.model},
${photo.focalLength},
${photo.focalLengthIn35MmFormat},
${photo.lensMake},
${photo.lensModel},
${photo.fNumber},
${photo.iso},
${photo.exposureTime},
@ -188,6 +211,8 @@ export const updatePhoto = (photo: PhotoDbInsert) =>
model=${photo.model},
focal_length=${photo.focalLength},
focal_length_in_35mm_format=${photo.focalLengthIn35MmFormat},
lens_make=${photo.lensMake},
lens_model=${photo.lensModel},
f_number=${photo.fNumber},
iso=${photo.iso},
exposure_time=${photo.exposureTime},
@ -270,6 +295,24 @@ export const getUniqueCameras = async () =>
})))
, 'getUniqueCameras');
export const getUniqueLenses = async () =>
safelyQueryPhotos(() => sql`
SELECT DISTINCT lens_make||' '||lens_model as lens,
lens_make, lens_model, COUNT(*)
FROM photos
WHERE hidden IS NOT TRUE
AND trim(lens_make) <> ''
AND trim(lens_model) <> ''
GROUP BY lens_make, lens_model
ORDER BY lens ASC
`.then(({ rows }): Lenses => rows
.map(({ lens_make: make, lens_model: model, count }) => ({
lensKey: createLensKey({ make, model }),
lens: { make, model },
count: parseInt(count, 10),
})))
, 'getUniqueCameras');
export const getUniqueFilmSimulations = async () =>
safelyQueryPhotos(() => sql`
SELECT DISTINCT film_simulation, COUNT(*)

View File

@ -103,6 +103,8 @@ const FORM_METADATA = (
},
focalLength: { label: 'focal length' },
focalLengthIn35MmFormat: { label: 'focal length 35mm-equivalent' },
lensMake: { label: 'lens make' },
lensModel: { label: 'lens model' },
fNumber: { label: 'aperture' },
iso: { label: 'ISO' },
exposureTime: { label: 'exposure time' },
@ -195,6 +197,8 @@ export const convertExifToFormData = (
model: data.tags?.Model,
focalLength: data.tags?.FocalLength?.toString(),
focalLengthIn35MmFormat: data.tags?.FocalLengthIn35mmFormat?.toString(),
lensMake: data.tags?.LensMake,
lensModel: data.tags?.LensModel,
fNumber: data.tags?.FNumber?.toString(),
iso: data.tags?.ISO?.toString(),
exposureTime: data.tags?.ExposureTime?.toString(),

View File

@ -48,6 +48,8 @@ export interface PhotoExif {
model?: string
focalLength?: number
focalLengthIn35MmFormat?: number
lensMake?: string
lensModel?: string
fNumber?: number
iso?: number
exposureTime?: number

View File

@ -40,7 +40,7 @@ export const extractImageDataFromBlobPath = async (
const extension = getExtensionFromStorageUrl(url);
const fileBytes = blobPath
? await fetch(url).then(res => res.arrayBuffer())
? await fetch(url, { cache: 'no-store' }).then(res => res.arrayBuffer())
: undefined;
let exifData: ExifData | undefined;