fix(library): support thumbnail generation and display for HEIC and TIF files
This commit is contained in:
@@ -14,8 +14,8 @@
|
||||
// smart collections) that hand-rolled cursors would make ugly.
|
||||
import type { Recipe } from '../../shared/types';
|
||||
import { readCapturedAt } from './imageOps';
|
||||
import { isRawName, rawThumbnail } from './rawDevelop';
|
||||
import { heicThumbnail, isHeicName } from './heicDevelop';
|
||||
import { isRawName, rawThumbnail, tiffThumbnail } from './rawDevelop';
|
||||
import { heicThumbnail, heicToJpeg, isHeicName } from './heicDevelop';
|
||||
import { openAt, walkPass, type Walk, type WalkFile } from './rollWalk';
|
||||
|
||||
const DB_NAME = 'recipescam-library';
|
||||
@@ -905,20 +905,38 @@ export async function scanFolder(
|
||||
}
|
||||
const raw = isRawName(file.name);
|
||||
const isTiff = /\.(tiff?)$/i.test(file.name);
|
||||
// A HEIC is read for its tile the way a RAW is, and reads less: the head of
|
||||
// the file is the whole of what its own thumbnail item needs (see
|
||||
// heicDevelop.ts), so it takes the same slice an ordinary photo does.
|
||||
const heic = isHeicName(file.name);
|
||||
const RAW_HEADER_BYTES = 16 * 1024 * 1024;
|
||||
const sliceBuffer = await file.slice(0, (raw || isTiff) ? Math.min(file.size, RAW_HEADER_BYTES) : HEAD_BYTES).arrayBuffer();
|
||||
|
||||
// Slice buffer: HEIC uses up to 4MB; RAW & TIFF use up to 32MB (or full file if smaller).
|
||||
const MAX_SLICE_BYTES = (raw || isTiff) ? 32 * 1024 * 1024 : heic ? 4 * 1024 * 1024 : HEAD_BYTES;
|
||||
const sliceBuffer = await file.slice(0, Math.min(file.size, MAX_SLICE_BYTES)).arrayBuffer();
|
||||
const bytes = new Uint8Array(sliceBuffer);
|
||||
const preview = heic
|
||||
? await heicThumbnail(bytes)
|
||||
: raw || isTiff
|
||||
? await rawThumbnail(bytes, file.name)
|
||||
: null;
|
||||
const src = preview ? new Blob([preview as BlobPart], { type: 'image/jpeg' }) : raw || heic ? null : file;
|
||||
const size = preview ? jpegSize(preview) : raw || heic ? null : jpegSize(bytes);
|
||||
|
||||
let preview: Uint8Array | null = null;
|
||||
if (heic) {
|
||||
preview = await heicThumbnail(bytes);
|
||||
if (!preview) {
|
||||
try {
|
||||
const fullBytes = new Uint8Array(await file.arrayBuffer());
|
||||
preview = await heicToJpeg(fullBytes, 320);
|
||||
} catch {
|
||||
preview = null;
|
||||
}
|
||||
}
|
||||
} else if (raw || isTiff) {
|
||||
preview = await rawThumbnail(bytes, file.name);
|
||||
if (!preview && isTiff) {
|
||||
try {
|
||||
const fullBytes = new Uint8Array(await file.arrayBuffer());
|
||||
preview = tiffThumbnail(fullBytes);
|
||||
} catch {
|
||||
preview = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const src = preview ? new Blob([preview as BlobPart], { type: 'image/jpeg' }) : (raw || heic || isTiff) ? null : file;
|
||||
const size = preview ? jpegSize(preview) : (raw || heic || isTiff) ? null : jpegSize(bytes);
|
||||
const thumb = src ? await tile(src, size) : null;
|
||||
const taken = (await readCapturedAt(bytes)) ?? file.lastModified;
|
||||
const cut = rel.lastIndexOf('/');
|
||||
|
||||
Reference in New Issue
Block a user