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.11.0 to 0.12.0

258

index.js

@@ -14,10 +14,11 @@ 'use strict';

* @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.difference] {Number} - Pixel difference value 1 to 255
* @param [options.percent] {Number} - Percent of pixels that exceed difference value.
* @param [options.regions] {Array} - Array of regions.
* @param [options.regions[i].name] {String} - Name of region.
* @param [options.regions[i].difference] {Number} - Difference value for region.
* @param [options.regions[i].percent] {Number} - Percent value for region.
* @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}
* @param [mask] {Boolean} - Indicate if regions should be used as masks of pixels to ignore instead of areas of interest.
* @param [callback] {Function} - Function to be called when diff event occurs.
*/

@@ -29,2 +30,3 @@ constructor(options, callback) {

this.percent = PamDiff._parseOptions('percent', options);//global option, can be overridden per region
this.mask = PamDiff._parseOptions('mask', options);//should be processed before regions
this.regions = PamDiff._parseOptions('regions', options);//can be no regions or a single region or multiple regions. if no regions, all pixels will be compared.

@@ -72,7 +74,8 @@ this.callback = callback;//callback function to be called when pixel difference is detected

*
* @deprecated
* @param string {String}
* @param bool
* @return {boolean}
* @private
*/
setGrayscale(string) {
console.warn('grayscale option has been removed, "average" has proven to most accurate and is the default');
static _validateBoolean(bool) {
return (bool === true || bool === 'true' || bool === 1 || bool === '1');
}

@@ -86,2 +89,3 @@

this._difference = PamDiff._validateNumber(parseInt(number), 5, 1, 255);
this._configurePixelDiffEngine();
}

@@ -113,2 +117,3 @@

this._percent = PamDiff._validateNumber(parseInt(number), 5, 1, 100);
this._configurePixelDiffEngine();
}

@@ -141,5 +146,4 @@

