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 1.1.0 to 1.2.0

588

index.js
'use strict';
const { Transform } = require('stream');
const { Transform } = require('node:stream');
const { performance } = require('node:perf_hooks');
const PP = require('polygon-points');

@@ -13,27 +15,20 @@

* @param [options] {Object}
* @param [options.debug=false] {Boolean} - If true, debug info will be logged to console
* @param [options.difference=5] {Number} - Pixel difference value 1 to 255
* @param [options.difference=5] {Number} - Pixel difference value, int 1 to 255
* @param [options.percent=5] {Number} - Percent of pixels or blobs that exceed difference value, float 0.0 to 100.0
* @param [options.response=percent] {String} - Accepted values: percent or bounds or blobs
* @param [options.draw=false] {Boolean} - If true and response is 'bounds' or 'blobs', return a pixel buffer with drawn bounding box
* @param [options.regions] {Array} - Array of region objects
* @param options.regions[i].name {String} - Name of region
* @param [options.regions[i].difference=options.difference] {Number} - Difference value for region
* @param [options.regions[i].difference=options.difference] {Number} - Difference value for region, int 1 to 255
* @param [options.regions[i].percent=options.percent] {Number} - Percent value for region, float 0.0 to 100.0
* @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 [options.mask=false] {Boolean} - Indicate if regions should be used as masks of pixels to ignore
* @param [callback] {Function} - Function to be called when diff event occurs
* @param [options.draw=false] {Boolean} - If true and response is 'bounds' or 'blobs', return a pixel buffer with drawn bounding box
* @param [options.debug=false] {Boolean} - If true, debug object will be attached to output
* @param [callback] {Function} - Function to be called when diff event occurs. Deprecated
*/
constructor(options, callback) {
super(options);
Transform.call(this, { objectMode: true });
this.debug = PamDiff._parseOptions('debug', options); // output debug info to console. defaults to false
this.response = PamDiff._parseOptions('response', options); // percent, bounds, blobs
this.draw = PamDiff._parseOptions('draw', options); // return pixels with bounding box if response is bounds or blobs
this.difference = PamDiff._parseOptions('difference', options); // global value, can be overridden per region
this.percent = PamDiff._parseOptions('percent', options); // global value, can be overridden per region
this.mask = PamDiff._parseOptions('mask', options); // should be processed before regions
this.regions = PamDiff._parseOptions('regions', options); // can be zero regions, a single region, or multiple regions. if no regions, all pixels will be compared.
this.callback = callback; // callback function to be called when pixel difference is detected
this._parseChunk = this._parseFirstChunk; // first parsing will be reading settings and configuring internal pixel reading
super({ objectMode: true });
this.config = options; // configuration for pixel change detection
this.callback = callback; // callback function to be called when pixel change is detected
this._parseChunk = this._parseFirstChunk; // first parsing will be used to configure pixel diff engine
}

@@ -43,12 +38,15 @@

