mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 10:30:15 +02:00
Expose optional minAmplitude parameter of blur operation (#4172)
This commit is contained in:
parent
67a5854b89
commit
735fee74db
@ -250,6 +250,7 @@ When a `sigma` is provided, performs a slower, more accurate Gaussian blur.
|
|||||||
| [options] | <code>Object</code> \| <code>number</code> \| <code>Boolean</code> | | |
|
| [options] | <code>Object</code> \| <code>number</code> \| <code>Boolean</code> | | |
|
||||||
| [options.sigma] | <code>number</code> | | a value between 0.3 and 1000 representing the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`. |
|
| [options.sigma] | <code>number</code> | | a value between 0.3 and 1000 representing the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`. |
|
||||||
| [options.precision] | <code>string</code> | <code>"'integer'"</code> | How accurate the operation should be, one of: integer, float, approximate. |
|
| [options.precision] | <code>string</code> | <code>"'integer'"</code> | How accurate the operation should be, one of: integer, float, approximate. |
|
||||||
|
| [options.minAmplitude] | <code>number</code> | <code>0.2</code> | A value between 0.001 and 1. A smaller value will generate a larger, more accurate mask. |
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
```js
|
```js
|
||||||
|
File diff suppressed because one or more lines are too long
@ -227,6 +227,7 @@ const Sharp = function (input, options) {
|
|||||||
medianSize: 0,
|
medianSize: 0,
|
||||||
blurSigma: 0,
|
blurSigma: 0,
|
||||||
precision: 'integer',
|
precision: 'integer',
|
||||||
|
minAmpl: 0.2,
|
||||||
sharpenSigma: 0,
|
sharpenSigma: 0,
|
||||||
sharpenM1: 1,
|
sharpenM1: 1,
|
||||||
sharpenM2: 2,
|
sharpenM2: 2,
|
||||||
|
2
lib/index.d.ts
vendored
2
lib/index.d.ts
vendored
@ -1347,6 +1347,8 @@ declare namespace sharp {
|
|||||||
interface BlurOptions {
|
interface BlurOptions {
|
||||||
/** A value between 0.3 and 1000 representing the sigma of the Gaussian mask, where `sigma = 1 + radius / 2` */
|
/** A value between 0.3 and 1000 representing the sigma of the Gaussian mask, where `sigma = 1 + radius / 2` */
|
||||||
sigma: number;
|
sigma: number;
|
||||||
|
/** A value between 0.001 and 1. A smaller value will generate a larger, more accurate mask. */
|
||||||
|
minAmplitude?: number;
|
||||||
/** How accurate the operation should be, one of: integer, float, approximate. (optional, default "integer") */
|
/** How accurate the operation should be, one of: integer, float, approximate. (optional, default "integer") */
|
||||||
precision?: Precision | undefined;
|
precision?: Precision | undefined;
|
||||||
}
|
}
|
||||||
|
@ -381,6 +381,7 @@ function median (size) {
|
|||||||
* @param {Object|number|Boolean} [options]
|
* @param {Object|number|Boolean} [options]
|
||||||
* @param {number} [options.sigma] a value between 0.3 and 1000 representing the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`.
|
* @param {number} [options.sigma] a value between 0.3 and 1000 representing the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`.
|
||||||
* @param {string} [options.precision='integer'] How accurate the operation should be, one of: integer, float, approximate.
|
* @param {string} [options.precision='integer'] How accurate the operation should be, one of: integer, float, approximate.
|
||||||
|
* @param {number} [options.minAmplitude=0.2] A value between 0.001 and 1. A smaller value will generate a larger, more accurate mask.
|
||||||
* @returns {Sharp}
|
* @returns {Sharp}
|
||||||
* @throws {Error} Invalid parameters
|
* @throws {Error} Invalid parameters
|
||||||
*/
|
*/
|
||||||
@ -400,6 +401,13 @@ function blur (options) {
|
|||||||
throw is.invalidParameterError('precision', 'one of: integer, float, approximate', options.precision);
|
throw is.invalidParameterError('precision', 'one of: integer, float, approximate', options.precision);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ('minAmplitude' in options) {
|
||||||
|
if (is.number(options.minAmplitude) && is.inRange(options.minAmplitude, 0.001, 1)) {
|
||||||
|
this.options.minAmpl = options.minAmplitude;
|
||||||
|
} else {
|
||||||
|
throw is.invalidParameterError('minAmplitude', 'number between 0.001 and 1', options.minAmplitude);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is.defined(options)) {
|
if (!is.defined(options)) {
|
||||||
|
@ -144,7 +144,7 @@ namespace sharp {
|
|||||||
/*
|
/*
|
||||||
* Gaussian blur. Use sigma of -1.0 for fast blur.
|
* Gaussian blur. Use sigma of -1.0 for fast blur.
|
||||||
*/
|
*/
|
||||||
VImage Blur(VImage image, double const sigma, VipsPrecision precision) {
|
VImage Blur(VImage image, double const sigma, VipsPrecision precision, double const minAmpl) {
|
||||||
if (sigma == -1.0) {
|
if (sigma == -1.0) {
|
||||||
// Fast, mild blur - averages neighbouring pixels
|
// Fast, mild blur - averages neighbouring pixels
|
||||||
VImage blur = VImage::new_matrixv(3, 3,
|
VImage blur = VImage::new_matrixv(3, 3,
|
||||||
@ -156,7 +156,8 @@ namespace sharp {
|
|||||||
} else {
|
} else {
|
||||||
// Slower, accurate Gaussian blur
|
// Slower, accurate Gaussian blur
|
||||||
return StaySequential(image).gaussblur(sigma, VImage::option()
|
return StaySequential(image).gaussblur(sigma, VImage::option()
|
||||||
->set("precision", precision));
|
->set("precision", precision)
|
||||||
|
->set("min_ampl", minAmpl));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ namespace sharp {
|
|||||||
/*
|
/*
|
||||||
* Gaussian blur. Use sigma of -1.0 for fast blur.
|
* Gaussian blur. Use sigma of -1.0 for fast blur.
|
||||||
*/
|
*/
|
||||||
VImage Blur(VImage image, double const sigma, VipsPrecision precision);
|
VImage Blur(VImage image, double const sigma, VipsPrecision precision, double const minAmpl);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convolution with a kernel.
|
* Convolution with a kernel.
|
||||||
|
@ -592,7 +592,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
|
|
||||||
// Blur
|
// Blur
|
||||||
if (shouldBlur) {
|
if (shouldBlur) {
|
||||||
image = sharp::Blur(image, baton->blurSigma, baton->precision);
|
image = sharp::Blur(image, baton->blurSigma, baton->precision, baton->minAmpl);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unflatten the image
|
// Unflatten the image
|
||||||
@ -1542,6 +1542,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|||||||
baton->negateAlpha = sharp::AttrAsBool(options, "negateAlpha");
|
baton->negateAlpha = sharp::AttrAsBool(options, "negateAlpha");
|
||||||
baton->blurSigma = sharp::AttrAsDouble(options, "blurSigma");
|
baton->blurSigma = sharp::AttrAsDouble(options, "blurSigma");
|
||||||
baton->precision = sharp::AttrAsEnum<VipsPrecision>(options, "precision", VIPS_TYPE_PRECISION);
|
baton->precision = sharp::AttrAsEnum<VipsPrecision>(options, "precision", VIPS_TYPE_PRECISION);
|
||||||
|
baton->minAmpl = sharp::AttrAsDouble(options, "minAmpl");
|
||||||
baton->brightness = sharp::AttrAsDouble(options, "brightness");
|
baton->brightness = sharp::AttrAsDouble(options, "brightness");
|
||||||
baton->saturation = sharp::AttrAsDouble(options, "saturation");
|
baton->saturation = sharp::AttrAsDouble(options, "saturation");
|
||||||
baton->hue = sharp::AttrAsInt32(options, "hue");
|
baton->hue = sharp::AttrAsInt32(options, "hue");
|
||||||
|
@ -79,6 +79,7 @@ struct PipelineBaton {
|
|||||||
bool negateAlpha;
|
bool negateAlpha;
|
||||||
double blurSigma;
|
double blurSigma;
|
||||||
VipsPrecision precision;
|
VipsPrecision precision;
|
||||||
|
double minAmpl;
|
||||||
double brightness;
|
double brightness;
|
||||||
double saturation;
|
double saturation;
|
||||||
int hue;
|
int hue;
|
||||||
|
@ -63,6 +63,7 @@ sharp().blur();
|
|||||||
sharp().blur(1);
|
sharp().blur(1);
|
||||||
sharp().blur({ sigma: 1 });
|
sharp().blur({ sigma: 1 });
|
||||||
sharp().blur({ sigma: 1, precision: 'approximate' });
|
sharp().blur({ sigma: 1, precision: 'approximate' });
|
||||||
|
sharp().blur({ sigma: 1, minAmplitude: 0.8 });
|
||||||
|
|
||||||
sharp({
|
sharp({
|
||||||
create: {
|
create: {
|
||||||
|
@ -111,6 +111,16 @@ describe('Blur', function () {
|
|||||||
}, /Expected one of: integer, float, approximate for precision but received invalid of type string/);
|
}, /Expected one of: integer, float, approximate for precision but received invalid of type string/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('invalid minAmplitude', function () {
|
||||||
|
assert.throws(function () {
|
||||||
|
sharp(fixtures.inputJpg).blur({ sigma: 1, minAmplitude: 0 });
|
||||||
|
}, /Expected number between 0.001 and 1 for minAmplitude but received 0 of type number/);
|
||||||
|
|
||||||
|
assert.throws(function () {
|
||||||
|
sharp(fixtures.inputJpg).blur({ sigma: 1, minAmplitude: 1.01 });
|
||||||
|
}, /Expected number between 0.001 and 1 for minAmplitude but received 1.01 of type number/);
|
||||||
|
});
|
||||||
|
|
||||||
it('specific radius 10 and precision approximate', async () => {
|
it('specific radius 10 and precision approximate', async () => {
|
||||||
const approximate = await sharp(fixtures.inputJpg)
|
const approximate = await sharp(fixtures.inputJpg)
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
@ -125,6 +135,20 @@ describe('Blur', function () {
|
|||||||
await fixtures.assertSimilar(fixtures.expected('blur-10.jpg'), approximate);
|
await fixtures.assertSimilar(fixtures.expected('blur-10.jpg'), approximate);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('specific radius 10 and minAmplitude 0.01', async () => {
|
||||||
|
const minAmplitudeLow = await sharp(fixtures.inputJpg)
|
||||||
|
.resize(320, 240)
|
||||||
|
.blur({ sigma: 10, minAmplitude: 0.01 })
|
||||||
|
.toBuffer();
|
||||||
|
const minAmplitudeDefault = await sharp(fixtures.inputJpg)
|
||||||
|
.resize(320, 240)
|
||||||
|
.blur(10)
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
assert.notDeepEqual(minAmplitudeLow, minAmplitudeDefault);
|
||||||
|
await fixtures.assertSimilar(fixtures.expected('blur-10.jpg'), minAmplitudeLow);
|
||||||
|
});
|
||||||
|
|
||||||
it('options.sigma is required if options object is passed', function () {
|
it('options.sigma is required if options object is passed', function () {
|
||||||
assert.throws(function () {
|
assert.throws(function () {
|
||||||
sharp(fixtures.inputJpg).blur({ precision: 'invalid' });
|
sharp(fixtures.inputJpg).blur({ precision: 'invalid' });
|
||||||
|
Loading…
x
Reference in New Issue
Block a user