Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added example/LargeImage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/SmallImage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 37 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
var gulp = require('gulp');
var jasmine = require('gulp-jasmine');
var gutil = require('gulp-util');

var srcFiles = 'resemble.js';
var specFiles = 'resemble.spec.js';

function runTests(breakOnError) {
return gulp.src(specFiles)
.pipe(jasmine({
includeStackTrace: true
}))
.on('error', errorHandler(breakOnError));
}

function errorHandler(breakOnError) {
return function(error) {
if (breakOnError) {
throw error;
} else {
gutil.log(gutil.colors.red('[Jasmine]'), error.toString());
this.emit('end');
}
}
}

gulp.task('test', function() {
return runTests(true);
});

gulp.task('test:auto', function() {
runTests(false);

return gulp.watch([srcFiles, specFiles], function() {
runTests(false);
});
});
8 changes: 8 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
"version": "0.0.4",
"description": "Image analysis and comparison for nodejs",
"main": "resemble.js",
"scripts": {
"test": "gulp test"
},
"repository": {
"type": "git",
"url": "https://github.com/lksv/node-resemble.js.git"
Expand All @@ -21,5 +24,10 @@
"homepage": "https://github.com/lksv/node-resemble.js",
"dependencies": {
"pngjs2": "~1.0.0"
},
"devDependencies": {
"gulp": "3.9.0",
"gulp-jasmine": "2.2.1",
"gulp-util": "3.0.7"
}
}
7 changes: 6 additions & 1 deletion resemble.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ var _this = {};
};

var errorPixelTransformer = errorPixelTransform.flat;
var largeImageThreshold = 1200;

