Ensure conv kernel scale is clamped to min val of 1 #561

This commit is contained in:
Lovell Fuller 2016-09-03 20:06:49 +01:00
parent 7c06a48ec0
commit af9d09f8ae
4 changed files with 75 additions and 56 deletions

View File

@ -4,6 +4,12 @@
Requires libvips v8.3.3 Requires libvips v8.3.3
#### v0.16.1 - TBD
* Ensure convolution kernel scale is clamped to a minimum value of 1.
[#561](https://github.com/lovell/sharp/issues/561)
[@abagshaw](https://github.com/abagshaw)
#### v0.16.0 - 18<sup>th</sup> August 2016 #### v0.16.0 - 18<sup>th</sup> August 2016
* Add pre-compiled libvips for OS X, ARMv7 and ARMv8. * Add pre-compiled libvips for OS X, ARMv7 and ARMv8.

View File

@ -503,22 +503,25 @@ Sharp.prototype.blur = function(sigma) {
Convolve the image with a kernel. Convolve the image with a kernel.
*/ */
Sharp.prototype.convolve = function(kernel) { Sharp.prototype.convolve = function(kernel) {
if (!isDefined(kernel) || !isDefined(kernel.kernel) || if (!isObject(kernel) || !Array.isArray(kernel.kernel) ||
!isDefined(kernel.width) || !isDefined(kernel.height) || !isInteger(kernel.width) || !isInteger(kernel.height) ||
!inRange(kernel.width,3,1001) || !inRange(kernel.height,3,1001) || !inRange(kernel.width, 3, 1001) || !inRange(kernel.height, 3, 1001) ||
kernel.height * kernel.width != kernel.kernel.length kernel.height * kernel.width != kernel.kernel.length
) { ) {
// must pass in a kernel // must pass in a kernel
throw new Error('Invalid convolution kernel'); throw new Error('Invalid convolution kernel');
} }
if(!isDefined(kernel.scale)) { // Default scale is sum of kernel values
var sum = 0; if (!isInteger(kernel.scale)) {
kernel.kernel.forEach(function(e) { kernel.scale = kernel.kernel.reduce(function(a, b) {
sum += e; return a + b;
}); }, 0);
kernel.scale = sum;
} }
if(!isDefined(kernel.offset)) { // Clamp scale to a minimum value of 1
if (kernel.scale < 1) {
kernel.scale = 1;
}
if (!isInteger(kernel.offset)) {
kernel.offset = 0; kernel.offset = 0;
} }
this.options.convKernel = kernel; this.options.convKernel = kernel;

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -9,18 +9,17 @@ describe('Convolve', function() {
it('specific convolution kernel 1', function(done) { it('specific convolution kernel 1', function(done) {
sharp(fixtures.inputPngStripesV) sharp(fixtures.inputPngStripesV)
.resize(320, 240) .convolve({
.convolve( width: 3,
{ height: 3,
'width': 3, scale: 50,
'height': 3, offset: 0,
'scale': 50, kernel: [ 10, 20, 10,
'offset': 0, 0, 0, 0,
'kernel': [ 10, 20, 10, 10, 20, 10 ]
0, 0, 0, })
10, 20, 10 ]
})
.toBuffer(function(err, data, info) { .toBuffer(function(err, data, info) {
if (err) throw err;
assert.strictEqual('png', info.format); assert.strictEqual('png', info.format);
assert.strictEqual(320, info.width); assert.strictEqual(320, info.width);
assert.strictEqual(240, info.height); assert.strictEqual(240, info.height);
@ -30,16 +29,15 @@ describe('Convolve', function() {
it('specific convolution kernel 2', function(done) { it('specific convolution kernel 2', function(done) {
sharp(fixtures.inputPngStripesH) sharp(fixtures.inputPngStripesH)
.resize(320, 240) .convolve({
.convolve( width: 3,
{ height: 3,
'width': 3, kernel: [ 1, 0, 1,
'height': 3, 2, 0, 2,
'kernel': [ 1, 0, 1, 1, 0, 1 ]
2, 0, 2, })
1, 0, 1 ]
})
.toBuffer(function(err, data, info) { .toBuffer(function(err, data, info) {
if (err) throw err;
assert.strictEqual('png', info.format); assert.strictEqual('png', info.format);
assert.strictEqual(320, info.width); assert.strictEqual(320, info.width);
assert.strictEqual(240, info.height); assert.strictEqual(240, info.height);
@ -47,36 +45,48 @@ describe('Convolve', function() {
}); });
}); });
it('invalid kernel specification: no data', function() { it('horizontal Sobel operator', function(done) {
assert.throws(function() { sharp(fixtures.inputJpg)
sharp(fixtures.inputJpg).convolve( .resize(320, 240)
{ .convolve({
'width': 3, width: 3,
'height': 3, height: 3,
'kernel': [] kernel: [ -1, 0, 1,
}); -2, 0, 2,
}); -1, 0, 1 ]
})
.toBuffer(function(err, data, info) {
if (err) throw err;
assert.strictEqual('jpeg', info.format);
assert.strictEqual(320, info.width);
assert.strictEqual(240, info.height);
fixtures.assertSimilar(fixtures.expected('conv-sobel-horizontal.jpg'), data, done);
});
}); });
it('invalid kernel specification: bad data format', function() { describe('invalid kernel specification', function() {
assert.throws(function() { it('missing', function() {
sharp(fixtures.inputJpg).convolve( assert.throws(function() {
{ sharp(fixtures.inputJpg).convolve({});
'width': 3, });
'height': 3,
'kernel': [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
});
}); });
}); it('incorrect data format', function() {
assert.throws(function() {
it('invalid kernel specification: wrong width', function() { sharp(fixtures.inputJpg).convolve({
assert.throws(function() { width: 3,
sharp(fixtures.inputJpg).convolve( height: 3,
{ kernel: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
'width': 3,
'height': 4,
'kernel': [1, 2, 3, 4, 5, 6, 7, 8, 9]
}); });
});
});
it('incorrect dimensions', function() {
assert.throws(function() {
sharp(fixtures.inputJpg).convolve({
width: 3,
height: 4,
kernel: [1, 2, 3, 4, 5, 6, 7, 8, 9]
});
});
}); });
}); });
}); });