Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f384e1c6c | ||
|
|
35e8c8b25e | ||
|
|
dc53f1baff | ||
|
|
70139600b5 | ||
|
|
1b4d1521e0 | ||
|
|
ed3377cb2d | ||
|
|
d72852b3aa | ||
|
|
4b6b6189bf | ||
|
|
b69a54fc75 | ||
|
|
81e388a4cc | ||
|
|
5bd5e5052a |
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
Remove alpha channel, if any. This is a no-op if the image does not have an alpha channel.
|
Remove alpha channel, if any. This is a no-op if the image does not have an alpha channel.
|
||||||
|
|
||||||
|
See also [flatten][1].
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
@@ -25,7 +27,7 @@ This is a no-op if the image already has an alpha channel.
|
|||||||
|
|
||||||
### Parameters
|
### 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
|
### Examples
|
||||||
|
|
||||||
@@ -43,7 +45,7 @@ const rgba = await sharp(rgb)
|
|||||||
.toBuffer();
|
.toBuffer();
|
||||||
```
|
```
|
||||||
|
|
||||||
* Throws **[Error][2]** Invalid alpha transparency level
|
* Throws **[Error][3]** Invalid alpha transparency level
|
||||||
|
|
||||||
Returns **Sharp**
|
Returns **Sharp**
|
||||||
|
|
||||||
@@ -57,7 +59,7 @@ Extract a single channel from a multi-channel image.
|
|||||||
|
|
||||||
### Parameters
|
### 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
|
### Examples
|
||||||
|
|
||||||
@@ -71,7 +73,7 @@ sharp(input)
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
* Throws **[Error][2]** Invalid channel
|
* Throws **[Error][3]** Invalid channel
|
||||||
|
|
||||||
Returns **Sharp**
|
Returns **Sharp**
|
||||||
|
|
||||||
@@ -90,12 +92,12 @@ For raw pixel input, the `options` object should contain a `raw` attribute, whic
|
|||||||
|
|
||||||
### Parameters
|
### Parameters
|
||||||
|
|
||||||
* `images` **([Array][4]<([string][3] | [Buffer][5])> | [string][3] | [Buffer][5])** one or more images (file paths, Buffers).
|
* `images` **([Array][5]<([string][4] | [Buffer][6])> | [string][4] | [Buffer][6])** one or more images (file paths, Buffers).
|
||||||
* `options` **[Object][6]** image options, see `sharp()` constructor.
|
* `options` **[Object][7]** image options, see `sharp()` constructor.
|
||||||
|
|
||||||
<!---->
|
<!---->
|
||||||
|
|
||||||
* Throws **[Error][2]** Invalid parameters
|
* Throws **[Error][3]** Invalid parameters
|
||||||
|
|
||||||
Returns **Sharp**
|
Returns **Sharp**
|
||||||
|
|
||||||
@@ -105,7 +107,7 @@ Perform a bitwise boolean operation on all input image channels (bands) to produ
|
|||||||
|
|
||||||
### Parameters
|
### 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
|
### Examples
|
||||||
|
|
||||||
@@ -119,18 +121,20 @@ sharp('3-channel-rgb-input.png')
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
* Throws **[Error][2]** Invalid parameters
|
* Throws **[Error][3]** Invalid parameters
|
||||||
|
|
||||||
Returns **Sharp**
|
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
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ and [https://www.cairographics.org/operators/][2]
|
|||||||
* `images[].raw.width` **[Number][7]?**
|
* `images[].raw.width` **[Number][7]?**
|
||||||
* `images[].raw.height` **[Number][7]?**
|
* `images[].raw.height` **[Number][7]?**
|
||||||
* `images[].raw.channels` **[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
|
### Examples
|
||||||
|
|
||||||
@@ -61,7 +63,7 @@ sharp('input.png')
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
* Throws **[Error][10]** Invalid parameters
|
* Throws **[Error][11]** Invalid parameters
|
||||||
|
|
||||||
Returns **Sharp**
|
Returns **Sharp**
|
||||||
|
|
||||||
@@ -87,4 +89,6 @@ Returns **Sharp**
|
|||||||
|
|
||||||
[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
|
[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
|
||||||
|
|||||||
@@ -176,6 +176,8 @@ Returns **Sharp**
|
|||||||
|
|
||||||
Merge alpha transparency channel, if any, with a background, then remove the alpha channel.
|
Merge alpha transparency channel, if any, with a background, then remove the alpha channel.
|
||||||
|
|
||||||
|
See also [removeAlpha][8].
|
||||||
|
|
||||||
### Parameters
|
### Parameters
|
||||||
|
|
||||||
* `options` **[Object][2]?**
|
* `options` **[Object][2]?**
|
||||||
@@ -186,7 +188,7 @@ Merge alpha transparency channel, if any, with a background, then remove the alp
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
await sharp(rgbaInput)
|
await sharp(rgbaInput)
|
||||||
.flatten({background: '#F0A703' })
|
.flatten({ background: '#F0A703' })
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -243,6 +245,33 @@ Alternative spelling of normalise.
|
|||||||
|
|
||||||
Returns **Sharp**
|
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
|
||||||
|
|
||||||
Convolve the image with the specified kernel.
|
Convolve the image with the specified kernel.
|
||||||
@@ -252,7 +281,7 @@ Convolve the image with the specified kernel.
|
|||||||
* `kernel` **[Object][2]**
|
* `kernel` **[Object][2]**
|
||||||
|
|
||||||
* `kernel.width` **[number][1]** width of the kernel in pixels.
|
* `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.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.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`)
|
* `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
|
### 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.
|
* `operator` **[string][3]** one of `and`, `or` or `eor` to perform that bitwise operation, like the C logic operators `&`, `|` and `^` respectively.
|
||||||
* `options` **[Object][2]?**
|
* `options` **[Object][2]?**
|
||||||
|
|
||||||
@@ -421,4 +450,8 @@ Returns **Sharp**
|
|||||||
|
|
||||||
[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
|
[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
|
||||||
|
|||||||
@@ -4,6 +4,17 @@
|
|||||||
|
|
||||||
Requires libvips v8.10.6
|
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
|
### v0.28.2 - 10th May 2021
|
||||||
|
|
||||||
* Allow `withMetadata` to set `density`.
|
* Allow `withMetadata` to set `density`.
|
||||||
|
|||||||
@@ -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" 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="apple-touch-icon-precomposed" href="https://pixel.plumbing/px/57x57/sharp-logo.svg">
|
||||||
<link rel="author" href="/humans.txt" type="text/plain">
|
<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="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://pixel.plumbing">
|
||||||
<link rel="dns-prefetch" href="https://www.google-analytics.com">
|
<link rel="dns-prefetch" href="https://www.google-analytics.com">
|
||||||
@@ -139,7 +139,7 @@
|
|||||||
docuteApiTitlePlugin,
|
docuteApiTitlePlugin,
|
||||||
docuteApiSearchPlugin
|
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: [
|
nav: [
|
||||||
{
|
{
|
||||||
title: 'Funding',
|
title: 'Funding',
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { extractDescription, extractKeywords } = require('./extract');
|
const { extractDescription, extractKeywords, extractParameters } = require('./extract');
|
||||||
|
|
||||||
const searchIndex = [];
|
const searchIndex = [];
|
||||||
|
|
||||||
@@ -37,18 +37,19 @@ for (const match of matches) {
|
|||||||
].forEach((section) => {
|
].forEach((section) => {
|
||||||
const contents = fs.readFileSync(path.join(__dirname, '..', `api-${section}.md`), 'utf8');
|
const contents = fs.readFileSync(path.join(__dirname, '..', `api-${section}.md`), 'utf8');
|
||||||
const matches = contents.matchAll(
|
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) {
|
for (const match of matches) {
|
||||||
const { title, firstparagraph } = match.groups;
|
const { title, firstparagraph, parameters } = match.groups;
|
||||||
const description = firstparagraph.startsWith('###')
|
const description = firstparagraph.startsWith('###')
|
||||||
? 'Constructor'
|
? 'Constructor'
|
||||||
: extractDescription(firstparagraph);
|
: extractDescription(firstparagraph);
|
||||||
|
const parameterNames = parameters ? extractParameters(parameters) : '';
|
||||||
|
|
||||||
searchIndex.push({
|
searchIndex.push({
|
||||||
t: title,
|
t: title,
|
||||||
d: description,
|
d: description,
|
||||||
k: extractKeywords(`${title} ${description}`),
|
k: extractKeywords(`${title} ${description} ${parameterNames}`),
|
||||||
l: `/api-${section}#${title.toLowerCase()}`
|
l: `/api-${section}#${title.toLowerCase()}`
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ const stopWords = require('./stop-words');
|
|||||||
|
|
||||||
const extractDescription = (str) =>
|
const extractDescription = (str) =>
|
||||||
str
|
str
|
||||||
|
.replace(/### Examples.*/sg, '')
|
||||||
.replace(/\(http[^)]+/g, '')
|
.replace(/\(http[^)]+/g, '')
|
||||||
.replace(/\s+/g, ' ')
|
.replace(/\s+/g, ' ')
|
||||||
.replace(/[^A-Za-z0-9_/\-,. ]/g, '')
|
.replace(/[^A-Za-z0-9_/\-,. ]/g, '')
|
||||||
@@ -11,6 +12,11 @@ const extractDescription = (str) =>
|
|||||||
.substr(0, 180)
|
.substr(0, 180)
|
||||||
.trim();
|
.trim();
|
||||||
|
|
||||||
|
const extractParameters = (str) =>
|
||||||
|
[...str.matchAll(/options\.(?<name>[^.`]+)/gs)]
|
||||||
|
.map((match) => match.groups.name)
|
||||||
|
.join(' ');
|
||||||
|
|
||||||
const extractKeywords = (str) =>
|
const extractKeywords = (str) =>
|
||||||
[
|
[
|
||||||
...new Set(
|
...new Set(
|
||||||
@@ -21,4 +27,4 @@ const extractKeywords = (str) =>
|
|||||||
)
|
)
|
||||||
].join(' ');
|
].join(' ');
|
||||||
|
|
||||||
module.exports = { extractDescription, extractKeywords };
|
module.exports = { extractDescription, extractKeywords, extractParameters };
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ module.exports = [
|
|||||||
'before',
|
'before',
|
||||||
'both',
|
'both',
|
||||||
'call',
|
'call',
|
||||||
|
'callback',
|
||||||
'can',
|
'can',
|
||||||
'containing',
|
'containing',
|
||||||
'default',
|
'default',
|
||||||
@@ -26,6 +27,7 @@ module.exports = [
|
|||||||
'ensure',
|
'ensure',
|
||||||
'etc',
|
'etc',
|
||||||
'every',
|
'every',
|
||||||
|
'except',
|
||||||
'for',
|
'for',
|
||||||
'from',
|
'from',
|
||||||
'get',
|
'get',
|
||||||
@@ -49,12 +51,16 @@ module.exports = [
|
|||||||
'occur',
|
'occur',
|
||||||
'occurs',
|
'occurs',
|
||||||
'options',
|
'options',
|
||||||
|
'other',
|
||||||
|
'out',
|
||||||
'over',
|
'over',
|
||||||
'perform',
|
'perform',
|
||||||
'performs',
|
'performs',
|
||||||
'provide',
|
'provide',
|
||||||
'provided',
|
'provided',
|
||||||
'ready',
|
'ready',
|
||||||
|
'requires',
|
||||||
|
'returned',
|
||||||
'same',
|
'same',
|
||||||
'see',
|
'see',
|
||||||
'set',
|
'set',
|
||||||
@@ -67,9 +73,11 @@ module.exports = [
|
|||||||
'supported',
|
'supported',
|
||||||
'sure',
|
'sure',
|
||||||
'take',
|
'take',
|
||||||
|
'than',
|
||||||
'that',
|
'that',
|
||||||
'the',
|
'the',
|
||||||
'their',
|
'their',
|
||||||
|
'then',
|
||||||
'there',
|
'there',
|
||||||
'therefore',
|
'therefore',
|
||||||
'these',
|
'these',
|
||||||
|
|||||||
11
install/can-compile.js
Normal 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;
|
||||||
|
}
|
||||||
@@ -43,7 +43,6 @@ const fail = function (err) {
|
|||||||
if (err.code === 'EACCES') {
|
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('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');
|
libvips.log('Please see https://sharp.pixelplumbing.com/install for required dependencies');
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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.
|
* 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
|
* @example
|
||||||
* sharp('rgba.png')
|
* sharp('rgba.png')
|
||||||
* .removeAlpha()
|
* .removeAlpha()
|
||||||
|
|||||||
@@ -89,6 +89,8 @@ const blend = {
|
|||||||
* @param {Number} [images[].raw.width]
|
* @param {Number} [images[].raw.width]
|
||||||
* @param {Number} [images[].raw.height]
|
* @param {Number} [images[].raw.height]
|
||||||
* @param {Number} [images[].raw.channels]
|
* @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}
|
* @returns {Sharp}
|
||||||
* @throws {Error} Invalid parameters
|
* @throws {Error} Invalid parameters
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -216,6 +216,9 @@ const Sharp = function (input, options) {
|
|||||||
gammaOut: 0,
|
gammaOut: 0,
|
||||||
greyscale: false,
|
greyscale: false,
|
||||||
normalise: false,
|
normalise: false,
|
||||||
|
claheWidth: 0,
|
||||||
|
claheHeight: 0,
|
||||||
|
claheMaxSlope: 3,
|
||||||
brightness: 1,
|
brightness: 1,
|
||||||
saturation: 1,
|
saturation: 1,
|
||||||
hue: 0,
|
hue: 0,
|
||||||
|
|||||||
@@ -270,9 +270,11 @@ function blur (sigma) {
|
|||||||
/**
|
/**
|
||||||
* Merge alpha transparency channel, if any, with a background, then remove the alpha channel.
|
* Merge alpha transparency channel, if any, with a background, then remove the alpha channel.
|
||||||
*
|
*
|
||||||
|
* See also {@link /api-channel#removealpha|removeAlpha}.
|
||||||
|
*
|
||||||
* @example
|
* @example
|
||||||
* await sharp(rgbaInput)
|
* await sharp(rgbaInput)
|
||||||
* .flatten({background: '#F0A703' })
|
* .flatten({ background: '#F0A703' })
|
||||||
* .toBuffer();
|
* .toBuffer();
|
||||||
*
|
*
|
||||||
* @param {Object} [options]
|
* @param {Object} [options]
|
||||||
@@ -350,6 +352,47 @@ function normalize (normalize) {
|
|||||||
return this.normalise(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.
|
* Convolve the image with the specified kernel.
|
||||||
*
|
*
|
||||||
@@ -368,7 +411,7 @@ function normalize (normalize) {
|
|||||||
*
|
*
|
||||||
* @param {Object} kernel
|
* @param {Object} kernel
|
||||||
* @param {number} kernel.width - width of the kernel in pixels.
|
* @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 {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.scale=sum] - the scale of the kernel in pixels.
|
||||||
* @param {number} [kernel.offset=0] - the offset 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,
|
negate,
|
||||||
normalise,
|
normalise,
|
||||||
normalize,
|
normalize,
|
||||||
|
clahe,
|
||||||
convolve,
|
convolve,
|
||||||
threshold,
|
threshold,
|
||||||
boolean,
|
boolean,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "sharp",
|
"name": "sharp",
|
||||||
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, AVIF and TIFF images",
|
"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>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://github.com/lovell/sharp",
|
"homepage": "https://github.com/lovell/sharp",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
@@ -76,10 +76,11 @@
|
|||||||
"Leon Radley <leon@radley.se>",
|
"Leon Radley <leon@radley.se>",
|
||||||
"alza54 <alza54@thiocod.in>",
|
"alza54 <alza54@thiocod.in>",
|
||||||
"Jacob Smith <jacob@frende.me>",
|
"Jacob Smith <jacob@frende.me>",
|
||||||
"Michael Nutt <michael@nutt.im>"
|
"Michael Nutt <michael@nutt.im>",
|
||||||
|
"Brad Parham <baparham@gmail.com>"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"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.*",
|
"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": "npm run test-lint && npm run test-unit && npm run test-licensing",
|
||||||
"test-lint": "semistandard && cpplint",
|
"test-lint": "semistandard && cpplint",
|
||||||
@@ -122,7 +123,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"color": "^3.1.3",
|
"color": "^3.1.3",
|
||||||
"detect-libc": "^1.0.3",
|
"detect-libc": "^1.0.3",
|
||||||
"node-addon-api": "^3.1.0",
|
"node-addon-api": "^3.2.0",
|
||||||
"prebuild-install": "^6.1.2",
|
"prebuild-install": "^6.1.2",
|
||||||
"semver": "^7.3.5",
|
"semver": "^7.3.5",
|
||||||
"simple-get": "^3.1.0",
|
"simple-get": "^3.1.0",
|
||||||
|
|||||||
@@ -92,6 +92,13 @@ namespace sharp {
|
|||||||
return image;
|
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
|
* Gamma encoding/decoding
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -35,6 +35,11 @@ namespace sharp {
|
|||||||
*/
|
*/
|
||||||
VImage Normalise(VImage image);
|
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
|
* Gamma encoding/decoding
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
xshrink == yshrink && xshrink >= 2 * shrink_on_load_factor &&
|
xshrink == yshrink && xshrink >= 2 * shrink_on_load_factor &&
|
||||||
(inputImageType == sharp::ImageType::JPEG || inputImageType == sharp::ImageType::WEBP) &&
|
(inputImageType == sharp::ImageType::JPEG || inputImageType == sharp::ImageType::WEBP) &&
|
||||||
baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimThreshold == 0.0 &&
|
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) {
|
if (xshrink >= 8 * shrink_on_load_factor) {
|
||||||
xfactor = xfactor / 8;
|
xfactor = xfactor / 8;
|
||||||
@@ -345,6 +345,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
bool const shouldApplyMedian = baton->medianSize > 0;
|
bool const shouldApplyMedian = baton->medianSize > 0;
|
||||||
bool const shouldComposite = !baton->composite.empty();
|
bool const shouldComposite = !baton->composite.empty();
|
||||||
bool const shouldModulate = baton->brightness != 1.0 || baton->saturation != 1.0 || baton->hue != 0.0;
|
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)) {
|
if (shouldComposite && !sharp::HasAlpha(image)) {
|
||||||
image = sharp::EnsureAlpha(image, 1);
|
image = sharp::EnsureAlpha(image, 1);
|
||||||
@@ -650,6 +651,11 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
image = sharp::Normalise(image);
|
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
|
// Apply bitwise boolean operation between images
|
||||||
if (baton->boolean != nullptr) {
|
if (baton->boolean != nullptr) {
|
||||||
VImage booleanImage;
|
VImage booleanImage;
|
||||||
@@ -1330,6 +1336,9 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|||||||
baton->linearB = sharp::AttrAsDouble(options, "linearB");
|
baton->linearB = sharp::AttrAsDouble(options, "linearB");
|
||||||
baton->greyscale = sharp::AttrAsBool(options, "greyscale");
|
baton->greyscale = sharp::AttrAsBool(options, "greyscale");
|
||||||
baton->normalise = sharp::AttrAsBool(options, "normalise");
|
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->useExifOrientation = sharp::AttrAsBool(options, "useExifOrientation");
|
||||||
baton->angle = sharp::AttrAsInt32(options, "angle");
|
baton->angle = sharp::AttrAsInt32(options, "angle");
|
||||||
baton->rotationAngle = sharp::AttrAsDouble(options, "rotationAngle");
|
baton->rotationAngle = sharp::AttrAsDouble(options, "rotationAngle");
|
||||||
|
|||||||
@@ -109,6 +109,9 @@ struct PipelineBaton {
|
|||||||
double gammaOut;
|
double gammaOut;
|
||||||
bool greyscale;
|
bool greyscale;
|
||||||
bool normalise;
|
bool normalise;
|
||||||
|
int claheWidth;
|
||||||
|
int claheHeight;
|
||||||
|
int claheMaxSlope;
|
||||||
bool useExifOrientation;
|
bool useExifOrientation;
|
||||||
int angle;
|
int angle;
|
||||||
double rotationAngle;
|
double rotationAngle;
|
||||||
@@ -234,6 +237,9 @@ struct PipelineBaton {
|
|||||||
gamma(0.0),
|
gamma(0.0),
|
||||||
greyscale(false),
|
greyscale(false),
|
||||||
normalise(false),
|
normalise(false),
|
||||||
|
claheWidth(0),
|
||||||
|
claheHeight(0),
|
||||||
|
claheMaxSlope(3),
|
||||||
useExifOrientation(false),
|
useExifOrientation(false),
|
||||||
angle(0),
|
angle(0),
|
||||||
rotationAngle(0.0),
|
rotationAngle(0.0),
|
||||||
|
|||||||
BIN
test/fixtures/concert.jpg
vendored
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
test/fixtures/expected/clahe-100-100-0.jpg
vendored
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
test/fixtures/expected/clahe-100-50-3.jpg
vendored
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
test/fixtures/expected/clahe-11-25-14.jpg
vendored
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
test/fixtures/expected/clahe-5-5-0.jpg
vendored
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
test/fixtures/expected/clahe-5-5-5.jpg
vendored
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
test/fixtures/expected/clahe-50-50-0.jpg
vendored
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
test/fixtures/expected/clahe-50-50-14.jpg
vendored
Normal file
|
After Width: | Height: | Size: 21 KiB |
2
test/fixtures/index.js
vendored
@@ -121,6 +121,8 @@ module.exports = {
|
|||||||
|
|
||||||
inputV: getPath('vfile.v'),
|
inputV: getPath('vfile.v'),
|
||||||
|
|
||||||
|
inputJpgClahe: getPath('concert.jpg'), // public domain - https://www.flickr.com/photos/mars_/14389236779/
|
||||||
|
|
||||||
testPattern: getPath('test-pattern.png'),
|
testPattern: getPath('test-pattern.png'),
|
||||||
|
|
||||||
// Path for tests requiring human inspection
|
// Path for tests requiring human inspection
|
||||||
|
|||||||
139
test/unit/clahe.js
Normal 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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||