_this['resemble'] = function( fileData ){

Expand Down Expand Up @@ -339,7 +340,7 @@ var _this = {};
var currentRectangle = null;
var rectagnlesIdx = 0;

if( (width > 1200 || height > 1200) && ignoreAntialiasing){
if(!!largeImageThreshold && ignoreAntialiasing && (width > largeImageThreshold || height > largeImageThreshold)){
skip = 6;
}

Expand Down Expand Up @@ -562,6 +563,10 @@ var _this = {};

pixelTransparency = options.transparency || pixelTransparency;

if (options.largeImageThreshold !== undefined) {
largeImageThreshold = options.largeImageThreshold;
}

return this;
};

Expand Down
182 changes: 182 additions & 0 deletions resemble.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
'use strict';

describe('node-resemble.js', function() {
var EXAMPLE_LARGE_IMAGE = 'example/LargeImage.png';
var EXAMPLE_SMALL_IMAGE = 'example/SmallImage.png';
var OPTIMISATION_SKIP_STEP = 6;
var DEFAULT_LARGE_IMAGE_THRESHOLD = 1200;

var resemble = require('./resemble.js');

describe('largeImageThreshold', function() {
describe('when unset', function() {
describe('when ignoreAntialiasing is enabled', function() {
it('skips pixels when a dimension is larger than the default threshold (1200)', function(done) {
getLargeImageComparison().ignoreAntialiasing().onComplete(function(data) {
expectPixelsToBeSkipped(data.getDiffImage(), OPTIMISATION_SKIP_STEP);
done();
});
});

it('does not skip pixels when both dimensions are smaller than the default threshold (1200)', function(done) {
getSmallImageComparison().ignoreAntialiasing().onComplete(function(data) {
expectPixelsNotToBeSkipped(data.getDiffImage(), OPTIMISATION_SKIP_STEP);
done();
});
});
});

describe('when ignoreAntialiasing is disabled', function() {
it('does not skip pixels when a dimension is larger than the default threshold (1200)', function(done) {
getLargeImageComparison().onComplete(function(data) {
expectPixelsNotToBeSkipped(data.getDiffImage(), OPTIMISATION_SKIP_STEP);
done();
});
});

it('does not skip pixels when both dimensions are smaller than the default threshold (1200)', function(done) {
getSmallImageComparison().onComplete(function(data) {
expectPixelsNotToBeSkipped(data.getDiffImage(), OPTIMISATION_SKIP_STEP);
done();
});
});
});
});

describe('when explicitly set', function() {
afterAll(function() {
resemble.outputSettings({largeImageThreshold: DEFAULT_LARGE_IMAGE_THRESHOLD});
});

describe('when ignoreAntialiasing is enabled', function() {
it('skips pixels on images with a dimension larger than the given threshold', function(done) {
resemble.outputSettings({largeImageThreshold: 999});
getSmallImageComparison().ignoreAntialiasing().onComplete(function(data) {
expectPixelsToBeSkipped(data.getDiffImage(), OPTIMISATION_SKIP_STEP);
done();
});
});

it('does not skip pixels on images with a dimension equal to the given threshold', function(done) {
resemble.outputSettings({largeImageThreshold: 1000});
getSmallImageComparison().ignoreAntialiasing().onComplete(function(data) {
expectPixelsNotToBeSkipped(data.getDiffImage(), OPTIMISATION_SKIP_STEP);
done();
});
});

it('does not skip pixels on images with both dimensions smaller than the given threshold', function(done) {
resemble.outputSettings({largeImageThreshold: 1001});
getSmallImageComparison().ignoreAntialiasing().onComplete(function(data) {
expectPixelsNotToBeSkipped(data.getDiffImage(), OPTIMISATION_SKIP_STEP);
done();
});
});
});

describe('when ignoreAntialiasing is disabled', function() {
it('does not skip pixels on images with a dimension larger than the given threshold', function(done) {
resemble.outputSettings({largeImageThreshold: 999});
getSmallImageComparison().onComplete(function(data) {
expectPixelsNotToBeSkipped(data.getDiffImage(), OPTIMISATION_SKIP_STEP);
done();
});
});

it('does not skip pixels on images with a dimension equal to the given threshold', function(done) {
resemble.outputSettings({largeImageThreshold: 1000});
getSmallImageComparison().onComplete(function(data) {
expectPixelsNotToBeSkipped(data.getDiffImage(), OPTIMISATION_SKIP_STEP);
done();
});
});

it('does not skip pixels on images with both dimensions smaller than the given threshold', function(done) {
resemble.outputSettings({largeImageThreshold: 1001});
getSmallImageComparison().onComplete(function(data) {
expectPixelsNotToBeSkipped(data.getDiffImage(), OPTIMISATION_SKIP_STEP);
done();
});
});
});
});

describe('when set to a falsy value', function() {
beforeEach(function() {
resemble.outputSettings({largeImageThreshold: 0});
});

afterAll(function() {
resemble.outputSettings({largeImageThreshold: DEFAULT_LARGE_IMAGE_THRESHOLD});
});

describe('when ignoreAntialiasing is enabled', function() {
it('does not skip pixels on images with a dimension larger than the default threshold (1200)', function(done) {
getLargeImageComparison().ignoreAntialiasing().onComplete(function(data) {
expectPixelsNotToBeSkipped(data.getDiffImage(), OPTIMISATION_SKIP_STEP);
done();
});
});

it('does not skip pixels on images with a dimension smaller than the default threshold (1200)', function(done) {
getSmallImageComparison().ignoreAntialiasing().onComplete(function(data) {
expectPixelsNotToBeSkipped(data.getDiffImage(), OPTIMISATION_SKIP_STEP);
done();
});
});
});

describe('when ignoreAntialiasing is disabled', function() {
it('does not skip pixels on images with a dimension larger than the default threshold (1200)', function(done) {
getLargeImageComparison().onComplete(function(data) {
expectPixelsNotToBeSkipped(data.getDiffImage(), OPTIMISATION_SKIP_STEP);
done();
});
});

it('does not skip pixels on images with a dimension smaller than the default threshold (1200)', function(done) {
getSmallImageComparison().onComplete(function(data) {
expectPixelsNotToBeSkipped(data.getDiffImage(), OPTIMISATION_SKIP_STEP);
done();
});
});
});
});

function expectPixelsToBeSkipped(image, step) {
expect(getPixelForLocation(image, 1, step - 1).alpha).not.toBe(0);
expect(getPixelForLocation(image, 1, step).alpha).toBe(0);
expect(getPixelForLocation(image, 1, step + 1).alpha).not.toBe(0);

expect(getPixelForLocation(image, step - 1, 1).alpha).not.toBe(0);
expect(getPixelForLocation(image, step, 1).alpha).toBe(0);
expect(getPixelForLocation(image, step + 1, 1).alpha).not.toBe(0);

expect(getPixelForLocation(image, step, step).alpha).toBe(0);
}

function expectPixelsNotToBeSkipped(image, step) {
expect(getPixelForLocation(image, 1, step).alpha).not.toBe(0);
expect(getPixelForLocation(image, step, 1).alpha).not.toBe(0);
expect(getPixelForLocation(image, step, step).alpha).not.toBe(0);
}
});

function getLargeImageComparison() {
return resemble(EXAMPLE_LARGE_IMAGE).compareTo(EXAMPLE_LARGE_IMAGE);
}

function getSmallImageComparison() {
return resemble(EXAMPLE_SMALL_IMAGE).compareTo(EXAMPLE_SMALL_IMAGE);
}

function getPixelForLocation(image, x, y) {
var index = (image.width * y + x) << 2;
return {
red: image.data[index],
green: image.data[index + 1],
blue: image.data[index + 2],
alpha: image.data[index + 3]
};
}
});