Expand range of sharpen params to match libvips #3427

This commit is contained in:
Lovell Fuller 2022-12-07 09:28:01 +00:00
parent def99a294a
commit 2a71f1830f
5 changed files with 42 additions and 35 deletions

View File

@ -151,22 +151,24 @@ Returns **Sharp** 
## sharpen ## sharpen
Sharpen the image. Sharpen the image.
When used without parameters, performs a fast, mild sharpen of the output image. When used without parameters, performs a fast, mild sharpen of the output image.
When a `sigma` is provided, performs a slower, more accurate sharpen of the L channel in the LAB colour space. When a `sigma` is provided, performs a slower, more accurate sharpen of the L channel in the LAB colour space.
Separate control over the level of sharpening in "flat" and "jagged" areas is available. Fine-grained control over the level of sharpening in "flat" (m1) and "jagged" (m2) areas is available.
See [libvips sharpen][8] operation. See [libvips sharpen][8] operation.
### Parameters ### Parameters
* `options` **([Object][2] | [number][1])?** if present, is an Object with attributes or (deprecated) a number for `options.sigma`. * `options` **([Object][2] | [number][1])?** if present, is an Object with attributes
* `options.sigma` **[number][1]?** the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`. * `options.sigma` **[number][1]?** the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`, between 0.000001 and 10000
* `options.m1` **[number][1]** the level of sharpening to apply to "flat" areas. (optional, default `1.0`) * `options.m1` **[number][1]** the level of sharpening to apply to "flat" areas, between 0 and 1000000 (optional, default `1.0`)
* `options.m2` **[number][1]** the level of sharpening to apply to "jagged" areas. (optional, default `2.0`) * `options.m2` **[number][1]** the level of sharpening to apply to "jagged" areas, between 0 and 1000000 (optional, default `2.0`)
* `options.x1` **[number][1]** threshold between "flat" and "jagged" (optional, default `2.0`) * `options.x1` **[number][1]** threshold between "flat" and "jagged", between 0 and 1000000 (optional, default `2.0`)
* `options.y2` **[number][1]** maximum amount of brightening. (optional, default `10.0`) * `options.y2` **[number][1]** maximum amount of brightening, between 0 and 1000000 (optional, default `10.0`)
* `options.y3` **[number][1]** maximum amount of darkening. (optional, default `20.0`) * `options.y3` **[number][1]** maximum amount of darkening, between 0 and 1000000 (optional, default `20.0`)
* `flat` **[number][1]?** (deprecated) see `options.m1`. * `flat` **[number][1]?** (deprecated) see `options.m1`.
* `jagged` **[number][1]?** (deprecated) see `options.m2`. * `jagged` **[number][1]?** (deprecated) see `options.m2`.

View File

