73 lines
1.7 KiB
TypeScript
73 lines
1.7 KiB
TypeScript
let loadingSharp = false;
|
|
import { rgbaToThumbHash } from "thumbhash";
|
|
import ExifReader from 'exifreader';
|
|
|
|
let s: typeof import("sharp") | undefined;
|
|
|
|
async function getSharp(): Promise<typeof import("sharp") | undefined> {
|
|
|
|
if (s) return s;
|
|
s = (await import("sharp")).default;
|
|
return s;
|
|
|
|
if (!loadingSharp) {
|
|
loadingSharp = true;
|
|
setTimeout(async () => {
|
|
s = (await import("sharp")).default;
|
|
}, 1000);
|
|
return;
|
|
}
|
|
}
|
|
|
|
export async function generateThumbHash(image: { width: number, height: number }) {
|
|
|
|
const sharp = await getSharp();
|
|
if (!sharp) return;
|
|
|
|
const scaleFactor = 100 / Math.max(image.width, image.height);
|
|
|
|
const smallWidth = Math.floor(image.width * scaleFactor);
|
|
const smallHeight = Math.floor(image.height * scaleFactor);
|
|
|
|
//@ts-ignore
|
|
const smallImg = await sharp(image.fsPath)
|
|
.resize(smallWidth, smallHeight)
|
|
.withMetadata()
|
|
.raw()
|
|
.ensureAlpha()
|
|
.toBuffer();
|
|
|
|
const buffer = rgbaToThumbHash(smallWidth, smallHeight, smallImg);
|
|
return Buffer.from(buffer).toString("base64");
|
|
}
|
|
|
|
const allowedExif = [
|
|
"ApertureValue",
|
|
"DateTimeOriginal",
|
|
"ExposureTime",
|
|
"ApertureValue",
|
|
"FNumber",
|
|
"FocalLength",
|
|
"GPSLatitude",
|
|
"GPSLongitude",
|
|
"GPSAltitude",
|
|
"IsoSpeedRatings",
|
|
];
|
|
|
|
export async function getExifData(image: { fsPath: string }) {
|
|
const sharp = await getSharp();
|
|
if (!sharp) return;
|
|
const tags = await ExifReader.load(image.fsPath, { async: true });
|
|
|
|
const out: Record<string, any> = {};
|
|
let hasExif = false;
|
|
|
|
for (const key of allowedExif) {
|
|
if (!tags[key]) continue;
|
|
hasExif = true;
|
|
out[key] = tags[key].description;
|
|
}
|
|
|
|
return hasExif ? out : undefined;
|
|
}
|