template-project/watermark.js
2025-05-30 18:13:30 +08:00

125 lines
3.8 KiB
JavaScript

import sharp from "sharp";
import { exiftool } from "exiftool-vendored";
import fs from "fs";
import path from "path";
// Add watermark to all images
const addWatermark = async (filename,buffer, watermarkText) => {
const { width, height } = await sharp(buffer).metadata();
console.log(filename,': width and height:', width, height);
const textWidth = 280; // Approx width of text in pixels
const textHeight = 40; // Approx height of text
const padding = 10;
const rectX = width - textWidth - padding;
const rectY = height - textHeight - padding;
// Generate overlay text as an image
const svg = `
<svg width="${width}" height="${height}">
<style>
.label {
fill: #FF8C00;
font-size: 30px;
font-family: Arial, sans-serif;
font-weight: bold;
}
.bg {
fill: black; /* Background color */
/*opacity: 0.5; Make background semi-transparent */
}
</style>
<!-- Background rectangle -->
<!--<rect class="bg" x="${rectX}" y="${rectY}" width="${width}" height="${height}" />-->
<text x="${width - 10}" y="${height - 30}" text-anchor="end" class="label">${watermarkText}</text>
</svg>
`;
return sharp(buffer)
.composite([{ input: Buffer.from(svg), top: 0, left: 0 }])
.toBuffer();
};
function getDateInFilename(filename){
const datePattern = /\d{4}-\d{2}-\d{2}/;
const match = filename.match(datePattern);
return match ? match[0] : null;
}
function getTimeInFilename(filename){
//console.log(filename);
const time = filename.split("_")[2];
//console.log(time);
const timeFormatted = time.split('.')[0]+":"+time.split('.')[1];
return timeFormatted;
}
async function getImageDate(filename,imageInput) {
try {
const filePath = path.join(imageInput, filename);
const datePattern = /\d{4}-\d{2}-\d{2}/;
const hasDateInName = datePattern.test(filename);
let dateFromFilename = null;
let timeFromFilename = null;
if(hasDateInName){
dateFromFilename = getDateInFilename(filename);
console.log("date",dateFromFilename);
timeFromFilename = getTimeInFilename(filename);
}
//console.log('tags: ',tags)
if(dateFromFilename && timeFromFilename){
const formatted = `${dateFromFilename} ${timeFromFilename}`;
return formatted;
}
// Else, try getting from EXIF
const tags = await exiftool.read(filePath);
//console.log("tags: ", tags);
if(tags?.DateTimeOriginal?.rawValue){
console.log("datetimeoriginal from exiftool exists")
const [dateOnly, timeFull] = tags.DateTimeOriginal.rawValue.split(" ");
const timeOnly = timeFull?.slice(0, 5); // HH:MM
const [year, month, day] = dateOnly.split(":");
const formatted = `${year}-${month}-${day} ${timeOnly}`;
return formatted;
}
console.log("no datetimeoriginal from exiftool")
// Fallback: use filesystem's last modified time
const stats = await fs.promises.stat(filePath);
const mtime = stats.mtime; // JavaScript Date object
const year = mtime.getFullYear();
const month = String(mtime.getMonth() + 1).padStart(2, "0");
const day = String(mtime.getDate()).padStart(2, "0");
const hours = String(mtime.getHours()).padStart(2, "0");
const minutes = String(mtime.getMinutes()).padStart(2, "0");
return `${year}-${month}-${day} ${hours}:${minutes}`;
} catch (err) {
console.error("Failed to read EXIF:", err);
}
}
export 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;
}