/** * Perceptual hash (pHash) for image dedup using Sharp. * Average hashing: resize to 32x32 grayscale, compute mean, create 1024-bit hash. */ const sharp = require('sharp'); async function imageToPHash(buffer) { // Resize to 32x32 grayscale const { data, info } = await sharp(buffer) .resize(32, 32, { fit: 'fill' }) .greyscale() .raw() .toBuffer({ resolveWithObject: true }); // Compute average pixel value let sum = 0; for (let i = 0; i < data.length; i++) { sum += data[i]; } const avg = sum / data.length; // Create hash: 1 if pixel > avg, 0 otherwise let hash = ''; for (let i = 0; i < data.length; i++) { hash += data[i] > avg ? '1' : '0'; } return hash; } function hammingDistance(hash1, hash2) { if (hash1.length !== hash2.length) return Infinity; let dist = 0; for (let i = 0; i < hash1.length; i++) { if (hash1[i] !== hash2[i]) dist++; } return dist; } function isSimilar(hash1, hash2, threshold = 150) { return hammingDistance(hash1, hash2) <= threshold; } module.exports = { imageToPHash, hammingDistance, isSimilar };