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

pam-diff

Package Overview
Dependencies
Maintainers
1
Versions
53
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

pam-diff - npm Package Compare versions

Comparing version 0.10.7 to 0.11.0

lib/pixel-change.js

382

index.js

@@ -7,2 +7,4 @@ 'use strict';

const PC = require('./lib/pixel-change');
class PamDiff extends Transform {

@@ -13,2 +15,9 @@

* @param [options] {Object}
* @param [options.difference] {Number}
* @param [options.percent] {Number}
* @param [options.regions] {Array}
* @param [options.regions[i].name] {String}
* @param [options.regions[i].difference] {Number}
* @param [options.regions[i].percent] {Number}
* @param [options.regions[i].polygon] {Array} - Array of x y coordinates [{x:0,y:0},{x:0,y:360},{x:160,y:360},{x:160,y:0}]
* @param [callback] {Function}

@@ -128,33 +137,11 @@ */

if (!array) {
if (this._regions) {
delete this._regions;
delete this._regionsLength;
delete this._minDiff;
}
this._diffs = 0;
delete this._regions;
delete this._regionsArr;
delete this._regionsLen;
delete this._minDiff;
} else if (!Array.isArray(array) || array.length < 1) {
throw new Error(`Regions must be an array of at least 1 region object {name: 'region1', difference: 10, percent: 10, polygon: [[0, 0], [0, 50], [50, 50], [50, 0]]}`);
} else {
this._regions = [];
this._minDiff = 255;
for (const region of array) {
if (!region.hasOwnProperty('name') || !region.hasOwnProperty('polygon')) {
throw new Error('Region must include a name and a polygon property');
}
const polygonPoints = new PP(region.polygon);
const difference = PamDiff._validateNumber(parseInt(region.difference), this._difference, 1, 255);
const percent = PamDiff._validateNumber(parseInt(region.percent), this._percent, 1, 100);
this._minDiff = Math.min(this._minDiff, difference);
this._regions.push(
{
name: region.name,
polygon: polygonPoints,
difference: difference,
percent: percent,
diffs: 0
}
);
}
this._regionsLength = this._regions.length;
this._createPointsInPolygons(this._regions, this._width, this._height);
this._regions = array;
this._processRegions();
}

@@ -218,6 +205,11 @@ }

