Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

looks-same

Package Overview
Dependencies
Maintainers
7
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

looks-same - npm Package Compare versions

Comparing version 7.3.0 to 8.0.0

13

CHANGELOG.md

@@ -5,2 +5,15 @@ # Changelog

## [8.0.0](https://github.com/gemini-testing/looks-same/compare/v7.3.0...v8.0.0) (2022-09-19)
### ⚠ BREAKING CHANGES
* drop support of node versions less than 12
* dropped old node-style callback interface support
### Features
* async-await interface ([b33a6f9](https://github.com/gemini-testing/looks-same/commit/b33a6f925701a3ed6cfe9479cf3d8ad290320be5))
* increase supported node version up to 12 ([ae1e4b2](https://github.com/gemini-testing/looks-same/commit/ae1e4b265ee3f7af25e526256fdd4970b568ff7a))
## [7.3.0](https://github.com/gemini-testing/looks-same/compare/v7.2.4...v7.3.0) (2021-02-03)

@@ -7,0 +20,0 @@

165

index.js

@@ -51,23 +51,25 @@ 'use strict';

const iterateRect = (width, height, callback, endCallback) => {
const processRow = (y) => {
setImmediate(() => {
for (let x = 0; x < width; x++) {
callback(x, y);
}
const iterateRect = async (width, height, callback) => {
return new Promise((resolve) => {
const processRow = (y) => {
setImmediate(() => {
for (let x = 0; x < width; x++) {
callback(x, y);
}
y++;
y++;
if (y < height) {
processRow(y);
} else {
endCallback();
}
});
};
if (y < height) {
processRow(y);
} else {
resolve();
}
});
};
processRow(0);
processRow(0);
});
};
const buildDiffImage = (png1, png2, options, callback) => {
const buildDiffImage = async (png1, png2, options) => {
const width = Math.max(png1.width, png2.width);

@@ -80,3 +82,3 @@ const height = Math.max(png1.height, png2.height);

iterateRect(width, height, (x, y) => {
await iterateRect(width, height, (x, y) => {
if (x >= minWidth || y >= minHeight) {

@@ -95,3 +97,5 @@ result.setPixel(x, y, highlightColor);

}
}, () => callback(result));
});
return result;
};

@@ -143,107 +147,74 @@

module.exports = exports = async function looksSame(image1, image2, opts, callback) {
if (!callback) {
callback = opts;
opts = {};
}
module.exports = exports = async function looksSame(image1, image2, opts = {}) {
opts = prepareOpts(opts);
[image1, image2] = utils.formatImages(image1, image2);
try {
const {first, second} = await utils.readPair(image1, image2, utils.readBufferCb);
const areBuffersEqual = utils.areBuffersEqual(first, second);
const {first, second} = await utils.readPair(image1, image2, utils.readBufferCb);
const areBuffersEqual = utils.areBuffersEqual(first, second);
const refImg = {size: {width: first.width, height: first.height}};
const metaInfo = {refImg};
const refImg = {size: {width: first.width, height: first.height}};
const metaInfo = {refImg};
if (areBuffersEqual) {
const diffBounds = (new DiffArea()).area;
process.nextTick(() => callback(null, {equal: true, metaInfo, diffBounds, diffClusters: [diffBounds]}));
if (areBuffersEqual) {
const diffBounds = (new DiffArea()).area;
return;
}
return {equal: true, metaInfo, diffBounds, diffClusters: [diffBounds]};
}
if (first.width !== second.width || first.height !== second.height) {
const diffBounds = getMaxDiffBounds(first, second);
process.nextTick(() => callback(null, {equal: false, metaInfo, diffBounds, diffClusters: [diffBounds]}));
if (first.width !== second.width || first.height !== second.height) {
const diffBounds = getMaxDiffBounds(first, second);
return;
}
return {equal: false, metaInfo, diffBounds, diffClusters: [diffBounds]};
}
const {first: png1, second: png2} = await utils.readPair(
{...image1, source: first.buffer},
{...image2, source: second.buffer},
utils.readPngCb
);
const {first: png1, second: png2} = await utils.readPair(
{...image1, source: first.buffer},
{...image2, source: second.buffer},
utils.readPngCb
);
const comparator = createComparator(png1, png2, opts);
const {stopOnFirstFail, shouldCluster, clustersSize} = opts;
const comparator = createComparator(png1, png2, opts);
const {stopOnFirstFail, shouldCluster, clustersSize} = opts;
utils.getDiffPixelsCoords(png1, png2, comparator, {stopOnFirstFail, shouldCluster, clustersSize}, ({diffArea, diffClusters}) => {
const diffBounds = diffArea.area;
const equal = diffArea.isEmpty();
const {diffArea, diffClusters} = await utils.getDiffPixelsCoords(png1, png2, comparator, {stopOnFirstFail, shouldCluster, clustersSize});
const diffBounds = diffArea.area;
const equal = diffArea.isEmpty();
callback(null, {equal, metaInfo, diffBounds, diffClusters});
});
} catch (err) {
return callback(err);
}
return {equal, metaInfo, diffBounds, diffClusters};
};
exports.getDiffArea = function(image1, image2, opts, callback) {
if (!callback) {
callback = opts;
opts = {};
}
exports.getDiffArea = async function(image1, image2, opts = {}) {
opts = prepareOpts(opts);
[image1, image2] = utils.formatImages(image1, image2);
utils
.readPair(image1, image2)
.then(({first, second}) => {
if (first.width !== second.width || first.height !== second.height) {
return process.nextTick(() => callback(null, getMaxDiffBounds(first, second)));
}
const {first, second} = await utils.readPair(image1, image2);
const comparator = createComparator(first, second, opts);
if (first.width !== second.width || first.height !== second.height) {
return getMaxDiffBounds(first, second);
}
utils.getDiffPixelsCoords(first, second, comparator, opts, ({diffArea}) => {
if (diffArea.isEmpty()) {
return callback(null, null);
}
const comparator = createComparator(first, second, opts);
callback(null, diffArea.area);
});
})
.catch(error => {
callback(error);
});
const {diffArea} = await utils.getDiffPixelsCoords(first, second, comparator, opts);
if (diffArea.isEmpty()) {
return null;
}
return diffArea.area;
};
exports.createDiff = function saveDiff(opts, callback) {
exports.createDiff = async function saveDiff(opts) {
opts = prepareOpts(opts);
const [image1, image2] = utils.formatImages(opts.reference, opts.current);
const {first, second} = await utils.readPair(image1, image2);
const diffImage = await buildDiffImage(first, second, {
highlightColor: parseColorString(opts.highlightColor),
comparator: createComparator(first, second, opts)
});
utils
.readPair(image1, image2)
.then(({first, second}) => {
const diffOptions = {
highlightColor: parseColorString(opts.highlightColor),
comparator: createComparator(first, second, opts)
};
buildDiffImage(first, second, diffOptions, (result) => {
if (opts.diff === undefined) {
result.createBuffer(callback);
} else {
result.save(opts.diff, callback);
}
});
})
.catch(error => {
callback(error);
});
return opts.diff === undefined
? diffImage.createBuffer()
: diffImage.save(opts.diff);
};

@@ -250,0 +221,0 @@

@@ -35,18 +35,18 @@ 'use strict';

save(path, callback) {
async save(path) {
const writeStream = fs.createWriteStream(path);
this._png.pack().pipe(writeStream);
writeStream.on('error', (error) => callback(error));
writeStream.on('finish', () => callback(null));
return new Promise((resolve, reject) => {
writeStream.on('error', (error) => reject(error));
writeStream.on('finish', () => resolve(null));
});
}
createBuffer(callback) {
this._png.pack().pipe(concat(gotDiff));
this._png.on('error', (error) => callback(error, null));
function gotDiff(data) {
callback(null, data);
}
async createBuffer() {
return new Promise((resolve, reject) => {
this._png.pack().pipe(concat(resolve));
this._png.on('error', reject);
});
}
};

@@ -30,8 +30,3 @@ 'use strict';

exports.getDiffPixelsCoords = (png1, png2, predicate, opts, callback) => {
if (!callback) {
callback = opts;
opts = {};
}
exports.getDiffPixelsCoords = async (png1, png2, predicate, opts = {}) => {
const stopOnFirstFail = opts.hasOwnProperty('stopOnFirstFail') ? opts.stopOnFirstFail : false;

@@ -45,39 +40,41 @@

const processRow = (y) => {
setImmediate(() => {
for (let x = 0; x < width; x++) {
const color1 = png1.getPixel(x, y);
const color2 = png2.getPixel(x, y);
return new Promise((resolve) => {
const processRow = (y) => {
setImmediate(() => {
for (let x = 0; x < width; x++) {
const color1 = png1.getPixel(x, y);
const color2 = png2.getPixel(x, y);
const result = predicate({
color1, color2,
png1, png2,
x, y,
width, height
});
const result = predicate({
color1, color2,
png1, png2,
x, y,
width, height
});
if (!result) {
const {x: actX, y: actY} = png1.getActualCoord(x, y);
diffArea.update(actX, actY);
if (opts.shouldCluster) {
diffClusters.update(actX, actY);
}
if (!result) {
const {x: actX, y: actY} = png1.getActualCoord(x, y);
diffArea.update(actX, actY);
if (opts.shouldCluster) {
diffClusters.update(actX, actY);
}
if (stopOnFirstFail) {
return callback({diffArea, diffClusters: getDiffClusters(diffClusters, diffArea, opts)});
if (stopOnFirstFail) {
return resolve({diffArea, diffClusters: getDiffClusters(diffClusters, diffArea, opts)});
}
}
}
}
y++;
y++;
if (y < height) {
processRow(y);
} else {
callback({diffArea, diffClusters: getDiffClusters(diffClusters, diffArea, opts)});
}
});
};
if (y < height) {
processRow(y);
} else {
resolve({diffArea, diffClusters: getDiffClusters(diffClusters, diffArea, opts)});
}
});
};
processRow(0);
processRow(0);
});
};

@@ -84,0 +81,0 @@

{
"name": "looks-same",
"version": "7.3.0",
"version": "8.0.0",
"description": "Pure node.js library for comparing PNG-images, taking into account human color perception.",

@@ -27,3 +27,2 @@ "main": "index.js",

"gm": "^1.23.1",
"matcha": "^0.7.0",
"mocha": "^5.2.0",

@@ -40,7 +39,6 @@ "proxyquire": "^1.7.10",

"test": "npm run test-unit && npm run lint",
"bench": "matcha benchmark/*",
"release": "standard-version"
},
"engines": {
"node": ">= 8.0.0"
"node": ">= 12.0.0"
},

@@ -47,0 +45,0 @@ "author": "Sergey Tatarintsev <sevinf@yandex-team.ru> (https://github.com/SevInf)",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc