sharp 0.20.5 → 0.21.0
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/README.md +3 -3
- package/binding.gyp +5 -0
- package/docs/api-channel.md +16 -0
- package/docs/api-colour.md +1 -19
- package/docs/api-composite.md +2 -3
- package/docs/api-constructor.md +2 -2
- package/docs/api-input.md +6 -2
- package/docs/api-operation.md +40 -115
- package/docs/api-output.md +3 -0
- package/docs/api-resize.md +159 -109
- package/docs/api-utility.md +4 -7
- package/docs/changelog.md +87 -0
- package/docs/index.md +10 -4
- package/docs/install.md +18 -38
- package/docs/performance.md +14 -21
- package/install/dll-copy.js +3 -2
- package/install/libvips.js +55 -36
- package/lib/channel.js +18 -0
- package/lib/colour.js +34 -15
- package/lib/composite.js +2 -3
- package/lib/constructor.js +19 -41
- package/lib/input.js +7 -3
- package/lib/libvips.js +38 -6
- package/lib/operation.js +27 -118
- package/lib/output.js +22 -2
- package/lib/platform.js +4 -1
- package/lib/resize.js +308 -104
- package/lib/utility.js +5 -8
- package/package.json +20 -13
- package/src/common.cc +50 -13
- package/src/common.h +12 -10
- package/src/libvips/cplusplus/VImage.cpp +95 -95
- package/src/libvips/cplusplus/vips-operators.cpp +268 -185
- package/src/metadata.cc +15 -0
- package/src/metadata.h +3 -0
- package/src/operations.cc +27 -54
- package/src/operations.h +6 -1
- package/src/pipeline.cc +81 -89
- package/src/pipeline.h +25 -13
- package/src/stats.cc +11 -8
- package/src/stats.h +3 -1
- package/src/utilities.cc +1 -1
package/lib/operation.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const color = require('color');
|
|
3
4
|
const is = require('./is');
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Rotate the output image by either an explicit angle
|
|
7
8
|
* or auto-orient based on the EXIF `Orientation` tag.
|
|
8
9
|
*
|
|
9
|
-
* If an angle is provided, it is converted to a valid
|
|
10
|
+
* If an angle is provided, it is converted to a valid positive degree rotation.
|
|
10
11
|
* For example, `-450` will produce a 270deg rotation.
|
|
11
12
|
*
|
|
13
|
+
* When rotating by an angle other than a multiple of 90,
|
|
14
|
+
* the background colour can be provided with the `background` option.
|
|
15
|
+
*
|
|
12
16
|
* If no angle is provided, it is determined from the EXIF data.
|
|
13
17
|
* Mirroring is supported and may infer the use of a flip operation.
|
|
14
18
|
*
|
|
@@ -28,64 +32,30 @@ const is = require('./is');
|
|
|
28
32
|
* });
|
|
29
33
|
* readableStream.pipe(pipeline);
|
|
30
34
|
*
|
|
31
|
-
* @param {Number} [angle=auto] angle of rotation
|
|
35
|
+
* @param {Number} [angle=auto] angle of rotation.
|
|
36
|
+
* @param {Object} [options] - if present, is an Object with optional attributes.
|
|
37
|
+
* @param {String|Object} [options.background="#000000"] parsed by the [color](https://www.npmjs.org/package/color) module to extract values for red, green, blue and alpha.
|
|
32
38
|
* @returns {Sharp}
|
|
33
39
|
* @throws {Error} Invalid parameters
|
|
34
40
|
*/
|
|
35
|
-
function rotate (angle) {
|
|
41
|
+
function rotate (angle, options) {
|
|
36
42
|
if (!is.defined(angle)) {
|
|
37
43
|
this.options.useExifOrientation = true;
|
|
38
44
|
} else if (is.integer(angle) && !(angle % 90)) {
|
|
39
45
|
this.options.angle = angle;
|
|
40
|
-
} else {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
*
|
|
49
|
-
|
|
50
|
-
* - Use `extract` after `resize` for post-resize extraction.
|
|
51
|
-
* - Use `extract` before and after for both.
|
|
52
|
-
*
|
|
53
|
-
* @example
|
|
54
|
-
* sharp(input)
|
|
55
|
-
* .extract({ left: left, top: top, width: width, height: height })
|
|
56
|
-
* .toFile(output, function(err) {
|
|
57
|
-
* // Extract a region of the input image, saving in the same format.
|
|
58
|
-
* });
|
|
59
|
-
* @example
|
|
60
|
-
* sharp(input)
|
|
61
|
-
* .extract({ left: leftOffsetPre, top: topOffsetPre, width: widthPre, height: heightPre })
|
|
62
|
-
* .resize(width, height)
|
|
63
|
-
* .extract({ left: leftOffsetPost, top: topOffsetPost, width: widthPost, height: heightPost })
|
|
64
|
-
* .toFile(output, function(err) {
|
|
65
|
-
* // Extract a region, resize, then extract from the resized image
|
|
66
|
-
* });
|
|
67
|
-
*
|
|
68
|
-
* @param {Object} options
|
|
69
|
-
* @param {Number} options.left - zero-indexed offset from left edge
|
|
70
|
-
* @param {Number} options.top - zero-indexed offset from top edge
|
|
71
|
-
* @param {Number} options.width - dimension of extracted image
|
|
72
|
-
* @param {Number} options.height - dimension of extracted image
|
|
73
|
-
* @returns {Sharp}
|
|
74
|
-
* @throws {Error} Invalid parameters
|
|
75
|
-
*/
|
|
76
|
-
function extract (options) {
|
|
77
|
-
const suffix = this.options.width === -1 && this.options.height === -1 ? 'Pre' : 'Post';
|
|
78
|
-
['left', 'top', 'width', 'height'].forEach(function (name) {
|
|
79
|
-
const value = options[name];
|
|
80
|
-
if (is.integer(value) && value >= 0) {
|
|
81
|
-
this.options[name + (name === 'left' || name === 'top' ? 'Offset' : '') + suffix] = value;
|
|
82
|
-
} else {
|
|
83
|
-
throw new Error('Non-integer value for ' + name + ' of ' + value);
|
|
46
|
+
} else if (is.number(angle)) {
|
|
47
|
+
this.options.rotationAngle = angle;
|
|
48
|
+
if (is.object(options) && options.background) {
|
|
49
|
+
const backgroundColour = color(options.background);
|
|
50
|
+
this.options.rotationBackground = [
|
|
51
|
+
backgroundColour.red(),
|
|
52
|
+
backgroundColour.green(),
|
|
53
|
+
backgroundColour.blue(),
|
|
54
|
+
Math.round(backgroundColour.alpha() * 255)
|
|
55
|
+
];
|
|
84
56
|
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (suffix === 'Pre' && ((this.options.angle % 360) !== 0 || this.options.useExifOrientation === true)) {
|
|
88
|
-
this.options.rotateBeforePreExtract = true;
|
|
57
|
+
} else {
|
|
58
|
+
throw new Error('Unsupported angle: must be a number.');
|
|
89
59
|
}
|
|
90
60
|
return this;
|
|
91
61
|
}
|
|
@@ -201,72 +171,14 @@ function blur (sigma) {
|
|
|
201
171
|
}
|
|
202
172
|
|
|
203
173
|
/**
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
* @example
|
|
208
|
-
* // Resize to 140 pixels wide, then add 10 transparent pixels
|
|
209
|
-
* // to the top, left and right edges and 20 to the bottom edge
|
|
210
|
-
* sharp(input)
|
|
211
|
-
* .resize(140)
|
|
212
|
-
* .background({r: 0, g: 0, b: 0, alpha: 0})
|
|
213
|
-
* .extend({top: 10, bottom: 20, left: 10, right: 10})
|
|
214
|
-
* ...
|
|
215
|
-
*
|
|
216
|
-
* @param {(Number|Object)} extend - single pixel count to add to all edges or an Object with per-edge counts
|
|
217
|
-
* @param {Number} [extend.top]
|
|
218
|
-
* @param {Number} [extend.left]
|
|
219
|
-
* @param {Number} [extend.bottom]
|
|
220
|
-
* @param {Number} [extend.right]
|
|
221
|
-
* @returns {Sharp}
|
|
222
|
-
* @throws {Error} Invalid parameters
|
|
223
|
-
*/
|
|
224
|
-
function extend (extend) {
|
|
225
|
-
if (is.integer(extend) && extend > 0) {
|
|
226
|
-
this.options.extendTop = extend;
|
|
227
|
-
this.options.extendBottom = extend;
|
|
228
|
-
this.options.extendLeft = extend;
|
|
229
|
-
this.options.extendRight = extend;
|
|
230
|
-
} else if (
|
|
231
|
-
is.object(extend) &&
|
|
232
|
-
is.integer(extend.top) && extend.top >= 0 &&
|
|
233
|
-
is.integer(extend.bottom) && extend.bottom >= 0 &&
|
|
234
|
-
is.integer(extend.left) && extend.left >= 0 &&
|
|
235
|
-
is.integer(extend.right) && extend.right >= 0
|
|
236
|
-
) {
|
|
237
|
-
this.options.extendTop = extend.top;
|
|
238
|
-
this.options.extendBottom = extend.bottom;
|
|
239
|
-
this.options.extendLeft = extend.left;
|
|
240
|
-
this.options.extendRight = extend.right;
|
|
241
|
-
} else {
|
|
242
|
-
throw new Error('Invalid edge extension ' + extend);
|
|
243
|
-
}
|
|
244
|
-
return this;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Merge alpha transparency channel, if any, with `background`.
|
|
249
|
-
* @param {Boolean} [flatten=true]
|
|
250
|
-
* @returns {Sharp}
|
|
251
|
-
*/
|
|
252
|
-
function flatten (flatten) {
|
|
253
|
-
this.options.flatten = is.bool(flatten) ? flatten : true;
|
|
254
|
-
return this;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Trim "boring" pixels from all edges that contain values within a percentage similarity of the top-left pixel.
|
|
259
|
-
* @param {Number} [tolerance=10] value between 1 and 99 representing the percentage similarity.
|
|
174
|
+
* Merge alpha transparency channel, if any, with a background.
|
|
175
|
+
* @param {String|Object} [options.background={r: 0, g: 0, b: 0}] - background colour, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to black.
|
|
260
176
|
* @returns {Sharp}
|
|
261
|
-
* @throws {Error} Invalid parameters
|
|
262
177
|
*/
|
|
263
|
-
function
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
this.options.trimTolerance = tolerance;
|
|
268
|
-
} else {
|
|
269
|
-
throw new Error('Invalid trim tolerance (1 to 99) ' + tolerance);
|
|
178
|
+
function flatten (options) {
|
|
179
|
+
this.options.flatten = is.bool(options) ? options : true;
|
|
180
|
+
if (is.object(options)) {
|
|
181
|
+
this._setColourOption('flattenBackground', options.background);
|
|
270
182
|
}
|
|
271
183
|
return this;
|
|
272
184
|
}
|
|
@@ -460,15 +372,12 @@ function linear (a, b) {
|
|
|
460
372
|
module.exports = function (Sharp) {
|
|
461
373
|
[
|
|
462
374
|
rotate,
|
|
463
|
-
extract,
|
|
464
375
|
flip,
|
|
465
376
|
flop,
|
|
466
377
|
sharpen,
|
|
467
378
|
median,
|
|
468
379
|
blur,
|
|
469
|
-
extend,
|
|
470
380
|
flatten,
|
|
471
|
-
trim,
|
|
472
381
|
gamma,
|
|
473
382
|
negate,
|
|
474
383
|
normalise,
|
package/lib/output.js
CHANGED
|
@@ -150,6 +150,8 @@ function withMetadata (withMetadata) {
|
|
|
150
150
|
* @param {Boolean} [options.optimizeScans=false] - alternative spelling of optimiseScans
|
|
151
151
|
* @param {Boolean} [options.optimiseCoding=true] - optimise Huffman coding tables
|
|
152
152
|
* @param {Boolean} [options.optimizeCoding=true] - alternative spelling of optimiseCoding
|
|
153
|
+
* @param {Number} [options.quantisationTable=0] - quantization table to use, integer 0-8, requires mozjpeg
|
|
154
|
+
* @param {Number} [options.quantizationTable=0] - alternative spelling of quantisationTable
|
|
153
155
|
* @param {Boolean} [options.force=true] - force JPEG output, otherwise attempt to use input format
|
|
154
156
|
* @returns {Sharp}
|
|
155
157
|
* @throws {Error} Invalid options
|
|
@@ -191,6 +193,14 @@ function jpeg (options) {
|
|
|
191
193
|
if (is.defined(options.optimiseCoding)) {
|
|
192
194
|
this._setBooleanOption('jpegOptimiseCoding', options.optimiseCoding);
|
|
193
195
|
}
|
|
196
|
+
options.quantisationTable = is.number(options.quantizationTable) ? options.quantizationTable : options.quantisationTable;
|
|
197
|
+
if (is.defined(options.quantisationTable)) {
|
|
198
|
+
if (is.integer(options.quantisationTable) && is.inRange(options.quantisationTable, 0, 8)) {
|
|
199
|
+
this.options.jpegQuantisationTable = options.quantisationTable;
|
|
200
|
+
} else {
|
|
201
|
+
throw new Error('Invalid quantisation table (integer, 0-8) ' + options.quantisationTable);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
194
204
|
}
|
|
195
205
|
return this._updateFormatOut('jpeg', options);
|
|
196
206
|
}
|
|
@@ -261,10 +271,10 @@ function webp (options) {
|
|
|
261
271
|
}
|
|
262
272
|
}
|
|
263
273
|
if (is.object(options) && is.defined(options.alphaQuality)) {
|
|
264
|
-
if (is.integer(options.alphaQuality) && is.inRange(options.alphaQuality,
|
|
274
|
+
if (is.integer(options.alphaQuality) && is.inRange(options.alphaQuality, 0, 100)) {
|
|
265
275
|
this.options.webpAlphaQuality = options.alphaQuality;
|
|
266
276
|
} else {
|
|
267
|
-
throw new Error('Invalid webp alpha quality (integer,
|
|
277
|
+
throw new Error('Invalid webp alpha quality (integer, 0-100) ' + options.alphaQuality);
|
|
268
278
|
}
|
|
269
279
|
}
|
|
270
280
|
if (is.object(options) && is.defined(options.lossless)) {
|
|
@@ -413,6 +423,7 @@ function toFormat (format, options) {
|
|
|
413
423
|
* @param {Number} [tile.size=256] tile size in pixels, a value between 1 and 8192.
|
|
414
424
|
* @param {Number} [tile.overlap=0] tile overlap in pixels, a value between 0 and 8192.
|
|
415
425
|
* @param {Number} [tile.angle=0] tile angle of rotation, must be a multiple of 90.
|
|
426
|
+
* @param {String} [tile.depth] how deep to make the pyramid, possible values are `onepixel`, `onetile` or `one`, default based on layout.
|
|
416
427
|
* @param {String} [tile.container='fs'] tile container, with value `fs` (filesystem) or `zip` (compressed file).
|
|
417
428
|
* @param {String} [tile.layout='dz'] filesystem layout, possible values are `dz`, `zoomify` or `google`.
|
|
418
429
|
* @returns {Sharp}
|
|
@@ -464,6 +475,15 @@ function tile (tile) {
|
|
|
464
475
|
throw new Error('Unsupported angle: angle must be a positive/negative multiple of 90 ' + tile.angle);
|
|
465
476
|
}
|
|
466
477
|
}
|
|
478
|
+
|
|
479
|
+
// Depth of tiles
|
|
480
|
+
if (is.defined(tile.depth)) {
|
|
481
|
+
if (is.string(tile.depth) && is.inArray(tile.depth, ['onepixel', 'onetile', 'one'])) {
|
|
482
|
+
this.options.tileDepth = tile.depth;
|
|
483
|
+
} else {
|
|
484
|
+
throw new Error("Invalid tile depth '" + tile.depth + "', should be one of 'onepixel', 'onetile' or 'one'");
|
|
485
|
+
}
|
|
486
|
+
}
|
|
467
487
|
}
|
|
468
488
|
// Format
|
|
469
489
|
if (is.inArray(this.options.formatOut, ['jpeg', 'png', 'webp'])) {
|
package/lib/platform.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const detectLibc = require('detect-libc');
|
|
4
|
+
|
|
3
5
|
module.exports = function () {
|
|
4
6
|
const arch = process.env.npm_config_arch || process.arch;
|
|
5
7
|
const platform = process.env.npm_config_platform || process.platform;
|
|
8
|
+
const libc = (platform === 'linux' && detectLibc.isNonGlibcLinux) ? detectLibc.family : '';
|
|
6
9
|
|
|
7
|
-
const platformId = [platform];
|
|
10
|
+
const platformId = [`${platform}${libc}`];
|
|
8
11
|
if (arch === 'arm' || arch === 'armhf' || arch === 'arm64') {
|
|
9
12
|
const armVersion = (arch === 'arm64') ? '8' : process.env.npm_config_armv || process.config.variables.arm_version || '6';
|
|
10
13
|
platformId.push(`armv${armVersion}`);
|