const fs = require('fs'); | |
const _ = require('lodash'); | |
const PNG = require('pngjs').PNG; | |
const { promisify } = require('util'); | |
const md5File = require('md5-file'); | |
const images = [ | |
{ filename: 'graphic-gif.gif' }, | |
{ filename: 'graphic-jpg-0.jpg' }, | |
{ filename: 'graphic-jpg-76.jpg' }, | |
{ filename: 'graphic-jpg-100.jpg' }, | |
{ filename: 'graphic-png.png' }, | |
]; | |
for (const image of images) { | |
image.orig = `${__dirname}/files/${image.filename}`; | |
image.insta = image.orig.split('.')[0] + '-after.jpg'; | |
image.instapng = image.orig.split('.')[0] + '-after-png.png'; | |
} | |
const getPixels = promisify((filename, callback) => { | |
fs.createReadStream(filename) | |
.pipe(new PNG({ colorType: 2 })) | |
.on("parsed", function () { | |
const pixels = []; | |
for (var y = 0; y < this.height; y++) { | |
for (var x = 0; x < this.width; x++) { | |
var idx = (this.width * y + x) << 2; | |
pixels.push({ | |
r: this.data[idx + 0], | |
g: this.data[idx + 1], | |
b: this.data[idx + 2], | |
}); | |
} | |
} | |
callback(null, pixels); | |
}); | |
}); | |
const comparePixels = (e1, e2) => { | |
const rmean = (e1.r + e2.r) / 2; | |
const r = e1.r - e2.r; | |
const g = e1.g - e2.g; | |
const b = e1.b - e2.b; | |
const v = Math.sqrt((((512+rmean)*r*r)>>8) + 4*g*g + (((767-rmean)*b*b)>>8)); | |
const perc = Math.min(1, Math.max(v / 764, 0)); | |
return perc; // 0 is identical, 1 is opposite | |
}; | |
(async () => { | |
// const origPixels = await getPixels('./files/photoshop-png.png'); | |
const origPixels = await getPixels('./files/graphic-png.png'); | |
for (const image of images) { | |
const imgPixels = await getPixels(image.instapng); | |
let percentDiff = 0; | |
for (const [i, aPixel] of origPixels.entries()){ | |
const bPixel = imgPixels[i]; | |
const pixelDiff = comparePixels(aPixel, bPixel); | |
percentDiff += pixelDiff; | |
} | |
percentDiff = percentDiff / origPixels.length; | |
image.diff = percentDiff; | |
let exactDiff = 0; | |
for (const [i, aPixel] of origPixels.entries()){ | |
const bPixel = imgPixels[i]; | |
const exactSame = JSON.stringify(aPixel) === JSON.stringify(bPixel); | |
exactDiff += exactSame ? 0 : 1; | |
} | |
image.exactdiff = exactDiff / origPixels.length; | |
image.origkb = Math.round(fs.statSync(image.orig).size/1024); | |
image.instakb = Math.round(fs.statSync(image.insta).size/1024); | |
const origHash = await md5File(image.orig); | |
const instaHash = await md5File(image.insta); | |
image.hashmatch = origHash === instaHash; | |
} | |
// results | |
for (const image of _.sortBy(images, i => i.diff)) { | |
console.log([ | |
image.filename, | |
((1-image.diff)*100).toFixed(4)+'%', | |
((1-image.exactdiff)*100).toFixed(4)+'%', | |
image.origkb+'kb', | |
image.instakb+'kb', | |
image.hashmatch, | |
].join(',')); | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment