sharp 0.17.2 → 0.18.2
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/CONTRIBUTING.md +1 -7
- package/binding.gyp +1 -1
- package/binding.js +14 -14
- package/docs/api-colour.md +2 -2
- package/docs/api-composite.md +11 -3
- package/docs/api-constructor.md +25 -5
- package/docs/api-input.md +4 -3
- package/docs/api-operation.md +20 -17
- package/docs/api-output.md +39 -30
- package/docs/api-resize.md +9 -8
- package/docs/api-utility.md +4 -4
- package/docs/changelog.md +103 -0
- package/docs/index.md +4 -1
- package/docs/install.md +44 -14
- package/lib/channel.js +6 -6
- package/lib/colour.js +10 -10
- package/lib/composite.js +11 -6
- package/lib/constructor.js +41 -18
- package/lib/input.js +52 -24
- package/lib/is.js +9 -0
- package/lib/operation.js +41 -38
- package/lib/output.js +103 -112
- package/lib/resize.js +25 -20
- package/lib/utility.js +8 -8
- package/package.json +22 -18
- package/src/common.cc +94 -20
- package/src/common.h +30 -3
- package/src/libvips/cplusplus/VImage.cpp +110 -104
- package/src/libvips/cplusplus/vips-operators.cpp +108 -44
- package/src/metadata.cc +19 -4
- package/src/metadata.h +1 -0
- package/src/operations.cc +18 -165
- package/src/operations.h +4 -26
- package/src/pipeline.cc +201 -97
- package/src/pipeline.h +14 -0
- package/src/sharp.cc +3 -0
package/lib/input.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const color = require('color');
|
|
4
4
|
const is = require('./is');
|
|
5
5
|
const sharp = require('../build/Release/sharp.node');
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@ const sharp = require('../build/Release/sharp.node');
|
|
|
8
8
|
* Create Object containing input and input-related options.
|
|
9
9
|
* @private
|
|
10
10
|
*/
|
|
11
|
-
|
|
11
|
+
function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
12
12
|
const inputDescriptor = {};
|
|
13
13
|
if (is.string(input)) {
|
|
14
14
|
// filesystem
|
|
@@ -16,6 +16,9 @@ const _createInputDescriptor = function _createInputDescriptor (input, inputOpti
|
|
|
16
16
|
} else if (is.buffer(input)) {
|
|
17
17
|
// Buffer
|
|
18
18
|
inputDescriptor.buffer = input;
|
|
19
|
+
} else if (is.plainObject(input) && !is.defined(inputOptions)) {
|
|
20
|
+
// Plain Object descriptor, e.g. create
|
|
21
|
+
inputOptions = input;
|
|
19
22
|
} else if (!is.defined(input) && is.object(containerOptions) && containerOptions.allowStream) {
|
|
20
23
|
// Stream
|
|
21
24
|
inputDescriptor.buffer = [];
|
|
@@ -35,8 +38,8 @@ const _createInputDescriptor = function _createInputDescriptor (input, inputOpti
|
|
|
35
38
|
if (is.defined(inputOptions.raw)) {
|
|
36
39
|
if (
|
|
37
40
|
is.object(inputOptions.raw) &&
|
|
38
|
-
is.integer(inputOptions.raw.width) &&
|
|
39
|
-
is.integer(inputOptions.raw.height) &&
|
|
41
|
+
is.integer(inputOptions.raw.width) && inputOptions.raw.width > 0 &&
|
|
42
|
+
is.integer(inputOptions.raw.height) && inputOptions.raw.height > 0 &&
|
|
40
43
|
is.integer(inputOptions.raw.channels) && is.inRange(inputOptions.raw.channels, 1, 4)
|
|
41
44
|
) {
|
|
42
45
|
inputDescriptor.rawWidth = inputOptions.raw.width;
|
|
@@ -46,11 +49,35 @@ const _createInputDescriptor = function _createInputDescriptor (input, inputOpti
|
|
|
46
49
|
throw new Error('Expected width, height and channels for raw pixel input');
|
|
47
50
|
}
|
|
48
51
|
}
|
|
52
|
+
// Create new image
|
|
53
|
+
if (is.defined(inputOptions.create)) {
|
|
54
|
+
if (
|
|
55
|
+
is.object(inputOptions.create) &&
|
|
56
|
+
is.integer(inputOptions.create.width) && inputOptions.create.width > 0 &&
|
|
57
|
+
is.integer(inputOptions.create.height) && inputOptions.create.height > 0 &&
|
|
58
|
+
is.integer(inputOptions.create.channels) && is.inRange(inputOptions.create.channels, 3, 4) &&
|
|
59
|
+
is.defined(inputOptions.create.background)
|
|
60
|
+
) {
|
|
61
|
+
inputDescriptor.createWidth = inputOptions.create.width;
|
|
62
|
+
inputDescriptor.createHeight = inputOptions.create.height;
|
|
63
|
+
inputDescriptor.createChannels = inputOptions.create.channels;
|
|
64
|
+
const background = color(inputOptions.create.background);
|
|
65
|
+
inputDescriptor.createBackground = [
|
|
66
|
+
background.red(),
|
|
67
|
+
background.green(),
|
|
68
|
+
background.blue(),
|
|
69
|
+
Math.round(background.alpha() * 255)
|
|
70
|
+
];
|
|
71
|
+
delete inputDescriptor.buffer;
|
|
72
|
+
} else {
|
|
73
|
+
throw new Error('Expected width, height, channels and background to create a new input image');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
49
76
|
} else if (is.defined(inputOptions)) {
|
|
50
77
|
throw new Error('Invalid input options ' + inputOptions);
|
|
51
78
|
}
|
|
52
79
|
return inputDescriptor;
|
|
53
|
-
}
|
|
80
|
+
}
|
|
54
81
|
|
|
55
82
|
/**
|
|
56
83
|
* Handle incoming Buffer chunk on Writable Stream.
|
|
@@ -59,7 +86,7 @@ const _createInputDescriptor = function _createInputDescriptor (input, inputOpti
|
|
|
59
86
|
* @param {String} encoding - unused
|
|
60
87
|
* @param {Function} callback
|
|
61
88
|
*/
|
|
62
|
-
|
|
89
|
+
function _write (chunk, encoding, callback) {
|
|
63
90
|
/* istanbul ignore else */
|
|
64
91
|
if (Array.isArray(this.options.input.buffer)) {
|
|
65
92
|
/* istanbul ignore else */
|
|
@@ -78,26 +105,26 @@ const _write = function _write (chunk, encoding, callback) {
|
|
|
78
105
|
} else {
|
|
79
106
|
callback(new Error('Unexpected data on Writable Stream'));
|
|
80
107
|
}
|
|
81
|
-
}
|
|
108
|
+
}
|
|
82
109
|
|
|
83
110
|
/**
|
|
84
111
|
* Flattens the array of chunks accumulated in input.buffer.
|
|
85
112
|
* @private
|
|
86
113
|
*/
|
|
87
|
-
|
|
114
|
+
function _flattenBufferIn () {
|
|
88
115
|
if (this._isStreamInput()) {
|
|
89
116
|
this.options.input.buffer = Buffer.concat(this.options.input.buffer);
|
|
90
117
|
}
|
|
91
|
-
}
|
|
118
|
+
}
|
|
92
119
|
|
|
93
120
|
/**
|
|
94
121
|
* Are we expecting Stream-based input?
|
|
95
122
|
* @private
|
|
96
123
|
* @returns {Boolean}
|
|
97
124
|
*/
|
|
98
|
-
|
|
125
|
+
function _isStreamInput () {
|
|
99
126
|
return Array.isArray(this.options.input.buffer);
|
|
100
|
-
}
|
|
127
|
+
}
|
|
101
128
|
|
|
102
129
|
/**
|
|
103
130
|
* Take a "snapshot" of the Sharp instance, returning a new instance.
|
|
@@ -114,11 +141,11 @@ const _isStreamInput = function _isStreamInput () {
|
|
|
114
141
|
*
|
|
115
142
|
* @returns {Sharp}
|
|
116
143
|
*/
|
|
117
|
-
|
|
144
|
+
function clone () {
|
|
118
145
|
const that = this;
|
|
119
146
|
// Clone existing options
|
|
120
147
|
const clone = this.constructor.call();
|
|
121
|
-
|
|
148
|
+
clone.options = Object.assign({}, this.options);
|
|
122
149
|
// Pass 'finish' event to clone for Stream-based input
|
|
123
150
|
this.on('finish', function () {
|
|
124
151
|
// Clone inherits input data
|
|
@@ -127,17 +154,18 @@ const clone = function clone () {
|
|
|
127
154
|
clone.emit('finish');
|
|
128
155
|
});
|
|
129
156
|
return clone;
|
|
130
|
-
}
|
|
157
|
+
}
|
|
131
158
|
|
|
132
159
|
/**
|
|
133
|
-
* Fast access to image metadata without decoding any compressed image data.
|
|
160
|
+
* Fast access to (uncached) image metadata without decoding any compressed image data.
|
|
134
161
|
* A Promises/A+ promise is returned when `callback` is not provided.
|
|
135
162
|
*
|
|
136
163
|
* - `format`: Name of decoder used to decompress image data e.g. `jpeg`, `png`, `webp`, `gif`, `svg`
|
|
137
164
|
* - `width`: Number of pixels wide
|
|
138
165
|
* - `height`: Number of pixels high
|
|
139
|
-
* - `space`: Name of colour space interpretation e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://github.com/jcupitt/libvips/blob/master/libvips/iofuncs/enumtypes.c#
|
|
166
|
+
* - `space`: Name of colour space interpretation e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://github.com/jcupitt/libvips/blob/master/libvips/iofuncs/enumtypes.c#L636)
|
|
140
167
|
* - `channels`: Number of bands e.g. `3` for sRGB, `4` for CMYK
|
|
168
|
+
* - `depth`: Name of pixel depth format e.g. `uchar`, `char`, `ushort`, `float` [...](https://github.com/jcupitt/libvips/blob/master/libvips/iofuncs/enumtypes.c#L672)
|
|
141
169
|
* - `density`: Number of pixels per inch (DPI), if present
|
|
142
170
|
* - `hasProfile`: Boolean indicating the presence of an embedded ICC profile
|
|
143
171
|
* - `hasAlpha`: Boolean indicating the presence of an alpha transparency channel
|
|
@@ -162,7 +190,7 @@ const clone = function clone () {
|
|
|
162
190
|
* @param {Function} [callback] - called with the arguments `(err, metadata)`
|
|
163
191
|
* @returns {Promise<Object>|Sharp}
|
|
164
192
|
*/
|
|
165
|
-
|
|
193
|
+
function metadata (callback) {
|
|
166
194
|
const that = this;
|
|
167
195
|
if (is.fn(callback)) {
|
|
168
196
|
if (this._isStreamInput()) {
|
|
@@ -200,7 +228,7 @@ const metadata = function metadata (callback) {
|
|
|
200
228
|
});
|
|
201
229
|
}
|
|
202
230
|
}
|
|
203
|
-
}
|
|
231
|
+
}
|
|
204
232
|
|
|
205
233
|
/**
|
|
206
234
|
* Do not process input images where the number of pixels (width * height) exceeds this limit.
|
|
@@ -210,20 +238,20 @@ const metadata = function metadata (callback) {
|
|
|
210
238
|
* @returns {Sharp}
|
|
211
239
|
* @throws {Error} Invalid limit
|
|
212
240
|
*/
|
|
213
|
-
|
|
241
|
+
function limitInputPixels (limit) {
|
|
214
242
|
// if we pass in false we represent the integer as 0 to disable
|
|
215
243
|
if (limit === false) {
|
|
216
244
|
limit = 0;
|
|
217
245
|
} else if (limit === true) {
|
|
218
|
-
limit =
|
|
246
|
+
limit = Math.pow(0x3FFF, 2);
|
|
219
247
|
}
|
|
220
248
|
if (is.integer(limit) && limit >= 0) {
|
|
221
249
|
this.options.limitInputPixels = limit;
|
|
222
250
|
} else {
|
|
223
|
-
throw
|
|
251
|
+
throw is.invalidParameterError('limitInputPixels', 'integer', limit);
|
|
224
252
|
}
|
|
225
253
|
return this;
|
|
226
|
-
}
|
|
254
|
+
}
|
|
227
255
|
|
|
228
256
|
/**
|
|
229
257
|
* An advanced setting that switches the libvips access method to `VIPS_ACCESS_SEQUENTIAL`.
|
|
@@ -231,10 +259,10 @@ const limitInputPixels = function limitInputPixels (limit) {
|
|
|
231
259
|
* @param {Boolean} [sequentialRead=true]
|
|
232
260
|
* @returns {Sharp}
|
|
233
261
|
*/
|
|
234
|
-
|
|
262
|
+
function sequentialRead (sequentialRead) {
|
|
235
263
|
this.options.sequentialRead = is.bool(sequentialRead) ? sequentialRead : true;
|
|
236
264
|
return this;
|
|
237
|
-
}
|
|
265
|
+
}
|
|
238
266
|
|
|
239
267
|
/**
|
|
240
268
|
* Decorate the Sharp prototype with input-related functions.
|
package/lib/is.js
CHANGED
|
@@ -16,6 +16,14 @@ const object = function (val) {
|
|
|
16
16
|
return typeof val === 'object';
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Is this value a plain object?
|
|
21
|
+
* @private
|
|
22
|
+
*/
|
|
23
|
+
const plainObject = function (val) {
|
|
24
|
+
return object(val) && Object.prototype.toString.call(val) === '[object Object]';
|
|
25
|
+
};
|
|
26
|
+
|
|
19
27
|
/**
|
|
20
28
|
* Is this value a function?
|
|
21
29
|
* @private
|
|
@@ -98,6 +106,7 @@ const invalidParameterError = function (name, expected, actual) {
|
|
|
98
106
|
module.exports = {
|
|
99
107
|
defined: defined,
|
|
100
108
|
object: object,
|
|
109
|
+
plainObject: plainObject,
|
|
101
110
|
fn: fn,
|
|
102
111
|
bool: bool,
|
|
103
112
|
buffer: buffer,
|
package/lib/operation.js
CHANGED
|
@@ -6,7 +6,10 @@ const is = require('./is');
|
|
|
6
6
|
* Rotate the output image by either an explicit angle
|
|
7
7
|
* or auto-orient based on the EXIF `Orientation` tag.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* If an angle is provided, it is converted to a valid 90/180/270deg rotation.
|
|
10
|
+
* For example, `-450` will produce a 270deg rotation.
|
|
11
|
+
*
|
|
12
|
+
* If no angle is provided, it is determined from the EXIF data.
|
|
10
13
|
* Mirroring is supported and may infer the use of a flip operation.
|
|
11
14
|
*
|
|
12
15
|
* The use of `rotate` implies the removal of the EXIF `Orientation` tag, if any.
|
|
@@ -25,20 +28,20 @@ const is = require('./is');
|
|
|
25
28
|
* });
|
|
26
29
|
* readableStream.pipe(pipeline);
|
|
27
30
|
*
|
|
28
|
-
* @param {Number} [angle=auto]
|
|
31
|
+
* @param {Number} [angle=auto] angle of rotation, must be a multiple of 90.
|
|
29
32
|
* @returns {Sharp}
|
|
30
33
|
* @throws {Error} Invalid parameters
|
|
31
34
|
*/
|
|
32
|
-
|
|
35
|
+
function rotate (angle) {
|
|
33
36
|
if (!is.defined(angle)) {
|
|
34
|
-
this.options.
|
|
35
|
-
} else if (is.integer(angle) &&
|
|
37
|
+
this.options.useExifOrientation = true;
|
|
38
|
+
} else if (is.integer(angle) && !(angle % 90)) {
|
|
36
39
|
this.options.angle = angle;
|
|
37
40
|
} else {
|
|
38
|
-
throw new Error('Unsupported angle
|
|
41
|
+
throw new Error('Unsupported angle: angle must be a positive/negative multiple of 90 ' + angle);
|
|
39
42
|
}
|
|
40
43
|
return this;
|
|
41
|
-
}
|
|
44
|
+
}
|
|
42
45
|
|
|
43
46
|
/**
|
|
44
47
|
* Extract a region of the image.
|
|
@@ -70,7 +73,7 @@ const rotate = function rotate (angle) {
|
|
|
70
73
|
* @returns {Sharp}
|
|
71
74
|
* @throws {Error} Invalid parameters
|
|
72
75
|
*/
|
|
73
|
-
|
|
76
|
+
function extract (options) {
|
|
74
77
|
const suffix = this.options.width === -1 && this.options.height === -1 ? 'Pre' : 'Post';
|
|
75
78
|
['left', 'top', 'width', 'height'].forEach(function (name) {
|
|
76
79
|
const value = options[name];
|
|
@@ -81,11 +84,11 @@ const extract = function extract (options) {
|
|
|
81
84
|
}
|
|
82
85
|
}, this);
|
|
83
86
|
// Ensure existing rotation occurs before pre-resize extraction
|
|
84
|
-
if (suffix === 'Pre' && this.options.angle !== 0) {
|
|
87
|
+
if (suffix === 'Pre' && ((this.options.angle % 360) !== 0 || this.options.useExifOrientation === true)) {
|
|
85
88
|
this.options.rotateBeforePreExtract = true;
|
|
86
89
|
}
|
|
87
90
|
return this;
|
|
88
|
-
}
|
|
91
|
+
}
|
|
89
92
|
|
|
90
93
|
/**
|
|
91
94
|
* Flip the image about the vertical Y axis. This always occurs after rotation, if any.
|
|
@@ -93,10 +96,10 @@ const extract = function extract (options) {
|
|
|
93
96
|
* @param {Boolean} [flip=true]
|
|
94
97
|
* @returns {Sharp}
|
|
95
98
|
*/
|
|
96
|
-
|
|
99
|
+
function flip (flip) {
|
|
97
100
|
this.options.flip = is.bool(flip) ? flip : true;
|
|
98
101
|
return this;
|
|
99
|
-
}
|
|
102
|
+
}
|
|
100
103
|
|
|
101
104
|
/**
|
|
102
105
|
* Flop the image about the horizontal X axis. This always occurs after rotation, if any.
|
|
@@ -104,10 +107,10 @@ const flip = function flip (flip) {
|
|
|
104
107
|
* @param {Boolean} [flop=true]
|
|
105
108
|
* @returns {Sharp}
|
|
106
109
|
*/
|
|
107
|
-
|
|
110
|
+
function flop (flop) {
|
|
108
111
|
this.options.flop = is.bool(flop) ? flop : true;
|
|
109
112
|
return this;
|
|
110
|
-
}
|
|
113
|
+
}
|
|
111
114
|
|
|
112
115
|
/**
|
|
113
116
|
* Sharpen the image.
|
|
@@ -121,7 +124,7 @@ const flop = function flop (flop) {
|
|
|
121
124
|
* @returns {Sharp}
|
|
122
125
|
* @throws {Error} Invalid parameters
|
|
123
126
|
*/
|
|
124
|
-
|
|
127
|
+
function sharpen (sigma, flat, jagged) {
|
|
125
128
|
if (!is.defined(sigma)) {
|
|
126
129
|
// No arguments: default to mild sharpen
|
|
127
130
|
this.options.sharpenSigma = -1;
|
|
@@ -151,7 +154,7 @@ const sharpen = function sharpen (sigma, flat, jagged) {
|
|
|
151
154
|
throw new Error('Invalid sharpen sigma (0.01 - 10000) ' + sigma);
|
|
152
155
|
}
|
|
153
156
|
return this;
|
|
154
|
-
}
|
|
157
|
+
}
|
|
155
158
|
|
|
156
159
|
/**
|
|
157
160
|
* Blur the image.
|
|
@@ -161,7 +164,7 @@ const sharpen = function sharpen (sigma, flat, jagged) {
|
|
|
161
164
|
* @returns {Sharp}
|
|
162
165
|
* @throws {Error} Invalid parameters
|
|
163
166
|
*/
|
|
164
|
-
|
|
167
|
+
function blur (sigma) {
|
|
165
168
|
if (!is.defined(sigma)) {
|
|
166
169
|
// No arguments: default to mild blur
|
|
167
170
|
this.options.blurSigma = -1;
|
|
@@ -175,7 +178,7 @@ const blur = function blur (sigma) {
|
|
|
175
178
|
throw new Error('Invalid blur sigma (0.3 - 1000.0) ' + sigma);
|
|
176
179
|
}
|
|
177
180
|
return this;
|
|
178
|
-
}
|
|
181
|
+
}
|
|
179
182
|
|
|
180
183
|
/**
|
|
181
184
|
* Extends/pads the edges of the image with the colour provided to the `background` method.
|
|
@@ -198,7 +201,7 @@ const blur = function blur (sigma) {
|
|
|
198
201
|
* @returns {Sharp}
|
|
199
202
|
* @throws {Error} Invalid parameters
|
|
200
203
|
*/
|
|
201
|
-
|
|
204
|
+
function extend (extend) {
|
|
202
205
|
if (is.integer(extend) && extend > 0) {
|
|
203
206
|
this.options.extendTop = extend;
|
|
204
207
|
this.options.extendBottom = extend;
|
|
@@ -219,17 +222,17 @@ const extend = function extend (extend) {
|
|
|
219
222
|
throw new Error('Invalid edge extension ' + extend);
|
|
220
223
|
}
|
|
221
224
|
return this;
|
|
222
|
-
}
|
|
225
|
+
}
|
|
223
226
|
|
|
224
227
|
/**
|
|
225
228
|
* Merge alpha transparency channel, if any, with `background`.
|
|
226
229
|
* @param {Boolean} [flatten=true]
|
|
227
230
|
* @returns {Sharp}
|
|
228
231
|
*/
|
|
229
|
-
|
|
232
|
+
function flatten (flatten) {
|
|
230
233
|
this.options.flatten = is.bool(flatten) ? flatten : true;
|
|
231
234
|
return this;
|
|
232
|
-
}
|
|
235
|
+
}
|
|
233
236
|
|
|
234
237
|
/**
|
|
235
238
|
* Trim "boring" pixels from all edges that contain values within a percentage similarity of the top-left pixel.
|
|
@@ -237,7 +240,7 @@ const flatten = function flatten (flatten) {
|
|
|
237
240
|
* @returns {Sharp}
|
|
238
241
|
* @throws {Error} Invalid parameters
|
|
239
242
|
*/
|
|
240
|
-
|
|
243
|
+
function trim (tolerance) {
|
|
241
244
|
if (!is.defined(tolerance)) {
|
|
242
245
|
this.options.trimTolerance = 10;
|
|
243
246
|
} else if (is.integer(tolerance) && is.inRange(tolerance, 1, 99)) {
|
|
@@ -246,7 +249,7 @@ const trim = function trim (tolerance) {
|
|
|
246
249
|
throw new Error('Invalid trim tolerance (1 to 99) ' + tolerance);
|
|
247
250
|
}
|
|
248
251
|
return this;
|
|
249
|
-
}
|
|
252
|
+
}
|
|
250
253
|
|
|
251
254
|
/**
|
|
252
255
|
* Apply a gamma correction by reducing the encoding (darken) pre-resize at a factor of `1/gamma`
|
|
@@ -258,7 +261,7 @@ const trim = function trim (tolerance) {
|
|
|
258
261
|
* @returns {Sharp}
|
|
259
262
|
* @throws {Error} Invalid parameters
|
|
260
263
|
*/
|
|
261
|
-
|
|
264
|
+
function gamma (gamma) {
|
|
262
265
|
if (!is.defined(gamma)) {
|
|
263
266
|
// Default gamma correction of 2.2 (sRGB)
|
|
264
267
|
this.options.gamma = 2.2;
|
|
@@ -268,36 +271,36 @@ const gamma = function gamma (gamma) {
|
|
|
268
271
|
throw new Error('Invalid gamma correction (1.0 to 3.0) ' + gamma);
|
|
269
272
|
}
|
|
270
273
|
return this;
|
|
271
|
-
}
|
|
274
|
+
}
|
|
272
275
|
|
|
273
276
|
/**
|
|
274
277
|
* Produce the "negative" of the image.
|
|
275
278
|
* @param {Boolean} [negate=true]
|
|
276
279
|
* @returns {Sharp}
|
|
277
280
|
*/
|
|
278
|
-
|
|
281
|
+
function negate (negate) {
|
|
279
282
|
this.options.negate = is.bool(negate) ? negate : true;
|
|
280
283
|
return this;
|
|
281
|
-
}
|
|
284
|
+
}
|
|
282
285
|
|
|
283
286
|
/**
|
|
284
287
|
* Enhance output image contrast by stretching its luminance to cover the full dynamic range.
|
|
285
288
|
* @param {Boolean} [normalise=true]
|
|
286
289
|
* @returns {Sharp}
|
|
287
290
|
*/
|
|
288
|
-
|
|
291
|
+
function normalise (normalise) {
|
|
289
292
|
this.options.normalise = is.bool(normalise) ? normalise : true;
|
|
290
293
|
return this;
|
|
291
|
-
}
|
|
294
|
+
}
|
|
292
295
|
|
|
293
296
|
/**
|
|
294
297
|
* Alternative spelling of normalise.
|
|
295
298
|
* @param {Boolean} [normalize=true]
|
|
296
299
|
* @returns {Sharp}
|
|
297
300
|
*/
|
|
298
|
-
|
|
301
|
+
function normalize (normalize) {
|
|
299
302
|
return this.normalise(normalize);
|
|
300
|
-
}
|
|
303
|
+
}
|
|
301
304
|
|
|
302
305
|
/**
|
|
303
306
|
* Convolve the image with the specified kernel.
|
|
@@ -324,7 +327,7 @@ const normalize = function normalize (normalize) {
|
|
|
324
327
|
* @returns {Sharp}
|
|
325
328
|
* @throws {Error} Invalid parameters
|
|
326
329
|
*/
|
|
327
|
-
|
|
330
|
+
function convolve (kernel) {
|
|
328
331
|
if (!is.object(kernel) || !Array.isArray(kernel.kernel) ||
|
|
329
332
|
!is.integer(kernel.width) || !is.integer(kernel.height) ||
|
|
330
333
|
!is.inRange(kernel.width, 3, 1001) || !is.inRange(kernel.height, 3, 1001) ||
|
|
@@ -348,7 +351,7 @@ const convolve = function convolve (kernel) {
|
|
|
348
351
|
}
|
|
349
352
|
this.options.convKernel = kernel;
|
|
350
353
|
return this;
|
|
351
|
-
}
|
|
354
|
+
}
|
|
352
355
|
|
|
353
356
|
/**
|
|
354
357
|
* Any pixel value greather than or equal to the threshold value will be set to 255, otherwise it will be set to 0.
|
|
@@ -359,7 +362,7 @@ const convolve = function convolve (kernel) {
|
|
|
359
362
|
* @returns {Sharp}
|
|
360
363
|
* @throws {Error} Invalid parameters
|
|
361
364
|
*/
|
|
362
|
-
|
|
365
|
+
function threshold (threshold, options) {
|
|
363
366
|
if (!is.defined(threshold)) {
|
|
364
367
|
this.options.threshold = 128;
|
|
365
368
|
} else if (is.bool(threshold)) {
|
|
@@ -375,7 +378,7 @@ const threshold = function threshold (threshold, options) {
|
|
|
375
378
|
this.options.thresholdGrayscale = false;
|
|
376
379
|
}
|
|
377
380
|
return this;
|
|
378
|
-
}
|
|
381
|
+
}
|
|
379
382
|
|
|
380
383
|
/**
|
|
381
384
|
* Perform a bitwise boolean operation with operand image.
|
|
@@ -393,7 +396,7 @@ const threshold = function threshold (threshold, options) {
|
|
|
393
396
|
* @returns {Sharp}
|
|
394
397
|
* @throws {Error} Invalid parameters
|
|
395
398
|
*/
|
|
396
|
-
|
|
399
|
+
function boolean (operand, operator, options) {
|
|
397
400
|
this.options.boolean = this._createInputDescriptor(operand, options);
|
|
398
401
|
if (is.string(operator) && is.inArray(operator, ['and', 'or', 'eor'])) {
|
|
399
402
|
this.options.booleanOp = operator;
|
|
@@ -401,7 +404,7 @@ const boolean = function boolean (operand, operator, options) {
|
|
|
401
404
|
throw new Error('Invalid boolean operator ' + operator);
|
|
402
405
|
}
|
|
403
406
|
return this;
|
|
404
|
-
}
|
|
407
|
+
}
|
|
405
408
|
|
|
406
409
|
/**
|
|
407
410
|
* Decorate the Sharp prototype with operation-related functions.
|