Prepare for inlining

This commit is contained in:
Manav Rathi
2024-04-25 11:15:42 +05:30
parent 420f52f78f
commit e8e53b2ca5
2 changed files with 98 additions and 74 deletions

View File

@@ -4,7 +4,7 @@ import { validateAndGetCreationUnixTimeInMicroSeconds } from "@ente/shared/time"
import { NULL_LOCATION } from "constants/upload";
import exifr from "exifr";
import piexif from "piexifjs";
import { Location } from "types/upload";
import { Location, type ParsedExtractedMetadata } from "types/upload";
type ParsedEXIFData = Record<string, any> &
Partial<{
@@ -34,6 +34,60 @@ type RawEXIFData = Record<string, any> &
ImageHeight: number;
}>;
const EXIF_TAGS_NEEDED = [
"DateTimeOriginal",
"CreateDate",
"ModifyDate",
"GPSLatitude",
"GPSLongitude",
"GPSLatitudeRef",
"GPSLongitudeRef",
"DateCreated",
"ExifImageWidth",
"ExifImageHeight",
"ImageWidth",
"ImageHeight",
"PixelXDimension",
"PixelYDimension",
"MetadataDate",
];
/**
* Read EXIF data from an image and use that to construct and return an
* {@link ParsedExtractedMetadata}. This function is tailored for use when we
* upload files.
*
* @param fileOrData The image {@link File}, or its contents.
*/
export const parseImageMetadata = async (
fileOrData: File | Uint8Array,
fileTypeInfo: FileTypeInfo,
): Promise<ParsedExtractedMetadata> => {
/*
if (!(receivedFile instanceof File)) {
receivedFile = new File(
[await receivedFile.blob()],
receivedFile.name,
{
lastModified: receivedFile.lastModified,
},
);
}
*/
const exifData = await getParsedExifData(
fileOrData,
fileTypeInfo,
EXIF_TAGS_NEEDED,
);
return {
location: getEXIFLocation(exifData),
creationTime: getEXIFTime(exifData),
width: exifData?.imageWidth ?? null,
height: exifData?.imageHeight ?? null,
};
};
export async function getParsedExifData(
receivedFile: File,
{ extension }: FileTypeInfo,

View File

@@ -12,7 +12,7 @@ import {
import type { DataStream } from "@ente/shared/utils/data-stream";
import { Remote } from "comlink";
import { FILE_READER_CHUNK_SIZE, NULL_LOCATION } from "constants/upload";
import { getEXIFLocation, getEXIFTime, getParsedExifData } from "services/exif";
import { parseImageMetadata } from "services/exif";
import * as ffmpegService from "services/ffmpeg";
import { getElectronFileStream, getFileStream } from "services/readerService";
import { FilePublicMagicMetadataProps } from "types/file";
@@ -30,24 +30,6 @@ import {
} from "./takeout";
import { getFileName } from "./uploadService";
const EXIF_TAGS_NEEDED = [
"DateTimeOriginal",
"CreateDate",
"ModifyDate",
"GPSLatitude",
"GPSLongitude",
"GPSLatitudeRef",
"GPSLongitudeRef",
"DateCreated",
"ExifImageWidth",
"ExifImageHeight",
"ImageWidth",
"ImageHeight",
"PixelXDimension",
"PixelYDimension",
"MetadataDate",
];
const NULL_EXTRACTED_METADATA: ParsedExtractedMetadata = {
location: NULL_LOCATION,
creationTime: null,
@@ -84,6 +66,45 @@ export const extractAssetMetadata = async (
);
};
async function extractLivePhotoMetadata(
worker: Remote<DedicatedCryptoWorker>,
parsedMetadataJSONMap: Map<string, ParsedMetadataJSON>,
collectionID: number,
fileTypeInfo: FileTypeInfo,
livePhotoAssets: LivePhotoAssets2,
): Promise<ExtractMetadataResult> {
const imageFileTypeInfo: FileTypeInfo = {
fileType: FILE_TYPE.IMAGE,
extension: fileTypeInfo.imageType,
};
const {
metadata: imageMetadata,
publicMagicMetadata: imagePublicMagicMetadata,
} = await extractFileMetadata(
worker,
parsedMetadataJSONMap,
collectionID,
imageFileTypeInfo,
livePhotoAssets.image,
);
const videoHash = await getFileHash(
worker,
/* TODO(MR): ElectronFile changes */
livePhotoAssets.video as File | ElectronFile,
);
return {
metadata: {
...imageMetadata,
title: getFileName(livePhotoAssets.image),
fileType: FILE_TYPE.LIVE_PHOTO,
imageHash: imageMetadata.hash,
videoHash: videoHash,
hash: undefined,
},
publicMagicMetadata: imagePublicMagicMetadata,
};
}
async function extractFileMetadata(
worker: Remote<DedicatedCryptoWorker>,
parsedMetadataJSONMap: Map<string, ParsedMetadataJSON>,
@@ -152,7 +173,6 @@ async function getImageMetadata(
receivedFile: File | ElectronFile,
fileTypeInfo: FileTypeInfo,
): Promise<ParsedExtractedMetadata> {
let imageMetadata = NULL_EXTRACTED_METADATA;
try {
if (!(receivedFile instanceof File)) {
receivedFile = new File(
@@ -163,22 +183,11 @@ async function getImageMetadata(
},
);
}
const exifData = await getParsedExifData(
receivedFile,
fileTypeInfo,
EXIF_TAGS_NEEDED,
);
imageMetadata = {
location: getEXIFLocation(exifData),
creationTime: getEXIFTime(exifData),
width: exifData?.imageWidth ?? null,
height: exifData?.imageHeight ?? null,
};
return await parseImageMetadata(receivedFile, fileTypeInfo);
} catch (e) {
log.error("getExifData failed", e);
log.error("Failed to parse image metadata", e);
return NULL_EXTRACTED_METADATA;
}
return imageMetadata;
}
// tries to extract date from file name if available else returns null
@@ -237,45 +246,6 @@ async function getVideoMetadata(file: File | ElectronFile) {
return videoMetadata;
}
async function extractLivePhotoMetadata(
worker: Remote<DedicatedCryptoWorker>,
parsedMetadataJSONMap: Map<string, ParsedMetadataJSON>,
collectionID: number,
fileTypeInfo: FileTypeInfo,
livePhotoAssets: LivePhotoAssets2,
): Promise<ExtractMetadataResult> {
const imageFileTypeInfo: FileTypeInfo = {
fileType: FILE_TYPE.IMAGE,
extension: fileTypeInfo.imageType,
};
const {
metadata: imageMetadata,
publicMagicMetadata: imagePublicMagicMetadata,
} = await extractFileMetadata(
worker,
parsedMetadataJSONMap,
collectionID,
imageFileTypeInfo,
livePhotoAssets.image,
);
const videoHash = await getFileHash(
worker,
/* TODO(MR): ElectronFile changes */
livePhotoAssets.video as File | ElectronFile,
);
return {
metadata: {
...imageMetadata,
title: getFileName(livePhotoAssets.image),
fileType: FILE_TYPE.LIVE_PHOTO,
imageHash: imageMetadata.hash,
videoHash: videoHash,
hash: undefined,
},
publicMagicMetadata: imagePublicMagicMetadata,
};
}
async function getFileHash(
worker: Remote<DedicatedCryptoWorker>,
file: File | ElectronFile,