Skip to content

Instantly share code, notes, and snippets.

@bendytree
Created May 3, 2020 01:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bendytree/225e115bcdcfaf1410bd9c7a86981527 to your computer and use it in GitHub Desktop.
Save bendytree/225e115bcdcfaf1410bd9c7a86981527 to your computer and use it in GitHub Desktop.
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