Compare commits

..

11 Commits

Author SHA1 Message Date
Lovell Fuller
9f384e1c6c Release v0.28.3 2021-05-24 16:26:34 +01:00
Lovell Fuller
35e8c8b25e Docs: ensure ops without examples are indexed 2021-05-24 16:24:04 +01:00
Lovell Fuller
dc53f1baff Bump deps 2021-05-24 16:08:10 +01:00
Lovell Fuller
70139600b5 Docs: fix CLAHE link 2021-05-23 18:49:54 +01:00
Lovell Fuller
1b4d1521e0 Docs: cross-link removeAlpha and flatten 2021-05-23 18:46:23 +01:00
Lovell Fuller
ed3377cb2d Docs: add parameter names to search keywords 2021-05-23 18:02:18 +01:00
Lovell Fuller
d72852b3aa Docs: changelog entry for #2726 2021-05-23 17:45:43 +01:00
Brad Parham
4b6b6189bf Add contrast limiting adaptive histogram equalization (CLAHE) operator (#2726) 2021-05-23 17:36:04 +01:00
Lovell Fuller
b69a54fc75 Ensure presence of libvips before invoking node-gyp 2021-05-16 19:40:43 +01:00
Lovell Fuller
81e388a4cc Docs: composite supports failOnError and limitInputPixels 2021-05-15 14:52:33 +01:00
Lovell Fuller
5bd5e5052a Skip shrink-on-load for multi-page WebP #2714 2021-05-15 14:13:16 +01:00
30 changed files with 334 additions and 37 deletions

View File

@@ -4,6 +4,8 @@
Remove alpha channel, if any. This is a no-op if the image does not have an alpha channel.
See also [flatten][1].
### Examples
```javascript
@@ -25,7 +27,7 @@ This is a no-op if the image already has an alpha channel.
### Parameters
* `alpha` **[number][1]** alpha transparency level (0=fully-transparent, 1=fully-opaque) (optional, default `1`)
* `alpha` **[number][2]** alpha transparency level (0=fully-transparent, 1=fully-opaque) (optional, default `1`)
### Examples
@@ -43,7 +45,7 @@ const rgba = await sharp(rgb)
.toBuffer();
```
* Throws **[Error][2]** Invalid alpha transparency level
* Throws **[Error][3]** Invalid alpha transparency level
Returns **Sharp**
@@ -57,7 +59,7 @@ Extract a single channel from a multi-channel image.
### Parameters
* `channel` **([number][1] | [string][3])** zero-indexed channel/band number to extract, or `red`, `green`, `blue` or `alpha`.
* `channel` **([number][2] | [string][4])** zero-indexed channel/band number to extract, or `red`, `green`, `blue` or `alpha`.
### Examples
@@ -71,7 +73,7 @@ sharp(input)
});
```
* Throws **[Error][2]** Invalid channel
* Throws **[Error][3]** Invalid channel
Returns **Sharp**
@@ -90,12 +92,12 @@ For raw pixel input, the `options` object should contain a `raw` attribute, whic
### Parameters
* `images` **([Array][4]<([string][3] | [Buffer][5])> | [string][3] | [Buffer][5])** one or more images (file paths, Buffers).
* `options` **[Object][6]** image options, see `sharp()` constructor.
* `images` **([Array][5]<([string][4] | [Buffer][6])> | [string][4] | [Buffer][6])** one or more images (file paths, Buffers).
* `options` **[Object][7]** image options, see `sharp()` constructor.
<!---->
* Throws **[Error][2]** Invalid parameters
* Throws **[Error][3]** Invalid parameters
Returns **Sharp**
@@ -105,7 +107,7 @@ Perform a bitwise boolean operation on all input image channels (bands) to produ
### Parameters
* `boolOp` **[string][3]** one of `and`, `or` or `eor` to perform that bitwise operation, like the C logic operators `&`, `|` and `^` respectively.
* `boolOp` **[string][4]** one of `and`, `or` or `eor` to perform that bitwise operation, like the C logic operators `&`, `|` and `^` respectively.
### Examples
@@ -119,18 +121,20 @@ sharp('3-channel-rgb-input.png')
});
```
* Throws **[Error][2]** Invalid parameters
* Throws **[Error][3]** Invalid parameters
Returns **Sharp**
[1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[1]: /api-operation#flatten
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[5]: https://nodejs.org/api/buffer.html
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[6]: https://nodejs.org/api/buffer.html
[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object

View File

@@ -41,6 +41,8 @@ and [https://www.cairographics.org/operators/][2]
* `images[].raw.width` **[Number][7]?**
* `images[].raw.height` **[Number][7]?**
* `images[].raw.channels` **[Number][7]?**
* `images[].failOnError` **[boolean][9]** @see [constructor parameters][10] (optional, default `true`)
* `images[].limitInputPixels` **([number][7] | [boolean][9])** @see [constructor parameters][10] (optional, default `268402689`)
### Examples
@@ -61,7 +63,7 @@ sharp('input.png')
});
```
* Throws **[Error][10]** Invalid parameters
* Throws **[Error][11]** Invalid parameters
Returns **Sharp**
@@ -87,4 +89,6 @@ Returns **Sharp**
[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[10]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[10]: /api-constructor#parameters
[11]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error

View File

@@ -176,6 +176,8 @@ Returns **Sharp**
Merge alpha transparency channel, if any, with a background, then remove the alpha channel.
See also [removeAlpha][8].
### Parameters
* `options` **[Object][2]?**
@@ -186,7 +188,7 @@ Merge alpha transparency channel, if any, with a background, then remove the alp
```javascript
await sharp(rgbaInput)
.flatten({background: '#F0A703' })
.flatten({ background: '#F0A703' })
.toBuffer();
```
@@ -243,6 +245,33 @@ Alternative spelling of normalise.
Returns **Sharp**
## clahe
Perform contrast limiting adaptive histogram equalization
[CLAHE][9].
This will, in general, enhance the clarity of the image by bringing out darker details.
### Parameters
* `options` **[Object][2]**
* `options.width` **[number][1]** integer width of the region in pixels.
* `options.height` **[number][1]** integer height of the region in pixels.
* `options.maxSlope` **[number][1]** maximum value for the slope of the
cumulative histogram. A value of 0 disables contrast limiting. Valid values
are integers in the range 0-100 (inclusive) (optional, default `3`)
<!---->
* Throws **[Error][5]** Invalid parameters
Returns **Sharp**
**Meta**
* **since**: 0.28.3
## convolve
Convolve the image with the specified kernel.
@@ -252,7 +281,7 @@ Convolve the image with the specified kernel.
* `kernel` **[Object][2]**
* `kernel.width` **[number][1]** width of the kernel in pixels.
* `kernel.height` **[number][1]** width of the kernel in pixels.
* `kernel.height` **[number][1]** height of the kernel in pixels.
* `kernel.kernel` **[Array][7]<[number][1]>** Array of length `width*height` containing the kernel values.
* `kernel.scale` **[number][1]** the scale of the kernel in pixels. (optional, default `sum`)
* `kernel.offset` **[number][1]** the offset of the kernel in pixels. (optional, default `0`)
@@ -304,7 +333,7 @@ the selected bitwise boolean `operation` between the corresponding pixels of the
### Parameters
* `operand` **([Buffer][8] | [string][3])** Buffer containing image data or string containing the path to an image file.
* `operand` **([Buffer][10] | [string][3])** Buffer containing image data or string containing the path to an image file.
* `operator` **[string][3]** one of `and`, `or` or `eor` to perform that bitwise operation, like the C logic operators `&`, `|` and `^` respectively.
* `options` **[Object][2]?**
@@ -421,4 +450,8 @@ Returns **Sharp**
[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
[8]: https://nodejs.org/api/buffer.html
[8]: /api-channel#removealpha
[9]: https://en.wikipedia.org/wiki/Adaptive_histogram_equalization#Contrast_Limited_AHE
[10]: https://nodejs.org/api/buffer.html

View File

@@ -4,6 +4,17 @@
Requires libvips v8.10.6
### v0.28.3 - 24th May 2021
* Ensure presence of libvips, vendored or global, before invoking node-gyp.
* Skip shrink-on-load for multi-page WebP.
[#2714](https://github.com/lovell/sharp/issues/2714)
* Add contrast limiting adaptive histogram equalization (CLAHE) operator.
[#2726](https://github.com/lovell/sharp/pull/2726)
[@baparham](https://github.com/baparham)
### v0.28.2 - 10th May 2021
* Allow `withMetadata` to set `density`.

View File

@@ -19,7 +19,7 @@
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="https://pixel.plumbing/px/72x72/sharp-logo.svg">
<link rel="apple-touch-icon-precomposed" href="https://pixel.plumbing/px/57x57/sharp-logo.svg">
<link rel="author" href="/humans.txt" type="text/plain">
<link rel="preload" href="https://cdn.jsdelivr.net/gh/lovell/sharp@v0.28.2/docs/README.md" as="fetch" type="text/markdown" crossorigin>
<link rel="preload" href="https://cdn.jsdelivr.net/gh/lovell/sharp@v0.28.3/docs/README.md" as="fetch" type="text/markdown" crossorigin>
<link rel="preload" href="https://cdn.jsdelivr.net/gh/lovell/sharp@master/docs/image/sharp-logo.svg" as="image" type="image/svg+xml" crossorigin>
<link rel="dns-prefetch" href="https://pixel.plumbing">
<link rel="dns-prefetch" href="https://www.google-analytics.com">
@@ -139,7 +139,7 @@
docuteApiTitlePlugin,
docuteApiSearchPlugin
],
sourcePath: 'https://cdn.jsdelivr.net/gh/lovell/sharp@v0.28.2/docs',
sourcePath: 'https://cdn.jsdelivr.net/gh/lovell/sharp@v0.28.3/docs',
nav: [
{
title: 'Funding',

File diff suppressed because one or more lines are too long

View File

@@ -2,7 +2,7 @@
const fs = require('fs');
const path = require('path');
const { extractDescription, extractKeywords } = require('./extract');
const { extractDescription, extractKeywords, extractParameters } = require('./extract');
const searchIndex = [];
@@ -37,18 +37,19 @@ for (const match of matches) {
].forEach((section) => {
const contents = fs.readFileSync(path.join(__dirname, '..', `api-${section}.md`), 'utf8');
const matches = contents.matchAll(
/\n## (?<title>[A-Za-z]+)\n\n(?<firstparagraph>.+?)\n\n/gs
/\n## (?<title>[A-Za-z]+)\n\n(?<firstparagraph>.+?)\n\n(?<parameters>### Parameters.+?Returns)?/gs
);
for (const match of matches) {
const { title, firstparagraph } = match.groups;
const { title, firstparagraph, parameters } = match.groups;
const description = firstparagraph.startsWith('###')
? 'Constructor'
: extractDescription(firstparagraph);
const parameterNames = parameters ? extractParameters(parameters) : '';
searchIndex.push({
t: title,
d: description,
k: extractKeywords(`${title} ${description}`),
k: extractKeywords(`${title} ${description} ${parameterNames}`),
l: `/api-${section}#${title.toLowerCase()}`
});
}

