chore: allow reprocess to use raw source files

This commit is contained in:
chris 2025-12-08 15:56:12 -05:00
parent d230e88bd1
commit a94d938131

View File

@ -21,6 +21,7 @@ const path = require('path');
const crypto = require('crypto'); const crypto = require('crypto');
const sharp = require('sharp'); const sharp = require('sharp');
const mongoose = require('mongoose'); const mongoose = require('mongoose');
const heicConvert = require('heic-convert');
const Photo = require('../models/photo'); const Photo = require('../models/photo');
const MONGO_URI = process.env.MONGO_URI || 'mongodb://localhost:27017/photogallery'; const MONGO_URI = process.env.MONGO_URI || 'mongodb://localhost:27017/photogallery';
@ -32,6 +33,7 @@ const VARIANTS = {
medium: { size: 1200, quality: 80, suffix: '-md' }, medium: { size: 1200, quality: 80, suffix: '-md' },
thumb: { size: 640, quality: 76, suffix: '-sm' }, thumb: { size: 640, quality: 76, suffix: '-sm' },
}; };
const SOURCE_EXTS = ['.webp', '.jpg', '.jpeg', '.png', '.heic', '.heif', '.avif', '.bmp', '.tif', '.tiff'];
const diagonalOverlay = Buffer.from(` const diagonalOverlay = Buffer.from(`
<svg width="2400" height="2400" viewBox="0 0 2400 2400" xmlns="http://www.w3.org/2000/svg"> <svg width="2400" height="2400" viewBox="0 0 2400 2400" xmlns="http://www.w3.org/2000/svg">
@ -64,19 +66,23 @@ function parseBaseName(doc) {
function sourceCandidates(doc) { function sourceCandidates(doc) {
const baseName = parseBaseName(doc); const baseName = parseBaseName(doc);
const preferred = []; const preferred = new Set();
const fromDocPath = doc.path ? doc.path.replace(/^\/+/, '') : ''; const fromDocPath = doc.path ? doc.path.replace(/^\/+/, '') : '';
const fromDocFile = doc.filename ? path.join('uploads', doc.filename) : ''; const fromDocFile = doc.filename ? path.join('uploads', doc.filename) : '';
[fromDocPath, fromDocFile] [fromDocPath, fromDocFile]
.filter(Boolean) .filter(Boolean)
.forEach(rel => preferred.push(path.join(UPLOAD_DIR, rel.replace(/^uploads[\\/]/, '')))); .forEach(rel => preferred.add(path.join(UPLOAD_DIR, rel.replace(/^uploads[\\/]/, ''))));
preferred.push( // Look for any common source extension using the base name
path.join(UPLOAD_DIR, `${baseName}.webp`), for (const ext of SOURCE_EXTS) {
path.join(UPLOAD_DIR, `${baseName}-md.webp`), preferred.add(path.join(UPLOAD_DIR, `${baseName}${ext}`));
path.join(UPLOAD_DIR, `${baseName}-sm.webp`) }
); // Also check variant-style names in case only a variant exists
return preferred; for (const ext of SOURCE_EXTS) {
preferred.add(path.join(UPLOAD_DIR, `${baseName}-md${ext}`));
preferred.add(path.join(UPLOAD_DIR, `${baseName}-sm${ext}`));
}
return Array.from(preferred);
} }
async function findExistingFile(candidates) { async function findExistingFile(candidates) {
@ -89,6 +95,19 @@ async function findExistingFile(candidates) {
return null; return null;
} }
async function loadSourceBuffer(filePath) {
const ext = path.extname(filePath).toLowerCase();
let inputBuffer = await fsPromises.readFile(filePath);
if (ext === '.heic' || ext === '.heif' || ext === '.avif' || isHeifBuffer(inputBuffer)) {
inputBuffer = await heicConvert({
buffer: inputBuffer,
format: 'JPEG',
quality: 1,
});
}
return inputBuffer;
}
async function stampAndVariants(inputBuffer, baseName) { async function stampAndVariants(inputBuffer, baseName) {
// Build main stamped image // Build main stamped image
const base = sharp(inputBuffer) const base = sharp(inputBuffer)
@ -139,7 +158,7 @@ async function processDoc(doc) {
}; };
} }
const inputBuffer = await fsPromises.readFile(sourceFile); const inputBuffer = await loadSourceBuffer(sourceFile);
const hash = crypto.createHash('sha256').update(inputBuffer).digest('hex'); const hash = crypto.createHash('sha256').update(inputBuffer).digest('hex');
const outputs = await stampAndVariants(inputBuffer, parseBaseName(doc)); const outputs = await stampAndVariants(inputBuffer, parseBaseName(doc));