From 300b0d5ba1ce683ee6128fb4e19362edca774c4c Mon Sep 17 00:00:00 2001 From: Lovell Fuller Date: Tue, 10 Oct 2017 20:16:38 +0100 Subject: [PATCH] Doc refresh, changelog and dead code removal for #977 --- docs/api-resize.md | 18 ++----- docs/changelog.md | 4 ++ docs/index.md | 1 + lib/resize.js | 43 ++--------------- package.json | 3 +- src/pipeline.cc | 1 - src/pipeline.h | 1 - test/unit/interpolation.js | 99 -------------------------------------- test/unit/resize.js | 36 ++++++++++++++ 9 files changed, 51 insertions(+), 155 deletions(-) delete mode 100644 test/unit/interpolation.js diff --git a/docs/api-resize.md b/docs/api-resize.md index af1fdb5f9..aafc7e2aa 100644 --- a/docs/api-resize.md +++ b/docs/api-resize.md @@ -15,29 +15,20 @@ Resize image to `width` x `height`. By default, the resized image is centre cropped to the exact size specified. -Possible reduction kernels are: +Possible kernels are: - `nearest`: Use [nearest neighbour interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation). - `cubic`: Use a [Catmull-Rom spline](https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline). - `lanczos2`: Use a [Lanczos kernel](https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel) with `a=2`. - `lanczos3`: Use a Lanczos kernel with `a=3` (the default). -Possible enlargement interpolators are: - -- `nearest`: Use [nearest neighbour interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation). -- `bilinear`: Use [bilinear interpolation](http://en.wikipedia.org/wiki/Bilinear_interpolation), faster than bicubic but with less smooth results. -- `vertexSplitQuadraticBasisSpline`: Use the smoother [VSQBS interpolation](https://github.com/jcupitt/libvips/blob/master/libvips/resample/vsqbs.cpp#L48) to prevent "staircasing" when enlarging. -- `bicubic`: Use [bicubic interpolation](http://en.wikipedia.org/wiki/Bicubic_interpolation) (the default). -- `locallyBoundedBicubic`: Use [LBB interpolation](https://github.com/jcupitt/libvips/blob/master/libvips/resample/lbb.cpp#L100), which prevents some "[acutance](http://en.wikipedia.org/wiki/Acutance)" but typically reduces performance by a factor of 2. -- `nohalo`: Use [Nohalo interpolation](http://eprints.soton.ac.uk/268086/), which prevents acutance but typically reduces performance by a factor of 3. - **Parameters** - `width` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** pixels wide the resultant image should be. Use `null` or `undefined` to auto-scale the width to match the height. - `height` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** pixels high the resultant image should be. Use `null` or `undefined` to auto-scale the height to match the width. - `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)?** - `options.kernel` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** the kernel to use for image reduction. (optional, default `'lanczos3'`) - - `options.interpolator` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** the interpolator to use for image enlargement. (optional, default `'bicubic'`) + - `options.fastShrinkOnLoad` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** take greater advantage of the JPEG and WebP shrink-on-load feature, which can lead to a slight moiré pattern on some images. (optional, default `true`) - `options.centreSampling` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** use \*magick centre sampling convention instead of corner sampling. (optional, default `false`) - `options.centerSampling` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** alternative spelling of centreSampling. (optional, default `false`) @@ -46,15 +37,14 @@ Possible enlargement interpolators are: ```javascript sharp(inputBuffer) .resize(200, 300, { - kernel: sharp.kernel.lanczos2, - interpolator: sharp.interpolator.nohalo + kernel: sharp.kernel.nearest }) .background('white') .embed() .toFile('output.tiff') .then(function() { // output.tiff is a 200 pixels wide and 300 pixels high image - // containing a lanczos2/nohalo scaled version, embedded on a white canvas, + // containing a nearest-neighbour scaled version, embedded on a white canvas, // of the image data in inputBuffer }); ``` diff --git a/docs/changelog.md b/docs/changelog.md index de743a299..c72e1d337 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -18,6 +18,10 @@ Requires libvips v8.6.0. [#976](https://github.com/lovell/sharp/pull/976) [@mceachen](https://github.com/mceachen) +* Resize: switch to libvips' implementation, make fastShrinkOnLoad optional, remove interpolators. + [#977](https://github.com/lovell/sharp/pull/977) + [@jardakotesovec](https://github.com/jardakotesovec) + ### v0.18 - "*ridge*" Requires libvips v8.5.5. diff --git a/docs/index.md b/docs/index.md index fbe98cd87..431bd8523 100644 --- a/docs/index.md +++ b/docs/index.md @@ -103,6 +103,7 @@ the help and code contributions of the following people: * [Nicolas Coden](https://github.com/ncoden) * [Matt Parrish](https://github.com/pbomb) * [Matthew McEachen](https://github.com/mceachen) +* [Jarda Kotěšovec](https://github.com/jardakotesovec) Thank you! diff --git a/lib/resize.js b/lib/resize.js index dec0f95d1..1954cd73d 100644 --- a/lib/resize.js +++ b/lib/resize.js @@ -42,52 +42,27 @@ const kernel = { lanczos3: 'lanczos3' }; -/** - * Enlargement interpolators. - * @member - * @private - */ -const interpolator = { - nearest: 'nearest', - bilinear: 'bilinear', - bicubic: 'bicubic', - nohalo: 'nohalo', - lbb: 'lbb', - locallyBoundedBicubic: 'lbb', - vsqbs: 'vsqbs', - vertexSplitQuadraticBasisSpline: 'vsqbs' -}; - /** * Resize image to `width` x `height`. * By default, the resized image is centre cropped to the exact size specified. * - * Possible reduction kernels are: + * Possible kernels are: * - `nearest`: Use [nearest neighbour interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation). * - `cubic`: Use a [Catmull-Rom spline](https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline). * - `lanczos2`: Use a [Lanczos kernel](https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel) with `a=2`. * - `lanczos3`: Use a Lanczos kernel with `a=3` (the default). * - * Possible enlargement interpolators are: - * - `nearest`: Use [nearest neighbour interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation). - * - `bilinear`: Use [bilinear interpolation](http://en.wikipedia.org/wiki/Bilinear_interpolation), faster than bicubic but with less smooth results. - * - `vertexSplitQuadraticBasisSpline`: Use the smoother [VSQBS interpolation](https://github.com/jcupitt/libvips/blob/master/libvips/resample/vsqbs.cpp#L48) to prevent "staircasing" when enlarging. - * - `bicubic`: Use [bicubic interpolation](http://en.wikipedia.org/wiki/Bicubic_interpolation) (the default). - * - `locallyBoundedBicubic`: Use [LBB interpolation](https://github.com/jcupitt/libvips/blob/master/libvips/resample/lbb.cpp#L100), which prevents some "[acutance](http://en.wikipedia.org/wiki/Acutance)" but typically reduces performance by a factor of 2. - * - `nohalo`: Use [Nohalo interpolation](http://eprints.soton.ac.uk/268086/), which prevents acutance but typically reduces performance by a factor of 3. - * * @example * sharp(inputBuffer) * .resize(200, 300, { - * kernel: sharp.kernel.lanczos2, - * interpolator: sharp.interpolator.nohalo + * kernel: sharp.kernel.nearest * }) * .background('white') * .embed() * .toFile('output.tiff') * .then(function() { * // output.tiff is a 200 pixels wide and 300 pixels high image - * // containing a lanczos2/nohalo scaled version, embedded on a white canvas, + * // containing a nearest-neighbour scaled version, embedded on a white canvas, * // of the image data in inputBuffer * }); * @@ -95,7 +70,7 @@ const interpolator = { * @param {Number} [height] - pixels high the resultant image should be. Use `null` or `undefined` to auto-scale the height to match the width. * @param {Object} [options] * @param {String} [options.kernel='lanczos3'] - the kernel to use for image reduction. - * @param {String} [options.interpolator='bicubic'] - the interpolator to use for image enlargement. + * @param {Boolean} [options.fastShrinkOnLoad=true] - take greater advantage of the JPEG and WebP shrink-on-load feature, which can lead to a slight moiré pattern on some images. * @param {Boolean} [options.centreSampling=false] - use *magick centre sampling convention instead of corner sampling. * @param {Boolean} [options.centerSampling=false] - alternative spelling of centreSampling. * @returns {Sharp} @@ -129,20 +104,11 @@ function resize (width, height, options) { throw is.invalidParameterError('kernel', 'valid kernel name', options.kernel); } } - // Interpolator - if (is.defined(options.interpolator)) { - if (is.string(interpolator[options.interpolator])) { - this.options.interpolator = interpolator[options.interpolator]; - } else { - throw is.invalidParameterError('interpolator', 'valid interpolator name', options.interpolator); - } - } // Centre sampling options.centreSampling = is.bool(options.centerSampling) ? options.centerSampling : options.centreSampling; if (is.defined(options.centreSampling)) { this._setBooleanOption('centreSampling', options.centreSampling); } - // Shrink on load if (is.defined(options.fastShrinkOnLoad)) { this._setBooleanOption('fastShrinkOnLoad', options.fastShrinkOnLoad); @@ -307,5 +273,4 @@ module.exports = function (Sharp) { Sharp.gravity = gravity; Sharp.strategy = strategy; Sharp.kernel = kernel; - Sharp.interpolator = interpolator; }; diff --git a/package.json b/package.json index 6ad64d977..1928b4840 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,8 @@ "Guy Maliar ", "Nicolas Coden ", "Matt Parrish ", - "Matthew McEachen " + "Matthew McEachen ", + "Jarda Kotěšovec " ], "scripts": { "clean": "rm -rf node_modules/ build/ vendor/ coverage/ test/fixtures/output.*", diff --git a/src/pipeline.cc b/src/pipeline.cc index 16a8870d5..bcf1d394c 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -1140,7 +1140,6 @@ NAN_METHOD(pipeline) { baton->withoutEnlargement = AttrTo(options, "withoutEnlargement"); baton->crop = AttrTo(options, "crop"); baton->kernel = AttrAsStr(options, "kernel"); - baton->interpolator = AttrAsStr(options, "interpolator"); baton->centreSampling = AttrTo(options, "centreSampling"); baton->fastShrinkOnLoad = AttrTo(options, "fastShrinkOnLoad"); // Join Channel Options diff --git a/src/pipeline.h b/src/pipeline.h index 6146f479c..df834a317 100644 --- a/src/pipeline.h +++ b/src/pipeline.h @@ -67,7 +67,6 @@ struct PipelineBaton { int cropOffsetTop; bool premultiplied; std::string kernel; - std::string interpolator; bool centreSampling; bool fastShrinkOnLoad; double background[4]; diff --git a/test/unit/interpolation.js b/test/unit/interpolation.js deleted file mode 100644 index 85372f6be..000000000 --- a/test/unit/interpolation.js +++ /dev/null @@ -1,99 +0,0 @@ -'use strict'; - -const assert = require('assert'); - -const sharp = require('../../'); -const fixtures = require('../fixtures'); - -describe('Interpolators and kernels', function () { - describe('Reducers', function () { - [ - sharp.kernel.nearest, - sharp.kernel.cubic, - sharp.kernel.lanczos2, - sharp.kernel.lanczos3 - ].forEach(function (kernel) { - it(kernel, function (done) { - sharp(fixtures.inputJpg) - .resize(320, null, { kernel: kernel }) - .toBuffer(function (err, data, info) { - if (err) throw err; - assert.strictEqual('jpeg', info.format); - assert.strictEqual(320, info.width); - fixtures.assertSimilar(fixtures.inputJpg, data, done); - }); - }); - }); - }); - - describe('Enlargers', function () { - [ - sharp.interpolator.nearest, - sharp.interpolator.bilinear, - sharp.interpolator.bicubic, - sharp.interpolator.nohalo, - sharp.interpolator.locallyBoundedBicubic, - sharp.interpolator.vertexSplitQuadraticBasisSpline - ].forEach(function (interpolator) { - describe(interpolator, function () { - it('x and y', function (done) { - sharp(fixtures.inputTiff8BitDepth) - .resize(200, 200, { interpolator: interpolator }) - .png() - .toBuffer(function (err, data, info) { - if (err) throw err; - assert.strictEqual(200, info.width); - assert.strictEqual(200, info.height); - done(); - }); - }); - it('x only', function (done) { - sharp(fixtures.inputTiff8BitDepth) - .resize(200, 21, { interpolator: interpolator }) - .png() - .toBuffer(function (err, data, info) { - if (err) throw err; - assert.strictEqual(200, info.width); - assert.strictEqual(21, info.height); - done(); - }); - }); - it('y only', function (done) { - sharp(fixtures.inputTiff8BitDepth) - .resize(21, 200, { interpolator: interpolator }) - .png() - .toBuffer(function (err, data, info) { - if (err) throw err; - assert.strictEqual(21, info.width); - assert.strictEqual(200, info.height); - done(); - }); - }); - }); - }); - - it('nearest with integral factor', function (done) { - sharp(fixtures.inputTiff8BitDepth) - .resize(210, 210, { interpolator: 'nearest' }) - .png() - .toBuffer(function (err, data, info) { - if (err) throw err; - assert.strictEqual(210, info.width); - assert.strictEqual(210, info.height); - done(); - }); - }); - }); - - it('unknown kernel throws', function () { - assert.throws(function () { - sharp().resize(null, null, { kernel: 'unknown' }); - }); - }); - - it('unknown interpolator throws', function () { - assert.throws(function () { - sharp().resize(null, null, { interpolator: 'unknown' }); - }); - }); -}); diff --git a/test/unit/resize.js b/test/unit/resize.js index 4325090d7..b0421a57d 100644 --- a/test/unit/resize.js +++ b/test/unit/resize.js @@ -478,4 +478,40 @@ describe('Resize dimensions', function () { fixtures.assertSimilar(fixtures.expected('fast-shrink-on-load-true.png'), data, done); }); }); + + [ + sharp.kernel.nearest, + sharp.kernel.cubic, + sharp.kernel.lanczos2, + sharp.kernel.lanczos3 + ].forEach(function (kernel) { + it(`kernel ${kernel}`, function (done) { + sharp(fixtures.inputJpg) + .resize(320, null, { kernel: kernel }) + .toBuffer(function (err, data, info) { + if (err) throw err; + assert.strictEqual('jpeg', info.format); + assert.strictEqual(320, info.width); + fixtures.assertSimilar(fixtures.inputJpg, data, done); + }); + }); + }); + + it('nearest upsampling with integral factor', function (done) { + sharp(fixtures.inputTiff8BitDepth) + .resize(210, 210, { kernel: 'nearest' }) + .png() + .toBuffer(function (err, data, info) { + if (err) throw err; + assert.strictEqual(210, info.width); + assert.strictEqual(210, info.height); + done(); + }); + }); + + it('unknown kernel throws', function () { + assert.throws(function () { + sharp().resize(null, null, { kernel: 'unknown' }); + }); + }); });