This commit is contained in:
Manav Rathi
2024-07-08 15:37:20 +05:30
parent f1c76adb38
commit c82ef796f2
3 changed files with 58 additions and 33 deletions

View File

@@ -9,6 +9,34 @@ import DownloadManager from "../download";
import type { UploadItem } from "../upload/types";
import type { MLWorkerElectron } from "./worker-electron";
export interface ImageBitmapAndData {
bitmap: ImageBitmap;
}
/**
* Return an {@link ImageBitmap} and its {@link ImageData}.
*
* @param enteFile The {@link EnteFile} to index.
*
* @param uploadItem If we're called during the upload process, then this will
* be set to the {@link UploadItem} that was uploaded. This way, we can directly
* use the on-disk file instead of needing to download the original from remote.
*
* @param electron The {@link MLWorkerElectron} instance that allows us to call
* our Node.js layer for various functionality.
*/
export const imageBitmapAndData = async (
enteFile: EnteFile,
uploadItem: UploadItem | undefined,
electron: MLWorkerElectron,
): Promise<ImageBitmapAndData> => {
const imageBitmap = uploadItem
? await renderableUploadItemImageBitmap(enteFile, uploadItem, electron)
: await renderableImageBitmap(enteFile);
return { bitmap: imageBitmap };
};
/**
* Return a {@link ImageBitmap} that downloads the source image corresponding to
* {@link enteFile} from remote.

View File

@@ -19,11 +19,7 @@ import {
translate,
type Matrix as TransformationMatrix,
} from "transformation-matrix";
import type { UploadItem } from "../upload/types";
import {
renderableImageBitmap,
renderableUploadItemImageBitmap,
} from "./bitmap";
import type { ImageBitmapAndData } from "./bitmap";
import { saveFaceCrops } from "./crop";
import {
clamp,
@@ -227,40 +223,37 @@ export interface Box {
*/
export const indexFaces = async (
enteFile: EnteFile,
uploadItem: UploadItem | undefined,
image: ImageBitmapAndData,
electron: MLWorkerElectron,
userAgent: string,
): Promise<FaceIndex> => {
const imageBitmap = uploadItem
? await renderableUploadItemImageBitmap(enteFile, uploadItem, electron)
: await renderableImageBitmap(enteFile);
const imageBitmap = image.bitmap;
const { width, height } = imageBitmap;
const fileID = enteFile.id;
const faceIndex = {
fileID,
width,
height,
faceEmbedding: {
version: faceIndexingVersion,
client: userAgent,
faces: await indexFacesInBitmap(fileID, imageBitmap, electron),
},
};
// This step, saving face crops, is not part of the indexing pipeline;
// we just do it here since we have already have the ImageBitmap at
// hand. Ignore errors that happen during this since it does not impact
// the generated face index.
try {
const faceIndex = {
fileID,
width,
height,
faceEmbedding: {
version: faceIndexingVersion,
client: userAgent,
faces: await indexFacesInBitmap(fileID, imageBitmap, electron),
},
};
// This step, saving face crops, is not part of the indexing pipeline;
// we just do it here since we have already have the ImageBitmap at
// hand. Ignore errors that happen during this since it does not impact
// the generated face index.
try {
await saveFaceCrops(imageBitmap, faceIndex);
} catch (e) {
log.error(`Failed to save face crops for file ${fileID}`, e);
}
return faceIndex;
} finally {
imageBitmap.close();
await saveFaceCrops(imageBitmap, faceIndex);
} catch (e) {
log.error(`Failed to save face crops for file ${fileID}`, e);
}
return faceIndex;
};
const indexFacesInBitmap = async (

View File

@@ -11,6 +11,7 @@ import { expose } from "comlink";
import downloadManager from "../download";
import { getAllLocalFiles, getLocalTrashedFiles } from "../files";
import type { UploadItem } from "../upload/types";
import { imageBitmapAndData } from "./bitmap";
import {
indexableFileIDs,
markIndexingFailed,
@@ -328,7 +329,7 @@ const syncWithLocalFilesAndGetFilesToIndex = async (
*
* @param userAgent The UA of the client that is doing the indexing (us).
*/
export const index = async (
const index = async (
enteFile: EnteFile,
uploadItem: UploadItem | undefined,
electron: MLWorkerElectron,
@@ -337,13 +338,16 @@ export const index = async (
const f = fileLogID(enteFile);
const startTime = Date.now();
const image = await imageBitmapAndData(enteFile, uploadItem, electron);
let faceIndex: FaceIndex;
try {
faceIndex = await indexFaces(enteFile, uploadItem, electron, userAgent);
faceIndex = await indexFaces(enteFile, image, electron, userAgent);
} catch (e) {
log.error(`Failed to index faces in ${f}`, e);
await markIndexingFailed(enteFile.id);
throw e;
} finally {
image.bitmap.close();
}
// [Note: Transient and permanent indexing failures]