Browse Source

Added linting

pull/136/head
james.cryer 7 years ago
parent
commit
75b22ecd88
  1. 14
      .editorconfig
  2. 3
      .eslintignore
  3. 27
      .eslintrc
  4. 123
      chai-tests/main_spec.js
  5. 8
      compareImages.js
  6. 282
      demoassets/main.js
  7. 17
      memory-leak-test.js
  8. 30
      nodejs-tests/compareImages.test.js
  9. 111
      nodejs-tests/resemble.test.js
  10. 4527
      package-lock.json
  11. 26
      package.json
  12. 498
      resemble.js

14
.editorconfig

@ -0,0 +1,14 @@
root = true
[*]
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
[*.md]
trim_trailing_whitespace = false
[{.travis.yml}]
indent_style = space
indent_size = 2

3
.eslintignore

@ -0,0 +1,3 @@
/node_modules
/libs
/demoassets

27
.eslintrc

@ -0,0 +1,27 @@
{
"extends": [
"eslint-config-es5",
"plugin:prettier/recommended"
],
"parserOptions": {
"ecmaVersion": 2017,
"sourceType": "module"
},
"rules": {
"prettier/prettier": [
"error",
{
"singleQuote": true,
"tabWidth": "4"
}
],
"no-console": "off",
"no-use-before-define": ["warn", { "functions": false, "classes": false, "variables": true }],
"func-names": ["warn", "as-needed"]
},
"env": {
"amd": true,
"es6": true
}
}

123
chai-tests/main_spec.js

File diff suppressed because one or more lines are too long

8
compareImages.js

