sharp 0.30.1 → 0.30.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/binding.gyp +0 -2
- package/lib/colour.js +9 -0
- package/lib/composite.js +17 -2
- package/lib/constructor.js +7 -7
- package/lib/input.js +31 -12
- package/lib/libvips.js +8 -3
- package/lib/operation.js +147 -28
- package/lib/output.js +2 -0
- package/lib/sharp.js +1 -1
- package/package.json +7 -6
- package/src/common.cc +12 -11
- package/src/common.h +2 -2
- package/src/operations.cc +10 -3
- package/src/operations.h +2 -1
- package/src/pipeline.cc +28 -15
- package/src/pipeline.h +10 -4
- package/src/sharp.cc +0 -16
package/binding.gyp
CHANGED
|
@@ -39,7 +39,6 @@
|
|
|
39
39
|
'VCCLCompilerTool': {
|
|
40
40
|
'ExceptionHandling': 1,
|
|
41
41
|
'Optimization': 1,
|
|
42
|
-
'RuntimeLibrary': '2', # /MD
|
|
43
42
|
'WholeProgramOptimization': 'true'
|
|
44
43
|
},
|
|
45
44
|
'VCLibrarianTool': {
|
|
@@ -206,7 +205,6 @@
|
|
|
206
205
|
'VCCLCompilerTool': {
|
|
207
206
|
'ExceptionHandling': 1,
|
|
208
207
|
'Optimization': 1,
|
|
209
|
-
'RuntimeLibrary': '2', # /MD
|
|
210
208
|
'WholeProgramOptimization': 'true'
|
|
211
209
|
},
|
|
212
210
|
'VCLibrarianTool': {
|
package/lib/colour.js
CHANGED
|
@@ -19,6 +19,11 @@ const colourspace = {
|
|
|
19
19
|
* Tint the image using the provided chroma while preserving the image luminance.
|
|
20
20
|
* An alpha channel may be present and will be unchanged by the operation.
|
|
21
21
|
*
|
|
22
|
+
* @example
|
|
23
|
+
* const output = await sharp(input)
|
|
24
|
+
* .tint({ r: 255, g: 240, b: 16 })
|
|
25
|
+
* .toBuffer();
|
|
26
|
+
*
|
|
22
27
|
* @param {string|Object} rgb - parsed by the [color](https://www.npmjs.org/package/color) module to extract chroma values.
|
|
23
28
|
* @returns {Sharp}
|
|
24
29
|
* @throws {Error} Invalid parameter
|
|
@@ -37,6 +42,10 @@ function tint (rgb) {
|
|
|
37
42
|
* This may be overridden by other sharp operations such as `toColourspace('b-w')`,
|
|
38
43
|
* which will produce an output image containing one color channel.
|
|
39
44
|
* An alpha channel may be present, and will be unchanged by the operation.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* const output = await sharp(input).greyscale().toBuffer();
|
|
48
|
+
*
|
|
40
49
|
* @param {Boolean} [greyscale=true]
|
|
41
50
|
* @returns {Sharp}
|
|
42
51
|
*/
|
package/lib/composite.js
CHANGED
|
@@ -56,6 +56,21 @@ const blend = {
|
|
|
56
56
|
* @since 0.22.0
|
|
57
57
|
*
|
|
58
58
|
* @example
|
|
59
|
+
* await sharp(background)
|
|
60
|
+
* .composite([
|
|
61
|
+
* { input: layer1, gravity: 'northwest' },
|
|
62
|
+
* { input: layer2, gravity: 'southeast' },
|
|
63
|
+
* ])
|
|
64
|
+
* .toFile('combined.png');
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* const output = await sharp('input.gif', { animated: true })
|
|
68
|
+
* .composite([
|
|
69
|
+
* { input: 'overlay.png', tile: true, blend: 'saturate' }
|
|
70
|
+
* ])
|
|
71
|
+
* .toBuffer();
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
59
74
|
* sharp('input.png')
|
|
60
75
|
* .rotate(180)
|
|
61
76
|
* .resize(300)
|
|
@@ -89,7 +104,8 @@ const blend = {
|
|
|
89
104
|
* @param {Number} [images[].raw.width]
|
|
90
105
|
* @param {Number} [images[].raw.height]
|
|
91
106
|
* @param {Number} [images[].raw.channels]
|
|
92
|
-
* @param {boolean} [images[].
|
|
107
|
+
* @param {boolean} [images[].animated=false] - Set to `true` to read all frames/pages of an animated image.
|
|
108
|
+
* @param {string} [images[].failOn='warning'] - @see {@link /api-constructor#parameters|constructor parameters}
|
|
93
109
|
* @param {number|boolean} [images[].limitInputPixels=268402689] - @see {@link /api-constructor#parameters|constructor parameters}
|
|
94
110
|
* @returns {Sharp}
|
|
95
111
|
* @throws {Error} Invalid parameters
|
|
@@ -162,7 +178,6 @@ function composite (images) {
|
|
|
162
178
|
throw is.invalidParameterError('premultiplied', 'boolean', image.premultiplied);
|
|
163
179
|
}
|
|
164
180
|
}
|
|
165
|
-
|
|
166
181
|
return composite;
|
|
167
182
|
});
|
|
168
183
|
return this;
|
package/lib/constructor.js
CHANGED
|
@@ -98,8 +98,7 @@ const debuglog = util.debuglog('sharp');
|
|
|
98
98
|
* a String containing the filesystem path to an JPEG, PNG, WebP, AVIF, GIF, SVG or TIFF image file.
|
|
99
99
|
* JPEG, PNG, WebP, AVIF, GIF, SVG, TIFF or raw pixel image data can be streamed into the object when not present.
|
|
100
100
|
* @param {Object} [options] - if present, is an Object with optional attributes.
|
|
101
|
-
* @param {
|
|
102
|
-
* Set this flag to `false` if you'd rather apply a "best effort" to decode images, even if the data is corrupt or invalid.
|
|
101
|
+
* @param {string} [options.failOn='warning'] - level of sensitivity to invalid images, one of (in order of sensitivity): 'none' (least), 'truncated', 'error' or 'warning' (most), highers level imply lower levels.
|
|
103
102
|
* @param {number|boolean} [options.limitInputPixels=268402689] - Do not process input images where the number of pixels
|
|
104
103
|
* (width x height) exceeds this limit. Assumes image dimensions contained in the input metadata can be trusted.
|
|
105
104
|
* An integral Number of pixels, zero or false to remove limit, true to use default limit of 268402689 (0x3FFF x 0x3FFF).
|
|
@@ -186,8 +185,11 @@ const Sharp = function (input, options) {
|
|
|
186
185
|
medianSize: 0,
|
|
187
186
|
blurSigma: 0,
|
|
188
187
|
sharpenSigma: 0,
|
|
189
|
-
|
|
190
|
-
|
|
188
|
+
sharpenM1: 1,
|
|
189
|
+
sharpenM2: 2,
|
|
190
|
+
sharpenX1: 2,
|
|
191
|
+
sharpenY2: 10,
|
|
192
|
+
sharpenY3: 20,
|
|
191
193
|
threshold: 0,
|
|
192
194
|
thresholdGrayscale: true,
|
|
193
195
|
trimThreshold: 0,
|
|
@@ -317,9 +319,7 @@ Object.setPrototypeOf(Sharp, stream.Duplex);
|
|
|
317
319
|
* // Using Promises to know when the pipeline is complete
|
|
318
320
|
* const fs = require("fs");
|
|
319
321
|
* const got = require("got");
|
|
320
|
-
* const sharpStream = sharp({
|
|
321
|
-
* failOnError: false
|
|
322
|
-
* });
|
|
322
|
+
* const sharpStream = sharp({ failOn: 'none' });
|
|
323
323
|
*
|
|
324
324
|
* const promises = [];
|
|
325
325
|
*
|
package/lib/input.js
CHANGED
|
@@ -9,9 +9,9 @@ const sharp = require('./sharp');
|
|
|
9
9
|
* @private
|
|
10
10
|
*/
|
|
11
11
|
function _inputOptionsFromObject (obj) {
|
|
12
|
-
const { raw, density, limitInputPixels, unlimited, sequentialRead, failOnError, animated, page, pages, subifd } = obj;
|
|
13
|
-
return [raw, density, limitInputPixels, unlimited, sequentialRead, failOnError, animated, page, pages, subifd].some(is.defined)
|
|
14
|
-
? { raw, density, limitInputPixels, unlimited, sequentialRead, failOnError, animated, page, pages, subifd }
|
|
12
|
+
const { raw, density, limitInputPixels, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd } = obj;
|
|
13
|
+
return [raw, density, limitInputPixels, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd].some(is.defined)
|
|
14
|
+
? { raw, density, limitInputPixels, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd }
|
|
15
15
|
: undefined;
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -21,7 +21,7 @@ function _inputOptionsFromObject (obj) {
|
|
|
21
21
|
*/
|
|
22
22
|
function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
23
23
|
const inputDescriptor = {
|
|
24
|
-
|
|
24
|
+
failOn: 'warning',
|
|
25
25
|
limitInputPixels: Math.pow(0x3FFF, 2),
|
|
26
26
|
unlimited: false,
|
|
27
27
|
sequentialRead: false
|
|
@@ -39,7 +39,7 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
39
39
|
if (input.length === 0) {
|
|
40
40
|
throw Error('Input Bit Array is empty');
|
|
41
41
|
}
|
|
42
|
-
inputDescriptor.buffer = Buffer.from(input.buffer);
|
|
42
|
+
inputDescriptor.buffer = Buffer.from(input.buffer, input.byteOffset, input.byteLength);
|
|
43
43
|
} else if (is.plainObject(input) && !is.defined(inputOptions)) {
|
|
44
44
|
// Plain Object descriptor, e.g. create
|
|
45
45
|
inputOptions = input;
|
|
@@ -56,14 +56,22 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
56
56
|
}`);
|
|
57
57
|
}
|
|
58
58
|
if (is.object(inputOptions)) {
|
|
59
|
-
//
|
|
59
|
+
// Deprecated: failOnError
|
|
60
60
|
if (is.defined(inputOptions.failOnError)) {
|
|
61
61
|
if (is.bool(inputOptions.failOnError)) {
|
|
62
|
-
inputDescriptor.
|
|
62
|
+
inputDescriptor.failOn = inputOptions.failOnError ? 'warning' : 'none';
|
|
63
63
|
} else {
|
|
64
64
|
throw is.invalidParameterError('failOnError', 'boolean', inputOptions.failOnError);
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
|
+
// failOn
|
|
68
|
+
if (is.defined(inputOptions.failOn)) {
|
|
69
|
+
if (is.string(inputOptions.failOn) && is.inArray(inputOptions.failOn, ['none', 'truncated', 'error', 'warning'])) {
|
|
70
|
+
inputDescriptor.failOn = inputOptions.failOn;
|
|
71
|
+
} else {
|
|
72
|
+
throw is.invalidParameterError('failOn', 'one of: none, truncated, error, warning', inputOptions.failOn);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
67
75
|
// Density
|
|
68
76
|
if (is.defined(inputOptions.density)) {
|
|
69
77
|
if (is.inRange(inputOptions.density, 1, 100000)) {
|
|
@@ -299,8 +307,8 @@ function _isStreamInput () {
|
|
|
299
307
|
*
|
|
300
308
|
* - `format`: Name of decoder used to decompress image data e.g. `jpeg`, `png`, `webp`, `gif`, `svg`
|
|
301
309
|
* - `size`: Total size of image in bytes, for Stream and Buffer input only
|
|
302
|
-
* - `width`: Number of pixels wide (EXIF orientation is not taken into consideration)
|
|
303
|
-
* - `height`: Number of pixels high (EXIF orientation is not taken into consideration)
|
|
310
|
+
* - `width`: Number of pixels wide (EXIF orientation is not taken into consideration, see example below)
|
|
311
|
+
* - `height`: Number of pixels high (EXIF orientation is not taken into consideration, see example below)
|
|
304
312
|
* - `space`: Name of colour space interpretation e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://libvips.github.io/libvips/API/current/VipsImage.html#VipsInterpretation)
|
|
305
313
|
* - `channels`: Number of bands e.g. `3` for sRGB, `4` for CMYK
|
|
306
314
|
* - `depth`: Name of pixel depth format e.g. `uchar`, `char`, `ushort`, `float` [...](https://libvips.github.io/libvips/API/current/VipsImage.html#VipsBandFormat)
|
|
@@ -343,6 +351,17 @@ function _isStreamInput () {
|
|
|
343
351
|
* // data contains a WebP image half the width and height of the original JPEG
|
|
344
352
|
* });
|
|
345
353
|
*
|
|
354
|
+
* @example
|
|
355
|
+
* // Based on EXIF rotation metadata, get the right-side-up width and height:
|
|
356
|
+
*
|
|
357
|
+
* const size = getNormalSize(await sharp(input).metadata());
|
|
358
|
+
*
|
|
359
|
+
* function getNormalSize({ width, height, orientation }) {
|
|
360
|
+
* return orientation || 0 >= 5
|
|
361
|
+
* ? { width: height, height: width }
|
|
362
|
+
* : { width, height };
|
|
363
|
+
* }
|
|
364
|
+
*
|
|
346
365
|
* @param {Function} [callback] - called with the arguments `(err, metadata)`
|
|
347
366
|
* @returns {Promise<Object>|Sharp}
|
|
348
367
|
*/
|
|
@@ -401,9 +420,9 @@ function metadata (callback) {
|
|
|
401
420
|
* - `maxX` (x-coordinate of one of the pixel where the maximum lies)
|
|
402
421
|
* - `maxY` (y-coordinate of one of the pixel where the maximum lies)
|
|
403
422
|
* - `isOpaque`: Is the image fully opaque? Will be `true` if the image has no alpha channel or if every pixel is fully opaque.
|
|
404
|
-
* - `entropy`: Histogram-based estimation of greyscale entropy, discarding alpha channel if any
|
|
405
|
-
* - `sharpness`: Estimation of greyscale sharpness based on the standard deviation of a Laplacian convolution, discarding alpha channel if any
|
|
406
|
-
* - `dominant`: Object containing most dominant sRGB colour based on a 4096-bin 3D histogram
|
|
423
|
+
* - `entropy`: Histogram-based estimation of greyscale entropy, discarding alpha channel if any.
|
|
424
|
+
* - `sharpness`: Estimation of greyscale sharpness based on the standard deviation of a Laplacian convolution, discarding alpha channel if any.
|
|
425
|
+
* - `dominant`: Object containing most dominant sRGB colour based on a 4096-bin 3D histogram.
|
|
407
426
|
*
|
|
408
427
|
* **Note**: Statistics are derived from the original input image. Any operations performed on the image must first be
|
|
409
428
|
* written to a buffer in order to run `stats` on the result (see third example).
|
package/lib/libvips.js
CHANGED
|
@@ -86,9 +86,14 @@ const removeVendoredLibvips = function () {
|
|
|
86
86
|
const pkgConfigPath = function () {
|
|
87
87
|
if (process.platform !== 'win32') {
|
|
88
88
|
const brewPkgConfigPath = spawnSync('which brew >/dev/null 2>&1 && eval $(brew --env) && echo $PKG_CONFIG_LIBDIR', spawnSyncOptions).stdout || '';
|
|
89
|
-
return [
|
|
90
|
-
.
|
|
91
|
-
.
|
|
89
|
+
return [
|
|
90
|
+
brewPkgConfigPath.trim(),
|
|
91
|
+
env.PKG_CONFIG_PATH,
|
|
92
|
+
'/usr/local/lib/pkgconfig',
|
|
93
|
+
'/usr/lib/pkgconfig',
|
|
94
|
+
'/usr/local/libdata/pkgconfig',
|
|
95
|
+
'/usr/libdata/pkgconfig'
|
|
96
|
+
].filter(Boolean).join(':');
|
|
92
97
|
} else {
|
|
93
98
|
return '';
|
|
94
99
|
}
|
package/lib/operation.js
CHANGED
|
@@ -63,6 +63,10 @@ function rotate (angle, options) {
|
|
|
63
63
|
/**
|
|
64
64
|
* Flip the image about the vertical Y axis. This always occurs after rotation, if any.
|
|
65
65
|
* The use of `flip` implies the removal of the EXIF `Orientation` tag, if any.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* const output = await sharp(input).flip().toBuffer();
|
|
69
|
+
*
|
|
66
70
|
* @param {Boolean} [flip=true]
|
|
67
71
|
* @returns {Sharp}
|
|
68
72
|
*/
|
|
@@ -74,6 +78,10 @@ function flip (flip) {
|
|
|
74
78
|
/**
|
|
75
79
|
* Flop the image about the horizontal X axis. This always occurs after rotation, if any.
|
|
76
80
|
* The use of `flop` implies the removal of the EXIF `Orientation` tag, if any.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* const output = await sharp(input).flop().toBuffer();
|
|
84
|
+
*
|
|
77
85
|
* @param {Boolean} [flop=true]
|
|
78
86
|
* @returns {Sharp}
|
|
79
87
|
*/
|
|
@@ -185,40 +193,107 @@ function affine (matrix, options) {
|
|
|
185
193
|
* When a `sigma` is provided, performs a slower, more accurate sharpen of the L channel in the LAB colour space.
|
|
186
194
|
* Separate control over the level of sharpening in "flat" and "jagged" areas is available.
|
|
187
195
|
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
* @
|
|
196
|
+
* See {@link https://www.libvips.org/API/current/libvips-convolution.html#vips-sharpen|libvips sharpen} operation.
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* const data = await sharp(input).sharpen().toBuffer();
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* const data = await sharp(input).sharpen({ sigma: 2 }).toBuffer();
|
|
203
|
+
*
|
|
204
|
+
* @example
|
|
205
|
+
* const data = await sharp(input)
|
|
206
|
+
* .sharpen({
|
|
207
|
+
* sigma: 2,
|
|
208
|
+
* m1: 0
|
|
209
|
+
* m2: 3,
|
|
210
|
+
* x1: 3,
|
|
211
|
+
* y2: 15,
|
|
212
|
+
* y3: 15,
|
|
213
|
+
* })
|
|
214
|
+
* .toBuffer();
|
|
215
|
+
*
|
|
216
|
+
* @param {Object|number} [options] - if present, is an Object with attributes or (deprecated) a number for `options.sigma`.
|
|
217
|
+
* @param {number} [options.sigma] - the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`.
|
|
218
|
+
* @param {number} [options.m1=1.0] - the level of sharpening to apply to "flat" areas.
|
|
219
|
+
* @param {number} [options.m2=2.0] - the level of sharpening to apply to "jagged" areas.
|
|
220
|
+
* @param {number} [options.x1=2.0] - threshold between "flat" and "jagged"
|
|
221
|
+
* @param {number} [options.y2=10.0] - maximum amount of brightening.
|
|
222
|
+
* @param {number} [options.y3=20.0] - maximum amount of darkening.
|
|
223
|
+
* @param {number} [flat] - (deprecated) see `options.m1`.
|
|
224
|
+
* @param {number} [jagged] - (deprecated) see `options.m2`.
|
|
191
225
|
* @returns {Sharp}
|
|
192
226
|
* @throws {Error} Invalid parameters
|
|
193
227
|
*/
|
|
194
|
-
function sharpen (
|
|
195
|
-
if (!is.defined(
|
|
228
|
+
function sharpen (options, flat, jagged) {
|
|
229
|
+
if (!is.defined(options)) {
|
|
196
230
|
// No arguments: default to mild sharpen
|
|
197
231
|
this.options.sharpenSigma = -1;
|
|
198
|
-
} else if (is.bool(
|
|
199
|
-
//
|
|
200
|
-
this.options.sharpenSigma =
|
|
201
|
-
} else if (is.number(
|
|
202
|
-
//
|
|
203
|
-
this.options.sharpenSigma =
|
|
204
|
-
//
|
|
232
|
+
} else if (is.bool(options)) {
|
|
233
|
+
// Deprecated boolean argument: apply mild sharpen?
|
|
234
|
+
this.options.sharpenSigma = options ? -1 : 0;
|
|
235
|
+
} else if (is.number(options) && is.inRange(options, 0.01, 10000)) {
|
|
236
|
+
// Deprecated numeric argument: specific sigma
|
|
237
|
+
this.options.sharpenSigma = options;
|
|
238
|
+
// Deprecated control over flat areas
|
|
205
239
|
if (is.defined(flat)) {
|
|
206
240
|
if (is.number(flat) && is.inRange(flat, 0, 10000)) {
|
|
207
|
-
this.options.
|
|
241
|
+
this.options.sharpenM1 = flat;
|
|
208
242
|
} else {
|
|
209
243
|
throw is.invalidParameterError('flat', 'number between 0 and 10000', flat);
|
|
210
244
|
}
|
|
211
245
|
}
|
|
212
|
-
//
|
|
246
|
+
// Deprecated control over jagged areas
|
|
213
247
|
if (is.defined(jagged)) {
|
|
214
248
|
if (is.number(jagged) && is.inRange(jagged, 0, 10000)) {
|
|
215
|
-
this.options.
|
|
249
|
+
this.options.sharpenM2 = jagged;
|
|
216
250
|
} else {
|
|
217
251
|
throw is.invalidParameterError('jagged', 'number between 0 and 10000', jagged);
|
|
218
252
|
}
|
|
219
253
|
}
|
|
254
|
+
} else if (is.plainObject(options)) {
|
|
255
|
+
if (is.number(options.sigma) && is.inRange(options.sigma, 0.01, 10000)) {
|
|
256
|
+
this.options.sharpenSigma = options.sigma;
|
|
257
|
+
} else {
|
|
258
|
+
throw is.invalidParameterError('options.sigma', 'number between 0.01 and 10000', options.sigma);
|
|
259
|
+
}
|
|
260
|
+
if (is.defined(options.m1)) {
|
|
261
|
+
if (is.number(options.m1) && is.inRange(options.m1, 0, 10000)) {
|
|
262
|
+
this.options.sharpenM1 = options.m1;
|
|
263
|
+
} else {
|
|
264
|
+
throw is.invalidParameterError('options.m1', 'number between 0 and 10000', options.m1);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
if (is.defined(options.m2)) {
|
|
268
|
+
if (is.number(options.m2) && is.inRange(options.m2, 0, 10000)) {
|
|
269
|
+
this.options.sharpenM2 = options.m2;
|
|
270
|
+
} else {
|
|
271
|
+
throw is.invalidParameterError('options.m2', 'number between 0 and 10000', options.m2);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (is.defined(options.x1)) {
|
|
275
|
+
if (is.number(options.x1) && is.inRange(options.x1, 0, 10000)) {
|
|
276
|
+
this.options.sharpenX1 = options.x1;
|
|
277
|
+
} else {
|
|
278
|
+
throw is.invalidParameterError('options.x1', 'number between 0 and 10000', options.x1);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if (is.defined(options.y2)) {
|
|
282
|
+
if (is.number(options.y2) && is.inRange(options.y2, 0, 10000)) {
|
|
283
|
+
this.options.sharpenY2 = options.y2;
|
|
284
|
+
} else {
|
|
285
|
+
throw is.invalidParameterError('options.y2', 'number between 0 and 10000', options.y2);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
if (is.defined(options.y3)) {
|
|
289
|
+
if (is.number(options.y3) && is.inRange(options.y3, 0, 10000)) {
|
|
290
|
+
this.options.sharpenY3 = options.y3;
|
|
291
|
+
} else {
|
|
292
|
+
throw is.invalidParameterError('options.y3', 'number between 0 and 10000', options.y3);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
220
295
|
} else {
|
|
221
|
-
throw is.invalidParameterError('sigma', 'number between 0.01 and 10000',
|
|
296
|
+
throw is.invalidParameterError('sigma', 'number between 0.01 and 10000', options);
|
|
222
297
|
}
|
|
223
298
|
return this;
|
|
224
299
|
}
|
|
@@ -226,6 +301,13 @@ function sharpen (sigma, flat, jagged) {
|
|
|
226
301
|
/**
|
|
227
302
|
* Apply median filter.
|
|
228
303
|
* When used without parameters the default window is 3x3.
|
|
304
|
+
*
|
|
305
|
+
* @example
|
|
306
|
+
* const output = await sharp(input).median().toBuffer();
|
|
307
|
+
*
|
|
308
|
+
* @example
|
|
309
|
+
* const output = await sharp(input).median(5).toBuffer();
|
|
310
|
+
*
|
|
229
311
|
* @param {number} [size=3] square mask size: size x size
|
|
230
312
|
* @returns {Sharp}
|
|
231
313
|
* @throws {Error} Invalid parameters
|
|
@@ -338,6 +420,17 @@ function gamma (gamma, gammaOut) {
|
|
|
338
420
|
|
|
339
421
|
/**
|
|
340
422
|
* Produce the "negative" of the image.
|
|
423
|
+
*
|
|
424
|
+
* @example
|
|
425
|
+
* const output = await sharp(input)
|
|
426
|
+
* .negate()
|
|
427
|
+
* .toBuffer();
|
|
428
|
+
*
|
|
429
|
+
* @example
|
|
430
|
+
* const output = await sharp(input)
|
|
431
|
+
* .negate({ alpha: false })
|
|
432
|
+
* .toBuffer();
|
|
433
|
+
*
|
|
341
434
|
* @param {Object} [options]
|
|
342
435
|
* @param {Boolean} [options.alpha=true] Whether or not to negate any alpha channel
|
|
343
436
|
* @returns {Sharp}
|
|
@@ -356,6 +449,10 @@ function negate (options) {
|
|
|
356
449
|
|
|
357
450
|
/**
|
|
358
451
|
* Enhance output image contrast by stretching its luminance to cover the full dynamic range.
|
|
452
|
+
*
|
|
453
|
+
* @example
|
|
454
|
+
* const output = await sharp(input).normalise().toBuffer();
|
|
455
|
+
*
|
|
359
456
|
* @param {Boolean} [normalise=true]
|
|
360
457
|
* @returns {Sharp}
|
|
361
458
|
*/
|
|
@@ -366,6 +463,10 @@ function normalise (normalise) {
|
|
|
366
463
|
|
|
367
464
|
/**
|
|
368
465
|
* Alternative spelling of normalise.
|
|
466
|
+
*
|
|
467
|
+
* @example
|
|
468
|
+
* const output = await sharp(input).normalize().toBuffer();
|
|
469
|
+
*
|
|
369
470
|
* @param {Boolean} [normalize=true]
|
|
370
471
|
* @returns {Sharp}
|
|
371
472
|
*/
|
|
@@ -381,6 +482,14 @@ function normalize (normalize) {
|
|
|
381
482
|
*
|
|
382
483
|
* @since 0.28.3
|
|
383
484
|
*
|
|
485
|
+
* @example
|
|
486
|
+
* const output = await sharp(input)
|
|
487
|
+
* .clahe({
|
|
488
|
+
* width: 3,
|
|
489
|
+
* height: 3,
|
|
490
|
+
* })
|
|
491
|
+
* .toBuffer();
|
|
492
|
+
*
|
|
384
493
|
* @param {Object} options
|
|
385
494
|
* @param {number} options.width - integer width of the region in pixels.
|
|
386
495
|
* @param {number} options.height - integer height of the region in pixels.
|
|
@@ -590,28 +699,38 @@ function recomb (inputMatrix) {
|
|
|
590
699
|
* @since 0.22.1
|
|
591
700
|
*
|
|
592
701
|
* @example
|
|
593
|
-
*
|
|
702
|
+
* // increase brightness by a factor of 2
|
|
703
|
+
* const output = await sharp(input)
|
|
594
704
|
* .modulate({
|
|
595
|
-
* brightness: 2
|
|
596
|
-
* })
|
|
705
|
+
* brightness: 2
|
|
706
|
+
* })
|
|
707
|
+
* .toBuffer();
|
|
597
708
|
*
|
|
598
|
-
*
|
|
709
|
+
* @example
|
|
710
|
+
* // hue-rotate by 180 degrees
|
|
711
|
+
* const output = await sharp(input)
|
|
599
712
|
* .modulate({
|
|
600
|
-
* hue: 180
|
|
601
|
-
* })
|
|
713
|
+
* hue: 180
|
|
714
|
+
* })
|
|
715
|
+
* .toBuffer();
|
|
602
716
|
*
|
|
603
|
-
*
|
|
717
|
+
* @example
|
|
718
|
+
* // increase lightness by +50
|
|
719
|
+
* const output = await sharp(input)
|
|
604
720
|
* .modulate({
|
|
605
|
-
* lightness: 50
|
|
606
|
-
* })
|
|
721
|
+
* lightness: 50
|
|
722
|
+
* })
|
|
723
|
+
* .toBuffer();
|
|
607
724
|
*
|
|
725
|
+
* @example
|
|
608
726
|
* // decreate brightness and saturation while also hue-rotating by 90 degrees
|
|
609
|
-
* sharp(input)
|
|
727
|
+
* const output = await sharp(input)
|
|
610
728
|
* .modulate({
|
|
611
729
|
* brightness: 0.5,
|
|
612
730
|
* saturation: 0.5,
|
|
613
|
-
* hue: 90
|
|
614
|
-
* })
|
|
731
|
+
* hue: 90,
|
|
732
|
+
* })
|
|
733
|
+
* .toBuffer();
|
|
615
734
|
*
|
|
616
735
|
* @param {Object} [options]
|
|
617
736
|
* @param {number} [options.brightness] Brightness multiplier
|
package/lib/output.js
CHANGED
|
@@ -151,6 +151,8 @@ function toBuffer (options, callback) {
|
|
|
151
151
|
* The default behaviour, when `withMetadata` is not used, is to convert to the device-independent
|
|
152
152
|
* sRGB colour space and strip all metadata, including the removal of any ICC profile.
|
|
153
153
|
*
|
|
154
|
+
* EXIF metadata is unsupported for TIFF output.
|
|
155
|
+
*
|
|
154
156
|
* @example
|
|
155
157
|
* sharp('input.jpg')
|
|
156
158
|
* .withMetadata()
|
package/lib/sharp.js
CHANGED
|
@@ -21,7 +21,7 @@ try {
|
|
|
21
21
|
'- Consult the installation documentation: https://sharp.pixelplumbing.com/install'
|
|
22
22
|
);
|
|
23
23
|
// Check loaded
|
|
24
|
-
if (process.platform === 'win32') {
|
|
24
|
+
if (process.platform === 'win32' || /symbol/.test(err.message)) {
|
|
25
25
|
const loadedModule = Object.keys(require.cache).find((i) => /[\\/]build[\\/]Release[\\/]sharp(.*)\.node$/.test(i));
|
|
26
26
|
if (loadedModule) {
|
|
27
27
|
const [, loadedPackage] = loadedModule.match(/node_modules[\\/]([^\\/]+)[\\/]/);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sharp",
|
|
3
3
|
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, GIF, AVIF and TIFF images",
|
|
4
|
-
"version": "0.30.
|
|
4
|
+
"version": "0.30.4",
|
|
5
5
|
"author": "Lovell Fuller <npm@lovell.info>",
|
|
6
6
|
"homepage": "https://github.com/lovell/sharp",
|
|
7
7
|
"contributors": [
|
|
@@ -81,7 +81,8 @@
|
|
|
81
81
|
"Taneli Vatanen <taneli.vatanen@gmail.com>",
|
|
82
82
|
"Joris Dugué <zaruike10@gmail.com>",
|
|
83
83
|
"Chris Banks <christopher.bradley.banks@gmail.com>",
|
|
84
|
-
"Ompal Singh <ompal.hitm09@gmail.com>"
|
|
84
|
+
"Ompal Singh <ompal.hitm09@gmail.com>",
|
|
85
|
+
"Brodan <christopher.hranj@gmail.com"
|
|
85
86
|
],
|
|
86
87
|
"scripts": {
|
|
87
88
|
"install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node install/can-compile && node-gyp rebuild && node install/dll-copy)",
|
|
@@ -126,11 +127,11 @@
|
|
|
126
127
|
"vips"
|
|
127
128
|
],
|
|
128
129
|
"dependencies": {
|
|
129
|
-
"color": "^4.2.
|
|
130
|
-
"detect-libc": "^2.0.
|
|
130
|
+
"color": "^4.2.3",
|
|
131
|
+
"detect-libc": "^2.0.1",
|
|
131
132
|
"node-addon-api": "^4.3.0",
|
|
132
133
|
"prebuild-install": "^7.0.1",
|
|
133
|
-
"semver": "^7.3.
|
|
134
|
+
"semver": "^7.3.7",
|
|
134
135
|
"simple-get": "^4.0.1",
|
|
135
136
|
"tar-fs": "^2.1.1",
|
|
136
137
|
"tunnel-agent": "^0.6.0"
|
|
@@ -143,7 +144,7 @@
|
|
|
143
144
|
"exif-reader": "^1.0.3",
|
|
144
145
|
"icc": "^2.0.0",
|
|
145
146
|
"license-checker": "^25.0.1",
|
|
146
|
-
"mocha": "^9.2.
|
|
147
|
+
"mocha": "^9.2.2",
|
|
147
148
|
"mock-fs": "^5.1.2",
|
|
148
149
|
"nyc": "^15.1.0",
|
|
149
150
|
"prebuild": "^11.0.3",
|
package/src/common.cc
CHANGED
|
@@ -85,7 +85,9 @@ namespace sharp {
|
|
|
85
85
|
descriptor->buffer = buffer.Data();
|
|
86
86
|
descriptor->isBuffer = TRUE;
|
|
87
87
|
}
|
|
88
|
-
descriptor->
|
|
88
|
+
descriptor->failOn = static_cast<VipsFailOn>(
|
|
89
|
+
vips_enum_from_nick(nullptr, VIPS_TYPE_FAIL_ON,
|
|
90
|
+
AttrAsStr(input, "failOn").data()));
|
|
89
91
|
// Density for vector-based input
|
|
90
92
|
if (HasAttr(input, "density")) {
|
|
91
93
|
descriptor->density = AttrAsDouble(input, "density");
|
|
@@ -329,7 +331,7 @@ namespace sharp {
|
|
|
329
331
|
try {
|
|
330
332
|
vips::VOption *option = VImage::option()
|
|
331
333
|
->set("access", descriptor->access)
|
|
332
|
-
->set("
|
|
334
|
+
->set("fail_on", descriptor->failOn);
|
|
333
335
|
if (descriptor->unlimited && (imageType == ImageType::SVG || imageType == ImageType::PNG)) {
|
|
334
336
|
option->set("unlimited", TRUE);
|
|
335
337
|
}
|
|
@@ -375,12 +377,6 @@ namespace sharp {
|
|
|
375
377
|
VImage::option()->set("mean", descriptor->createNoiseMean)->set("sigma", descriptor->createNoiseSigma)));
|
|
376
378
|
}
|
|
377
379
|
image = image.bandjoin(bands);
|
|
378
|
-
image = image.cast(VipsBandFormat::VIPS_FORMAT_UCHAR);
|
|
379
|
-
if (channels < 3) {
|
|
380
|
-
image = image.colourspace(VIPS_INTERPRETATION_B_W);
|
|
381
|
-
} else {
|
|
382
|
-
image = image.colourspace(VIPS_INTERPRETATION_sRGB);
|
|
383
|
-
}
|
|
384
380
|
} else {
|
|
385
381
|
std::vector<double> background = {
|
|
386
382
|
descriptor->createBackground[0],
|
|
@@ -392,19 +388,24 @@ namespace sharp {
|
|
|
392
388
|
}
|
|
393
389
|
image = VImage::new_matrix(descriptor->createWidth, descriptor->createHeight).new_from_image(background);
|
|
394
390
|
}
|
|
395
|
-
image.get_image()->Type =
|
|
391
|
+
image.get_image()->Type = image.guess_interpretation();
|
|
392
|
+
image = image.cast(VIPS_FORMAT_UCHAR);
|
|
396
393
|
imageType = ImageType::RAW;
|
|
397
394
|
} else {
|
|
398
395
|
// From filesystem
|
|
399
396
|
imageType = DetermineImageType(descriptor->file.data());
|
|
400
397
|
if (imageType == ImageType::MISSING) {
|
|
401
|
-
|
|
398
|
+
if (descriptor->file.find("<svg") != std::string::npos) {
|
|
399
|
+
throw vips::VError("Input file is missing, did you mean "
|
|
400
|
+
"sharp(Buffer.from('" + descriptor->file.substr(0, 8) + "...')?");
|
|
401
|
+
}
|
|
402
|
+
throw vips::VError("Input file is missing: " + descriptor->file);
|
|
402
403
|
}
|
|
403
404
|
if (imageType != ImageType::UNKNOWN) {
|
|
404
405
|
try {
|
|
405
406
|
vips::VOption *option = VImage::option()
|
|
406
407
|
->set("access", descriptor->access)
|
|
407
|
-
->set("
|
|
408
|
+
->set("fail_on", descriptor->failOn);
|
|
408
409
|
if (descriptor->unlimited && (imageType == ImageType::SVG || imageType == ImageType::PNG)) {
|
|
409
410
|
option->set("unlimited", TRUE);
|
|
410
411
|
}
|
package/src/common.h
CHANGED
|
@@ -48,7 +48,7 @@ namespace sharp {
|
|
|
48
48
|
std::string name;
|
|
49
49
|
std::string file;
|
|
50
50
|
char *buffer;
|
|
51
|
-
|
|
51
|
+
VipsFailOn failOn;
|
|
52
52
|
int limitInputPixels;
|
|
53
53
|
bool unlimited;
|
|
54
54
|
VipsAccess access;
|
|
@@ -74,7 +74,7 @@ namespace sharp {
|
|
|
74
74
|
|
|
75
75
|
InputDescriptor():
|
|
76
76
|
buffer(nullptr),
|
|
77
|
-
|
|
77
|
+
failOn(VIPS_FAIL_ON_WARNING),
|
|
78
78
|
limitInputPixels(0x3FFF * 0x3FFF),
|
|
79
79
|
unlimited(FALSE),
|
|
80
80
|
access(VIPS_ACCESS_RANDOM),
|
package/src/operations.cc
CHANGED
|
@@ -209,7 +209,8 @@ namespace sharp {
|
|
|
209
209
|
/*
|
|
210
210
|
* Sharpen flat and jagged areas. Use sigma of -1.0 for fast sharpen.
|
|
211
211
|
*/
|
|
212
|
-
VImage Sharpen(VImage image, double const sigma, double const
|
|
212
|
+
VImage Sharpen(VImage image, double const sigma, double const m1, double const m2,
|
|
213
|
+
double const x1, double const y2, double const y3) {
|
|
213
214
|
if (sigma == -1.0) {
|
|
214
215
|
// Fast, mild sharpen
|
|
215
216
|
VImage sharpen = VImage::new_matrixv(3, 3,
|
|
@@ -224,8 +225,14 @@ namespace sharp {
|
|
|
224
225
|
if (colourspaceBeforeSharpen == VIPS_INTERPRETATION_RGB) {
|
|
225
226
|
colourspaceBeforeSharpen = VIPS_INTERPRETATION_sRGB;
|
|
226
227
|
}
|
|
227
|
-
return image
|
|
228
|
-
VImage::option()
|
|
228
|
+
return image
|
|
229
|
+
.sharpen(VImage::option()
|
|
230
|
+
->set("sigma", sigma)
|
|
231
|
+
->set("m1", m1)
|
|
232
|
+
->set("m2", m2)
|
|
233
|
+
->set("x1", x1)
|
|
234
|
+
->set("y2", y2)
|
|
235
|
+
->set("y3", y3))
|
|
229
236
|
.colourspace(colourspaceBeforeSharpen);
|
|
230
237
|
}
|
|
231
238
|
}
|
package/src/operations.h
CHANGED
|
@@ -64,7 +64,8 @@ namespace sharp {
|
|
|
64
64
|
/*
|
|
65
65
|
* Sharpen flat and jagged areas. Use sigma of -1.0 for fast sharpen.
|
|
66
66
|
*/
|
|
67
|
-
VImage Sharpen(VImage image, double const sigma, double const
|
|
67
|
+
VImage Sharpen(VImage image, double const sigma, double const m1, double const m2,
|
|
68
|
+
double const x1, double const y2, double const y3);
|
|
68
69
|
|
|
69
70
|
/*
|
|
70
71
|
Threshold an image
|
package/src/pipeline.cc
CHANGED
|
@@ -200,7 +200,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
200
200
|
vips::VOption *option = VImage::option()
|
|
201
201
|
->set("access", baton->input->access)
|
|
202
202
|
->set("shrink", jpegShrinkOnLoad)
|
|
203
|
-
->set("
|
|
203
|
+
->set("fail_on", baton->input->failOn);
|
|
204
204
|
if (baton->input->buffer != nullptr) {
|
|
205
205
|
// Reload JPEG buffer
|
|
206
206
|
VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);
|
|
@@ -214,7 +214,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
214
214
|
vips::VOption *option = VImage::option()
|
|
215
215
|
->set("access", baton->input->access)
|
|
216
216
|
->set("scale", scale)
|
|
217
|
-
->set("
|
|
217
|
+
->set("fail_on", baton->input->failOn);
|
|
218
218
|
if (inputImageType == sharp::ImageType::WEBP) {
|
|
219
219
|
option->set("n", baton->input->pages);
|
|
220
220
|
option->set("page", baton->input->page);
|
|
@@ -241,8 +241,10 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
241
241
|
// Reload SVG file
|
|
242
242
|
image = VImage::svgload(const_cast<char*>(baton->input->file.data()), option);
|
|
243
243
|
}
|
|
244
|
-
|
|
245
244
|
sharp::SetDensity(image, baton->input->density);
|
|
245
|
+
if (image.width() > 32767 || image.height() > 32767) {
|
|
246
|
+
throw vips::VError("Input SVG image will exceed 32767x32767 pixel limit when scaled");
|
|
247
|
+
}
|
|
246
248
|
} else if (inputImageType == sharp::ImageType::PDF) {
|
|
247
249
|
option->set("n", baton->input->pages);
|
|
248
250
|
option->set("page", baton->input->page);
|
|
@@ -260,6 +262,10 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
260
262
|
|
|
261
263
|
sharp::SetDensity(image, baton->input->density);
|
|
262
264
|
}
|
|
265
|
+
} else {
|
|
266
|
+
if (inputImageType == sharp::ImageType::SVG && (image.width() > 32767 || image.height() > 32767)) {
|
|
267
|
+
throw vips::VError("Input SVG image exceeds 32767x32767 pixel limit");
|
|
268
|
+
}
|
|
263
269
|
}
|
|
264
270
|
|
|
265
271
|
// Any pre-shrinking may already have been done
|
|
@@ -292,7 +298,8 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
292
298
|
if (
|
|
293
299
|
sharp::HasProfile(image) &&
|
|
294
300
|
image.interpretation() != VIPS_INTERPRETATION_LABS &&
|
|
295
|
-
image.interpretation() != VIPS_INTERPRETATION_GREY16
|
|
301
|
+
image.interpretation() != VIPS_INTERPRETATION_GREY16 &&
|
|
302
|
+
image.interpretation() != VIPS_INTERPRETATION_B_W
|
|
296
303
|
) {
|
|
297
304
|
// Convert to sRGB/P3 using embedded profile
|
|
298
305
|
try {
|
|
@@ -353,7 +360,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
353
360
|
}
|
|
354
361
|
|
|
355
362
|
bool const shouldPremultiplyAlpha = sharp::HasAlpha(image) &&
|
|
356
|
-
(shouldResize || shouldBlur || shouldConv || shouldSharpen
|
|
363
|
+
(shouldResize || shouldBlur || shouldConv || shouldSharpen);
|
|
357
364
|
|
|
358
365
|
// Premultiply image alpha channel before all transformations to avoid
|
|
359
366
|
// dark fringing around bright pixels
|
|
@@ -576,11 +583,14 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
576
583
|
|
|
577
584
|
// Sharpen
|
|
578
585
|
if (shouldSharpen) {
|
|
579
|
-
image = sharp::Sharpen(image, baton->sharpenSigma, baton->
|
|
586
|
+
image = sharp::Sharpen(image, baton->sharpenSigma, baton->sharpenM1, baton->sharpenM2,
|
|
587
|
+
baton->sharpenX1, baton->sharpenY2, baton->sharpenY3);
|
|
580
588
|
}
|
|
581
589
|
|
|
582
590
|
// Composite
|
|
583
591
|
if (shouldComposite) {
|
|
592
|
+
std::vector<VImage> images = { image };
|
|
593
|
+
std::vector<int> modes, xs, ys;
|
|
584
594
|
for (Composite *composite : baton->composite) {
|
|
585
595
|
VImage compositeImage;
|
|
586
596
|
sharp::ImageType compositeImageType = sharp::ImageType::UNKNOWN;
|
|
@@ -626,12 +636,12 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
626
636
|
// gravity was used for extract_area, set it back to its default value of 0
|
|
627
637
|
composite->gravity = 0;
|
|
628
638
|
}
|
|
629
|
-
// Ensure image to composite is sRGB with
|
|
639
|
+
// Ensure image to composite is sRGB with unpremultiplied alpha
|
|
630
640
|
compositeImage = compositeImage.colourspace(VIPS_INTERPRETATION_sRGB);
|
|
631
641
|
if (!sharp::HasAlpha(compositeImage)) {
|
|
632
642
|
compositeImage = sharp::EnsureAlpha(compositeImage, 1);
|
|
633
643
|
}
|
|
634
|
-
if (
|
|
644
|
+
if (composite->premultiplied) compositeImage = compositeImage.unpremultiply();
|
|
635
645
|
// Calculate position
|
|
636
646
|
int left;
|
|
637
647
|
int top;
|
|
@@ -649,12 +659,12 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
649
659
|
std::tie(left, top) = sharp::CalculateCrop(image.width(), image.height(),
|
|
650
660
|
compositeImage.width(), compositeImage.height(), composite->gravity);
|
|
651
661
|
}
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
->set("y", top));
|
|
662
|
+
images.push_back(compositeImage);
|
|
663
|
+
modes.push_back(composite->mode);
|
|
664
|
+
xs.push_back(left);
|
|
665
|
+
ys.push_back(top);
|
|
657
666
|
}
|
|
667
|
+
image = image.composite(images, modes, VImage::option()->set("x", xs)->set("y", ys));
|
|
658
668
|
}
|
|
659
669
|
|
|
660
670
|
// Reverse premultiplication after all transformations:
|
|
@@ -1397,8 +1407,11 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1397
1407
|
baton->lightness = sharp::AttrAsDouble(options, "lightness");
|
|
1398
1408
|
baton->medianSize = sharp::AttrAsUint32(options, "medianSize");
|
|
1399
1409
|
baton->sharpenSigma = sharp::AttrAsDouble(options, "sharpenSigma");
|
|
1400
|
-
baton->
|
|
1401
|
-
baton->
|
|
1410
|
+
baton->sharpenM1 = sharp::AttrAsDouble(options, "sharpenM1");
|
|
1411
|
+
baton->sharpenM2 = sharp::AttrAsDouble(options, "sharpenM2");
|
|
1412
|
+
baton->sharpenX1 = sharp::AttrAsDouble(options, "sharpenX1");
|
|
1413
|
+
baton->sharpenY2 = sharp::AttrAsDouble(options, "sharpenY2");
|
|
1414
|
+
baton->sharpenY3 = sharp::AttrAsDouble(options, "sharpenY3");
|
|
1402
1415
|
baton->threshold = sharp::AttrAsInt32(options, "threshold");
|
|
1403
1416
|
baton->thresholdGrayscale = sharp::AttrAsBool(options, "thresholdGrayscale");
|
|
1404
1417
|
baton->trimThreshold = sharp::AttrAsDouble(options, "trimThreshold");
|
package/src/pipeline.h
CHANGED
|
@@ -90,8 +90,11 @@ struct PipelineBaton {
|
|
|
90
90
|
double lightness;
|
|
91
91
|
int medianSize;
|
|
92
92
|
double sharpenSigma;
|
|
93
|
-
double
|
|
94
|
-
double
|
|
93
|
+
double sharpenM1;
|
|
94
|
+
double sharpenM2;
|
|
95
|
+
double sharpenX1;
|
|
96
|
+
double sharpenY2;
|
|
97
|
+
double sharpenY3;
|
|
95
98
|
int threshold;
|
|
96
99
|
bool thresholdGrayscale;
|
|
97
100
|
double trimThreshold;
|
|
@@ -234,8 +237,11 @@ struct PipelineBaton {
|
|
|
234
237
|
lightness(0),
|
|
235
238
|
medianSize(0),
|
|
236
239
|
sharpenSigma(0.0),
|
|
237
|
-
|
|
238
|
-
|
|
240
|
+
sharpenM1(1.0),
|
|
241
|
+
sharpenM2(2.0),
|
|
242
|
+
sharpenX1(2.0),
|
|
243
|
+
sharpenY2(10.0),
|
|
244
|
+
sharpenY3(20.0),
|
|
239
245
|
threshold(0),
|
|
240
246
|
thresholdGrayscale(true),
|
|
241
247
|
trimThreshold(0.0),
|
package/src/sharp.cc
CHANGED
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
// limitations under the License.
|
|
14
14
|
|
|
15
15
|
#include <napi.h>
|
|
16
|
-
#include <cstdlib>
|
|
17
16
|
#include <vips/vips8>
|
|
18
17
|
|
|
19
18
|
#include "common.h"
|
|
@@ -22,14 +21,6 @@
|
|
|
22
21
|
#include "utilities.h"
|
|
23
22
|
#include "stats.h"
|
|
24
23
|
|
|
25
|
-
#if defined(_MSC_VER) && _MSC_VER >= 1400 // MSVC 2005/8
|
|
26
|
-
static void empty_invalid_parameter_handler(const wchar_t* expression,
|
|
27
|
-
const wchar_t* function, const wchar_t* file, unsigned int line,
|
|
28
|
-
uintptr_t reserved) {
|
|
29
|
-
// No-op.
|
|
30
|
-
}
|
|
31
|
-
#endif
|
|
32
|
-
|
|
33
24
|
static void* sharp_vips_init(void*) {
|
|
34
25
|
g_setenv("VIPS_MIN_STACK_SIZE", "2m", FALSE);
|
|
35
26
|
vips_init("sharp");
|
|
@@ -43,13 +34,6 @@ Napi::Object init(Napi::Env env, Napi::Object exports) {
|
|
|
43
34
|
g_log_set_handler("VIPS", static_cast<GLogLevelFlags>(G_LOG_LEVEL_WARNING),
|
|
44
35
|
static_cast<GLogFunc>(sharp::VipsWarningCallback), nullptr);
|
|
45
36
|
|
|
46
|
-
// Tell the CRT to not exit the application when an invalid parameter is
|
|
47
|
-
// passed. The main issue is that invalid FDs will trigger this behaviour.
|
|
48
|
-
// See: https://github.com/libvips/libvips/pull/2571.
|
|
49
|
-
#if defined(_MSC_VER) && _MSC_VER >= 1400 // MSVC 2005/8
|
|
50
|
-
_set_invalid_parameter_handler(empty_invalid_parameter_handler);
|
|
51
|
-
#endif
|
|
52
|
-
|
|
53
37
|
// Methods available to JavaScript
|
|
54
38
|
exports.Set("metadata", Napi::Function::New(env, metadata));
|
|
55
39
|
exports.Set("pipeline", Napi::Function::New(env, pipeline));
|