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/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 90/180/270deg rotation.
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, must be a multiple of 90.
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
- throw new Error('Unsupported angle: angle must be a positive/negative multiple of 90 ' + angle);
42
- }
43
- return this;
44
- }
45
-
46
- /**
47
- * Extract a region of the image.
48
- *
49
- * - Use `extract` before `resize` for pre-resize extraction.
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
- }, this);
86
- // Ensure existing rotation occurs before pre-resize extraction
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
- * Extends/pads the edges of the image with the colour provided to the `background` method.
205
- * This operation will always occur after resizing and extraction, if any.
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 trim (tolerance) {
264
- if (!is.defined(tolerance)) {
265
- this.options.trimTolerance = 10;
266
- } else if (is.integer(tolerance) && is.inRange(tolerance, 1, 99)) {
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, 1, 100)) {
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, 1-100) ' + options.alphaQuality);
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}`);