@ -1,8 +1,8 @@
var resemble = require('./resemble'); const resemble = require("./resemble");
module.exports = function(image1, image2, options) { module.exports = function compareImages(image1, image2, options) {
return new Promise(function(resolve, reject) { return new Promise((resolve, reject) => {
resemble.compare(image1, image2, options, function(err, data) { resemble.compare(image1, image2, options, (err, data) => {
if (err) { if (err) {
reject(err); reject(err);
} else { } else {

282
demoassets/main.js

@ -1,27 +1,27 @@
$(function() { $(function() {
var $target = $('#drop-zone'); var $target = $("#drop-zone");
function dropZone($target, onDrop) { function dropZone($target, onDrop) {
$target. $target
bind('dragover', function(){ .bind("dragover", function() {
$target.addClass( 'drag-over' ); $target.addClass("drag-over");
return false; return false;
}). })
bind("dragend", function () { .bind("dragend", function() {
$target.removeClass( 'drag-over' ); $target.removeClass("drag-over");
return false; return false;
}). })
bind("dragleave", function () { .bind("dragleave", function() {
$target.removeClass( 'drag-over' ); $target.removeClass("drag-over");
return false; return false;
}). })
bind("drop", function(event) { .bind("drop", function(event) {
var file = event.originalEvent.dataTransfer.files[0]; var file = event.originalEvent.dataTransfer.files[0];
event.stopPropagation(); event.stopPropagation();
event.preventDefault(); event.preventDefault();
$target.removeClass( 'drag-over' ); $target.removeClass("drag-over");
var droppedImage = new Image(); var droppedImage = new Image();
var fileReader = new FileReader(); var fileReader = new FileReader();
@ -38,18 +38,16 @@ $(function(){
} }
dropZone($target, function(file) { dropZone($target, function(file) {
resemble(file).onComplete(function(data) { resemble(file).onComplete(function(data) {
$('#image-data').show(); $("#image-data").show();
$('#red').css('width',data.red+'%'); $("#red").css("width", data.red + "%");
$('#green').css('width',data.green+'%'); $("#green").css("width", data.green + "%");
$('#blue').css('width',data.blue+'%'); $("#blue").css("width", data.blue + "%");
$('#alpha').css('width',data.alpha+'%'); $("#alpha").css("width", data.alpha + "%");
$('#brightness').css('width',data.brightness+'%'); $("#brightness").css("width", data.brightness + "%");
$('#white').css('width',data.white+'%'); $("#white").css("width", data.white + "%");
$('#black').css('width',data.black+'%'); $("#black").css("width", data.black + "%");
}); });
}); });
function onComplete(data) { function onComplete(data) {
@ -57,7 +55,7 @@ $(function(){
var diffImage = new Image(); var diffImage = new Image();
diffImage.src = data.getImageDataUrl(); diffImage.src = data.getImageDataUrl();
$('#image-diff').html(diffImage); $("#image-diff").html(diffImage);
$(diffImage).click(function() { $(diffImage).click(function() {
var w = window.open("about:blank", "_blank"); var w = window.open("about:blank", "_blank");
@ -74,25 +72,26 @@ $(function(){
img.alt = "image diff"; img.alt = "image diff";
img.style.maxWidth = "100%"; img.style.maxWidth = "100%";
img.addEventListener("click", function() { img.addEventListener("click", function() {
this.style.maxWidth = this.style.maxWidth === "100%" ? "" : "100%"; this.style.maxWidth =
this.style.maxWidth === "100%" ? "" : "100%";
}); });
body.appendChild(img); body.appendChild(img);
}); });
$('.buttons').show(); $(".buttons").show();
if (data.misMatchPercentage == 0) { if (data.misMatchPercentage == 0) {
$('#thesame').show(); $("#thesame").show();
$('#diff-results').hide(); $("#diff-results").hide();
} else { } else {
$('#mismatch').text(data.misMatchPercentage); $("#mismatch").text(data.misMatchPercentage);
if (!data.isSameDimensions) { if (!data.isSameDimensions) {
$('#differentdimensions').show(); $("#differentdimensions").show();
} else { } else {
$('#differentdimensions').hide(); $("#differentdimensions").hide();
} }
$('#diff-results').show(); $("#diff-results").show();
$('#thesame').hide(); $("#thesame").hide();
} }
} }
@ -100,138 +99,137 @@ $(function(){
var file2; var file2;
var resembleControl; var resembleControl;
dropZone($('#dropzone1'), function(file){ dropZone($("#dropzone1"), function(file) {
file1 = file; file1 = file;
if (file2) { if (file2) {
resembleControl = resemble(file).compareTo(file2).onComplete(onComplete); resembleControl = resemble(file)
.compareTo(file2)
.onComplete(onComplete);
} }
}); });
dropZone($('#dropzone2'), function(file){ dropZone($("#dropzone2"), function(file) {
file2 = file; file2 = file;
if (file1) { if (file1) {
resembleControl = resemble(file).compareTo(file1).onComplete(onComplete); resembleControl = resemble(file)
.compareTo(file1)
.onComplete(onComplete);
} }
}); });
var buttons = $('.buttons button'); var buttons = $(".buttons button");
buttons.click(function() { buttons.click(function() {
var $this = $(this); var $this = $(this);
$this.parent('.buttons').find('button').removeClass('active'); $this
$this.addClass('active'); .parent(".buttons")
.find("button")
.removeClass("active");
$this.addClass("active");
if($this.is('#raw')){ if ($this.is("#raw")) {
resembleControl.ignoreNothing(); resembleControl.ignoreNothing();
} } else if ($this.is("#less")) {
else
if($this.is('#less')){
resembleControl.ignoreLess(); resembleControl.ignoreLess();
} }
if($this.is('#colors')){ if ($this.is("#colors")) {
resembleControl.ignoreColors(); resembleControl.ignoreColors();
} } else if ($this.is("#antialising")) {
else
if($this.is('#antialising')){
resembleControl.ignoreAntialiasing(); resembleControl.ignoreAntialiasing();
} } else if ($this.is("#alpha")) {
else
if($this.is('#alpha')){
resembleControl.ignoreAlpha(); resembleControl.ignoreAlpha();
} } else if ($this.is("#same-size")) {
else
if($this.is('#same-size')){
resembleControl.scaleToSameSize(); resembleControl.scaleToSameSize();
} } else if ($this.is("#original-size")) {
else
if($this.is('#original-size')){
resembleControl.useOriginalSize(); resembleControl.useOriginalSize();
} } else if ($this.is("#pink")) {
else resembleControl
if($this.is('#pink')){ .outputSettings({
resembleControl.outputSettings({
errorColor: { errorColor: {
red: 255, red: 255,
green: 0, green: 0,
blue: 255 blue: 255
} }
}).repaint(); })
} .repaint();
else } else if ($this.is("#yellow")) {
if($this.is('#yellow')){ resembleControl
resembleControl.outputSettings({ .outputSettings({
errorColor: { errorColor: {
red: 255, red: 255,
green: 255, green: 255,
blue: 0 blue: 0
} }
}).repaint(); })
} .repaint();
else } else if ($this.is("#flat")) {
if($this.is('#flat')){ resembleControl
resembleControl.outputSettings({ .outputSettings({
errorType: 'flat' errorType: "flat"
}).repaint(); })
} .repaint();
else } else if ($this.is("#movement")) {
if($this.is('#movement')){ resembleControl
resembleControl.outputSettings({ .outputSettings({
errorType: 'movement' errorType: "movement"
}).repaint(); })
} .repaint();
else } else if ($this.is("#flatDifferenceIntensity")) {
if($this.is('#flatDifferenceIntensity')){ resembleControl
resembleControl.outputSettings({ .outputSettings({
errorType: 'flatDifferenceIntensity' errorType: "flatDifferenceIntensity"
}).repaint(); })
} .repaint();
else } else if ($this.is("#movementDifferenceIntensity")) {
if($this.is('#movementDifferenceIntensity')){ resembleControl
resembleControl.outputSettings({ .outputSettings({
errorType: 'movementDifferenceIntensity' errorType: "movementDifferenceIntensity"
}).repaint(); })
} .repaint();
else } else if ($this.is("#diffOnly")) {
if($this.is('#diffOnly')){ resembleControl
resembleControl.outputSettings({ .outputSettings({
errorType: 'diffOnly' errorType: "diffOnly"
}).repaint(); })
} .repaint();
else } else if ($this.is("#opaque")) {
if($this.is('#opaque')){ resembleControl
resembleControl.outputSettings({ .outputSettings({
transparency: 1 transparency: 1
}).repaint(); })
} .repaint();
else } else if ($this.is("#transparent")) {
if($this.is('#transparent')){ resembleControl
resembleControl.outputSettings({ .outputSettings({
transparency: 0.3 transparency: 0.3
}).repaint(); })
} .repaint();
else } else if ($this.is("#boundingBox")) {
if($this.is('#boundingBox')){ resembleControl
resembleControl.outputSettings({ .outputSettings({
boundingBox: { boundingBox: {
left: $("#bounding-box-x1").val(), left: $("#bounding-box-x1").val(),
top: $("#bounding-box-y1").val(), top: $("#bounding-box-y1").val(),
right: $("#bounding-box-x2").val(), right: $("#bounding-box-x2").val(),
bottom: $("#bounding-box-y2").val() bottom: $("#bounding-box-y2").val()
} }
}).repaint(); })
$this.removeClass('active'); .repaint();
$this.removeClass("active");
} }
if($this.is('#ignoredBox')){ if ($this.is("#ignoredBox")) {
resembleControl.outputSettings({ resembleControl
.outputSettings({
ignoredBox: { ignoredBox: {
left: $("#ignored-box-x1").val(), left: $("#ignored-box-x1").val(),
top: $("#ignored-box-y1").val(), top: $("#ignored-box-y1").val(),
right: $("#ignored-box-x2").val(), right: $("#ignored-box-x2").val(),
bottom: $("#ignored-box-y2").val() bottom: $("#ignored-box-y2").val()
} }
}).repaint(); })
$this.removeClass('active'); .repaint();
$this.removeClass("active");
} }
}); });
@ -243,59 +241,63 @@ $(function(){
var dtwo = $.Deferred(); var dtwo = $.Deferred();
var dthree = $.Deferred(); var dthree = $.Deferred();
xhr.open('GET', 'demoassets/People.jpg', true); xhr.open("GET", "demoassets/People.jpg", true);
xhr.responseType = 'blob'; xhr.responseType = "blob";
xhr.onload = function(e) { xhr.onload = function(e) {
done.resolve(this.response); done.resolve(this.response);
}; };
xhr.send(); xhr.send();
xhr2.open('GET', 'demoassets/People2.jpg', true); xhr2.open("GET", "demoassets/People2.jpg", true);
xhr2.responseType = 'blob'; xhr2.responseType = "blob";
xhr2.onload = function(e) { xhr2.onload = function(e) {
dtwo.resolve(this.response); dtwo.resolve(this.response);
}; };
xhr2.send(); xhr2.send();
xhr3.open('GET', 'demoassets/PeopleAlpha.png', true); xhr3.open("GET", "demoassets/PeopleAlpha.png", true);
xhr3.responseType = 'blob'; xhr3.responseType = "blob";
xhr3.onload = function(e) { xhr3.onload = function(e) {
dthree.resolve(this.response); dthree.resolve(this.response);
}; };
xhr3.send(); xhr3.send();
$('#example-images').click(function(){ $("#example-images").click(function() {
$("#dropzone1").html('<img src="demoassets/People.jpg"/>');
$('#dropzone1').html('<img src="demoassets/People.jpg"/>'); $("#dropzone2").html('<img src="demoassets/People2.jpg"/>');
$('#dropzone2').html('<img src="demoassets/People2.jpg"/>');
$.when(done, dtwo).done(function(file, file1) { $.when(done, dtwo).done(function(file, file1) {
if (typeof FileReader === 'undefined') { if (typeof FileReader === "undefined") {
resembleControl = resemble('demoassets/People.jpg').compareTo('demoassets/People2.jpg').onComplete(onComplete); resembleControl = resemble("demoassets/People.jpg")
.compareTo("demoassets/People2.jpg")
.onComplete(onComplete);
} else { } else {
resembleControl = resemble(file).compareTo(file1).onComplete(onComplete); resembleControl = resemble(file)
.compareTo(file1)
.onComplete(onComplete);
} }
}); });
return false; return false;
}); });
$('#example-images-alpha').click(function(){ $("#example-images-alpha").click(function() {
$("#dropzone1").html('<img src="demoassets/People.jpg"/>');
$('#dropzone1').html('<img src="demoassets/People.jpg"/>'); $("#dropzone2").html('<img src="demoassets/PeopleAlpha.png"/>');
$('#dropzone2').html('<img src="demoassets/PeopleAlpha.png"/>');
$.when(done, dthree).done(function(file, file1) { $.when(done, dthree).done(function(file, file1) {
if (typeof FileReader === 'undefined') { if (typeof FileReader === "undefined") {
resembleControl = resemble('demoassets/People.jpg').compareTo('demoassets/PeopleAlpha.png').onComplete(onComplete); resembleControl = resemble("demoassets/People.jpg")
.compareTo("demoassets/PeopleAlpha.png")
.onComplete(onComplete);
} else { } else {
resembleControl = resemble(file).compareTo(file1).onComplete(onComplete); resembleControl = resemble(file)
.compareTo(file1)
.onComplete(onComplete);
} }
}); });
return false; return false;
}); });
})();
}());
}); });

17
memory-leak-test.js

@ -1,7 +1,10 @@
/* eslint no-process-exit: "warn"*/
// node --expose-gc memory-leak-test.js // node --expose-gc memory-leak-test.js
const fs = require('fs'); const fs = require("fs");
const resemble = require('./resemble'); const resemble = require("./resemble");
let max = 2000; let max = 2000;
const timerLabel = "2000 compare"; const timerLabel = "2000 compare";
console.time(timerLabel); console.time(timerLabel);
@ -9,10 +12,12 @@ console.time(timerLabel);
compare(); compare();
function compare() { function compare() {
const people = fs.readFileSync('./demoassets/ghost1.png'); const people = fs.readFileSync("./demoassets/ghost1.png");
const people2 = fs.readFileSync('./demoassets/ghost2.png'); const people2 = fs.readFileSync("./demoassets/ghost2.png");
resemble(people).compareTo(people2).onComplete(function() { resemble(people)
.compareTo(people2)
.onComplete(() => {
if (--max >= 0) { if (--max >= 0) {
process.nextTick(compare); process.nextTick(compare);
} else { } else {
@ -20,7 +25,7 @@ function compare(){
} }
global.gc(); global.gc();
if (max % 100 === 0) { if (max % 100 === 0) {
var mem = process.memoryUsage(); const mem = process.memoryUsage();
console.log(max, mem.rss, mem.heapUsed, mem.external); console.log(max, mem.rss, mem.heapUsed, mem.external);
} }
}); });

30
nodejs-tests/compareImages.test.js

@ -1,15 +1,17 @@
const compareImages = require('../compareImages'); /* eslint-env jest*/
const fs = require('fs');
describe('compareImages', () => { const compareImages = require("../compareImages");
test('works with buffers', async () => { const fs = require("fs");
describe("compareImages", () => {
test("works with buffers", async () => {
const data = await compareImages( const data = await compareImages(
fs.readFileSync('./demoassets/People.jpg'), fs.readFileSync("./demoassets/People.jpg"),
fs.readFileSync('./demoassets/People2.jpg') fs.readFileSync("./demoassets/People2.jpg")
); );
expect(data.isSameDimensions).toBe(true); expect(data.isSameDimensions).toBe(true);
expect(data.misMatchPercentage).toEqual('8.66'); expect(data.misMatchPercentage).toEqual("8.66");
const buffer = data.getBuffer(); const buffer = data.getBuffer();
@ -17,23 +19,25 @@ describe('compareImages', () => {
expect(buffer.length).toBe(91876); expect(buffer.length).toBe(91876);
const comparison = fs.readFileSync( const comparison = fs.readFileSync(
'./nodejs-tests/PeopleComparedToPeople2.png' "./nodejs-tests/PeopleComparedToPeople2.png"
); );
expect(buffer.equals(comparison)).toBe(true); expect(buffer.equals(comparison)).toBe(true);
const buffer2 = data.getBuffer(true); const buffer2 = data.getBuffer(true);
const comparison2 = fs.readFileSync( const comparison2 = fs.readFileSync(
'./nodejs-tests/PeopleComparedToPeople2WithOriginal.png' "./nodejs-tests/PeopleComparedToPeople2WithOriginal.png"
); );
expect(buffer2.equals(comparison2)).toBe(true); expect(buffer2.equals(comparison2)).toBe(true);
}); });
test('throws when failed', async () => { test("throws when failed", async () => {
const promise = compareImages( const promise = compareImages(
fs.readFileSync('./demoassets/People.jpg'), fs.readFileSync("./demoassets/People.jpg"),
'bogus data' "bogus data"
);
await expect(promise).rejects.toMatch(
"Error: error while reading from input stream"
); );
await expect(promise).rejects.toMatch('Error: error while reading from input stream');
}); });
}); });

111
nodejs-tests/resemble.test.js

@ -1,18 +1,24 @@
const resemble = require('../resemble'); /* eslint-env jest*/
const fs = require('fs');
const resemble = require("../resemble");
describe('resemble', () => { const fs = require("fs");
test('base64', () => {
const people_src = describe("resemble", () => {
'data:image/jpeg;base64,' + test("base64", () => {
fs.readFileSync('./demoassets/People.jpg', 'base64'); const peopleSrc = `data:image/jpeg;base64,${fs.readFileSync(
const people2_src = "./demoassets/People.jpg",
'data:image/jpeg;base64,' + "base64"
fs.readFileSync('./demoassets/People2.jpg', 'base64'); )}`;
const people2Src = `data:image/jpeg;base64,${fs.readFileSync(
return new Promise(function(resolve, reject) { "./demoassets/People2.jpg",
resemble(people_src).compareTo(people2_src).onComplete(function(data) { "base64"
// console.info('Reached oncomplete for base64_string'); )}`;
return new Promise(resolve => {
resemble(peopleSrc)
.compareTo(people2Src)
.onComplete(data => {
// console.info('Reached oncomplete for base64String');
expect(data.diffBounds.bottom).toEqual(431); expect(data.diffBounds.bottom).toEqual(431);
expect(data.diffBounds.left).toEqual(22); expect(data.diffBounds.left).toEqual(22);
expect(data.diffBounds.right).toEqual(450); expect(data.diffBounds.right).toEqual(450);
@ -20,7 +26,7 @@ describe('resemble', () => {
expect(data.dimensionDifference.height).toEqual(0); expect(data.dimensionDifference.height).toEqual(0);
expect(data.dimensionDifference.width).toEqual(0); expect(data.dimensionDifference.width).toEqual(0);
expect(data.isSameDimensions).toBe(true); expect(data.isSameDimensions).toBe(true);
expect(data.misMatchPercentage).toEqual('8.66'); expect(data.misMatchPercentage).toEqual("8.66");
resolve(); resolve();
}); });
}); });
@ -29,7 +35,7 @@ describe('resemble', () => {
// this doesn't work on windows // this doesn't work on windows
// test('files', () => { // test('files', () => {
// return new Promise(function(resolve, reject) { // return new Promise(function(resolve) {
// console.log('hello there how are you'); // console.log('hello there how are you');
// resemble('demoassets/People.jpg') // resemble('demoassets/People.jpg')
// .compareTo('demoassets/People2.jpg') // .compareTo('demoassets/People2.jpg')
@ -57,26 +63,29 @@ describe('resemble', () => {
// }); // });
// }); // });
test('file not found', () => { test("file not found", () =>
return new Promise(function(resolve, reject) { new Promise(resolve => {
resemble('../demoassets/People.jpg') resemble("../demoassets/People.jpg")
.compareTo('../demoassets/404-image.jpg') .compareTo("../demoassets/404-image.jpg")
.onComplete(function(data) { .onComplete(data => {
// console.info('Reached oncomplete for request_404'); // console.info('Reached oncomplete for request404');
// console.log(data); // console.log(data);
expect(data.error).toEqual('Error: error while reading from input stream'); expect(data.error).toEqual(
"Error: error while reading from input stream"
);
resolve(); resolve();
}); });
}); }));
});
test('node buffers jpg', () => { test("node buffers jpg", () => {
const people = fs.readFileSync('./demoassets/People.jpg'); const people = fs.readFileSync("./demoassets/People.jpg");
const people2 = fs.readFileSync('./demoassets/People2.jpg'); const people2 = fs.readFileSync("./demoassets/People2.jpg");
return new Promise(function(resolve, reject) { return new Promise(resolve => {
resemble(people).compareTo(people2).onComplete(function(data) { resemble(people)
// console.info('Reached oncomplete for base64_string'); .compareTo(people2)
.onComplete(data => {
// console.info('Reached oncomplete for base64String');
expect(data.diffBounds.bottom).toEqual(431); expect(data.diffBounds.bottom).toEqual(431);
expect(data.diffBounds.left).toEqual(22); expect(data.diffBounds.left).toEqual(22);
expect(data.diffBounds.right).toEqual(450); expect(data.diffBounds.right).toEqual(450);
@ -84,20 +93,21 @@ describe('resemble', () => {
expect(data.dimensionDifference.height).toEqual(0); expect(data.dimensionDifference.height).toEqual(0);
expect(data.dimensionDifference.width).toEqual(0); expect(data.dimensionDifference.width).toEqual(0);
expect(data.isSameDimensions).toBe(true); expect(data.isSameDimensions).toBe(true);
expect(data.misMatchPercentage).toEqual('8.66'); expect(data.misMatchPercentage).toEqual("8.66");
resolve(); resolve();
}); });
}); });
}); });
test("node buffers png", () => {
const people = fs.readFileSync("./demoassets/ghost1.png");
const people2 = fs.readFileSync("./demoassets/ghost2.png");
test('node buffers png', () => { return new Promise(resolve => {
const people = fs.readFileSync('./demoassets/ghost1.png'); resemble(people)
const people2 = fs.readFileSync('./demoassets/ghost2.png'); .compareTo(people2)
.onComplete(data => {
return new Promise(function(resolve, reject) { // console.info('Reached oncomplete for base64String');
resemble(people).compareTo(people2).onComplete(function(data) {
// console.info('Reached oncomplete for base64_string');
expect(data.diffBounds.bottom).toEqual(138); expect(data.diffBounds.bottom).toEqual(138);
expect(data.diffBounds.left).toEqual(90); expect(data.diffBounds.left).toEqual(90);
expect(data.diffBounds.right).toEqual(157); expect(data.diffBounds.right).toEqual(157);
@ -105,19 +115,17 @@ describe('resemble', () => {
expect(data.dimensionDifference.height).toEqual(0); expect(data.dimensionDifference.height).toEqual(0);
expect(data.dimensionDifference.width).toEqual(0); expect(data.dimensionDifference.width).toEqual(0);
expect(data.isSameDimensions).toBe(true); expect(data.isSameDimensions).toBe(true);
expect(data.misMatchPercentage).toEqual('0.27'); expect(data.misMatchPercentage).toEqual("0.27");
resolve(); resolve();
}); });
}); });
}); });
test("test partial diff with bounding box", () => {
const people = fs.readFileSync("./demoassets/ghost1.png");
const people2 = fs.readFileSync("./demoassets/ghost2.png");
test('test partial diff with bounding box', () => { return new Promise(resolve => {
const people = fs.readFileSync('./demoassets/ghost1.png');
const people2 = fs.readFileSync('./demoassets/ghost2.png');
return new Promise(function(resolve, reject) {
resemble.outputSettings({ resemble.outputSettings({
boundingBox: { boundingBox: {
left: 80, left: 80,
@ -127,13 +135,12 @@ describe('resemble', () => {
} }
}); });
resemble(people).compareTo(people2).onComplete(function(data) { resemble(people)
expect(data.misMatchPercentage).toEqual('0.04'); .compareTo(people2)
.onComplete(data => {
expect(data.misMatchPercentage).toEqual("0.04");
resolve(); resolve();
}); });
}); });
}); });
}); });

4527
package-lock.json generated

File diff suppressed because it is too large Load Diff

26
package.json

@ -7,14 +7,7 @@
"type": "git", "type": "git",
"url": "https://github.com/Huddle/Resemble.js.git" "url": "https://github.com/Huddle/Resemble.js.git"
}, },
"keywords": [ "keywords": ["comparison", "visual", "image", "diff", "compare", "html5"],
"comparison",
"visual",
"image",
"diff",
"compare",
"html5"
],
"author": "James Cryer", "author": "James Cryer",
"license": "MIT", "license": "MIT",
"bugs": { "bugs": {
@ -23,16 +16,29 @@
"homepage": "https://github.com/Huddle/Resemble.js", "homepage": "https://github.com/Huddle/Resemble.js",
"scripts": { "scripts": {
"test": "jest nodejs-tests", "test": "jest nodejs-tests",
"test-watch": "jest --watch nodejs-tests" "test-watch": "jest --watch nodejs-tests",
"precommit": "lint-staged",
"lint": "eslint **/*.js --fix"
},
"lint-staged": {
"*.{js,json,css,md}": ["prettier --write", "git add"]
}, },
"dependencies": { "dependencies": {
"canvas-prebuilt": "^1.6.5-prerelease.1" "canvas-prebuilt": "^1.6.5-prerelease.1"
}, },
"devDependencies": { "devDependencies": {
"chai": "^3.4.1", "chai": "^3.4.1",
"color-convert": "^1.9.0",
"eslint": "^4.19.1",
"eslint-config-es5": "^0.5.0",
"eslint-config-prettier": "^2.9.0",
"eslint-plugin-import": "^2.9.0",
"eslint-plugin-prettier": "^2.6.0",
"husky": "^0.14.3",
"jest": "^20.0.4", "jest": "^20.0.4",
"jest-cli": "^20.0.4", "jest-cli": "^20.0.4",
"color-convert": "^1.9.0" "lint-staged": "^7.0.0",
"prettier": "^1.11.1"
}, },
"jest": { "jest": {
"testEnvironment": "node" "testEnvironment": "node"

498
resemble.js

@ -4,28 +4,31 @@ URL: https://github.com/Huddle/Resemble.js
*/ */
(function(root, factory) { (function(root, factory) {
'use strict'; "use strict";
if (typeof define === 'function' && define.amd) { if (typeof define === "function" && define.amd) {
define([], factory); define([], factory);
} else if (typeof module === 'object' && module.exports) { } else if (typeof module === "object" && module.exports) {
module.exports = factory(); module.exports = factory();
} else { } else {
root.resemble = factory(); root.resemble = factory();
} }
}(this, function () { })(this, function() {
'use strict'; "use strict";
var Img; var Img;
var Canvas; var Canvas;
if (typeof Image !== 'undefined') { if (typeof Image !== "undefined") {
Img = Image; Img = Image;
} else { } else {
Canvas = require('canvas-prebuilt'); Canvas = require("canvas-prebuilt"); // eslint-disable-line global-require
Img = Canvas.Image; Img = Canvas.Image;
} }
var document = typeof window !== "undefined" ? window.document : { var document =
typeof window !== "undefined"
? window.document
: {
createElement: function() { createElement: function() {
// This will work as long as only createElement is used on window.document // This will work as long as only createElement is used on window.document
return new Canvas(); return new Canvas();
@ -36,17 +39,19 @@ URL: https://github.com/Huddle/Resemble.js
var globalOutputSettings = oldGlobalSettings; var globalOutputSettings = oldGlobalSettings;
function setGlobalOutputSettings(settings) { function setGlobalOutputSettings(settings) {
var msg = 'warning resemble.outputSettings mutates global state, and ' + var msg =
'will be removed in 3.0.0'; "warning resemble.outputSettings mutates global state, and " +
"will be removed in 3.0.0";
console.warn(msg); console.warn(msg);
globalOutputSettings = settings; globalOutputSettings = settings;
return this return this;
} }
var resemble = function(fileData) { var resemble = function(fileData) {
var pixelTransparency = 1; var pixelTransparency = 1;
var errorPixelColor = { // Color for Error Pixels. Between 0 and 255. var errorPixelColor = {
// Color for Error Pixels. Between 0 and 255.
red: 255, red: 255,
green: 0, green: 0,
blue: 255, blue: 255,
@ -56,24 +61,37 @@ URL: https://github.com/Huddle/Resemble.js
var targetPix = { r: 0, g: 0, b: 0, a: 0 }; // isAntialiased var targetPix = { r: 0, g: 0, b: 0, a: 0 }; // isAntialiased
function colorsDistance(c1, c2) { function colorsDistance(c1, c2) {
return (Math.abs(c1.r - c2.r) + Math.abs(c1.g - c2.g) + Math.abs(c1.b - c2.b))/3; return (
(Math.abs(c1.r - c2.r) +
Math.abs(c1.g - c2.g) +
Math.abs(c1.b - c2.b)) /
3
);
} }
function withinBoundingBox(x, y, width, height, box) { function withinBoundingBox(x, y, width, height, box) {
return x > (box.left || 0) && return (
x > (box.left || 0) &&
x < (box.right || width) && x < (box.right || width) &&
y > (box.top || 0) && y > (box.top || 0) &&
y < (box.bottom || height); y < (box.bottom || height)
);
} }
function withinComparedArea(x, y, width, height) { function withinComparedArea(x, y, width, height) {
var isIncluded = true; var isIncluded = true;
if (boundingBox !== undefined && !withinBoundingBox(x, y, width, height, boundingBox)) { if (
boundingBox !== undefined &&
!withinBoundingBox(x, y, width, height, boundingBox)
) {
isIncluded = false; isIncluded = false;
} }
if (ignoredBox !== undefined && withinBoundingBox(x, y, width, height, ignoredBox)) { if (
ignoredBox !== undefined &&
withinBoundingBox(x, y, width, height, ignoredBox)
) {
isIncluded = false; isIncluded = false;
} }
@ -88,9 +106,17 @@ URL: https://github.com/Huddle/Resemble.js
px[offset + 3] = errorPixelColor.alpha; px[offset + 3] = errorPixelColor.alpha;
}, },
movement: function(px, offset, d1, d2) { movement: function(px, offset, d1, d2) {
px[offset] = ((d2.r * (errorPixelColor.red / 255)) + errorPixelColor.red) / 2; px[offset] =
px[offset + 1] = ((d2.g * (errorPixelColor.green / 255)) + errorPixelColor.green) / 2; (d2.r * (errorPixelColor.red / 255) + errorPixelColor.red) /
px[offset + 2] = ((d2.b * (errorPixelColor.blue / 255)) + errorPixelColor.blue) / 2; 2;
px[offset + 1] =
(d2.g * (errorPixelColor.green / 255) +
errorPixelColor.green) /
2;
px[offset + 2] =
(d2.b * (errorPixelColor.blue / 255) +
errorPixelColor.blue) /
2;
px[offset + 3] = d2.a; px[offset + 3] = d2.a;
}, },
flatDifferenceIntensity: function(px, offset, d1, d2) { flatDifferenceIntensity: function(px, offset, d1, d2) {
@ -102,9 +128,15 @@ URL: https://github.com/Huddle/Resemble.js
movementDifferenceIntensity: function(px, offset, d1, d2) { movementDifferenceIntensity: function(px, offset, d1, d2) {
var ratio = colorsDistance(d1, d2) / 255 * 0.8; var ratio = colorsDistance(d1, d2) / 255 * 0.8;
px[offset] = ((1 - ratio) * (d2.r * (errorPixelColor.red / 255)) + ratio * errorPixelColor.red); px[offset] =
px[offset + 1] = ((1 - ratio) * (d2.g * (errorPixelColor.green / 255)) + ratio * errorPixelColor.green); (1 - ratio) * (d2.r * (errorPixelColor.red / 255)) +
px[offset + 2] = ((1 - ratio) * (d2.b * (errorPixelColor.blue / 255)) + ratio * errorPixelColor.blue); ratio * errorPixelColor.red;
px[offset + 1] =
(1 - ratio) * (d2.g * (errorPixelColor.green / 255)) +
ratio * errorPixelColor.green;
px[offset + 2] =
(1 - ratio) * (d2.b * (errorPixelColor.blue / 255)) +
ratio * errorPixelColor.blue;
px[offset + 3] = d2.a; px[offset + 3] = d2.a;
}, },
diffOnly: function(px, offset, d1, d2) { diffOnly: function(px, offset, d1, d2) {
@ -125,7 +157,8 @@ URL: https://github.com/Huddle/Resemble.js
var images = []; var images = [];
var updateCallbackArray = []; var updateCallbackArray = [];
var tolerance = { // between 0 and 255 var tolerance = {
// between 0 and 255
red: 16, red: 16,
green: 16, green: 16,
blue: 16, blue: 16,
@ -142,14 +175,15 @@ URL: https://github.com/Huddle/Resemble.js
var len = updateCallbackArray.length; var len = updateCallbackArray.length;
var i; var i;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
if (typeof updateCallbackArray[i] === 'function'){ if (typeof updateCallbackArray[i] === "function") {
updateCallbackArray[i](data); updateCallbackArray[i](data);
} }
} }
} }
function loop(w, h, callback) { function loop(w, h, callback) {
var x,y; var x;
var y;
for (x = 0; x < w; x++) { for (x = 0; x < w; x++) {
for (y = 0; y < h; y++) { for (y = 0; y < h; y++) {
@ -159,7 +193,6 @@ URL: https://github.com/Huddle/Resemble.js
} }
function parseImage(sourceImageData, width, height) { function parseImage(sourceImageData, width, height) {
var pixelCount = 0; var pixelCount = 0;
var redTotal = 0; var redTotal = 0;
var greenTotal = 0; var greenTotal = 0;
@ -177,11 +210,11 @@ URL: https://github.com/Huddle/Resemble.js
var alpha = sourceImageData[offset + 3]; var alpha = sourceImageData[offset + 3];
var brightness = getBrightness(red, green, blue); var brightness = getBrightness(red, green, blue);
if (red == green && red == blue && alpha) { if (red === green && red === blue && alpha) {
if (red == 0) { if (red === 0) {
blackTotal++ blackTotal++;
} else if (red == 255) { } else if (red === 255) {
whiteTotal++ whiteTotal++;
} }
} }
@ -205,7 +238,7 @@ URL: https://github.com/Huddle/Resemble.js
triggerDataUpdate(); triggerDataUpdate();
} }
function loadImageData( fileData, callback ){ function loadImageData(fileDataForImage, callback) {
var fileReader; var fileReader;
var hiddenImage = new Img(); var hiddenImage = new Img();
@ -214,7 +247,7 @@ URL: https://github.com/Huddle/Resemble.js
} }
if (useCrossOrigin) { if (useCrossOrigin) {
hiddenImage.setAttribute('crossorigin', 'anonymous'); hiddenImage.setAttribute("crossorigin", "anonymous");
} }
hiddenImage.onerror = function(err) { hiddenImage.onerror = function(err) {
@ -228,14 +261,14 @@ URL: https://github.com/Huddle/Resemble.js
hiddenImage.onload = null; // fixes pollution between calls hiddenImage.onload = null; // fixes pollution between calls
hiddenImage.onerror = null; hiddenImage.onerror = null;
var hiddenCanvas = document.createElement('canvas'); var hiddenCanvas = document.createElement("canvas");
var imageData; var imageData;
// don't assign to hiddenImage, see https://github.com/Huddle/Resemble.js/pull/87/commits/300d43352a2845aad289b254bfbdc7cd6a37e2d7 // don't assign to hiddenImage, see https://github.com/Huddle/Resemble.js/pull/87/commits/300d43352a2845aad289b254bfbdc7cd6a37e2d7
var width = hiddenImage.width; var width = hiddenImage.width;
var height = hiddenImage.height; var height = hiddenImage.height;
if( scaleToSameSize && images.length == 1 ){ if (scaleToSameSize && images.length === 1) {
width = images[0].width; width = images[0].width;
height = images[0].height; height = images[0].height;
} }
@ -243,46 +276,57 @@ URL: https://github.com/Huddle/Resemble.js
hiddenCanvas.width = width; hiddenCanvas.width = width;
hiddenCanvas.height = height; hiddenCanvas.height = height;
hiddenCanvas.getContext('2d').drawImage(hiddenImage, 0, 0, width, height); hiddenCanvas
imageData = hiddenCanvas.getContext('2d').getImageData(0, 0, width, height); .getContext("2d")
.drawImage(hiddenImage, 0, 0, width, height);
imageData = hiddenCanvas
.getContext("2d")
.getImageData(0, 0, width, height);
images.push(imageData); images.push(imageData);
callback(imageData, width, height); callback(imageData, width, height);
}; };
if (typeof fileData === 'string') { if (typeof fileDataForImage === "string") {
hiddenImage.src = fileData; hiddenImage.src = fileDataForImage;
if (hiddenImage.complete && hiddenImage.naturalWidth > 0) { if (hiddenImage.complete && hiddenImage.naturalWidth > 0) {
hiddenImage.onload(); hiddenImage.onload();
} }
} else if (typeof fileData.data !== 'undefined' } else if (
&& typeof fileData.width === 'number' typeof fileDataForImage.data !== "undefined" &&
&& typeof fileData.height === 'number') { typeof fileDataForImage.width === "number" &&
typeof fileDataForImage.height === "number"
images.push(fileData); ) {
images.push(fileDataForImage);
callback(fileData, fileData.width, fileData.height);
} else if (typeof Buffer !== 'undefined' && fileData instanceof Buffer){ callback(
fileDataForImage,
fileDataForImage.width,
fileDataForImage.height
);
} else if (
typeof Buffer !== "undefined" &&
fileDataForImage instanceof Buffer
) {
// If we have Buffer, assume we're on Node+Canvas and its supported // If we have Buffer, assume we're on Node+Canvas and its supported
hiddenImage.src = fileData; hiddenImage.src = fileDataForImage;
} else { } else {
fileReader = new FileReader(); fileReader = new FileReader();
fileReader.onload = function(event) { fileReader.onload = function(event) {
hiddenImage.src = event.target.result; hiddenImage.src = event.target.result;
}; };
fileReader.readAsDataURL(fileData); fileReader.readAsDataURL(fileDataForImage);
} }
} }
function isColorSimilar(a, b, color) { function isColorSimilar(a, b, color) {
var absDiff = Math.abs(a - b); var absDiff = Math.abs(a - b);
if(typeof a === 'undefined'){ if (typeof a === "undefined") {
return false; return false;
} }
if(typeof b === 'undefined'){ if (typeof b === "undefined") {
return false; return false;
} }
@ -290,14 +334,17 @@ URL: https://github.com/Huddle/Resemble.js
return true; return true;
} else if (absDiff < tolerance[color]) { } else if (absDiff < tolerance[color]) {
return true; return true;
} else {
return false;
} }
return false;
} }
function isPixelBrightnessSimilar(d1, d2) { function isPixelBrightnessSimilar(d1, d2) {
var alpha = isColorSimilar(d1.a, d2.a, 'alpha'); var alpha = isColorSimilar(d1.a, d2.a, "alpha");
var brightness = isColorSimilar(d1.brightness, d2.brightness, 'minBrightness'); var brightness = isColorSimilar(
d1.brightness,
d2.brightness,
"minBrightness"
);
return brightness && alpha; return brightness && alpha;
} }
@ -313,43 +360,60 @@ URL: https://github.com/Huddle/Resemble.js
} }
function isRGBSimilar(d1, d2) { function isRGBSimilar(d1, d2) {
var red = isColorSimilar(d1.r,d2.r,'red'); var red = isColorSimilar(d1.r, d2.r, "red");
var green = isColorSimilar(d1.g,d2.g,'green'); var green = isColorSimilar(d1.g, d2.g, "green");
var blue = isColorSimilar(d1.b,d2.b,'blue'); var blue = isColorSimilar(d1.b, d2.b, "blue");
var alpha = isColorSimilar(d1.a, d2.a, 'alpha'); var alpha = isColorSimilar(d1.a, d2.a, "alpha");
return red && green && blue && alpha; return red && green && blue && alpha;
} }
function isContrasting(d1, d2) { function isContrasting(d1, d2) {
return Math.abs(d1.brightness - d2.brightness) > tolerance.maxBrightness; return (
} Math.abs(d1.brightness - d2.brightness) >
tolerance.maxBrightness
function getHue(r,g,b){ );
}
r = r / 255;
g = g / 255; function getHue(red, green, blue) {
b = b / 255; var r = red / 255;
var max = Math.max(r, g, b), min = Math.min(r, g, b); var g = green / 255;
var b = blue / 255;
var max = Math.max(r, g, b);
var min = Math.min(r, g, b);
var h; var h;
var d; var d;
if (max == min){ if (max === min) {
h = 0; // achromatic h = 0; // achromatic
} else { } else {
d = max - min; d = max - min;
switch (max) { switch (max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break; case r:
case g: h = (b - r) / d + 2; break; h = (g - b) / d + (g < b ? 6 : 0);
case b: h = (r - g) / d + 4; break; break;
} case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
default:
h /= 6; h /= 6;
} }
}
return h; return h;
} }
function isAntialiased(sourcePix, data, cacheSet, verticalPos, horizontalPos, width){ function isAntialiased(
sourcePix,
pix,
cacheSet,
verticalPos,
horizontalPos,
width
) {
var offset; var offset;
var distance = 1; var distance = 1;
var i; var i;
@ -362,14 +426,14 @@ URL: https://github.com/Huddle/Resemble.js
for (i = distance * -1; i <= distance; i++) { for (i = distance * -1; i <= distance; i++) {
for (j = distance * -1; j <= distance; j++) { for (j = distance * -1; j <= distance; j++) {
if (i === 0 && j === 0) { if (i === 0 && j === 0) {
// ignore source pixel // ignore source pixel
} else { } else {
offset =
((verticalPos + j) * width + (horizontalPos + i)) *
4;
offset = ((verticalPos+j)*width + (horizontalPos+i)) * 4; if (!getPixelInfo(targetPix, pix, offset, cacheSet)) {
if(!getPixelInfo(targetPix , data, offset, cacheSet)){
continue; continue;
} }
@ -388,7 +452,10 @@ URL: https://github.com/Huddle/Resemble.js
hasSiblingWithDifferentHue++; hasSiblingWithDifferentHue++;
} }
if( hasSiblingWithDifferentHue > 1 || hasHighContrastSibling > 1){ if (
hasSiblingWithDifferentHue > 1 ||
hasHighContrastSibling > 1
) {
return true; return true;
} }
} }
@ -402,34 +469,34 @@ URL: https://github.com/Huddle/Resemble.js
return false; return false;
} }
function copyPixel(px, offset, data){ function copyPixel(px, offset, pix) {
if (errorType === 'diffOnly') { if (errorType === "diffOnly") {
return; return;
} }
px[offset] = data.r; //r px[offset] = pix.r; // r
px[offset + 1] = data.g; //g px[offset + 1] = pix.g; // g
px[offset + 2] = data.b; //b px[offset + 2] = pix.b; // b
px[offset + 3] = data.a * pixelTransparency; //a px[offset + 3] = pix.a * pixelTransparency; // a
} }
function copyGrayScalePixel(px, offset, data){ function copyGrayScalePixel(px, offset, pix) {
if (errorType === 'diffOnly') { if (errorType === "diffOnly") {
return; return;
} }
px[offset] = data.brightness; //r px[offset] = pix.brightness; // r
px[offset + 1] = data.brightness; //g px[offset + 1] = pix.brightness; // g
px[offset + 2] = data.brightness; //b px[offset + 2] = pix.brightness; // b
px[offset + 3] = data.a * pixelTransparency; //a px[offset + 3] = pix.a * pixelTransparency; // a
} }
function getPixelInfo(dst, data, offset) { function getPixelInfo(dst, pix, offset) {
if (data.length > offset) { if (pix.length > offset) {
dst.r = data[offset]; dst.r = pix[offset];
dst.g = data[offset + 1]; dst.g = pix[offset + 1];
dst.b = data[offset + 2]; dst.b = pix[offset + 2];
dst.a = data[offset + 3]; dst.a = pix[offset + 3];
return true; return true;
} }
@ -437,17 +504,16 @@ URL: https://github.com/Huddle/Resemble.js
return false; return false;
} }
function addBrightnessInfo(data){ function addBrightnessInfo(pix) {
data.brightness = getBrightness(data.r,data.g,data.b); // 'corrected' lightness pix.brightness = getBrightness(pix.r, pix.g, pix.b); // 'corrected' lightness
} }
function addHueInfo(data){ function addHueInfo(pix) {
data.h = getHue(data.r,data.g,data.b); pix.h = getHue(pix.r, pix.g, pix.b);
} }
function analyseImages(img1, img2, width, height) { function analyseImages(img1, img2, width, height) {
var hiddenCanvas = document.createElement("canvas");
var hiddenCanvas = document.createElement('canvas');
var data1 = img1.data; var data1 = img1.data;
var data2 = img2.data; var data2 = img2.data;
@ -455,9 +521,9 @@ URL: https://github.com/Huddle/Resemble.js
hiddenCanvas.width = width; hiddenCanvas.width = width;
hiddenCanvas.height = height; hiddenCanvas.height = height;
var context = hiddenCanvas.getContext('2d'); var context = hiddenCanvas.getContext("2d");
var imgd = context.createImageData(width, height); var imgd = context.createImageData(width, height);
var targetPix = imgd.data; var pix = imgd.data;
var mismatchCount = 0; var mismatchCount = 0;
var diffBounds = { var diffBounds = {
@ -477,7 +543,11 @@ URL: https://github.com/Huddle/Resemble.js
var skip; var skip;
if(!!largeImageThreshold && ignoreAntialiasing && (width > largeImageThreshold || height > largeImageThreshold)){ if (
!!largeImageThreshold &&
ignoreAntialiasing &&
(width > largeImageThreshold || height > largeImageThreshold)
) {
skip = 6; skip = 6;
} }
@ -485,29 +555,42 @@ URL: https://github.com/Huddle/Resemble.js
var pixel2 = { r: 0, g: 0, b: 0, a: 0 }; var pixel2 = { r: 0, g: 0, b: 0, a: 0 };
loop(width, height, function(horizontalPos, verticalPos) { loop(width, height, function(horizontalPos, verticalPos) {
if (skip) {
if(skip){ // only skip if the image isn't small // only skip if the image isn't small
if(verticalPos % skip === 0 || horizontalPos % skip === 0){ if (
verticalPos % skip === 0 ||
horizontalPos % skip === 0
) {
return; return;
} }
} }
var offset = (verticalPos * width + horizontalPos) * 4; var offset = (verticalPos * width + horizontalPos) * 4;
var isWithinComparedArea = withinComparedArea(horizontalPos, verticalPos, width, height); var isWithinComparedArea = withinComparedArea(
horizontalPos,
if (!getPixelInfo(pixel1, data1, offset, 1) || !getPixelInfo(pixel2, data2, offset, 2)) { verticalPos,
width,
height
);
if (
!getPixelInfo(pixel1, data1, offset, 1) ||
!getPixelInfo(pixel2, data2, offset, 2)
) {
return; return;
} }
if (ignoreColors) { if (ignoreColors) {
addBrightnessInfo(pixel1); addBrightnessInfo(pixel1);
addBrightnessInfo(pixel2); addBrightnessInfo(pixel2);
if( isPixelBrightnessSimilar(pixel1, pixel2) || !isWithinComparedArea ){ if (
copyGrayScalePixel(targetPix, offset, pixel2); isPixelBrightnessSimilar(pixel1, pixel2) ||
!isWithinComparedArea
) {
copyGrayScalePixel(pix, offset, pixel2);
} else { } else {
errorPixel(targetPix, offset, pixel1, pixel2); errorPixel(pix, offset, pixel1, pixel2);
mismatchCount++; mismatchCount++;
updateBounds(horizontalPos, verticalPos); updateBounds(horizontalPos, verticalPos);
} }
@ -515,31 +598,46 @@ URL: https://github.com/Huddle/Resemble.js
} }
if (isRGBSimilar(pixel1, pixel2) || !isWithinComparedArea) { if (isRGBSimilar(pixel1, pixel2) || !isWithinComparedArea) {
copyPixel(targetPix, offset, pixel1); copyPixel(pix, offset, pixel1);
} else if (
} else if( ignoreAntialiasing && ( ignoreAntialiasing &&
addBrightnessInfo(pixel1), // jit pixel info augmentation looks a little weird, sorry. (addBrightnessInfo(pixel1), // jit pixel info augmentation looks a little weird, sorry.
addBrightnessInfo(pixel2), addBrightnessInfo(pixel2),
isAntialiased(pixel1, data1, 1, verticalPos, horizontalPos, width) || isAntialiased(
isAntialiased(pixel2, data2, 2, verticalPos, horizontalPos, width) pixel1,
)){ data1,
1,
if( isPixelBrightnessSimilar(pixel1, pixel2) || !isWithinComparedArea ){ verticalPos,
copyGrayScalePixel(targetPix, offset, pixel2); horizontalPos,
width
) ||
isAntialiased(
pixel2,
data2,
2,
verticalPos,
horizontalPos,
width
))
) {
if (
isPixelBrightnessSimilar(pixel1, pixel2) ||
!isWithinComparedArea
) {
copyGrayScalePixel(pix, offset, pixel2);
} else { } else {
errorPixel(targetPix, offset, pixel1, pixel2); errorPixel(pix, offset, pixel1, pixel2);
mismatchCount++; mismatchCount++;
updateBounds(horizontalPos, verticalPos); updateBounds(horizontalPos, verticalPos);
} }
} else { } else {
errorPixel(targetPix, offset, pixel1, pixel2); errorPixel(pix, offset, pixel1, pixel2);
mismatchCount++; mismatchCount++;
updateBounds(horizontalPos, verticalPos); updateBounds(horizontalPos, verticalPos);
} }
}); });
data.rawMisMatchPercentage = (mismatchCount / (height*width) * 100); data.rawMisMatchPercentage = mismatchCount / (height * width) * 100;
data.misMatchPercentage = data.rawMisMatchPercentage.toFixed(2); data.misMatchPercentage = data.rawMisMatchPercentage.toFixed(2);
data.diffBounds = diffBounds; data.diffBounds = diffBounds;
data.analysisTime = Date.now() - time; data.analysisTime = Date.now() - time;
@ -568,14 +666,14 @@ URL: https://github.com/Huddle/Resemble.js
context.putImageData(imgd, 0, 0); context.putImageData(imgd, 0, 0);
} }
return hiddenCanvas.toBuffer(); return hiddenCanvas.toBuffer();
} };
} }
} }
function addLabel(text, context, hiddenCanvas) { function addLabel(text, context, hiddenCanvas) {
var textPadding = 2; var textPadding = 2;
context.font = '12px sans-serif'; context.font = "12px sans-serif";
var textWidth = context.measureText(text).width + textPadding * 2; var textWidth = context.measureText(text).width + textPadding * 2;
var barHeight = 22; var barHeight = 22;
@ -593,7 +691,7 @@ URL: https://github.com/Huddle/Resemble.js
context.fillStyle = "#fff"; context.fillStyle = "#fff";
context.textBaseline = "top"; context.textBaseline = "top";
context.font = '12px sans-serif'; context.font = "12px sans-serif";
context.fillText(text, textPadding, 1); context.fillText(text, textPadding, 1);
return barHeight; return barHeight;
@ -604,10 +702,10 @@ URL: https://github.com/Huddle/Resemble.js
var context; var context;
if (img.height < h || img.width < w) { if (img.height < h || img.width < w) {
c = document.createElement('canvas'); c = document.createElement("canvas");
c.width = w; c.width = w;
c.height = h; c.height = h;
context = c.getContext('2d'); context = c.getContext("2d");
context.putImageData(img, 0, 0); context.putImageData(img, 0, 0);
return context.getImageData(0, 0, w, h); return context.getImageData(0, 0, w, h);
} }
@ -617,11 +715,15 @@ URL: https://github.com/Huddle/Resemble.js
function outputSettings(options) { function outputSettings(options) {
var key; var key;
var undefined;
if (options.errorColor) { if (options.errorColor) {
for (key in options.errorColor) { for (key in options.errorColor) {
errorPixelColor[key] = options.errorColor[key] === undefined ? errorPixelColor[key] : options.errorColor[key]; if (options.hasOwnProperty(key)) {
errorPixelColor[key] =
options.errorColor[key] === void 0
? errorPixelColor[key]
: options.errorColor[key];
}
} }
} }
@ -630,11 +732,16 @@ URL: https://github.com/Huddle/Resemble.js
errorType = options.errorType; errorType = options.errorType;
} }
if(options.errorPixel && typeof options.errorPixel === "function") { if (
options.errorPixel &&
typeof options.errorPixel === "function"
) {
errorPixel = options.errorPixel; errorPixel = options.errorPixel;
} }
pixelTransparency = isNaN(Number(options.transparency)) ? pixelTransparency : options.transparency; pixelTransparency = isNaN(Number(options.transparency))
? pixelTransparency
: options.transparency;
if (options.largeImageThreshold !== undefined) { if (options.largeImageThreshold !== undefined) {
largeImageThreshold = options.largeImageThreshold; largeImageThreshold = options.largeImageThreshold;
@ -651,7 +758,6 @@ URL: https://github.com/Huddle/Resemble.js
if (options.ignoredBox !== undefined) { if (options.ignoredBox !== undefined) {
ignoredBox = options.ignoredBox; ignoredBox = options.ignoredBox;
} }
} }
function compare(one, two) { function compare(one, two) {
@ -665,22 +771,41 @@ URL: https://github.com/Huddle/Resemble.js
if (images.length === 2) { if (images.length === 2) {
if (images[0].error || images[1].error) { if (images[0].error || images[1].error) {
data = {}; data = {};
data.error = images[0].error ? images[0].error : images[1].error; data.error = images[0].error
? images[0].error
: images[1].error;
triggerDataUpdate(); triggerDataUpdate();
return; return;
} }
width = images[0].width > images[1].width ? images[0].width : images[1].width; width =
height = images[0].height > images[1].height ? images[0].height : images[1].height; images[0].width > images[1].width
? images[0].width
if( (images[0].width === images[1].width) && (images[0].height === images[1].height) ){ : images[1].width;
height =
images[0].height > images[1].height
? images[0].height
: images[1].height;
if (
images[0].width === images[1].width &&
images[0].height === images[1].height
) {
data.isSameDimensions = true; data.isSameDimensions = true;
} else { } else {
data.isSameDimensions = false; data.isSameDimensions = false;
} }
data.dimensionDifference = { width: images[0].width - images[1].width, height: images[0].height - images[1].height }; data.dimensionDifference = {
width: images[0].width - images[1].width,
height: images[0].height - images[1].height
};
analyseImages( normalise(images[0],width, height), normalise(images[1],width, height), width, height); analyseImages(
normalise(images[0], width, height),
normalise(images[1], width, height),
width,
height
);
triggerDataUpdate(); triggerDataUpdate();
} }
@ -692,9 +817,8 @@ URL: https://github.com/Huddle/Resemble.js
} }
function getCompareApi(param) { function getCompareApi(param) {
var secondFileData;
var secondFileData, var hasMethod = typeof param === "function";
hasMethod = typeof param === 'function';
if (!hasMethod) { if (!hasMethod) {
// assume it's file data // assume it's file data
@ -705,17 +829,20 @@ URL: https://github.com/Huddle/Resemble.js
scaleToSameSize: function() { scaleToSameSize: function() {
scaleToSameSize = true; scaleToSameSize = true;
if(hasMethod) { param(); } if (hasMethod) {
param();
}
return self; return self;
}, },
useOriginalSize: function() { useOriginalSize: function() {
scaleToSameSize = false; scaleToSameSize = false;
if(hasMethod) { param(); } if (hasMethod) {
param();
}
return self; return self;
}, },
ignoreNothing: function() { ignoreNothing: function() {
tolerance.red = 0; tolerance.red = 0;
tolerance.green = 0; tolerance.green = 0;
tolerance.blue = 0; tolerance.blue = 0;
@ -726,11 +853,12 @@ URL: https://github.com/Huddle/Resemble.js
ignoreAntialiasing = false; ignoreAntialiasing = false;
ignoreColors = false; ignoreColors = false;
if(hasMethod) { param(); } if (hasMethod) {
param();
}
return self; return self;
}, },
ignoreLess: function() { ignoreLess: function() {
tolerance.red = 16; tolerance.red = 16;
tolerance.green = 16; tolerance.green = 16;
tolerance.blue = 16; tolerance.blue = 16;
@ -741,11 +869,12 @@ URL: https://github.com/Huddle/Resemble.js
ignoreAntialiasing = false; ignoreAntialiasing = false;
ignoreColors = false; ignoreColors = false;
if(hasMethod) { param(); } if (hasMethod) {
param();
}
return self; return self;
}, },
ignoreAntialiasing: function() { ignoreAntialiasing: function() {
tolerance.red = 32; tolerance.red = 32;
tolerance.green = 32; tolerance.green = 32;
tolerance.blue = 32; tolerance.blue = 32;
@ -756,11 +885,12 @@ URL: https://github.com/Huddle/Resemble.js
ignoreAntialiasing = true; ignoreAntialiasing = true;
ignoreColors = false; ignoreColors = false;
if(hasMethod) { param(); } if (hasMethod) {
param();
}
return self; return self;
}, },
ignoreColors: function() { ignoreColors: function() {
tolerance.alpha = 16; tolerance.alpha = 16;
tolerance.minBrightness = 16; tolerance.minBrightness = 16;
tolerance.maxBrightness = 240; tolerance.maxBrightness = 240;
@ -768,11 +898,12 @@ URL: https://github.com/Huddle/Resemble.js
ignoreAntialiasing = false; ignoreAntialiasing = false;
ignoreColors = true; ignoreColors = true;
if(hasMethod) { param(); } if (hasMethod) {
param();
}
return self; return self;
}, },
ignoreAlpha: function() { ignoreAlpha: function() {
tolerance.red = 16; tolerance.red = 16;
tolerance.green = 16; tolerance.green = 16;
tolerance.blue = 16; tolerance.blue = 16;
@ -783,11 +914,15 @@ URL: https://github.com/Huddle/Resemble.js
ignoreAntialiasing = false; ignoreAntialiasing = false;
ignoreColors = false; ignoreColors = false;
if(hasMethod) { param(); } if (hasMethod) {
param();
}
return self; return self;
}, },
repaint: function() { repaint: function() {
if(hasMethod) { param(); } if (hasMethod) {
param();
}
return self; return self;
}, },
outputSettings: function(options) { outputSettings: function(options) {
@ -795,7 +930,6 @@ URL: https://github.com/Huddle/Resemble.js
return self; return self;
}, },
onComplete: function(callback) { onComplete: function(callback) {
updateCallbackArray.push(callback); updateCallbackArray.push(callback);
var wrapper = function() { var wrapper = function() {
@ -831,34 +965,40 @@ URL: https://github.com/Huddle/Resemble.js
function applyIgnore(api, ignore) { function applyIgnore(api, ignore) {
switch (ignore) { switch (ignore) {
case 'nothing': case "nothing":
api.ignoreNothing(); api.ignoreNothing();
break; break;
case 'less': case "less":
api.ignoreLess(); api.ignoreLess();
break; break;
case 'antialiasing': case "antialiasing":
api.ignoreAntialiasing(); api.ignoreAntialiasing();
break; break;
case 'colors': case "colors":
api.ignoreColors(); api.ignoreColors();
break; break;
case 'alpha': case "alpha":
api.ignoreAlpha(); api.ignoreAlpha();
break; break;
default: default:
throw new Error('Invalid ignore: ' + ignore); throw new Error("Invalid ignore: " + ignore);
break;
} }
} }
resemble.compare = function (image1, image2, options, callback) { resemble.compare = function(image1, image2, options, cb) {
if (typeof options === 'function') { let callback;
let opt;
if (typeof options === "function") {
callback = options; callback = options;
options = undefined; opt = {};
} else {
callback = cb;
opt = options || {};
} }
var res = resemble(image1), opt = options || {}, compare; var res = resemble(image1);
var compare;
if (opt.output) { if (opt.output) {
res.outputSettings(opt.output); res.outputSettings(opt.output);
@ -870,7 +1010,7 @@ URL: https://github.com/Huddle/Resemble.js
compare.scaleToSameSize(); compare.scaleToSameSize();
} }
if (typeof opt.ignore === 'string') { if (typeof opt.ignore === "string") {
applyIgnore(compare, opt.ignore); applyIgnore(compare, opt.ignore);
} else if (opt.ignore && opt.ignore.forEach) { } else if (opt.ignore && opt.ignore.forEach) {
opt.ignore.forEach(function(v) { opt.ignore.forEach(function(v) {
@ -889,4 +1029,4 @@ URL: https://github.com/Huddle/Resemble.js
resemble.outputSettings = setGlobalOutputSettings; resemble.outputSettings = setGlobalOutputSettings;
return resemble; return resemble;
})); });

Loading…
Cancel
Save