@ -9,6 +9,9 @@ Requires libvips v8.13.3
* Expose `interFrameMaxError` and `interPaletteMaxError` GIF optimisation properties. * Expose `interFrameMaxError` and `interPaletteMaxError` GIF optimisation properties.
[#3401](https://github.com/lovell/sharp/issues/3401) [#3401](https://github.com/lovell/sharp/issues/3401)
* Expand range of existing `sharpen` parameters to match libvips.
[#3427](https://github.com/lovell/sharp/issues/3427)
* Prevent possible race condition awaiting metadata of Stream-based input. * Prevent possible race condition awaiting metadata of Stream-based input.
[#3451](https://github.com/lovell/sharp/issues/3451) [#3451](https://github.com/lovell/sharp/issues/3451)

File diff suppressed because one or more lines are too long

View File

@ -205,9 +205,11 @@ function affine (matrix, options) {
/** /**
* Sharpen the image. * Sharpen the image.
*
* When used without parameters, performs a fast, mild sharpen of the output image. * When used without parameters, performs a fast, mild sharpen of the output image.
*
* When a `sigma` is provided, performs a slower, more accurate sharpen of the L channel in the LAB colour space. * When a `sigma` is provided, performs a slower, more accurate sharpen of the L channel in the LAB colour space.
* Separate control over the level of sharpening in "flat" and "jagged" areas is available. * Fine-grained control over the level of sharpening in "flat" (m1) and "jagged" (m2) areas is available.
* *
* See {@link https://www.libvips.org/API/current/libvips-convolution.html#vips-sharpen|libvips sharpen} operation. * See {@link https://www.libvips.org/API/current/libvips-convolution.html#vips-sharpen|libvips sharpen} operation.
* *
@ -229,13 +231,13 @@ function affine (matrix, options) {
* }) * })
* .toBuffer(); * .toBuffer();
* *
* @param {Object|number} [options] - if present, is an Object with attributes or (deprecated) a number for `options.sigma`. * @param {Object|number} [options] - if present, is an Object with attributes
* @param {number} [options.sigma] - the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`. * @param {number} [options.sigma] - the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`, between 0.000001 and 10000
* @param {number} [options.m1=1.0] - the level of sharpening to apply to "flat" areas. * @param {number} [options.m1=1.0] - the level of sharpening to apply to "flat" areas, between 0 and 1000000
* @param {number} [options.m2=2.0] - the level of sharpening to apply to "jagged" areas. * @param {number} [options.m2=2.0] - the level of sharpening to apply to "jagged" areas, between 0 and 1000000
* @param {number} [options.x1=2.0] - threshold between "flat" and "jagged" * @param {number} [options.x1=2.0] - threshold between "flat" and "jagged", between 0 and 1000000
* @param {number} [options.y2=10.0] - maximum amount of brightening. * @param {number} [options.y2=10.0] - maximum amount of brightening, between 0 and 1000000
* @param {number} [options.y3=20.0] - maximum amount of darkening. * @param {number} [options.y3=20.0] - maximum amount of darkening, between 0 and 1000000
* @param {number} [flat] - (deprecated) see `options.m1`. * @param {number} [flat] - (deprecated) see `options.m1`.
* @param {number} [jagged] - (deprecated) see `options.m2`. * @param {number} [jagged] - (deprecated) see `options.m2`.
* @returns {Sharp} * @returns {Sharp}
@ -268,44 +270,44 @@ function sharpen (options, flat, jagged) {
} }
} }
} else if (is.plainObject(options)) { } else if (is.plainObject(options)) {
if (is.number(options.sigma) && is.inRange(options.sigma, 0.01, 10000)) { if (is.number(options.sigma) && is.inRange(options.sigma, 0.000001, 10000)) {
this.options.sharpenSigma = options.sigma; this.options.sharpenSigma = options.sigma;
} else { } else {
throw is.invalidParameterError('options.sigma', 'number between 0.01 and 10000', options.sigma); throw is.invalidParameterError('options.sigma', 'number between 0.000001 and 10000', options.sigma);
} }
if (is.defined(options.m1)) { if (is.defined(options.m1)) {
if (is.number(options.m1) && is.inRange(options.m1, 0, 10000)) { if (is.number(options.m1) && is.inRange(options.m1, 0, 1000000)) {
this.options.sharpenM1 = options.m1; this.options.sharpenM1 = options.m1;
} else { } else {
throw is.invalidParameterError('options.m1', 'number between 0 and 10000', options.m1); throw is.invalidParameterError('options.m1', 'number between 0 and 1000000', options.m1);
} }
} }
if (is.defined(options.m2)) { if (is.defined(options.m2)) {
if (is.number(options.m2) && is.inRange(options.m2, 0, 10000)) { if (is.number(options.m2) && is.inRange(options.m2, 0, 1000000)) {
this.options.sharpenM2 = options.m2; this.options.sharpenM2 = options.m2;
} else { } else {
throw is.invalidParameterError('options.m2', 'number between 0 and 10000', options.m2); throw is.invalidParameterError('options.m2', 'number between 0 and 1000000', options.m2);
} }
} }
if (is.defined(options.x1)) { if (is.defined(options.x1)) {
if (is.number(options.x1) && is.inRange(options.x1, 0, 10000)) { if (is.number(options.x1) && is.inRange(options.x1, 0, 1000000)) {
this.options.sharpenX1 = options.x1; this.options.sharpenX1 = options.x1;
} else { } else {
throw is.invalidParameterError('options.x1', 'number between 0 and 10000', options.x1); throw is.invalidParameterError('options.x1', 'number between 0 and 1000000', options.x1);
} }
} }
if (is.defined(options.y2)) { if (is.defined(options.y2)) {
if (is.number(options.y2) && is.inRange(options.y2, 0, 10000)) { if (is.number(options.y2) && is.inRange(options.y2, 0, 1000000)) {
this.options.sharpenY2 = options.y2; this.options.sharpenY2 = options.y2;
} else { } else {
throw is.invalidParameterError('options.y2', 'number between 0 and 10000', options.y2); throw is.invalidParameterError('options.y2', 'number between 0 and 1000000', options.y2);
} }
} }
if (is.defined(options.y3)) { if (is.defined(options.y3)) {
if (is.number(options.y3) && is.inRange(options.y3, 0, 10000)) { if (is.number(options.y3) && is.inRange(options.y3, 0, 1000000)) {
this.options.sharpenY3 = options.y3; this.options.sharpenY3 = options.y3;
} else { } else {
throw is.invalidParameterError('options.y3', 'number between 0 and 10000', options.y3); throw is.invalidParameterError('options.y3', 'number between 0 and 1000000', options.y3);
} }
} }
} else { } else {

View File

@ -110,32 +110,32 @@ describe('Sharpen', function () {
it('invalid options.sigma', () => assert.throws( it('invalid options.sigma', () => assert.throws(
() => sharp().sharpen({ sigma: -1 }), () => sharp().sharpen({ sigma: -1 }),
/Expected number between 0\.01 and 10000 for options\.sigma but received -1 of type number/ /Expected number between 0\.000001 and 10000 for options\.sigma but received -1 of type number/
)); ));
it('invalid options.m1', () => assert.throws( it('invalid options.m1', () => assert.throws(
() => sharp().sharpen({ sigma: 1, m1: -1 }), () => sharp().sharpen({ sigma: 1, m1: -1 }),
/Expected number between 0 and 10000 for options\.m1 but received -1 of type number/ /Expected number between 0 and 1000000 for options\.m1 but received -1 of type number/
)); ));
it('invalid options.m2', () => assert.throws( it('invalid options.m2', () => assert.throws(
() => sharp().sharpen({ sigma: 1, m2: -1 }), () => sharp().sharpen({ sigma: 1, m2: -1 }),
/Expected number between 0 and 10000 for options\.m2 but received -1 of type number/ /Expected number between 0 and 1000000 for options\.m2 but received -1 of type number/
)); ));
it('invalid options.x1', () => assert.throws( it('invalid options.x1', () => assert.throws(
() => sharp().sharpen({ sigma: 1, x1: -1 }), () => sharp().sharpen({ sigma: 1, x1: -1 }),
/Expected number between 0 and 10000 for options\.x1 but received -1 of type number/ /Expected number between 0 and 1000000 for options\.x1 but received -1 of type number/
)); ));
it('invalid options.y2', () => assert.throws( it('invalid options.y2', () => assert.throws(
() => sharp().sharpen({ sigma: 1, y2: -1 }), () => sharp().sharpen({ sigma: 1, y2: -1 }),
/Expected number between 0 and 10000 for options\.y2 but received -1 of type number/ /Expected number between 0 and 1000000 for options\.y2 but received -1 of type number/
)); ));
it('invalid options.y3', () => assert.throws( it('invalid options.y3', () => assert.throws(
() => sharp().sharpen({ sigma: 1, y3: -1 }), () => sharp().sharpen({ sigma: 1, y3: -1 }),
/Expected number between 0 and 10000 for options\.y3 but received -1 of type number/ /Expected number between 0 and 1000000 for options\.y3 but received -1 of type number/
)); ));
it('sharpened image is larger than non-sharpened', function (done) { it('sharpened image is larger than non-sharpened', function (done) {