resetCache() {
//delete this._oldPix;
//delete this._newPix;
//delete this._width;
//delete this._length;
delete this._oldPix;
delete this._newPix;
delete this._width;
delete this._height;
delete this._wxh;
delete this._bufLen;
delete this._regionsArr;
delete this._regionsLen;
delete this._minDiff;
this._parseChunk = this._parseFirstChunk;

@@ -229,16 +221,7 @@ return this;

*
* @param regions {Array}
* @param width {Number}
* @param height {Number}
* @param chunk
* @private
*/
_createPointsInPolygons(regions, width, height) {
if (regions && width && height) {
this._pointsInPolygons = [];
for (const region of regions) {
const bitset = region.polygon.getBitset(this._width, this._height);
region.pointsLength = bitset.count;
this._pointsInPolygons.push(bitset.buffer);
}
}
_bwPixelDiff(chunk) {
throw new Error("black and white pixel diff not available, yet");
}

@@ -251,56 +234,21 @@

*/
_blackAndWhitePixelDiff(chunk) {
_grayPixelDiff(chunk) {
this._newPix = chunk.pixels;
for (let y = 0, i = 0; y < this._height; y++) {
for (let x = 0; x < this._width; x++, i++) {
const diff = this._oldPix[i] !== this._newPix[i];
if (this._regions && diff === true) {
for (let j = 0; j < this._regionsLength; j++) {
if (this._pointsInPolygons[j][i]) {
this._regions[j].diffs++;
}
}
} else {
if (diff === true) {
this._diffs++;
}
}
}
let results = [];
if (this._regions) {
results = PC.compareGrayRegions(this._minDiff, this._regionsLen, this._regionsArr, this._bufLen, this._oldPix, this._newPix);
} else {
results = PC.compareGrayPixels(this._difference, this._percent, this._wxh, this._bufLen, this._oldPix, this._newPix);
}
if (this._regions) {
const regionDiffArray = [];
for (let i = 0; i < this._regionsLength; i++) {
const percent = Math.floor(100 * this._regions[i].diffs / this._regions[i].pointsLength);
if (percent >= this._regions[i].percent) {
regionDiffArray.push({name: this._regions[i].name, percent: percent});
}
this._regions[i].diffs = 0;
if (results.length) {
const data = {trigger: results, pam:chunk.pam};
if (this._callback) {
this._callback(data);
}
if (regionDiffArray.length > 0) {
const data = {trigger: regionDiffArray, pam: chunk.pam};
if (this._callback) {
this._callback(data);
}
if (this._readableState.pipesCount > 0) {
this.push(data);
}
if (this.listenerCount('diff') > 0) {
this.emit('diff', data);
}
if (this._readableState.pipesCount > 0) {
this.push(data);
}
} else {
const percent = Math.floor(100 * this._diffs / this._length);
if (percent >= this._percent) {
const data = {trigger: [{name: 'percent', percent: percent}], pam: chunk.pam};
if (this._callback) {
this._callback(data);
}
if (this._readableState.pipesCount > 0) {
this.push(data);
}
if (this.listenerCount('diff') > 0) {
this.emit('diff', data);
}
if (this.listenerCount('diff') > 0) {
this.emit('diff', data);
}
this._diffs = 0;
}

@@ -310,63 +258,21 @@ this._oldPix = this._newPix;

/**
*
* @param chunk
* @private
*/
_grayScalePixelDiff(chunk) {
_rgbPixelDiff(chunk) {
this._newPix = chunk.pixels;
for (let y = 0, i = 0; y < this._height; y++) {
for (let x = 0; x < this._width; x++, i++) {
if (this._oldPix[i] !== this._newPix[i]) {
const diff = Math.abs(this._oldPix[i] - this._newPix[i]);
if (this._regions && diff >= this._minDiff) {
for (let j = 0; j < this._regionsLength; j++) {
if (this._pointsInPolygons[j][i] && diff >= this._regions[j].difference) {
this._regions[j].diffs++;
}
}
} else {
if (diff >= this._difference) {
this._diffs++;
}
}
}
}
let results = [];
if (this._regions) {
results = PC.compareRgbRegions(this._minDiff, this._regionsLen, this._regionsArr, this._bufLen, this._oldPix, this._newPix);
} else {
results = PC.compareRgbPixels(this._difference, this._percent, this._wxh, this._bufLen, this._oldPix, this._newPix);
}
if (this._regions) {
const regionDiffArray = [];
for (let i = 0; i < this._regionsLength; i++) {
const percent = Math.floor(100 * this._regions[i].diffs / this._regions[i].pointsLength);
if (percent >= this._regions[i].percent) {
regionDiffArray.push({name: this._regions[i].name, percent: percent});
}
this._regions[i].diffs = 0;
if (results.length) {
const data = {trigger: results, pam:chunk.pam};
if (this._callback) {
this._callback(data);
}
if (regionDiffArray.length > 0) {
const data = {trigger: regionDiffArray, pam: chunk.pam};
if (this._callback) {
this._callback(data);
}
if (this._readableState.pipesCount > 0) {
this.push(data);
}
if (this.listenerCount('diff') > 0) {
this.emit('diff', data);
}
if (this._readableState.pipesCount > 0) {
this.push(data);
}
} else {
const percent = Math.floor(100 * this._diffs / this._length);
if (percent >= this._percent) {
const data = {trigger: [{name: 'percent', percent: percent}], pam: chunk.pam};
if (this._callback) {
this._callback(data);
}
if (this._readableState.pipesCount > 0) {
this.push(data);
}
if (this.listenerCount('diff') > 0) {
this.emit('diff', data);
}
if (this.listenerCount('diff') > 0) {
this.emit('diff', data);
}
this._diffs = 0;
}

@@ -381,58 +287,21 @@ this._oldPix = this._newPix;

*/
_rgbPixelDiff(chunk) {
_rgbaPixelDiff(chunk) {
this._newPix = chunk.pixels;
for (let y = 0, i = 0, p = 0; y < this._height; y++) {
for (let x = 0; x < this._width; x++, i += 3, p++) {
if (this._oldPix[i] !== this._newPix[i] || this._oldPix[i + 1] !== this._newPix[i + 1] || this._oldPix[i + 2] !== this._newPix[i + 2]) {
const diff = Math.abs(this._oldPix[i] + this._oldPix[i + 1] + this._oldPix[i + 2] - this._newPix[i] - this._newPix[i + 1] - this._newPix[i + 2])/3;
if (this._regions && diff >= this._minDiff) {
for (let j = 0; j < this._regionsLength; j++) {
if (this._pointsInPolygons[j][p] && diff >= this._regions[j].difference) {
this._regions[j].diffs++;
}
}
} else {
if (diff >= this._difference) {
this._diffs++;
}
}
}
}
let results;
if (this._regions) {
results = PC.compareRgbaRegions(this._minDiff, this._regionsLen, this._regionsArr, this._bufLen, this._oldPix, this._newPix);
} else {
results = PC.compareRgbaPixels(this._difference, this._percent, this._wxh, this._bufLen, this._oldPix, this._newPix);
}
if (this._regions) {
const regionDiffArray = [];
for (let i = 0; i < this._regionsLength; i++) {
const percent = Math.floor(100 * this._regions[i].diffs / this._regions[i].pointsLength);
if (percent >= this._regions[i].percent) {
regionDiffArray.push({name: this._regions[i].name, percent: percent});
}
this._regions[i].diffs = 0;
if (results.length) {
const data = {trigger: results, pam:chunk.pam};
if (this._callback) {
this._callback(data);
}
if (regionDiffArray.length > 0) {
const data = {trigger: regionDiffArray, pam: chunk.pam};
if (this._callback) {
this._callback(data);
}
if (this._readableState.pipesCount > 0) {
this.push(data);
}
if (this.listenerCount('diff') > 0) {
this.emit('diff', data);
}
if (this._readableState.pipesCount > 0) {
this.push(data);
}
} else {
const percent = Math.floor(100 * this._diffs / this._length);
if (percent >= this._percent) {
const data = {trigger: [{name: 'percent', percent: percent}], pam: chunk.pam};
if (this._callback) {
this._callback(data);
}
if (this._readableState.pipesCount > 0) {
this.push(data);
}
if (this.listenerCount('diff') > 0) {
this.emit('diff', data);
}
if (this.listenerCount('diff') > 0) {
this.emit('diff', data);
}
this._diffs = 0;
}

@@ -442,65 +311,27 @@ this._oldPix = this._newPix;

/**
*
* @param chunk
* @private
*/
_rgbAlphaPixelDiff(chunk) {
this._newPix = chunk.pixels;
for (let y = 0, i = 0, p = 0; y < this._height; y++) {
for (let x = 0; x < this._width; x++, i += 4, p++) {
if (this._oldPix[i] !== this._newPix[i] || this._oldPix[i + 1] !== this._newPix[i + 1] || this._oldPix[i + 2] !== this._newPix[i + 2]) {
const diff = Math.abs(this._oldPix[i] + this._oldPix[i + 1] + this._oldPix[i + 2] - this._newPix[i] - this._newPix[i + 1] - this._newPix[i + 2])/3;
if (this._regions && diff >= this._minDiff) {
for (let j = 0; j < this._regionsLength; j++) {
if (this._pointsInPolygons[j][p] && diff >= this._regions[j].difference) {
this._regions[j].diffs++;
}
}
} else {
if (diff >= this._difference) {
this._diffs++;
}
_processRegions() {
if (this._regions && this._width && this._height) {
this._regionsArr = [];
this._minDiff = 255;
for (const region of this._regions) {
if (!region.hasOwnProperty('name') || !region.hasOwnProperty('polygon')) {
throw new Error('Region must include a name and a polygon property');
}
const polygonPoints = new PP(region.polygon);
const bitset = polygonPoints.getBitset(this._width, this._height);
const difference = PamDiff._validateNumber(parseInt(region.difference), this._difference, 1, 255);
const percent = PamDiff._validateNumber(parseInt(region.percent), this._percent, 1, 100);
this._minDiff = Math.min(this._minDiff, difference);
this._regionsArr.push(
{
name: region.name,
diff: difference,
percent: percent,
count: bitset.count,
bitset: bitset.buffer
}
}
);
}
this._regionsLen = this._regions.length;
}
if (this._regions) {
const regionDiffArray = [];
for (let i = 0; i < this._regionsLength; i++) {
const percent = Math.floor(100 * this._regions[i].diffs / this._regions[i].pointsLength);
if (percent >= this._regions[i].percent) {
regionDiffArray.push({name: this._regions[i].name, percent: percent});
}
this._regions[i].diffs = 0;
}
if (regionDiffArray.length > 0) {
const data = {trigger: regionDiffArray, pam: chunk.pam};
if (this._callback) {
this._callback(data);
}
if (this._readableState.pipesCount > 0) {
this.push(data);
}
if (this.listenerCount('diff') > 0) {
this.emit('diff', data);
}
}
} else {
const percent = Math.floor(100 * this._diffs / this._length);
if (percent >= this._percent) {
const data = {trigger: [{name: 'percent', percent: percent}], pam: chunk.pam};
if (this._callback) {
this._callback(data);
}
if (this._readableState.pipesCount > 0) {
this.push(data);
}
if (this.listenerCount('diff') > 0) {
this.emit('diff', data);
}
}
this._diffs = 0;
}
this._oldPix = this._newPix;
}

@@ -517,18 +348,32 @@

this._oldPix = chunk.pixels;
this._length = this._width * this._height;
this._createPointsInPolygons(this._regions, this._width, this._height);
this._wxh = this._width * this._height;
this._processRegions();
switch (chunk.tupltype) {
case 'blackandwhite' :
this._parseChunk = this._blackAndWhitePixelDiff;
this._bufLen = this._wxh;
if (this._bufLen !== this._oldPix.length) {
throw new Error("Pixel count does not match width * height");
}
this._parseChunk = this._bwPixelDiff;
break;
case 'grayscale' :
this._parseChunk = this._grayScalePixelDiff;
this._bufLen = this._wxh;
if (this._bufLen !== this._oldPix.length) {
throw new Error("Pixel count does not match width * height");
}
this._parseChunk = this._grayPixelDiff;
break;
case 'rgb' :
this._bufLen = this._wxh * 3;
if (this._bufLen !== this._oldPix.length) {
throw new Error("Pixel count does not match width * height * 3");
}
this._parseChunk = this._rgbPixelDiff;
//this._increment = 3;//future use
break;
case 'rgb_alpha' :
this._parseChunk = this._rgbAlphaPixelDiff;
//this._increment = 4;//future use
this._bufLen = this._wxh * 4;
if (this._bufLen !== this._oldPix.length) {
throw new Error("Pixel count does not match width * height * 4");
}
this._parseChunk = this._rgbaPixelDiff;
break;

@@ -567,3 +412,2 @@ default :

*/
module.exports = PamDiff;
//todo get bounding box of all regions combined to exclude some pixels before checking if they exist inside specific regions
module.exports = PamDiff;
{
"name": "pam-diff",
"version": "0.10.7",
"version": "0.11.0",
"description": "Measure differences between pixel arrays extracted from pam images",
"main": "index.js",
"scripts": {
"test": "node tests/test.js && node tests/test2.js && node tests/test3.js",
"test": "npm run gray && npm run rgb && npm run rgba",
"preversion": "npm test",

@@ -13,3 +13,6 @@ "postversion": "npm run doc",

"all": "npm test && npm run examples && npm run out",
"doc": "jsdoc index.js -d docs && git commit -m 'update docs' -- docs"
"doc": "jsdoc index.js -d docs && git commit -m 'update docs' -- docs",
"gray": "node tests/test_gray && node tests/test_gray2 && node tests/test_gray3",
"rgb": "node tests/test_rgb && node tests/test_rgb2 && node tests/test_rgb3",
"rgba": "node tests/test_rgba && node tests/test_rgba2 && node tests/test_rgba3"
},

@@ -16,0 +19,0 @@ "repository": {

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