*
* @param option {String}
* @param options {Object}
* @return {*}
* @private
* @param obj {Object}
*/
static _parseOptions(option, options) {
if (options && options.hasOwnProperty(option)) {
return options[option];
set config(obj) {
if (obj instanceof Object) {
this._difference = PamDiff._validateInt(obj.difference, 5, 1, 255);
this._percent = PamDiff._validateFloat(obj.percent, 5, 0, 100);
this._response = PamDiff._validateString(obj.response, ['percent', 'bounds', 'blobs']);
this._regions = PamDiff._validateArray(obj.regions);
this._mask = PamDiff._validateBoolean(obj.mask);
this._draw = PamDiff._validateBoolean(obj.draw);
this._debug = PamDiff._validateBoolean(obj.debug);
this._configurePixelDiffEngine();
}
return null;
}

@@ -58,19 +56,14 @@

*
* @param number {Number}
* @param def {Number}
* @param low {Number}
* @param high {Number}
* @return {Number}
* @private
* @returns {Object}
*/
static _validateNumber(number, def, low, high) {
if (isNaN(number)) {
return def;
} else if (number < low) {
return low;
} else if (number > high) {
return high;
} else {
return number;
}
get config() {
return {
difference: this._difference,
percent: this._percent,
response: this._response,
regions: this._regions,
mask: this._mask,
draw: this._draw,
debug: this._debug,
};
}

@@ -80,8 +73,7 @@

*
* @param bool
* @return {boolean}
* @private
* @param num {Number}
*/
static _validateBoolean(bool) {
return bool === true || bool === 'true' || bool === 1 || bool === '1';
set difference(num) {
this._difference = PamDiff._validateInt(num, 5, 1, 255);
this._configurePixelDiffEngine();
}

@@ -91,12 +83,6 @@

*
* @param string {String}
* @param strings {Array}
* @return {String}
* @private
* @return {Number}
*/
static _validateString(string, strings) {
if (strings.includes(string)) {
return string;
}
return strings[0];
get difference() {
return this._difference;
}

@@ -106,7 +92,17 @@

*
* @param bool {Boolean}
* @param num {Number}
* @return {PamDiff}
* @deprecated
*/
set debug(bool) {
this._debug = PamDiff._validateBoolean(bool);
this._processRegions();
setDifference(num) {
this.difference = num;
return this;
}
/**
*
* @param num {Number|String}
*/
set percent(num) {
this._percent = PamDiff._validateFloat(num, 5, 0, 100);
this._configurePixelDiffEngine();

@@ -117,6 +113,6 @@ }

*
* @return {Boolean}
* @return {Number}
*/
get debug() {
return this._debug;
get percent() {
return this._percent;
}

@@ -126,7 +122,8 @@

*
* @param bool {Boolean}
* @param num {Number}
* @return {PamDiff}
* @deprecated
*/
setDebug(bool) {
this.debug = bool;
setPercent(num) {
this.percent = num;
return this;

@@ -137,7 +134,6 @@ }

*
* @param string {String}
* @param str {String}
*/
set response(string) {
this._response = PamDiff._validateString(string, ['percent', 'bounds', 'blobs']);
this._processRegions();
set response(str) {
this._response = PamDiff._validateString(str, ['percent', 'bounds', 'blobs']);
this._configurePixelDiffEngine();

@@ -156,7 +152,8 @@ }

*
* @param string {String}
* @param str {String}
* @return {PamDiff}
* @deprecated
*/
setResponse(string) {
this.response = string;
setResponse(str) {
this.response = str;
return this;

@@ -167,7 +164,6 @@ }

*
* @param bool {Boolean}
* @param arr {Array}
*/
set draw(bool) {
this._draw = PamDiff._validateBoolean(bool);
this._processRegions();
set regions(arr) {
this._regions = PamDiff._validateArray(arr);
this._configurePixelDiffEngine();

@@ -178,6 +174,6 @@ }

*
* @return {Boolean}
* @return {Array}
*/
get draw() {
return this._draw;
get regions() {
return this._regions;
}

@@ -187,7 +183,8 @@

*
* @param bool {Boolean}
* @param arr {Object[]}
* @return {PamDiff}
* @deprecated
*/
setDraw(bool) {
this.draw = bool;
setRegions(arr) {
this.regions = arr;
return this;

@@ -198,6 +195,6 @@ }

*
* @param number {Number}
* @param bool {Boolean|String|Number}
*/
set difference(number) {
this._difference = PamDiff._validateNumber(parseInt(number), 5, 1, 255);
set mask(bool) {
this._mask = PamDiff._validateBoolean(bool);
this._configurePixelDiffEngine();

@@ -208,6 +205,6 @@ }

*
* @return {Number}
* @returns {Boolean}
*/
get difference() {
return this._difference;
get mask() {
return this._mask;
}

@@ -217,7 +214,8 @@

*
* @param number {Number}
* @return {PamDiff}
* @param bool {Boolean}
* @returns {PamDiff}
* @deprecated
*/
setDifference(number) {
this.difference = number;
setMask(bool) {
this.mask = bool;
return this;

@@ -228,6 +226,6 @@ }

*
* @param number {Number|String}
* @param bool {Boolean}
*/
set percent(number) {
this._percent = PamDiff._validateNumber(parseFloat(number), 5, 0, 100);
set draw(bool) {
this._draw = PamDiff._validateBoolean(bool);
this._configurePixelDiffEngine();

@@ -238,6 +236,6 @@ }

*
* @return {Number}
* @return {Boolean}
*/
get percent() {
return this._percent;
get draw() {
return this._draw;
}

@@ -247,7 +245,8 @@

*
* @param number {Number}
* @param bool {Boolean}
* @return {PamDiff}
* @deprecated
*/
setPercent(number) {
this.percent = number;
setDraw(bool) {
this.draw = bool;
return this;

@@ -258,17 +257,6 @@ }

*
* @param array {Array}
* @param bool {Boolean|String|Number}
*/
set regions(array) {
if (!array) {
delete this._regions;
delete this._regionObj;
delete this._maskObj;
} 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: 1, polygon: [{x: 0, y: 0}, {x: 0, y:50}, {x: 50, y:50}, {x: 50, y: 0}] }`
);
} else {
this._regions = array;
this._processRegions();
}
set debug(bool) {
this._debug = PamDiff._validateBoolean(bool);
this._configurePixelDiffEngine();

@@ -279,6 +267,6 @@ }

*
* @return {Array}
* @return {Boolean}
*/
get regions() {
return this._regions;
get debug() {
return this._debug;
}

@@ -288,32 +276,19 @@

*
* @param array {Array}
* @param bool {Boolean}
* @return {PamDiff}
* @deprecated
*/
setRegions(array) {
this.regions = array;
setDebug(bool) {
this.debug = bool;
return this;
}
set mask(bool) {
this._mask = PamDiff._validateBoolean(bool);
this._processRegions();
this._configurePixelDiffEngine();
}
get mask() {
return this._mask;
}
setMask(bool) {
this.mask = bool;
return this;
}
/**
*
* @param func {Function}
* @deprecated
*/
set callback(func) {
if (!func) {
delete this._callback;
this._callback = undefined;
} else if (typeof func === 'function' && func.length === 1) {

@@ -329,2 +304,3 @@ this._callback = func;

* @return {Function}
* @deprecated
*/

@@ -339,2 +315,3 @@ get callback() {

* @return {PamDiff}
* @deprecated
*/

@@ -349,12 +326,21 @@ setCallback(func) {

* @return {PamDiff}
* @deprecated
*/
resetCache() {
delete this._engine;
delete this._oldPix;
delete this._newPix;
delete this._width;
delete this._height;
delete this._depth;
delete this._tupltype;
delete this._regionObj;
return this.reset();
}
/**
*
* @return {PamDiff}
*/
reset() {
this.emit('reset');
this._debugInfo = undefined;
this._engine = undefined;
this._oldPix = undefined;
this._width = undefined;
this._height = undefined;
this._depth = undefined;
this._tupltype = undefined;
this._parseChunk = this._parseFirstChunk;

@@ -366,85 +352,86 @@ return this;

*
* @returns {Array|null}
* @private
*/
_processRegions() {
if (!this._regions || !this._width || !this._height) {
return;
}
const regions = [];
if (this._mask === true) {
// combine all regions to form a single region of flipped 0's and 1's
let minX = this._width;
let maxX = 0;
let minY = this._height;
let maxY = 0;
const wxh = this._width * this._height;
const maskBitset = Buffer.alloc(wxh, 1);
for (const region of this._regions) {
if (!region.hasOwnProperty('polygon')) {
throw new Error('Region must include a polygon property');
if (this._regions) {
const regions = [];
if (this._mask === true) {
// combine all regions to form a single region of flipped 0's and 1's
let minX = this._width;
let maxX = 0;
let minY = this._height;
let maxY = 0;
const wxh = this._width * this._height;
const maskBitset = 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);
if (bitset.count === 0) {
throw new Error('Bitset count must be greater than 0.');
}
const bitsetBuffer = bitset.buffer;
for (let i = 0; i < wxh; ++i) {
if (bitsetBuffer[i] === 1) {
maskBitset[i] = 0;
}
}
}
const pp = new PP(region.polygon);
const bitset = pp.getBitset(this._width, this._height);
if (bitset.count === 0) {
throw new Error('Bitset count must be greater than 0.');
}
const bitsetBuffer = bitset.buffer;
let maskBitsetCount = 0;
for (let i = 0; i < wxh; ++i) {
if (bitsetBuffer[i] === 1) {
maskBitset[i] = 0;
if (maskBitset[i] === 1) {
const y = Math.floor(i / this._width);
const x = i % this._width;
minX = Math.min(minX, x);
maxX = Math.max(maxX, x);
minY = Math.min(minY, y);
maxY = Math.max(maxY, y);
maskBitsetCount++;
}
}
}
let maskBitsetCount = 0;
for (let i = 0; i < wxh; ++i) {
if (maskBitset[i] === 1) {
const y = Math.floor(i / this._width);
const x = i % this._width;
minX = Math.min(minX, x);
maxX = Math.max(maxX, x);
minY = Math.min(minY, y);
maxY = Math.max(maxY, y);
maskBitsetCount++;
}
}
if (maskBitsetCount === 0) {
throw new Error('Bitset count must be greater than 0');
}
regions.push({
name: 'mask',
bitset: maskBitset,
bitsetCount: maskBitsetCount,
difference: this._difference,
percent: this._percent,
minX: minX,
maxX: maxX,
minY: minY,
maxY: maxY,
});
} else {
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);
if (bitset.count === 0) {
if (maskBitsetCount === 0) {
throw new Error('Bitset count must be greater than 0');
}
const difference = PamDiff._validateNumber(parseInt(region.difference), this._difference, 1, 255);
const percent = PamDiff._validateNumber(parseFloat(region.percent), this._percent, 0, 100);
regions.push({
name: region.name,
bitset: bitset.buffer,
bitsetCount: bitset.count,
difference: difference,
percent: percent,
minX: bitset.minX,
maxX: bitset.maxX,
minY: bitset.minY,
maxY: bitset.maxY,
name: 'mask',
bitset: maskBitset,
bitsetCount: maskBitsetCount,
difference: this._difference,
percent: this._percent,
minX: minX,
maxX: maxX,
minY: minY,
maxY: maxY,
});
} else {
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);
if (bitset.count === 0) {
throw new Error('Bitset count must be greater than 0');
}
const difference = PamDiff._validateInt(region.difference, this._difference, 1, 255);
const percent = PamDiff._validateFloat(region.percent, this._percent, 0, 100);
regions.push({
name: region.name,
bitset: bitset.buffer,
bitsetCount: bitset.count,
difference: difference,
percent: percent,
minX: bitset.minX,
maxX: bitset.maxX,
minY: bitset.minY,
maxY: bitset.maxY,
});
}
}
return regions;
}
this._regionObj = { length: regions.length, regions: regions };
return null;
}

@@ -460,31 +447,32 @@

}
let engine = this._tupltype;
engine += `_${this._width}_x_${this._height}`;
const config = { width: this._width, height: this._height, depth: this._depth, response: this._response, sync: false };
if (this._regionObj) {
engine += '_region';
// config.target = 'region';
config.regions = this._regionObj.regions;
if (this._regionObj.length > 1) {
engine += 's';
const regions = this._processRegions();
let name = `${this._tupltype}_${this._width}w_${this._height}h_${this._depth}d`;
const config = { width: this._width, height: this._height, depth: this._depth, response: this._response };
if (regions) {
if (regions.length === 1) {
if (this._mask === true) {
name += '_mask';
} else {
name += '_region';
}
} else {
name += `_regions`;
}
config.regions = regions;
} else {
engine += '_all';
// config.target = 'all';
name += '_all';
config.difference = this._difference;
config.percent = this._percent;
}
engine += `_${this._response}`;
name += `_${this._response}`;
if ((this._response === 'bounds' || this._response === 'blobs') && this._draw) {
config.draw = this._draw;
engine += '_draw';
name += '_draw';
}
engine += '_async';
name += '_async';
const pixelChange = PC(config);
this._engine = pixelChange.compare.bind(pixelChange);
if (this._debug) {
console.dir(this, { showHidden: false, depth: 0, colors: true });
this._parseChunk = this._parsePixelsDebug;
this._debugEngine = engine;
this._debugCount = 0;
this._debugInfo = { name, count: 0 };
} else {

@@ -497,23 +485,23 @@ this._parseChunk = this._parsePixels;

*
* @param chunk
* @param chunk {Object}
* @private
*/
_parsePixels(chunk) {
this._newPix = chunk.pixels;
this._engine(this._oldPix, this._newPix, (err, data) => {
const { results } = data;
if (results.length) {
const diff = { trigger: results, pam: chunk.pam, headers: chunk.headers, pixels: data.pixels || chunk.pixels };
if (this._callback) {
this._callback(diff);
}
if (this._readableState.pipesCount > 0) {
this.push(diff);
}
if (this.listenerCount('diff') > 0) {
const oldPix = this._oldPix;
const newPix = (this._oldPix = chunk.pixels);
this._engine(oldPix, newPix, (err, data) => {
if (data) {
const { results, pixels } = data;
const diff = { trigger: results, pam: chunk.pam, headers: chunk.headers, pixels: pixels || newPix };
this.emit('data', diff);
if (results.length) {
this.emit('diff', diff);
if (this._callback) {
this._callback(diff);
}
}
} else {
throw new Error(err);
}
});
this._oldPix = this._newPix;
}

@@ -523,26 +511,27 @@

*
* @param chunk
* @param chunk {Object}
* @private
*/
_parsePixelsDebug(chunk) {
const debugCount = this._debugCount++;
console.time(`${this._debugEngine}-${debugCount}`);
this._newPix = chunk.pixels;
this._engine(this._oldPix, this._newPix, (err, data) => {
console.timeEnd(`${this._debugEngine}-${debugCount}`);
const { results } = data;
if (results.length) {
const diff = { trigger: results, pam: chunk.pam, headers: chunk.headers, pixels: data.pixels || chunk.pixels };
if (this._callback) {
this._callback(diff);
}
if (this._readableState.pipesCount > 0) {
this.push(diff);
}
if (this.listenerCount('diff') > 0) {
const oldPix = this._oldPix;
const newPix = (this._oldPix = chunk.pixels);
const count = ++this._debugInfo.count;
const name = this._debugInfo.name;
const start = performance.now();
this._engine(oldPix, newPix, (err, data) => {
const duration = Math.round((performance.now() - start) * 1000) / 1000;
if (data) {
const { results, pixels } = data;
const diff = { trigger: results, pam: chunk.pam, headers: chunk.headers, pixels: pixels || newPix, debug: { name, count, duration } };
this.emit('data', diff);
if (results.length) {
this.emit('diff', diff);
if (this._callback) {
this._callback(diff);
}
}
} else {
throw new Error(err);
}
});
this._oldPix = this._newPix;
}

@@ -552,13 +541,13 @@

*
* @param chunk
* @param chunk {Object}
* @private
*/
_parseFirstChunk(chunk) {
this._width = parseInt(chunk.width);
this._height = parseInt(chunk.height);
this._depth = parseInt(chunk.depth);
this._width = Number.parseInt(chunk.width);
this._height = Number.parseInt(chunk.height);
this._depth = Number.parseInt(chunk.depth);
this._oldPix = chunk.pixels;
this._tupltype = chunk.tupltype;
this._processRegions();
this._configurePixelDiffEngine();
this.emit('initialized', { width: this._width, height: this._height, depth: this._depth, tupltype: this._tupltype });
}

@@ -568,3 +557,3 @@

*
* @param chunk
* @param chunk {Object}
* @param encoding

@@ -585,5 +574,64 @@ * @param callback

_flush(callback) {
this.resetCache();
this.reset();
callback();
}
/**
*
* @param num {Number|String}
* @param def {Number}
* @param min {Number}
* @param max {Number}
* @returns {Number}
* @private
*/
static _validateInt(num, def, min, max) {
num = Number.parseInt(num);
return Number.isNaN(num) ? def : num < min ? min : num > max ? max : num;
}
/**
*
* @param num {Number|String}
* @param def {Number}
* @param min {Number}
* @param max {Number}
* @returns {Number}
* @private
*/
static _validateFloat(num, def, min, max) {
num = Number.parseFloat(num);
return Number.isNaN(num) ? def : num < min ? min : num > max ? max : num;
}
/**
*
* @param bool {Boolean|String|Number}
* @return {Boolean}
* @private
*/
static _validateBoolean(bool) {
return bool === true || bool === 'true' || bool === 1 || bool === '1';
}
/**
*
* @param str {String}
* @param arr {String[]}
* @returns {String}
* @private
*/
static _validateString(str, arr) {
return arr.includes(str) ? str : arr[0];
}
/**
*
* @param arr (Array}
* @returns {Array|null}
* @private
*/
static _validateArray(arr) {
return Array.isArray(arr) && arr.length ? arr : null;
}
}

@@ -590,0 +638,0 @@

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

@@ -16,51 +16,51 @@ "main": "index.js",

"gray:all": "npm run gray:all:percent && npm run gray:all:bounds && npm run gray:all:blobs",
"gray:all:percent": "node tests/test_gray --response percent",
"gray:all:bounds": "node tests/test_gray --response bounds",
"gray:all:blobs": "node tests/test_gray --response blobs",
"gray:all:percent": "node tests/test_gray --response percent --pool 2",
"gray:all:bounds": "node tests/test_gray --response bounds --pool 2",
"gray:all:blobs": "node tests/test_gray --response blobs --pool 2",
"gray:mask": "npm run gray:mask:percent && npm run gray:mask:bounds && npm run gray:mask:blobs",
"gray:mask:percent": "node tests/test_gray2 --response percent",
"gray:mask:bounds": "node tests/test_gray2 --response bounds",
"gray:mask:blobs": "node tests/test_gray2 --response blobs",
"gray:mask:percent": "node tests/test_gray2 --response percent --pool 2",
"gray:mask:bounds": "node tests/test_gray2 --response bounds --pool 2",
"gray:mask:blobs": "node tests/test_gray2 --response blobs --pool 2",
"gray:region": "npm run gray:region:percent && npm run gray:region:bounds && npm run gray:region:blobs",
"gray:region:percent": "node tests/test_gray3 --response percent",
"gray:region:bounds": "node tests/test_gray3 --response bounds",
"gray:region:blobs": "node tests/test_gray3 --response blobs",
"gray:region:percent": "node tests/test_gray3 --response percent --pool 2",
"gray:region:bounds": "node tests/test_gray3 --response bounds --pool 2",
"gray:region:blobs": "node tests/test_gray3 --response blobs --pool 2",
"gray:regions": "npm run gray:regions:percent && npm run gray:regions:bounds && npm run gray:regions:blobs",
"gray:regions:percent": "node tests/test_gray4 --response percent",
"gray:regions:bounds": "node tests/test_gray4 --response bounds",
"gray:regions:blobs": "node tests/test_gray4 --response blobs",
"gray:regions:percent": "node tests/test_gray4 --response percent --pool 2",
"gray:regions:bounds": "node tests/test_gray4 --response bounds --pool 2",
"gray:regions:blobs": "node tests/test_gray4 --response blobs --pool 2",
"rgb": "npm run rgb:all && npm run rgb:mask && npm run rgb:region && npm run rgb:regions",
"rgb:all": "npm run rgb:all:percent && npm run rgb:all:bounds && npm run rgb:all:blobs",
"rgb:all:percent": "node tests/test_rgb --response percent",
"rgb:all:bounds": "node tests/test_rgb --response bounds",
"rgb:all:blobs": "node tests/test_rgb --response blobs",
"rgb:all:percent": "node tests/test_rgb --response percent --pool 2",
"rgb:all:bounds": "node tests/test_rgb --response bounds --pool 2",
"rgb:all:blobs": "node tests/test_rgb --response blobs --pool 2",
"rgb:mask": "npm run rgb:mask:percent && npm run rgb:mask:bounds && npm run rgb:mask:blobs",
"rgb:mask:percent": "node tests/test_rgb2 --response percent",
"rgb:mask:bounds": "node tests/test_rgb2 --response bounds",
"rgb:mask:blobs": "node tests/test_rgb2 --response blobs",
"rgb:mask:percent": "node tests/test_rgb2 --response percent --pool 2",
"rgb:mask:bounds": "node tests/test_rgb2 --response bounds --pool 2",
"rgb:mask:blobs": "node tests/test_rgb2 --response blobs --pool 2",
"rgb:region": "npm run rgb:region:percent && npm run rgb:region:bounds && npm run rgb:region:blobs",
"rgb:region:percent": "node tests/test_rgb3 --response percent",
"rgb:region:bounds": "node tests/test_rgb3 --response bounds",
"rgb:region:blobs": "node tests/test_rgb3 --response blobs",
"rgb:region:percent": "node tests/test_rgb3 --response percent --pool 2",
"rgb:region:bounds": "node tests/test_rgb3 --response bounds --pool 2",
"rgb:region:blobs": "node tests/test_rgb3 --response blobs --pool 2",
"rgb:regions": "npm run rgb:regions:percent && npm run rgb:regions:bounds && npm run rgb:regions:blobs",
"rgb:regions:percent": "node tests/test_rgb4 --response percent",
"rgb:regions:bounds": "node tests/test_rgb4 --response bounds",
"rgb:regions:blobs": "node tests/test_rgb4 --response blobs",
"rgb:regions:percent": "node tests/test_rgb4 --response percent --pool 2",
"rgb:regions:bounds": "node tests/test_rgb4 --response bounds --pool 2",
"rgb:regions:blobs": "node tests/test_rgb4 --response blobs --pool 2",
"rgba": "npm run rgba:all && npm run rgba:mask && npm run rgba:region && npm run rgba:regions",
"rgba:all": "npm run rgba:all:percent && npm run rgba:all:bounds && npm run rgba:all:blobs",
"rgba:all:percent": "node tests/test_rgba --response percent",
"rgba:all:bounds": "node tests/test_rgba --response bounds",
"rgba:all:blobs": "node tests/test_rgba -response blobs",
"rgba:all:percent": "node tests/test_rgba --response percent --pool 2",
"rgba:all:bounds": "node tests/test_rgba --response bounds --pool 2",
"rgba:all:blobs": "node tests/test_rgba -response blobs --pool 2",
"rgba:mask": "npm run rgba:mask:percent && npm run rgba:mask:bounds && npm run rgba:mask:blobs",
"rgba:mask:percent": "node tests/test_rgba2 --response percent",
"rgba:mask:bounds": "node tests/test_rgba2 --response bounds",
"rgba:mask:blobs": "node tests/test_rgba2 --response blobs",
"rgba:mask:percent": "node tests/test_rgba2 --response percent --pool 2",
"rgba:mask:bounds": "node tests/test_rgba2 --response bounds --pool 2",
"rgba:mask:blobs": "node tests/test_rgba2 --response blobs --pool 2",
"rgba:region": "npm run rgba:region:percent && npm run rgba:region:bounds && npm run rgba:region:blobs",
"rgba:region:percent": "node tests/test_rgba3 --response percent",
"rgba:region:bounds": "node tests/test_rgba3 --response bounds",
"rgba:region:blobs": "node tests/test_rgba3 --response blobs",
"rgba:region:percent": "node tests/test_rgba3 --response percent --pool 2",
"rgba:region:bounds": "node tests/test_rgba3 --response bounds --pool 2",
"rgba:region:blobs": "node tests/test_rgba3 --response blobs --pool 2",
"rgba:regions": "npm run rgba:regions:percent && npm run rgba:regions:bounds && npm run rgba:regions:blobs",
"rgba:regions:percent": "node tests/test_rgba4 --response percent",
"rgba:regions:bounds": "node tests/test_rgba4 --response bounds",
"rgba:regions:blobs": "node tests/test_rgba4 --response blobs",
"rgba:regions:percent": "node tests/test_rgba4 --response percent --pool 2",
"rgba:regions:bounds": "node tests/test_rgba4 --response bounds --pool 2",
"rgba:regions:blobs": "node tests/test_rgba4 --response blobs --pool 2",
"pam": "npm run pam:gray && npm run pam:rgb && npm run pam:rgba",

@@ -98,3 +98,3 @@ "pam:gray": "node --expose-gc examples/createPam --pixfmt gray --response bounds --draw false --target regions",

"dependencies": {
"pixel-change": "1.1.0",
"pixel-change": "^1.1.0",
"polygon-points": "^0.6.0"

@@ -104,11 +104,11 @@ },

"@ffmpeg-installer/ffmpeg": "^1.1.0",
"dotenv": "^10.0.0",
"eslint": "^7.32.0",
"eslint-config-prettier": "^7.1.0",
"eslint-plugin-markdown": "^2.2.1",
"eslint-plugin-prettier": "^3.4.1",
"jsdoc": "^3.6.7",
"minimist": "^1.2.5",
"pipe2pam": "^0.6.2",
"prettier": "^2.5.1"
"dotenv": "^16.3.1",
"eslint": "^8.46.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-markdown": "^3.0.1",
"eslint-plugin-prettier": "^5.0.0",
"jsdoc": "^4.0.2",
"minimist": "^1.2.8",
"pipe2pam": "^0.7.0",
"prettier": "^3.0.1"
},

@@ -123,4 +123,4 @@ "private": false,

"engines": {
"node": ">=10"
"node": ">=14"
}
}
# pam-diff
###### [![Build Status](https://github.com/kevinGodell/pam-diff/workflows/build/badge.svg)](https://github.com/kevinGodell/pam-diff/actions?query=workflow%3Abuild) [![Build Status](https://ci.appveyor.com/api/projects/status/hu6qw285sm6vfwtd/branch/master?svg=true)](https://ci.appveyor.com/project/kevinGodell/pam-diff/branch/master) [![GitHub Issues](https://img.shields.io/github/issues/kevinGodell/pam-diff.svg)](https://github.com/kevinGodell/pam-diff/issues) [![GitHub License](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/kevinGodell/pam-diff/master/LICENSE) [![npm](https://img.shields.io/npm/dt/pam-diff.svg?style=flat-square)](https://www.npmjs.com/package/pam-diff)
###### [![Buy me a coffee](https://img.shields.io/badge/-buy%20me%20a%20coffee-red?logo=buy%20me%20a%20coffee)](https://buymeacoffee.com/kevinGodell) [![Build Status](https://github.com/kevinGodell/pam-diff/workflows/build/badge.svg)](https://github.com/kevinGodell/pam-diff/actions?query=workflow%3Abuild) [![Build Status](https://ci.appveyor.com/api/projects/status/hu6qw285sm6vfwtd/branch/master?svg=true)](https://ci.appveyor.com/project/kevinGodell/pam-diff/branch/master) [![GitHub Issues](https://img.shields.io/github/issues/kevinGodell/pam-diff.svg)](https://github.com/kevinGodell/pam-diff/issues) [![GitHub License](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/kevinGodell/pam-diff/master/LICENSE) [![npm](https://img.shields.io/npm/dt/pam-diff.svg?style=flat-square)](https://www.npmjs.com/package/pam-diff)

@@ -15,4 +15,13 @@ Measure differences between pixel arrays extracted from pam images. Works well with node module [pipe2pam](https://www.npmjs.com/package/pipe2pam) to extract pam images from an ffmpeg pipe. Supported **_tupltypes_** are **_rgb_**, **_rgb_alpha_**, and **_grayscale_**. It is currently being used for a video motion detection project.

###### _version 1.1.0:_ Percent is now a float to allow for more precise results. Sync option is removed.
###### _version 1.2.0:_
* Dropping support for node.js < 14.
* Data event emitted for all results returned from [pixel-change](https://www.npmjs.com/package/pixel-change).
* Initialized event emitted after first chunk parsed.
* Debug object attached to output if debug property is set to true.
* Updated [docs](https://kevingodell.github.io/pam-diff/PamDiff.html) to show deprecations.
###### _version 1.1.0:_
* Percent is now a float to allow for more precise results.
* Sync option is removed.
## Usage Options:

@@ -43,5 +52,5 @@

{ x: 0, y: 0 },
{ x: 0, y: 225 },
{ x: 100, y: 225 },
{ x: 100, y: 0 },
{ x: 0, y: 224 },
{ x: 99, y: 224 },
{ x: 99, y: 0 },
],

@@ -55,5 +64,5 @@ };

{ x: 100, y: 0 },
{ x: 100, y: 225 },
{ x: 200, y: 225 },
{ x: 200, y: 0 },
{ x: 100, y: 224 },
{ x: 199, y: 224 },
{ x: 199, y: 0 },
],

@@ -69,3 +78,3 @@ };

- To use this option, create a regions array and set the mask option to true.
- `difference` and `percent` of the individual region is ignored. Set a global value.
- `difference` and `percent` of the individual region is ignored. Set global values.

@@ -77,5 +86,5 @@ ```javascript

{ x: 0, y: 0 },
{ x: 0, y: 225 },
{ x: 100, y: 225 },
{ x: 100, y: 0 },
{ x: 0, y: 224 },
{ x: 99, y: 224 },
{ x: 99, y: 0 },
],

@@ -87,5 +96,5 @@ };

{ x: 100, y: 0 },
{ x: 100, y: 225 },
{ x: 200, y: 225 },
{ x: 200, y: 0 },
{ x: 100, y: 224 },
{ x: 199, y: 224 },
{ x: 199, y: 0 },
],

@@ -100,5 +109,5 @@ };

1. event
- A _diff_ event will be emitted with a data object passed as the only argument.
- A _diff_ event will be emitted when there is a pixel difference detection.
```javascript
```javascript
pamDiff.on('diff', data => {

@@ -109,5 +118,14 @@ console.log(data);

2. callback
- A _data_ event will be emitted regardless of pixel difference detection.
```javascript
pamDiff.on('data', data => {
console.log(data);
});
```
2. callback (deprecated)
- A _callback_ function will be called with a data object passed as the only argument.
- The callback can be passed as the 2nd argument to the constructor, or it can be added later.
- Deprecated. Scheduled to be removed.

@@ -114,0 +132,0 @@ ```javascript

Sorry, the diff of this file is not supported yet

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