pixelworks
Version:
Utilities for working with ImageData in Workers
294 lines (231 loc) • 7.18 kB
JavaScript
/* eslint-env mocha */
var Processor = require('../../lib/processor');
var assert = require('chai').assert;
var newImageData = require('../../lib/util').newImageData;
var sinon = require('sinon');
describe('Processor', function() {
var identity = function(inputs) {
return inputs[0];
};
describe('constructor', function() {
it('creates a new processor', function() {
var processor = new Processor({
operation: identity
});
assert.instanceOf(processor, Processor);
});
});
describe('#process()', function() {
it('calls operation with input pixels', function(done) {
var processor = new Processor({
operation: function(inputs, meta) {
++meta.count;
var pixel = inputs[0];
for (var i = 0, ii = pixel.length; i < ii; ++i) {
meta.sum += pixel[i];
}
return pixel;
}
});
var array = new Uint8ClampedArray([1, 2, 3, 4, 5, 6, 7, 8]);
var input = newImageData(array, 1, 2);
processor.process([input], {count: 0, sum: 0}, function(err, output, m) {
if (err) {
done(err);
return;
}
assert.equal(m.count, 2);
assert.equal(m.sum, 36);
done();
});
});
it('calls callback with processed image data', function(done) {
var processor = new Processor({
operation: function(inputs) {
var pixel = inputs[0];
pixel[0] *= 2;
pixel[1] *= 2;
pixel[2] *= 2;
pixel[3] *= 2;
return pixel;
}
});
var array = new Uint8ClampedArray([1, 2, 3, 4, 5, 6, 7, 8]);
var input = newImageData(array, 1, 2);
processor.process([input], {}, function(err, output, m) {
if (err) {
done(err);
return;
}
assert.instanceOf(output, ImageData);
assert.deepEqual(output.data,
new Uint8ClampedArray([2, 4, 6, 8, 10, 12, 14, 16]));
done();
});
});
it('allows library functions to be called', function(done) {
var lib = {
sum: function(a, b) {
return a + b;
},
diff: function(a, b) {
return a - b;
}
};
var normalizedDiff = function(pixels) {
var pixel = pixels[0];
var r = pixel[0];
var g = pixel[1];
/* eslint-disable */
var nd = diff(r, g) / sum(r, g);
/* eslint-enable */
var index = Math.round(255 * (nd + 1) / 2);
return [index, index, index, pixel[3]];
};
var processor = new Processor({
operation: normalizedDiff,
lib: lib
});
var array = new Uint8ClampedArray([10, 2, 0, 0, 5, 8, 0, 1]);
var input = newImageData(array, 1, 2);
processor.process([input], {}, function(err, output, m) {
if (err) {
done(err);
return;
}
assert.instanceOf(output, ImageData);
var v0 = Math.round(255 * (1 + 8 / 12) / 2);
var v1 = Math.round(255 * (1 + -3 / 13) / 2);
assert.deepEqual(output.data,
new Uint8ClampedArray([
v0, v0, v0, 0,
v1, v1, v1, 1]));
done();
});
});
it('calls callbacks for each call', function(done) {
var processor = new Processor({
operation: identity
});
var calls = 0;
function createCallback(index) {
return function(err, output, meta) {
if (err) {
done(err);
return;
}
assert.instanceOf(output, ImageData);
++calls;
};
}
for (var i = 0; i < 5; ++i) {
var input = newImageData(new Uint8ClampedArray([1, 2, 3, 4]), 1, 1);
processor.process([input], {}, createCallback(i));
}
setTimeout(function() {
assert.equal(calls, 5);
done();
}, 1000);
});
it('respects max queue length', function(done) {
var processor = new Processor({
queue: 1,
operation: identity
});
var log = [];
function createCallback(index) {
return function(err, output, meta) {
if (err) {
done(err);
return;
}
log.push(output);
};
}
for (var i = 0; i < 5; ++i) {
var input = newImageData(new Uint8ClampedArray([1, 2, 3, 4]), 1, 1);
processor.process([input], {}, createCallback(i));
}
setTimeout(function() {
assert.lengthOf(log, 5);
assert.isNull(log[0], 'first call null');
assert.isNull(log[1], 'second call null');
assert.isNull(log[2], 'third call null');
assert.instanceOf(log[3], ImageData);
assert.instanceOf(log[4], ImageData);
done();
}, 1000);
});
});
describe('#process() - faux worker', function() {
var identitySpy;
beforeEach(function() {
identitySpy = sinon.spy(identity);
});
it('calls operation with input pixels', function(done) {
var processor = new Processor({
threads: 0,
operation: identitySpy
});
var array = new Uint8ClampedArray([1, 2, 3, 4, 5, 6, 7, 8]);
var input = newImageData(array, 1, 2);
processor.process([input], {}, function(err, output, m) {
if (err) {
done(err);
return;
}
assert.equal(identitySpy.callCount, 2);
var first = identitySpy.getCall(0);
assert.lengthOf(first.args, 2);
done();
});
});
it('passes meta object to operations', function(done) {
var processor = new Processor({
threads: 0,
operation: identitySpy
});
var array = new Uint8ClampedArray([1, 2, 3, 4]);
var input = newImageData(array, 1, 1);
var meta = {foo: 'bar'};
processor.process([input], meta, function(err, output, m) {
if (err) {
done(err);
return;
}
assert.deepEqual(m, meta);
assert.equal(identitySpy.callCount, 1);
done();
});
});
});
describe('#destroy()', function() {
it('stops callbacks from being called', function(done) {
var processor = new Processor({
operation: identity
});
var array = new Uint8ClampedArray([1, 2, 3, 4, 5, 6, 7, 8]);
var input = newImageData(array, 1, 2);
processor.process([input], {}, function() {
done(new Error('Expected abort to stop callback from being called'));
});
processor.destroy();
setTimeout(done, 500);
});
});
describe('#destroy() - faux worker', function() {
it('stops callbacks from being called', function(done) {
var processor = new Processor({
threads: 0,
operation: identity
});
var array = new Uint8ClampedArray([1, 2, 3, 4, 5, 6, 7, 8]);
var input = newImageData(array, 1, 2);
processor.process([input], {}, function() {
done(new Error('Expected abort to stop callback from being called'));
});
processor.destroy();
setTimeout(done, 20);
});
});
});