Comparing version 0.10.7 to 0.11.0
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": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
5
22433
457