mirror of
https://github.com/ente-io/ente.git
synced 2025-08-08 07:28:26 +00:00
Move
This commit is contained in:
parent
d59e50ff93
commit
67d1d6c597
@ -7,7 +7,6 @@ import type {
|
||||
} from "@/new/photos/types/metadata";
|
||||
import { validateAndGetCreationUnixTimeInMicroSeconds } from "@ente/shared/time";
|
||||
import exifr from "exifr";
|
||||
import piexif from "piexifjs";
|
||||
|
||||
type ParsedEXIFData = Record<string, any> &
|
||||
Partial<{
|
||||
@ -332,65 +331,3 @@ export function getEXIFTime(exifData: ParsedEXIFData): number {
|
||||
}
|
||||
return validateAndGetCreationUnixTimeInMicroSeconds(dateTime);
|
||||
}
|
||||
|
||||
export async function updateFileCreationDateInEXIF(
|
||||
fileBlob: Blob,
|
||||
updatedDate: Date,
|
||||
) {
|
||||
try {
|
||||
let imageDataURL = await blobToDataURL(fileBlob);
|
||||
// Since we pass a Blob without an associated type, we get back a
|
||||
// generic data URL like "data:application/octet-stream;base64,...".
|
||||
// Modify it to have a `image/jpeg` MIME type.
|
||||
imageDataURL =
|
||||
"data:image/jpeg;base64" +
|
||||
imageDataURL.slice(imageDataURL.indexOf(","));
|
||||
const exifObj = piexif.load(imageDataURL);
|
||||
if (!exifObj["Exif"]) {
|
||||
exifObj["Exif"] = {};
|
||||
}
|
||||
exifObj["Exif"][piexif.ExifIFD.DateTimeOriginal] =
|
||||
convertToExifDateFormat(updatedDate);
|
||||
log.debug(() => [
|
||||
"updateFileCreationDateInEXIF",
|
||||
{ updatedDate, exifObj },
|
||||
]);
|
||||
const exifBytes = piexif.dump(exifObj);
|
||||
const exifInsertedFile = piexif.insert(exifBytes, imageDataURL);
|
||||
return dataURLToBlob(exifInsertedFile);
|
||||
} catch (e) {
|
||||
log.error("updateFileModifyDateInEXIF failed", e);
|
||||
return fileBlob;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a blob to a `data:` URL.
|
||||
*/
|
||||
const blobToDataURL = (blob: Blob) =>
|
||||
new Promise<string>((resolve) => {
|
||||
const reader = new FileReader();
|
||||
// We need to cast to a string here. This should be safe since MDN says:
|
||||
//
|
||||
// > the result attribute contains the data as a data: URL representing
|
||||
// > the file's data as a base64 encoded string.
|
||||
// >
|
||||
// > https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL
|
||||
reader.onload = () => resolve(reader.result as string);
|
||||
reader.readAsDataURL(blob);
|
||||
});
|
||||
|
||||
/**
|
||||
* Convert a `data:` URL to a blob.
|
||||
*
|
||||
* Requires `connect-src data:` in the CSP (since it internally uses `fetch` to
|
||||
* perform the conversion).
|
||||
*/
|
||||
const dataURLToBlob = (dataURI: string) =>
|
||||
fetch(dataURI).then((res) => res.blob());
|
||||
|
||||
function convertToExifDateFormat(date: Date) {
|
||||
return `${date.getFullYear()}:${
|
||||
date.getMonth() + 1
|
||||
}:${date.getDate()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ import type { User } from "@ente/shared/user/types";
|
||||
import { downloadUsingAnchor } from "@ente/shared/utils";
|
||||
import { t } from "i18next";
|
||||
import { moveToHiddenCollection } from "services/collectionService";
|
||||
import { updateFileCreationDateInEXIF } from "services/exif";
|
||||
import { updateFileCreationDateInEXIF } from "@/new/photos/services/exif";
|
||||
import {
|
||||
deleteFromTrash,
|
||||
trashFiles,
|
||||
|
@ -192,7 +192,8 @@ For more details, see [translations.md](translations.md).
|
||||
## Media
|
||||
|
||||
- [ExifReader](https://github.com/mattiasw/ExifReader) is used for Exif
|
||||
parsing.
|
||||
parsing. [piexifjs](https://github.com/hMatoba/piexifjs) is used for writing
|
||||
back Exif (only supports JPEG).
|
||||
|
||||
- [jszip](https://github.com/Stuk/jszip) is used for reading zip files in the
|
||||
web code (Live photos are zip files under the hood). Note that the desktop
|
||||
|
64
web/packages/new/photos/services/exif-update.ts
Normal file
64
web/packages/new/photos/services/exif-update.ts
Normal file
@ -0,0 +1,64 @@
|
||||
import log from "@/base/log";
|
||||
import piexif from "piexifjs";
|
||||
|
||||
export const updateFileCreationDateInEXIF = async (
|
||||
fileBlob: Blob,
|
||||
updatedDate: Date,
|
||||
) => {
|
||||
try {
|
||||
let imageDataURL = await blobToDataURL(fileBlob);
|
||||
// Since we pass a Blob without an associated type, we get back a
|
||||
// generic data URL like "data:application/octet-stream;base64,...".
|
||||
// Modify it to have a `image/jpeg` MIME type.
|
||||
imageDataURL =
|
||||
"data:image/jpeg;base64" +
|
||||
imageDataURL.slice(imageDataURL.indexOf(","));
|
||||
const exifObj = piexif.load(imageDataURL);
|
||||
if (!exifObj["Exif"]) {
|
||||
exifObj["Exif"] = {};
|
||||
}
|
||||
exifObj["Exif"][piexif.ExifIFD.DateTimeOriginal] =
|
||||
convertToExifDateFormat(updatedDate);
|
||||
log.debug(() => [
|
||||
"updateFileCreationDateInEXIF",
|
||||
{ updatedDate, exifObj },
|
||||
]);
|
||||
const exifBytes = piexif.dump(exifObj);
|
||||
const exifInsertedFile = piexif.insert(exifBytes, imageDataURL);
|
||||
return dataURLToBlob(exifInsertedFile);
|
||||
} catch (e) {
|
||||
log.error("updateFileModifyDateInEXIF failed", e);
|
||||
return fileBlob;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a blob to a `data:` URL.
|
||||
*/
|
||||
const blobToDataURL = (blob: Blob) =>
|
||||
new Promise<string>((resolve) => {
|
||||
const reader = new FileReader();
|
||||
// We need to cast to a string here. This should be safe since MDN says:
|
||||
//
|
||||
// > the result attribute contains the data as a data: URL representing
|
||||
// > the file's data as a base64 encoded string.
|
||||
// >
|
||||
// > https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL
|
||||
reader.onload = () => resolve(reader.result as string);
|
||||
reader.readAsDataURL(blob);
|
||||
});
|
||||
|
||||
/**
|
||||
* Convert a `data:` URL to a blob.
|
||||
*
|
||||
* Requires `connect-src data:` in the CSP (since it internally uses `fetch` to
|
||||
* perform the conversion).
|
||||
*/
|
||||
const dataURLToBlob = (dataURI: string) =>
|
||||
fetch(dataURI).then((res) => res.blob());
|
||||
|
||||
function convertToExifDateFormat(date: Date) {
|
||||
return `${date.getFullYear()}:${
|
||||
date.getMonth() + 1
|
||||
}:${date.getDate()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user