View File

@@ -4,6 +4,7 @@ const stopWords = require('./stop-words');
const extractDescription = (str) =>
str
.replace(/### Examples.*/sg, '')
.replace(/\(http[^)]+/g, '')
.replace(/\s+/g, ' ')
.replace(/[^A-Za-z0-9_/\-,. ]/g, '')
@@ -11,6 +12,11 @@ const extractDescription = (str) =>
.substr(0, 180)
.trim();
const extractParameters = (str) =>
[...str.matchAll(/options\.(?<name>[^.`]+)/gs)]
.map((match) => match.groups.name)
.join(' ');
const extractKeywords = (str) =>
[
...new Set(
@@ -21,4 +27,4 @@ const extractKeywords = (str) =>
)
].join(' ');
module.exports = { extractDescription, extractKeywords };
module.exports = { extractDescription, extractKeywords, extractParameters };

View File

@@ -17,6 +17,7 @@ module.exports = [
'before',
'both',
'call',
'callback',
'can',
'containing',
'default',
@@ -26,6 +27,7 @@ module.exports = [
'ensure',
'etc',
'every',
'except',
'for',
'from',
'get',
@@ -49,12 +51,16 @@ module.exports = [
'occur',
'occurs',
'options',
'other',
'out',
'over',
'perform',
'performs',
'provide',
'provided',
'ready',
'requires',
'returned',
'same',
'see',
'set',
@@ -67,9 +73,11 @@ module.exports = [
'supported',
'sure',
'take',
'than',
'that',
'the',
'their',
'then',
'there',
'therefore',
'these',

11
install/can-compile.js Normal file
View File

@@ -0,0 +1,11 @@
'use strict';
const libvips = require('../lib/libvips');
try {
if (!(libvips.useGlobalLibvips() || libvips.hasVendoredLibvips())) {
process.exitCode = 1;
}
} catch (err) {
process.exitCode = 1;
}

View File

@@ -43,7 +43,6 @@ const fail = function (err) {
if (err.code === 'EACCES') {
libvips.log('Are you trying to install as a root or sudo user? Try again with the --unsafe-perm flag');
}
libvips.log('Attempting to build from source via node-gyp but this may fail due to the above error');
libvips.log('Please see https://sharp.pixelplumbing.com/install for required dependencies');
process.exit(1);
};

View File

@@ -15,6 +15,8 @@ const bool = {
/**
* Remove alpha channel, if any. This is a no-op if the image does not have an alpha channel.
*
* See also {@link /api-operation#flatten|flatten}.
*
* @example
* sharp('rgba.png')
* .removeAlpha()

View File

@@ -89,6 +89,8 @@ const blend = {
* @param {Number} [images[].raw.width]
* @param {Number} [images[].raw.height]
* @param {Number} [images[].raw.channels]
* @param {boolean} [images[].failOnError=true] - @see {@link /api-constructor#parameters|constructor parameters}
* @param {number|boolean} [images[].limitInputPixels=268402689] - @see {@link /api-constructor#parameters|constructor parameters}
* @returns {Sharp}
* @throws {Error} Invalid parameters
*/

View File

@@ -216,6 +216,9 @@ const Sharp = function (input, options) {
gammaOut: 0,
greyscale: false,
normalise: false,
claheWidth: 0,
claheHeight: 0,
claheMaxSlope: 3,
brightness: 1,
saturation: 1,
hue: 0,

View File

@@ -270,9 +270,11 @@ function blur (sigma) {
/**
* Merge alpha transparency channel, if any, with a background, then remove the alpha channel.
*
* See also {@link /api-channel#removealpha|removeAlpha}.
*
* @example
* await sharp(rgbaInput)
* .flatten({background: '#F0A703' })
* .flatten({ background: '#F0A703' })
* .toBuffer();
*
* @param {Object} [options]
@@ -350,6 +352,47 @@ function normalize (normalize) {
return this.normalise(normalize);
}
/**
* Perform contrast limiting adaptive histogram equalization
* {@link https://en.wikipedia.org/wiki/Adaptive_histogram_equalization#Contrast_Limited_AHE|CLAHE}.
*
* This will, in general, enhance the clarity of the image by bringing out darker details.
*
* @since 0.28.3
*
* @param {Object} options
* @param {number} options.width - integer width of the region in pixels.
* @param {number} options.height - integer height of the region in pixels.
* @param {number} [options.maxSlope=3] - maximum value for the slope of the
* cumulative histogram. A value of 0 disables contrast limiting. Valid values
* are integers in the range 0-100 (inclusive)
* @returns {Sharp}
* @throws {Error} Invalid parameters
*/
function clahe (options) {
if (!is.plainObject(options)) {
throw is.invalidParameterError('options', 'plain object', options);
}
if (!('width' in options) || !is.integer(options.width) || options.width <= 0) {
throw is.invalidParameterError('width', 'integer above zero', options.width);
} else {
this.options.claheWidth = options.width;
}
if (!('height' in options) || !is.integer(options.height) || options.height <= 0) {
throw is.invalidParameterError('height', 'integer above zero', options.height);
} else {
this.options.claheHeight = options.height;
}
if (!is.defined(options.maxSlope)) {
this.options.claheMaxSlope = 3;
} else if (!is.integer(options.maxSlope) || options.maxSlope < 0 || options.maxSlope > 100) {
throw is.invalidParameterError('maxSlope', 'integer 0-100', options.maxSlope);
} else {
this.options.claheMaxSlope = options.maxSlope;
}
return this;
}
/**
* Convolve the image with the specified kernel.
*
@@ -368,7 +411,7 @@ function normalize (normalize) {
*
* @param {Object} kernel
* @param {number} kernel.width - width of the kernel in pixels.
* @param {number} kernel.height - width of the kernel in pixels.
* @param {number} kernel.height - height of the kernel in pixels.
* @param {Array<number>} kernel.kernel - Array of length `width*height` containing the kernel values.
* @param {number} [kernel.scale=sum] - the scale of the kernel in pixels.
* @param {number} [kernel.offset=0] - the offset of the kernel in pixels.
@@ -594,6 +637,7 @@ module.exports = function (Sharp) {
negate,
normalise,
normalize,
clahe,
convolve,
threshold,
boolean,

View File

@@ -1,7 +1,7 @@
{
"name": "sharp",
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, AVIF and TIFF images",
"version": "0.28.2",
"version": "0.28.3",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://github.com/lovell/sharp",
"contributors": [
@@ -76,10 +76,11 @@
"Leon Radley <leon@radley.se>",
"alza54 <alza54@thiocod.in>",
"Jacob Smith <jacob@frende.me>",
"Michael Nutt <michael@nutt.im>"
"Michael Nutt <michael@nutt.im>",
"Brad Parham <baparham@gmail.com>"
],
"scripts": {
"install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node-gyp rebuild && node install/dll-copy)",
"install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node install/can-compile && node-gyp rebuild && node install/dll-copy)",
"clean": "rm -rf node_modules/ build/ vendor/ .nyc_output/ coverage/ test/fixtures/output.*",
"test": "npm run test-lint && npm run test-unit && npm run test-licensing",
"test-lint": "semistandard && cpplint",
@@ -122,7 +123,7 @@
"dependencies": {
"color": "^3.1.3",
"detect-libc": "^1.0.3",
"node-addon-api": "^3.1.0",
"node-addon-api": "^3.2.0",
"prebuild-install": "^6.1.2",
"semver": "^7.3.5",
"simple-get": "^3.1.0",

View File

@@ -92,6 +92,13 @@ namespace sharp {
return image;
}
/*
* Contrast limiting adapative histogram equalization (CLAHE)
*/
VImage Clahe(VImage image, int const width, int const height, int const maxSlope) {
return image.hist_local(width, height, VImage::option()->set("max_slope", maxSlope));
}
/*
* Gamma encoding/decoding
*/

View File

@@ -35,6 +35,11 @@ namespace sharp {
*/
VImage Normalise(VImage image);
/*
* Contrast limiting adapative histogram equalization (CLAHE)
*/
VImage Clahe(VImage image, int const width, int const height, int const maxSlope);
/*
* Gamma encoding/decoding
*/

View File

@@ -227,7 +227,7 @@ class PipelineWorker : public Napi::AsyncWorker {
xshrink == yshrink && xshrink >= 2 * shrink_on_load_factor &&
(inputImageType == sharp::ImageType::JPEG || inputImageType == sharp::ImageType::WEBP) &&
baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimThreshold == 0.0 &&
image.width() > 3 && image.height() > 3
image.width() > 3 && image.height() > 3 && baton->input->pages == 1
) {
if (xshrink >= 8 * shrink_on_load_factor) {
xfactor = xfactor / 8;
@@ -345,6 +345,7 @@ class PipelineWorker : public Napi::AsyncWorker {
bool const shouldApplyMedian = baton->medianSize > 0;
bool const shouldComposite = !baton->composite.empty();
bool const shouldModulate = baton->brightness != 1.0 || baton->saturation != 1.0 || baton->hue != 0.0;
bool const shouldApplyClahe = baton->claheWidth != 0 && baton->claheHeight != 0;
if (shouldComposite && !sharp::HasAlpha(image)) {
image = sharp::EnsureAlpha(image, 1);
@@ -650,6 +651,11 @@ class PipelineWorker : public Napi::AsyncWorker {
image = sharp::Normalise(image);
}
// Apply contrast limiting adaptive histogram equalization (CLAHE)
if (shouldApplyClahe) {
image = sharp::Clahe(image, baton->claheWidth, baton->claheHeight, baton->claheMaxSlope);
}
// Apply bitwise boolean operation between images
if (baton->boolean != nullptr) {
VImage booleanImage;
@@ -1330,6 +1336,9 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
baton->linearB = sharp::AttrAsDouble(options, "linearB");
baton->greyscale = sharp::AttrAsBool(options, "greyscale");
baton->normalise = sharp::AttrAsBool(options, "normalise");
baton->claheWidth = sharp::AttrAsUint32(options, "claheWidth");
baton->claheHeight = sharp::AttrAsUint32(options, "claheHeight");
baton->claheMaxSlope = sharp::AttrAsUint32(options, "claheMaxSlope");
baton->useExifOrientation = sharp::AttrAsBool(options, "useExifOrientation");
baton->angle = sharp::AttrAsInt32(options, "angle");
baton->rotationAngle = sharp::AttrAsDouble(options, "rotationAngle");

View File

@@ -109,6 +109,9 @@ struct PipelineBaton {
double gammaOut;
bool greyscale;
bool normalise;
int claheWidth;
int claheHeight;
int claheMaxSlope;
bool useExifOrientation;
int angle;
double rotationAngle;
@@ -234,6 +237,9 @@ struct PipelineBaton {
gamma(0.0),
greyscale(false),
normalise(false),
claheWidth(0),
claheHeight(0),
claheMaxSlope(3),
useExifOrientation(false),
angle(0),
rotationAngle(0.0),

BIN
test/fixtures/concert.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
test/fixtures/expected/clahe-5-5-0.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
test/fixtures/expected/clahe-5-5-5.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
test/fixtures/expected/clahe-50-50-0.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -121,6 +121,8 @@ module.exports = {
inputV: getPath('vfile.v'),
inputJpgClahe: getPath('concert.jpg'), // public domain - https://www.flickr.com/photos/mars_/14389236779/
testPattern: getPath('test-pattern.png'),
// Path for tests requiring human inspection

139
test/unit/clahe.js Normal file
View File

@@ -0,0 +1,139 @@
'use strict';
const assert = require('assert');
const sharp = require('../../lib');
const fixtures = require('../fixtures');
describe('Clahe', function () {
it('width 5 width 5 maxSlope 0', function (done) {
sharp(fixtures.inputJpgClahe)
.clahe({ width: 5, height: 5, maxSlope: 0 })
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('jpeg', info.format);
fixtures.assertSimilar(fixtures.expected('clahe-5-5-0.jpg'), data, { threshold: 10 }, done);
});
});
it('width 5 width 5 maxSlope 5', function (done) {
sharp(fixtures.inputJpgClahe)
.clahe({ width: 5, height: 5, maxSlope: 5 })
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('jpeg', info.format);
fixtures.assertSimilar(fixtures.expected('clahe-5-5-5.jpg'), data, done);
});
});
it('width 11 width 25 maxSlope 14', function (done) {
sharp(fixtures.inputJpgClahe)
.clahe({ width: 11, height: 25, maxSlope: 14 })
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('jpeg', info.format);
fixtures.assertSimilar(fixtures.expected('clahe-11-25-14.jpg'), data, done);
});
});
it('width 50 width 50 maxSlope 0', function (done) {
sharp(fixtures.inputJpgClahe)
.clahe({ width: 50, height: 50, maxSlope: 0 })
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('jpeg', info.format);
fixtures.assertSimilar(fixtures.expected('clahe-50-50-0.jpg'), data, done);
});
});
it('width 50 width 50 maxSlope 14', function (done) {
sharp(fixtures.inputJpgClahe)
.clahe({ width: 50, height: 50, maxSlope: 14 })
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('jpeg', info.format);
fixtures.assertSimilar(fixtures.expected('clahe-50-50-14.jpg'), data, done);
});
});
it('width 100 width 50 maxSlope 3', function (done) {
sharp(fixtures.inputJpgClahe)
.clahe({ width: 100, height: 50, maxSlope: 3 })
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('jpeg', info.format);
fixtures.assertSimilar(fixtures.expected('clahe-100-50-3.jpg'), data, done);
});
});
it('width 100 width 100 maxSlope 0', function (done) {
sharp(fixtures.inputJpgClahe)
.clahe({ width: 100, height: 100, maxSlope: 0 })
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('jpeg', info.format);
fixtures.assertSimilar(fixtures.expected('clahe-100-100-0.jpg'), data, done);
});
});
it('invalid maxSlope', function () {
assert.throws(function () {
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: 100, maxSlope: -5 });
});
assert.throws(function () {
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: 100, maxSlope: 110 });
});
assert.throws(function () {
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: 100, maxSlope: 5.5 });
});
assert.throws(function () {
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: 100, maxSlope: 'a string' });
});
});
it('invalid width', function () {
assert.throws(function () {
sharp(fixtures.inputJpgClahe).clahe({ width: 100.5, height: 100 });
});
assert.throws(function () {
sharp(fixtures.inputJpgClahe).clahe({ width: -5, height: 100 });
});
assert.throws(function () {
sharp(fixtures.inputJpgClahe).clahe({ width: true, height: 100 });
});
assert.throws(function () {
sharp(fixtures.inputJpgClahe).clahe({ width: 'string test', height: 100 });
});
});
it('invalid height', function () {
assert.throws(function () {
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: 100.5 });
});
assert.throws(function () {
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: -5 });
});
assert.throws(function () {
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: true });
});
assert.throws(function () {
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: 'string test' });
});
});
it('invalid options object', function () {
assert.throws(function () {
sharp(fixtures.inputJpgClahe).clahe(100, 100, 5);
});
});
it('uses default maxSlope of 3', function (done) {
sharp(fixtures.inputJpgClahe)
.clahe({ width: 100, height: 50 })
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('jpeg', info.format);
fixtures.assertSimilar(fixtures.expected('clahe-100-50-3.jpg'), data, done);
});
});
});