Compare commits

..

6 Commits

Author SHA1 Message Date
Lovell Fuller
8dac256096 Release v0.20.1 2018-03-17 14:04:35 +00:00
Lovell Fuller
8320da39c3 Changelog entry and doc refresh for #1161 2018-03-17 11:12:43 +00:00
Andrea Bianco
875937e3d8 Expose libvips' median filter operation (#1161) 2018-03-17 10:52:44 +00:00
Lovell Fuller
f880adbaac Bump dependencies ahead of v0.20.1 2018-03-16 20:46:08 +00:00
Lovell Fuller
48c5f86adb Improve install when global libvips below min version #1148 2018-03-13 20:37:42 +00:00
Lovell Fuller
f60f7dab12 Prevent error when cumulative rounding below target #1154 2018-03-13 19:42:10 +00:00
17 changed files with 253 additions and 93 deletions

View File

@@ -7,18 +7,19 @@
- [flip][3]
- [flop][4]
- [sharpen][5]
- [blur][6]
- [extend][7]
- [flatten][8]
- [trim][9]
- [gamma][10]
- [negate][11]
- [normalise][12]
- [normalize][13]
- [convolve][14]
- [threshold][15]
- [boolean][16]
- [linear][17]
- [median][6]
- [blur][7]
- [extend][8]
- [flatten][9]
- [trim][10]
- [gamma][11]
- [negate][12]
- [normalise][13]
- [normalize][14]
- [convolve][15]
- [threshold][16]
- [boolean][17]
- [linear][18]
## rotate
@@ -38,7 +39,7 @@ for example `rotate(x).extract(y)` will produce a different result to `extract(y
**Parameters**
- `angle` **[Number][18]** angle of rotation, must be a multiple of 90. (optional, default `auto`)
- `angle` **[Number][19]** angle of rotation, must be a multiple of 90. (optional, default `auto`)
**Examples**
@@ -54,7 +55,7 @@ const pipeline = sharp()
readableStream.pipe(pipeline);
```
- Throws **[Error][19]** Invalid parameters
- Throws **[Error][20]** Invalid parameters
Returns **Sharp**
@@ -68,11 +69,11 @@ Extract a region of the image.
**Parameters**
- `options` **[Object][20]**
- `options.left` **[Number][18]** zero-indexed offset from left edge
- `options.top` **[Number][18]** zero-indexed offset from top edge
- `options.width` **[Number][18]** dimension of extracted image
- `options.height` **[Number][18]** dimension of extracted image
- `options` **[Object][21]**
- `options.left` **[Number][19]** zero-indexed offset from left edge
- `options.top` **[Number][19]** zero-indexed offset from top edge
- `options.width` **[Number][19]** dimension of extracted image
- `options.height` **[Number][19]** dimension of extracted image
**Examples**
@@ -94,7 +95,7 @@ sharp(input)
});
```
- Throws **[Error][19]** Invalid parameters
- Throws **[Error][20]** Invalid parameters
Returns **Sharp**
@@ -105,7 +106,7 @@ The use of `flip` implies the removal of the EXIF `Orientation` tag, if any.
**Parameters**
- `flip` **[Boolean][21]** (optional, default `true`)
- `flip` **[Boolean][22]** (optional, default `true`)
Returns **Sharp**
@@ -116,7 +117,7 @@ The use of `flop` implies the removal of the EXIF `Orientation` tag, if any.
**Parameters**
- `flop` **[Boolean][21]** (optional, default `true`)
- `flop` **[Boolean][22]** (optional, default `true`)
Returns **Sharp**
@@ -129,12 +130,26 @@ Separate control over the level of sharpening in "flat" and "jagged" areas is av
**Parameters**
- `sigma` **[Number][18]?** the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`.
- `flat` **[Number][18]** the level of sharpening to apply to "flat" areas. (optional, default `1.0`)
- `jagged` **[Number][18]** the level of sharpening to apply to "jagged" areas. (optional, default `2.0`)
- `sigma` **[Number][19]?** the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`.
- `flat` **[Number][19]** the level of sharpening to apply to "flat" areas. (optional, default `1.0`)
- `jagged` **[Number][19]** the level of sharpening to apply to "jagged" areas. (optional, default `2.0`)
- Throws **[Error][19]** Invalid parameters
- Throws **[Error][20]** Invalid parameters
Returns **Sharp**
## median
Apply median filter.
When used without parameters the default window is 3x3.
**Parameters**
- `size` **[Number][19]** square mask size: size x size (optional, default `3`)
- Throws **[Error][20]** Invalid parameters
Returns **Sharp**
@@ -146,10 +161,10 @@ When a `sigma` is provided, performs a slower, more accurate Gaussian blur.
**Parameters**
- `sigma` **[Number][18]?** a value between 0.3 and 1000 representing the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`.
- `sigma` **[Number][19]?** a value between 0.3 and 1000 representing the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`.
- Throws **[Error][19]** Invalid parameters
- Throws **[Error][20]** Invalid parameters
Returns **Sharp**
@@ -160,11 +175,11 @@ This operation will always occur after resizing and extraction, if any.
**Parameters**
- `extend` **([Number][18] \| [Object][20])** single pixel count to add to all edges or an Object with per-edge counts
- `extend.top` **[Number][18]?**
- `extend.left` **[Number][18]?**
- `extend.bottom` **[Number][18]?**
- `extend.right` **[Number][18]?**
- `extend` **([Number][19] \| [Object][21])** single pixel count to add to all edges or an Object with per-edge counts
- `extend.top` **[Number][19]?**
- `extend.left` **[Number][19]?**
- `extend.bottom` **[Number][19]?**
- `extend.right` **[Number][19]?**
**Examples**
@@ -178,7 +193,7 @@ sharp(input)
...
```
- Throws **[Error][19]** Invalid parameters
- Throws **[Error][20]** Invalid parameters
Returns **Sharp**
@@ -188,7 +203,7 @@ Merge alpha transparency channel, if any, with `background`.
**Parameters**
- `flatten` **[Boolean][21]** (optional, default `true`)
- `flatten` **[Boolean][22]** (optional, default `true`)
Returns **Sharp**
@@ -198,10 +213,10 @@ Trim "boring" pixels from all edges that contain values within a percentage simi
**Parameters**
- `tolerance` **[Number][18]** value between 1 and 99 representing the percentage similarity. (optional, default `10`)
- `tolerance` **[Number][19]** value between 1 and 99 representing the percentage similarity. (optional, default `10`)
- Throws **[Error][19]** Invalid parameters
- Throws **[Error][20]** Invalid parameters
Returns **Sharp**
@@ -215,10 +230,10 @@ when applying a gamma correction.
**Parameters**
- `gamma` **[Number][18]** value between 1.0 and 3.0. (optional, default `2.2`)
- `gamma` **[Number][19]** value between 1.0 and 3.0. (optional, default `2.2`)
- Throws **[Error][19]** Invalid parameters
- Throws **[Error][20]** Invalid parameters
Returns **Sharp**
@@ -228,7 +243,7 @@ Produce the "negative" of the image.
**Parameters**
- `negate` **[Boolean][21]** (optional, default `true`)
- `negate` **[Boolean][22]** (optional, default `true`)
Returns **Sharp**
@@ -238,7 +253,7 @@ Enhance output image contrast by stretching its luminance to cover the full dyna
**Parameters**
- `normalise` **[Boolean][21]** (optional, default `true`)
- `normalise` **[Boolean][22]** (optional, default `true`)
Returns **Sharp**
@@ -248,7 +263,7 @@ Alternative spelling of normalise.
**Parameters**
- `normalize` **[Boolean][21]** (optional, default `true`)
- `normalize` **[Boolean][22]** (optional, default `true`)
Returns **Sharp**
@@ -258,12 +273,12 @@ Convolve the image with the specified kernel.
**Parameters**
- `kernel` **[Object][20]**
- `kernel.width` **[Number][18]** width of the kernel in pixels.
- `kernel.height` **[Number][18]** width of the kernel in pixels.
- `kernel.kernel` **[Array][22]<[Number][18]>** Array of length `width*height` containing the kernel values.
- `kernel.scale` **[Number][18]** the scale of the kernel in pixels. (optional, default `sum`)
- `kernel.offset` **[Number][18]** the offset of the kernel in pixels. (optional, default `0`)
- `kernel` **[Object][21]**
- `kernel.width` **[Number][19]** width of the kernel in pixels.
- `kernel.height` **[Number][19]** width of the kernel in pixels.
- `kernel.kernel` **[Array][23]<[Number][19]>** Array of length `width*height` containing the kernel values.
- `kernel.scale` **[Number][19]** the scale of the kernel in pixels. (optional, default `sum`)
- `kernel.offset` **[Number][19]** the offset of the kernel in pixels. (optional, default `0`)
**Examples**
@@ -281,7 +296,7 @@ sharp(input)
});
```
- Throws **[Error][19]** Invalid parameters
- Throws **[Error][20]** Invalid parameters
Returns **Sharp**
@@ -291,13 +306,13 @@ Any pixel value greather than or equal to the threshold value will be set to 255
**Parameters**
- `threshold` **[Number][18]** a value in the range 0-255 representing the level at which the threshold will be applied. (optional, default `128`)
- `options` **[Object][20]?**
- `options.greyscale` **[Boolean][21]** convert to single channel greyscale. (optional, default `true`)
- `options.grayscale` **[Boolean][21]** alternative spelling for greyscale. (optional, default `true`)
- `threshold` **[Number][19]** a value in the range 0-255 representing the level at which the threshold will be applied. (optional, default `128`)
- `options` **[Object][21]?**
- `options.greyscale` **[Boolean][22]** convert to single channel greyscale. (optional, default `true`)
- `options.grayscale` **[Boolean][22]** alternative spelling for greyscale. (optional, default `true`)
- Throws **[Error][19]** Invalid parameters
- Throws **[Error][20]** Invalid parameters
Returns **Sharp**
@@ -310,16 +325,16 @@ the selected bitwise boolean `operation` between the corresponding pixels of the
**Parameters**
- `operand` **([Buffer][23] \| [String][24])** Buffer containing image data or String containing the path to an image file.
- `operator` **[String][24]** one of `and`, `or` or `eor` to perform that bitwise operation, like the C logic operators `&`, `|` and `^` respectively.
- `options` **[Object][20]?**
- `options.raw` **[Object][20]?** describes operand when using raw pixel data.
- `options.raw.width` **[Number][18]?**
- `options.raw.height` **[Number][18]?**
- `options.raw.channels` **[Number][18]?**
- `operand` **([Buffer][24] \| [String][25])** Buffer containing image data or String containing the path to an image file.
- `operator` **[String][25]** one of `and`, `or` or `eor` to perform that bitwise operation, like the C logic operators `&`, `|` and `^` respectively.
- `options` **[Object][21]?**
- `options.raw` **[Object][21]?** describes operand when using raw pixel data.
- `options.raw.width` **[Number][19]?**
- `options.raw.height` **[Number][19]?**
- `options.raw.channels` **[Number][19]?**
- Throws **[Error][19]** Invalid parameters
- Throws **[Error][20]** Invalid parameters
Returns **Sharp**
@@ -329,11 +344,11 @@ Apply the linear formula a \* input + b to the image (levels adjustment)
**Parameters**
- `a` **[Number][18]** multiplier (optional, default `1.0`)
- `b` **[Number][18]** offset (optional, default `0.0`)
- `a` **[Number][19]** multiplier (optional, default `1.0`)
- `b` **[Number][19]** offset (optional, default `0.0`)
- Throws **[Error][19]** Invalid parameters
- Throws **[Error][20]** Invalid parameters
Returns **Sharp**
@@ -347,40 +362,42 @@ Returns **Sharp**
[5]: #sharpen
[6]: #blur
[6]: #median
[7]: #extend
[7]: #blur
[8]: #flatten
[8]: #extend
[9]: #trim
[9]: #flatten
[10]: #gamma
[10]: #trim
[11]: #negate
[11]: #gamma
[12]: #normalise
[12]: #negate
[13]: #normalize
[13]: #normalise
[14]: #convolve
[14]: #normalize
[15]: #threshold
[15]: #convolve
[16]: #boolean
[16]: #threshold
[17]: #linear
[17]: #boolean
[18]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[18]: #linear
[19]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[19]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[20]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[20]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[21]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[21]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[22]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
[22]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[23]: https://nodejs.org/api/buffer.html
[23]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
[24]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[24]: https://nodejs.org/api/buffer.html
[25]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String

View File

@@ -4,6 +4,19 @@
Requires libvips v8.6.1.
#### v0.20.1 - 17<sup>th</sup> March 2018
* Improve installation experience when a globally-installed libvips below the minimum required version is found.
[#1148](https://github.com/lovell/sharp/issues/1148)
* Prevent smartcrop error when cumulative rounding is below target size.
[#1154](https://github.com/lovell/sharp/issues/1154)
[@ralrom](https://github.com/ralrom)
* Expose libvips' median filter operation.
[#1161](https://github.com/lovell/sharp/pull/1161)
[@BiancoA](https://github.com/BiancoA)
#### v0.20.0 - 5<sup>th</sup> March 2018
* Add support for prebuilt sharp binaries on common platforms.

View File

@@ -18,8 +18,9 @@ const minimumLibvipsVersion = libvips.minimumLibvipsVersion;
const distBaseUrl = process.env.SHARP_DIST_BASE_URL || `https://github.com/lovell/sharp-libvips/releases/download/v${minimumLibvipsVersion}/`;
try {
const globalLibvipsVersion = libvips.globalLibvipsVersion();
if (globalLibvipsVersion) {
const useGlobalLibvips = libvips.useGlobalLibvips();
if (useGlobalLibvips) {
const globalLibvipsVersion = libvips.globalLibvipsVersion();
npmLog.info('sharp', `Detected globally-installed libvips v${globalLibvipsVersion}`);
npmLog.info('sharp', 'Building from source via node-gyp');
process.exit(1);

View File

@@ -153,6 +153,7 @@ const Sharp = function (input, options) {
background: [0, 0, 0, 255],
flatten: false,
negate: false,
medianSize: 0,
blurSigma: 0,
sharpenSigma: 0,
sharpenFlat: 1,

View File

@@ -156,6 +156,26 @@ function sharpen (sigma, flat, jagged) {
return this;
}
/**
* Apply median filter.
* When used without parameters the default window is 3x3.
* @param {Number} [size=3] square mask size: size x size
* @returns {Sharp}
* @throws {Error} Invalid parameters
*/
function median (size) {
if (!is.defined(size)) {
// No arguments: default to 3x3
this.options.medianSize = 3;
} else if (is.integer(size) && is.inRange(size, 1, 1000)) {
// Numeric argument: specific sigma
this.options.medianSize = size;
} else {
throw new Error('Invalid median size ' + size);
}
return this;
}
/**
* Blur the image.
* When used without parameters, performs a fast, mild blur of the output image.
@@ -444,6 +464,7 @@ module.exports = function (Sharp) {
flip,
flop,
sharpen,
median,
blur,
extend,
flatten,

View File

@@ -1,7 +1,7 @@
{
"name": "sharp",
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP and TIFF images",
"version": "0.20.0",
"version": "0.20.1",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://github.com/lovell/sharp",
"contributors": [
@@ -79,7 +79,7 @@
"dependencies": {
"color": "^3.0.0",
"detect-libc": "^1.0.3",
"nan": "^2.9.2",
"nan": "^2.10.0",
"fs-copy-file-sync": "^1.0.1",
"npmlog": "^4.1.2",
"prebuild-install": "^2.5.1",
@@ -91,11 +91,11 @@
"devDependencies": {
"async": "^2.6.0",
"cc": "^1.0.1",
"documentation": "^6.0.0",
"documentation": "^6.1.0",
"exif-reader": "^1.0.2",
"icc": "^1.0.0",
"mocha": "^5.0.1",
"nyc": "^11.5.0",
"mocha": "^5.0.4",
"nyc": "^11.6.0",
"prebuild": "^7.4.0",
"prebuild-ci": "^2.2.3",
"rimraf": "^2.6.2",

View File

@@ -359,6 +359,8 @@ class PipelineWorker : public Nan::AsyncWorker {
bool const shouldBlur = baton->blurSigma != 0.0;
bool const shouldConv = baton->convKernelWidth * baton->convKernelHeight > 0;
bool const shouldSharpen = baton->sharpenSigma != 0.0;
bool const shouldApplyMedian = baton->medianSize > 0;
bool const shouldPremultiplyAlpha = HasAlpha(image) &&
(shouldResize || shouldBlur || shouldConv || shouldSharpen || shouldOverlayWithAlpha);
@@ -482,6 +484,12 @@ class PipelineWorker : public Nan::AsyncWorker {
image = image.extract_area(left, top, width, height);
} else {
// Attention-based or Entropy-based crop
if (baton->width > image.width()) {
baton->width = image.width();
}
if (baton->height > image.height()) {
baton->height = image.height();
}
image = image.tilecache(VImage::option()
->set("access", baton->accessMethod)
->set("threaded", TRUE));
@@ -538,7 +546,10 @@ class PipelineWorker : public Nan::AsyncWorker {
image = image.embed(baton->extendLeft, baton->extendTop, baton->width, baton->height,
VImage::option()->set("extend", VIPS_EXTEND_BACKGROUND)->set("background", background));
}
// Median - must happen before blurring, due to the utility of blurring after thresholding
if (shouldApplyMedian) {
image = image.median(baton->medianSize);
}
// Threshold - must happen before blurring, due to the utility of blurring after thresholding
if (baton->threshold != 0) {
image = sharp::Threshold(image, baton->threshold, baton->thresholdGrayscale);
@@ -1188,6 +1199,7 @@ NAN_METHOD(pipeline) {
baton->flatten = AttrTo<bool>(options, "flatten");
baton->negate = AttrTo<bool>(options, "negate");
baton->blurSigma = AttrTo<double>(options, "blurSigma");
baton->medianSize = AttrTo<uint32_t>(options, "medianSize");
baton->sharpenSigma = AttrTo<double>(options, "sharpenSigma");
baton->sharpenFlat = AttrTo<double>(options, "sharpenFlat");
baton->sharpenJagged = AttrTo<double>(options, "sharpenJagged");

View File

@@ -73,6 +73,7 @@ struct PipelineBaton {
bool flatten;
bool negate;
double blurSigma;
int medianSize;
double sharpenSigma;
double sharpenFlat;
double sharpenJagged;
@@ -157,6 +158,7 @@ struct PipelineBaton {
flatten(false),
negate(false),
blurSigma(0.0),
medianSize(0),
sharpenSigma(0.0),
sharpenFlat(1.0),
sharpenJagged(2.0),

BIN
test/fixtures/expected/median_1.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
test/fixtures/expected/median_3.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 833 B

BIN
test/fixtures/expected/median_5.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 B

BIN
test/fixtures/expected/median_color.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -69,6 +69,8 @@ module.exports = {
inputJpgOverlayLayer2: getPath('alpha-layer-2-ink.jpg'),
inputJpgTruncated: getPath('truncated.jpg'), // head -c 10000 2569067123_aca715a2ee_o.jpg > truncated.jpg
inputJpgCenteredImage: getPath('centered_image.jpeg'),
inputJpgRandom: getPath('random.jpg'), // convert -size 200x200 xc: +noise Random random.jpg
inputJpgThRandom: getPath('thRandom.jpg'), // convert random.jpg -channel G -threshold 5% -separate +channel -negate thRandom.jpg
inputPng: getPath('50020484-00001.png'), // http://c.searspartsdirect.com/lis_png/PLDM/50020484-00001.png
inputPngWithTransparency: getPath('blackbug.png'), // public domain

BIN
test/fixtures/random.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
test/fixtures/thRandom.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -159,7 +159,7 @@ describe('Crop', function () {
});
});
it('Skip crop when post-resize dimensions are at or below target dimensions', function () {
it('Skip crop when post-resize dimensions are at target', function () {
return sharp(fixtures.inputJpg)
.resize(1600, 1200)
.toBuffer()
@@ -177,6 +177,25 @@ describe('Crop', function () {
});
});
it('Clamp before crop when one post-resize dimension is below target', function () {
return sharp(fixtures.inputJpg)
.resize(1024, 1034)
.toBuffer()
.then(function (input) {
return sharp(input)
.rotate(270)
.resize(256)
.crop(sharp.strategy.entropy)
.toBuffer({ resolveWithObject: true })
.then(function (result) {
assert.strictEqual(256, result.info.width);
assert.strictEqual(253, result.info.height);
assert.strictEqual(0, result.info.cropOffsetLeft);
assert.strictEqual(0, result.info.cropOffsetTop);
});
});
});
describe('Entropy-based strategy', function () {
it('JPEG', function (done) {
sharp(fixtures.inputJpg)

72
test/unit/median.js Normal file
View File

@@ -0,0 +1,72 @@
'use strict';
const assert = require('assert');
const sharp = require('../../');
const fixtures = require('../fixtures');
describe('Median filter', function () {
it('1x1 window', function (done) {
sharp(fixtures.inputJpgThRandom)
.median(1)
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('jpeg', info.format);
assert.strictEqual(200, info.width);
assert.strictEqual(200, info.height);
fixtures.assertSimilar(fixtures.expected('median_1.jpg'), data, done);
});
});
it('3x3 window', function (done) {
sharp(fixtures.inputJpgThRandom)
.median(3)
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('jpeg', info.format);
assert.strictEqual(200, info.width);
assert.strictEqual(200, info.height);
fixtures.assertSimilar(fixtures.expected('median_3.jpg'), data, done);
});
});
it('5x5 window', function (done) {
sharp(fixtures.inputJpgThRandom)
.median(5)
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('jpeg', info.format);
assert.strictEqual(200, info.width);
assert.strictEqual(200, info.height);
fixtures.assertSimilar(fixtures.expected('median_5.jpg'), data, done);
});
});
it('color image', function (done) {
sharp(fixtures.inputJpgRandom)
.median(5)
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('jpeg', info.format);
assert.strictEqual(200, info.width);
assert.strictEqual(200, info.height);
fixtures.assertSimilar(fixtures.expected('median_color.jpg'), data, done);
});
});
it('no windows size', function (done) {
sharp(fixtures.inputJpgThRandom)
.median()
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('jpeg', info.format);
assert.strictEqual(200, info.width);
assert.strictEqual(200, info.height);
fixtures.assertSimilar(fixtures.expected('median_3.jpg'), data, done);
});
});
it('invalid radius', function () {
assert.throws(function () {
sharp(fixtures.inputJpg).median(0.1);
});
});
});