delete this._regions;
delete this._regionsArr;
delete this._regionsLen;
delete this._minDiff;
delete this._regionObj;
delete this._maskObj;
} else if (!Array.isArray(array) || array.length < 1) {

@@ -151,2 +155,3 @@ 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]]}`);

}
this._configurePixelDiffEngine();
}

@@ -172,2 +177,17 @@

set mask(bool) {
this._mask = PamDiff._validateBoolean(bool);
this._processRegions();
this._configurePixelDiffEngine();
}
get mask() {
return this._mask;
}
setMask(bool) {
this.mask = bool;
return this;
}
/**

@@ -214,7 +234,6 @@ *

delete this._height;
delete this._wxh;
delete this._bufLen;
delete this._regionsArr;
delete this._regionsLen;
delete this._minDiff;
delete this._tupltype;
delete this._regionObj;
delete this._maskObj;
delete this._pixelDiffEngine;
this._parseChunk = this._parseFirstChunk;

@@ -226,7 +245,56 @@ return this;

*
* @param chunk
* @private
*/
_bwPixelDiff(chunk) {
throw new Error("black and white pixel diff not available, yet");
_processRegions() {
if (!this._regions || !this._width || !this._height) {
return;
}
if (this._mask) {
const wxh = this._width * this._height;
const buffer = Buffer.alloc(wxh, 1);
for (const region of this._regions) {
if (!region.hasOwnProperty('polygon')) {
throw new Error('Region must include a polygon property');
}
const pp = new PP(region.polygon);
const bitset = pp.getBitset(this._width, this._height);
const bitsetBuffer = bitset.buffer;
for (let i = 0; i < wxh; i++) {
if (bitsetBuffer[i]) {
buffer[i] = 0;
}
}
}
let count = 0;
for (let i = 0; i < wxh; i++) {
if (buffer[i]) {
count++;
}
}
this._maskObj = {count: count, bitset: buffer};
} else {
const regions = [];
let 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 pp = new PP(region.polygon);
const bitset = pp.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);
minDiff = Math.min(minDiff, difference);
regions.push(
{
name: region.name,
diff: difference,
percent: percent,
count: bitset.count,
bitset: bitset.buffer
}
);
}
this._regionObj = {minDiff: minDiff, length: regions.length, regions: regions};
}
}

@@ -236,36 +304,55 @@

*
* @param chunk
* @private
*/
_grayPixelDiff(chunk) {
this._newPix = chunk.pixels;
let results = [];
if (this._regions) {
results = PC.compareGrayRegions(this._minDiff, this._regionsLen, this._regionsArr, this._bufLen, this._oldPix, this._newPix);
_configurePixelDiffEngine() {
if (!this._tupltype || !this._width || ! this._height) {
return;
}
const wxh = this._width * this._height;
switch (this._tupltype) {
case 'grayscale':
if (this._regionObj) {
this._pixelDiffEngine = PC.compareGrayRegions.bind(this, this._regionObj.minDiff, this._regionObj.length, this._regionObj.regions, wxh);
} else if (this._maskObj) {
this._pixelDiffEngine = PC.compareGrayMask.bind(this, this._difference, this._percent, this._maskObj.count, this._maskObj.bitset, wxh);
} else {
this._pixelDiffEngine = PC.compareGrayPixels.bind(this, this._difference, this._percent, wxh, wxh);
}
break;
case 'rgb':
if (this._regionObj) {
this._pixelDiffEngine = PC.compareRgbRegions.bind(this, this._regionObj.minDiff, this._regionObj.length, this._regionObj.regions, wxh * 3);
} else if (this._maskObj) {
this._pixelDiffEngine = PC.compareRgbMask.bind(this, this._difference, this._percent, this._maskObj.count, this._maskObj.bitset, wxh * 3);
} else {
this._pixelDiffEngine = PC.compareRgbPixels.bind(this, this._difference, this._percent, wxh, wxh * 3);
}
break;
case 'rgb_alpha':
if (this._regionObj) {
this._pixelDiffEngine = PC.compareRgbaRegions.bind(this, this._regionObj.minDiff, this._regionObj.length, this._regionObj.regions, wxh * 4);
} else if (this._maskObj) {
this._pixelDiffEngine = PC.compareRgbaMask.bind(this, this._difference, this._percent, this._maskObj.count, this._maskObj.bitset, wxh * 4);
} else {
this._pixelDiffEngine = PC.compareRgbaPixels.bind(this, this._difference, this._percent, wxh, wxh * 4);
}
break;
default:
throw new Error('Did not find a matching tupltype');
}
if (process.env.NODE_ENV === 'development') {
this._parseChunk = this._parsePixelsDebug;
} else {
results = PC.compareGrayPixels(this._difference, this._percent, this._wxh, this._bufLen, this._oldPix, this._newPix);
this._parseChunk = this._parsePixels;
}
if (results.length) {
const data = {trigger: results, 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._oldPix = this._newPix;
}
_rgbPixelDiff(chunk) {
/**
*
* @param chunk
* @private
*/
_parsePixels(chunk) {
this._newPix = chunk.pixels;
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);
}
const results = this._pixelDiffEngine(this._oldPix, this._newPix);
if (results.length) {

@@ -291,10 +378,6 @@ const data = {trigger: results, pam:chunk.pam};

*/
_rgbaPixelDiff(chunk) {
_parsePixelsDebug(chunk) {
console.time(this._pixelDiffEngine.name);
this._newPix = chunk.pixels;
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);
}
const results = this._pixelDiffEngine(this._oldPix, this._newPix);
if (results.length) {

@@ -313,31 +396,5 @@ const data = {trigger: results, pam:chunk.pam};

this._oldPix = this._newPix;
console.timeEnd(this._pixelDiffEngine.name);
}
_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;
}
}
/**

@@ -352,36 +409,5 @@ *

this._oldPix = chunk.pixels;
this._wxh = this._width * this._height;
this._tupltype = chunk.tupltype;
this._processRegions();
switch (chunk.tupltype) {
case 'blackandwhite' :
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._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;
break;
case 'rgb_alpha' :
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;
default :
throw Error(`Unsupported tupltype: ${chunk.tupltype}. Supported tupltypes include grayscale(gray), blackandwhite(monob), rgb(rgb24), and rgb_alpha(rgba).`);
}
this._configurePixelDiffEngine();
}

@@ -388,0 +414,0 @@

@@ -9,3 +9,3 @@ 'use strict';

const perc = Math.floor(100 * diffs / wxh);
if (perc >= percent) {return [{name: "percent", percent: perc}];}
if (perc >= percent) {return [{name: "all", percent: perc}];}
return [];

@@ -18,3 +18,3 @@ }

const perc = Math.floor(100 * diffs / wxh);
if (perc >= percent) {return [{name: "percent", percent: perc}];}
if (perc >= percent) {return [{name: "all", percent: perc}];}
return [];

@@ -27,3 +27,3 @@ }

const perc = Math.floor(100 * diffs / wxh);
if (perc >= percent) {return [{name: "percent", percent: perc}];}
if (perc >= percent) {return [{name: "all", percent: perc}];}
return [];

@@ -91,2 +91,27 @@ }

}
static compareGrayMask(diff, percent, count, bitset, bufLen, buf0, buf1) {
let diffs = 0;
for (let i = 0; i < bufLen; i++) {if(bitset[i] && Math.abs(buf0[i] - buf1[i]) >= diff) {diffs++;}}
const perc = Math.floor(100 * diffs / count);
if (perc >= percent) {return [{name: "mask", percent: perc}];}
return [];
}
static compareRgbMask(diff, percent, count, bitset, bufLen, buf0, buf1) {
let diffs = 0;
for (let i = 0, p = 0; i < bufLen; i+=3, p++) {if(bitset[p] && Math.abs(buf0[i] + buf0[i+1] + buf0[i+2] - buf1[i] - buf1[i+1] - buf1[i+2])/3 >= diff) {diffs++;}}
const perc = Math.floor(100 * diffs / count);
if (perc >= percent) {return [{name: "mask", percent: perc}];}
return [];
}
static compareRgbaMask(diff, percent, count, bitset, bufLen, buf0, buf1) {
let diffs = 0;
for (let i = 0, p = 0; i < bufLen; i+=4, p++) {if(bitset[p] && Math.abs(buf0[i] + buf0[i+1] + buf0[i+2] - buf1[i] - buf1[i+1] - buf1[i+2])/3 >= diff) {diffs++;}}
const perc = Math.floor(100 * diffs / count);
if (perc >= percent) {return [{name: "mask", percent: perc}];}
return [];
}
}

@@ -93,0 +118,0 @@

{
"name": "pam-diff",
"version": "0.11.0",
"version": "0.12.0",
"description": "Measure differences between pixel arrays extracted from pam images",

@@ -14,5 +14,5 @@ "main": "index.js",

"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"
"gray": "node tests/test_gray && node tests/test_gray2 && node tests/test_gray3 && node tests/test_gray4",
"rgb": "node tests/test_rgb && node tests/test_rgb2 && node tests/test_rgb3 && node tests/test_rgb4",
"rgba": "node tests/test_rgba && node tests/test_rgba2 && node tests/test_rgba3 && node tests/test_rgba4"
},

@@ -19,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