87 lines
2.8 KiB
JavaScript
87 lines
2.8 KiB
JavaScript
const { createCanvas, loadImage, registerFont } = require("canvas");
|
|
const exiftool = require("exiftool-vendored");
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
|
|
// Optional: Register a custom font if needed (must be a .ttf or .otf file)
|
|
registerFont(path.join(__dirname, "fonts", "OpenSans-Regular.ttf"), {
|
|
family: "Open Sans",
|
|
});
|
|
|
|
function getDateInFilename(filename) {
|
|
const datePattern = /\d{4}-\d{2}-\d{2}/;
|
|
const match = filename.match(datePattern);
|
|
return match ? match[0] : null;
|
|
}
|
|
|
|
function getTimeInFilename(filename) {
|
|
const time = filename.split("_")[2];
|
|
return time ? time.split('.')[0] + ":" + time.split('.')[1] : null;
|
|
}
|
|
|
|
async function getImageDate(filename, imageInput) {
|
|
try {
|
|
const filePath = path.join(imageInput, filename);
|
|
const hasDateInName = /\d{4}-\d{2}-\d{2}/.test(filename);
|
|
let dateFromFilename = null;
|
|
let timeFromFilename = null;
|
|
|
|
if (hasDateInName) {
|
|
dateFromFilename = getDateInFilename(filename);
|
|
timeFromFilename = getTimeInFilename(filename);
|
|
}
|
|
|
|
if (dateFromFilename && timeFromFilename) {
|
|
return `${dateFromFilename} ${timeFromFilename}`;
|
|
}
|
|
|
|
const tags = await exiftool.exiftool.read(filePath);
|
|
if (tags?.DateTimeOriginal?.rawValue) {
|
|
const [dateOnly, timeFull] = tags.DateTimeOriginal.rawValue.split(" ");
|
|
const timeOnly = timeFull?.slice(0, 5);
|
|
const [year, month, day] = dateOnly.split(":");
|
|
return `${year}-${month}-${day} ${timeOnly}`;
|
|
}
|
|
|
|
const stats = await fs.promises.stat(filePath);
|
|
const mtime = stats.mtime;
|
|
return `${mtime.getFullYear()}-${String(mtime.getMonth() + 1).padStart(2, "0")}-${String(mtime.getDate()).padStart(2, "0")} ${String(mtime.getHours()).padStart(2, "0")}:${String(mtime.getMinutes()).padStart(2, "0")}`;
|
|
} catch (err) {
|
|
console.error("Failed to read EXIF:", err);
|
|
}
|
|
}
|
|
|
|
async function addWatermark(filename, buffer, watermarkText) {
|
|
const image = await loadImage(buffer);
|
|
const canvas = createCanvas(image.width, image.height);
|
|
const ctx = canvas.getContext("2d");
|
|
|
|
// Draw the original image
|
|
ctx.drawImage(image, 0, 0);
|
|
|
|
// Watermark styles
|
|
ctx.font = "32px 'Open Sans'";
|
|
ctx.fillStyle = "rgba(255, 255, 255, 0.8)";
|
|
ctx.textAlign = "right";
|
|
ctx.textBaseline = "bottom";
|
|
|
|
// Draw the watermark
|
|
ctx.fillText(watermarkText, image.width - 10, image.height - 10);
|
|
|
|
return canvas.toBuffer("image/jpeg");
|
|
}
|
|
|
|
async function watermarkAllImages(bufferMap, imageInput) {
|
|
const outputMap = {};
|
|
for (const [filename, buffer] of Object.entries(bufferMap)) {
|
|
const watermarkText = await getImageDate(filename, imageInput);
|
|
const watermarkedBuffer = await addWatermark(filename, buffer, watermarkText);
|
|
outputMap[filename] = watermarkedBuffer;
|
|
}
|
|
return outputMap;
|
|
}
|
|
|
|
module.exports = {
|
|
watermarkAllImages,
|
|
};
|