sharp 0.20.8 → 0.21.3

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/resize.js CHANGED
@@ -1,9 +1,10 @@
1
1
  'use strict';
2
2
 
3
+ const deprecate = require('util').deprecate;
3
4
  const is = require('./is');
4
5
 
5
6
  /**
6
- * Weighting to apply to image crop.
7
+ * Weighting to apply when using contain/cover fit.
7
8
  * @member
8
9
  * @private
9
10
  */
@@ -21,7 +22,23 @@ const gravity = {
21
22
  };
22
23
 
23
24
  /**
24
- * Strategies for automagic crop behaviour.
25
+ * Position to apply when using contain/cover fit.
26
+ * @member
27
+ * @private
28
+ */
29
+ const position = {
30
+ top: 1,
31
+ right: 2,
32
+ bottom: 3,
33
+ left: 4,
34
+ 'right top': 5,
35
+ 'right bottom': 6,
36
+ 'left bottom': 7,
37
+ 'left top': 8
38
+ };
39
+
40
+ /**
41
+ * Strategies for automagic cover behaviour.
25
42
  * @member
26
43
  * @private
27
44
  */
@@ -38,45 +55,144 @@ const strategy = {
38
55
  const kernel = {
39
56
  nearest: 'nearest',
40
57
  cubic: 'cubic',
58
+ mitchell: 'mitchell',
41
59
  lanczos2: 'lanczos2',
42
60
  lanczos3: 'lanczos3'
43
61
  };
44
62
 
45
63
  /**
46
- * Resize image to `width` x `height`.
47
- * By default, the resized image is centre cropped to the exact size specified.
64
+ * Methods by which an image can be resized to fit the provided dimensions.
65
+ * @member
66
+ * @private
67
+ */
68
+ const fit = {
69
+ contain: 'contain',
70
+ cover: 'cover',
71
+ fill: 'fill',
72
+ inside: 'inside',
73
+ outside: 'outside'
74
+ };
75
+
76
+ /**
77
+ * Map external fit property to internal canvas property.
78
+ * @member
79
+ * @private
80
+ */
81
+ const mapFitToCanvas = {
82
+ contain: 'embed',
83
+ cover: 'crop',
84
+ fill: 'ignore_aspect',
85
+ inside: 'max',
86
+ outside: 'min'
87
+ };
88
+
89
+ /**
90
+ * Resize image to `width`, `height` or `width x height`.
91
+ *
92
+ * When both a `width` and `height` are provided, the possible methods by which the image should **fit** these are:
93
+ * - `cover`: Crop to cover both provided dimensions (the default).
94
+ * - `contain`: Embed within both provided dimensions.
95
+ * - `fill`: Ignore the aspect ratio of the input and stretch to both provided dimensions.
96
+ * - `inside`: Preserving aspect ratio, resize the image to be as large as possible while ensuring its dimensions are less than or equal to both those specified.
97
+ * - `outside`: Preserving aspect ratio, resize the image to be as small as possible while ensuring its dimensions are greater than or equal to both those specified.
98
+ * Some of these values are based on the [object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) CSS property.
99
+ *
100
+ * When using a `fit` of `cover` or `contain`, the default **position** is `centre`. Other options are:
101
+ * - `sharp.position`: `top`, `right top`, `right`, `right bottom`, `bottom`, `left bottom`, `left`, `left top`.
102
+ * - `sharp.gravity`: `north`, `northeast`, `east`, `southeast`, `south`, `southwest`, `west`, `northwest`, `center` or `centre`.
103
+ * - `sharp.strategy`: `cover` only, dynamically crop using either the `entropy` or `attention` strategy.
104
+ * Some of these values are based on the [object-position](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position) CSS property.
105
+ *
106
+ * The experimental strategy-based approach resizes so one dimension is at its target length
107
+ * then repeatedly ranks edge regions, discarding the edge with the lowest score based on the selected strategy.
108
+ * - `entropy`: focus on the region with the highest [Shannon entropy](https://en.wikipedia.org/wiki/Entropy_%28information_theory%29).
109
+ * - `attention`: focus on the region with the highest luminance frequency, colour saturation and presence of skin tones.
48
110
  *
49
- * Possible kernels are:
111
+ * Possible interpolation kernels are:
50
112
  * - `nearest`: Use [nearest neighbour interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation).
51
113
  * - `cubic`: Use a [Catmull-Rom spline](https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline).
114
+ * - `mitchell`: Use a [Mitchell-Netravali spline](https://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf).
52
115
  * - `lanczos2`: Use a [Lanczos kernel](https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel) with `a=2`.
53
116
  * - `lanczos3`: Use a Lanczos kernel with `a=3` (the default).
54
117
  *
55
118
  * @example
56
- * sharp(inputBuffer)
119
+ * sharp(input)
120
+ * .resize({ width: 100 })
121
+ * .toBuffer()
122
+ * .then(data => {
123
+ * // 100 pixels wide, auto-scaled height
124
+ * });
125
+ *
126
+ * @example
127
+ * sharp(input)
128
+ * .resize({ height: 100 })
129
+ * .toBuffer()
130
+ * .then(data => {
131
+ * // 100 pixels high, auto-scaled width
132
+ * });
133
+ *
134
+ * @example
135
+ * sharp(input)
57
136
  * .resize(200, 300, {
58
- * kernel: sharp.kernel.nearest
137
+ * kernel: sharp.kernel.nearest,
138
+ * fit: 'contain',
139
+ * position: 'right top',
140
+ * background: { r: 255, g: 255, b: 255, alpha: 0.5 }
141
+ * })
142
+ * .toFile('output.png')
143
+ * .then(() => {
144
+ * // output.png is a 200 pixels wide and 300 pixels high image
145
+ * // containing a nearest-neighbour scaled version
146
+ * // contained within the north-east corner of a semi-transparent white canvas
147
+ * });
148
+ *
149
+ * @example
150
+ * const transformer = sharp()
151
+ * .resize({
152
+ * width: 200,
153
+ * height: 200,
154
+ * fit: sharp.fit.cover,
155
+ * position: sharp.strategy.entropy
156
+ * });
157
+ * // Read image data from readableStream
158
+ * // Write 200px square auto-cropped image data to writableStream
159
+ * readableStream
160
+ * .pipe(transformer)
161
+ * .pipe(writableStream);
162
+ *
163
+ * @example
164
+ * sharp(input)
165
+ * .resize(200, 200, {
166
+ * fit: sharp.fit.inside,
167
+ * withoutEnlargement: true
59
168
  * })
60
- * .background('white')
61
- * .embed()
62
- * .toFile('output.tiff')
63
- * .then(function() {
64
- * // output.tiff is a 200 pixels wide and 300 pixels high image
65
- * // containing a nearest-neighbour scaled version, embedded on a white canvas,
66
- * // of the image data in inputBuffer
169
+ * .toFormat('jpeg')
170
+ * .toBuffer()
171
+ * .then(function(outputBuffer) {
172
+ * // outputBuffer contains JPEG image data
173
+ * // no wider and no higher than 200 pixels
174
+ * // and no larger than the input image
67
175
  * });
68
176
  *
69
177
  * @param {Number} [width] - pixels wide the resultant image should be. Use `null` or `undefined` to auto-scale the width to match the height.
70
178
  * @param {Number} [height] - pixels high the resultant image should be. Use `null` or `undefined` to auto-scale the height to match the width.
71
179
  * @param {Object} [options]
180
+ * @param {String} [options.width] - alternative means of specifying `width`. If both are present this take priority.
181
+ * @param {String} [options.height] - alternative means of specifying `height`. If both are present this take priority.
182
+ * @param {String} [options.fit='cover'] - how the image should be resized to fit both provided dimensions, one of `cover`, `contain`, `fill`, `inside` or `outside`.
183
+ * @param {String} [options.position='centre'] - position, gravity or strategy to use when `fit` is `cover` or `contain`.
184
+ * @param {String|Object} [options.background={r: 0, g: 0, b: 0, alpha: 1}] - background colour when using a `fit` of `contain`, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to black without transparency.
72
185
  * @param {String} [options.kernel='lanczos3'] - the kernel to use for image reduction.
186
+ * @param {Boolean} [options.withoutEnlargement=false] - do not enlarge if the width *or* height are already less than the specified dimensions, equivalent to GraphicsMagick's `>` geometry option.
73
187
  * @param {Boolean} [options.fastShrinkOnLoad=true] - take greater advantage of the JPEG and WebP shrink-on-load feature, which can lead to a slight moiré pattern on some images.
74
188
  * @returns {Sharp}
75
189
  * @throws {Error} Invalid parameters
76
190
  */
77
191
  function resize (width, height, options) {
78
192
  if (is.defined(width)) {
79
- if (is.integer(width) && width > 0) {
193
+ if (is.object(width) && !is.defined(options)) {
194
+ options = width;
195
+ } else if (is.integer(width) && width > 0) {
80
196
  this.options.width = width;
81
197
  } else {
82
198
  throw is.invalidParameterError('width', 'positive integer', width);
@@ -94,6 +210,38 @@ function resize (width, height, options) {
94
210
  this.options.height = -1;
95
211
  }
96
212
  if (is.object(options)) {
213
+ // Width
214
+ if (is.integer(options.width) && options.width > 0) {
215
+ this.options.width = options.width;
216
+ }
217
+ // Height
218
+ if (is.integer(options.height) && options.height > 0) {
219
+ this.options.height = options.height;
220
+ }
221
+ // Fit
222
+ if (is.defined(options.fit)) {
223
+ const canvas = mapFitToCanvas[options.fit];
224
+ if (is.string(canvas)) {
225
+ this.options.canvas = canvas;
226
+ } else {
227
+ throw is.invalidParameterError('fit', 'valid fit', options.fit);
228
+ }
229
+ }
230
+ // Position
231
+ if (is.defined(options.position)) {
232
+ const pos = is.integer(options.position)
233
+ ? options.position
234
+ : strategy[options.position] || position[options.position] || gravity[options.position];
235
+ if (is.integer(pos) && (is.inRange(pos, 0, 8) || is.inRange(pos, 16, 17))) {
236
+ this.options.position = pos;
237
+ } else {
238
+ throw is.invalidParameterError('position', 'valid position/gravity/strategy', options.position);
239
+ }
240
+ }
241
+ // Background
242
+ if (is.defined(options.background)) {
243
+ this._setColourOption('resizeBackground', options.background);
244
+ }
97
245
  // Kernel
98
246
  if (is.defined(options.kernel)) {
99
247
  if (is.string(kernel[options.kernel])) {
@@ -102,6 +250,10 @@ function resize (width, height, options) {
102
250
  throw is.invalidParameterError('kernel', 'valid kernel name', options.kernel);
103
251
  }
104
252
  }
253
+ // Without enlargement
254
+ if (is.defined(options.withoutEnlargement)) {
255
+ this._setBooleanOption('withoutEnlargement', options.withoutEnlargement);
256
+ }
105
257
  // Shrink on load
106
258
  if (is.defined(options.fastShrinkOnLoad)) {
107
259
  this._setBooleanOption('fastShrinkOnLoad', options.fastShrinkOnLoad);
@@ -111,48 +263,144 @@ function resize (width, height, options) {
111
263
  }
112
264
 
113
265
  /**
114
- * Crop the resized image to the exact size specified, the default behaviour.
266
+ * Extends/pads the edges of the image with the provided background colour.
267
+ * This operation will always occur after resizing and extraction, if any.
115
268
  *
116
- * Possible attributes of the optional `sharp.gravity` are `north`, `northeast`, `east`, `southeast`, `south`,
117
- * `southwest`, `west`, `northwest`, `center` and `centre`.
269
+ * @example
270
+ * // Resize to 140 pixels wide, then add 10 transparent pixels
271
+ * // to the top, left and right edges and 20 to the bottom edge
272
+ * sharp(input)
273
+ * .resize(140)
274
+ * .extend({
275
+ * top: 10,
276
+ * bottom: 20,
277
+ * left: 10,
278
+ * right: 10
279
+ * background: { r: 0, g: 0, b: 0, alpha: 0 }
280
+ * })
281
+ * ...
118
282
  *
119
- * The experimental strategy-based approach resizes so one dimension is at its target length
120
- * then repeatedly ranks edge regions, discarding the edge with the lowest score based on the selected strategy.
121
- * - `entropy`: focus on the region with the highest [Shannon entropy](https://en.wikipedia.org/wiki/Entropy_%28information_theory%29).
122
- * - `attention`: focus on the region with the highest luminance frequency, colour saturation and presence of skin tones.
283
+ * @param {(Number|Object)} extend - single pixel count to add to all edges or an Object with per-edge counts
284
+ * @param {Number} [extend.top]
285
+ * @param {Number} [extend.left]
286
+ * @param {Number} [extend.bottom]
287
+ * @param {Number} [extend.right]
288
+ * @param {String|Object} [extend.background={r: 0, g: 0, b: 0, alpha: 1}] - background colour, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to black without transparency.
289
+ * @returns {Sharp}
290
+ * @throws {Error} Invalid parameters
291
+ */
292
+ function extend (extend) {
293
+ if (is.integer(extend) && extend > 0) {
294
+ this.options.extendTop = extend;
295
+ this.options.extendBottom = extend;
296
+ this.options.extendLeft = extend;
297
+ this.options.extendRight = extend;
298
+ } else if (
299
+ is.object(extend) &&
300
+ is.integer(extend.top) && extend.top >= 0 &&
301
+ is.integer(extend.bottom) && extend.bottom >= 0 &&
302
+ is.integer(extend.left) && extend.left >= 0 &&
303
+ is.integer(extend.right) && extend.right >= 0
304
+ ) {
305
+ this.options.extendTop = extend.top;
306
+ this.options.extendBottom = extend.bottom;
307
+ this.options.extendLeft = extend.left;
308
+ this.options.extendRight = extend.right;
309
+ this._setColourOption('extendBackground', extend.background);
310
+ } else {
311
+ throw new Error('Invalid edge extension ' + extend);
312
+ }
313
+ return this;
314
+ }
315
+
316
+ /**
317
+ * Extract a region of the image.
318
+ *
319
+ * - Use `extract` before `resize` for pre-resize extraction.
320
+ * - Use `extract` after `resize` for post-resize extraction.
321
+ * - Use `extract` before and after for both.
123
322
  *
124
323
  * @example
125
- * const transformer = sharp()
126
- * .resize(200, 200)
127
- * .crop(sharp.strategy.entropy)
128
- * .on('error', function(err) {
129
- * console.log(err);
324
+ * sharp(input)
325
+ * .extract({ left: left, top: top, width: width, height: height })
326
+ * .toFile(output, function(err) {
327
+ * // Extract a region of the input image, saving in the same format.
328
+ * });
329
+ * @example
330
+ * sharp(input)
331
+ * .extract({ left: leftOffsetPre, top: topOffsetPre, width: widthPre, height: heightPre })
332
+ * .resize(width, height)
333
+ * .extract({ left: leftOffsetPost, top: topOffsetPost, width: widthPost, height: heightPost })
334
+ * .toFile(output, function(err) {
335
+ * // Extract a region, resize, then extract from the resized image
130
336
  * });
131
- * // Read image data from readableStream
132
- * // Write 200px square auto-cropped image data to writableStream
133
- * readableStream.pipe(transformer).pipe(writableStream);
134
337
  *
135
- * @param {String} [crop='centre'] - A member of `sharp.gravity` to crop to an edge/corner or `sharp.strategy` to crop dynamically.
338
+ * @param {Object} options
339
+ * @param {Number} options.left - zero-indexed offset from left edge
340
+ * @param {Number} options.top - zero-indexed offset from top edge
341
+ * @param {Number} options.width - dimension of extracted image
342
+ * @param {Number} options.height - dimension of extracted image
136
343
  * @returns {Sharp}
137
344
  * @throws {Error} Invalid parameters
138
345
  */
346
+ function extract (options) {
347
+ const suffix = this.options.width === -1 && this.options.height === -1 ? 'Pre' : 'Post';
348
+ ['left', 'top', 'width', 'height'].forEach(function (name) {
349
+ const value = options[name];
350
+ if (is.integer(value) && value >= 0) {
351
+ this.options[name + (name === 'left' || name === 'top' ? 'Offset' : '') + suffix] = value;
352
+ } else {
353
+ throw new Error('Non-integer value for ' + name + ' of ' + value);
354
+ }
355
+ }, this);
356
+ // Ensure existing rotation occurs before pre-resize extraction
357
+ if (suffix === 'Pre' && ((this.options.angle % 360) !== 0 || this.options.useExifOrientation === true)) {
358
+ this.options.rotateBeforePreExtract = true;
359
+ }
360
+ return this;
361
+ }
362
+
363
+ /**
364
+ * Trim "boring" pixels from all edges that contain values similar to the top-left pixel.
365
+ * The `info` response Object will contain `trimOffsetLeft` and `trimOffsetTop` properties.
366
+ * @param {Number} [threshold=10] the allowed difference from the top-left pixel, a number greater than zero.
367
+ * @returns {Sharp}
368
+ * @throws {Error} Invalid parameters
369
+ */
370
+ function trim (threshold) {
371
+ if (!is.defined(threshold)) {
372
+ this.options.trimThreshold = 10;
373
+ } else if (is.number(threshold) && threshold > 0) {
374
+ this.options.trimThreshold = threshold;
375
+ } else {
376
+ throw is.invalidParameterError('threshold', 'number greater than zero', threshold);
377
+ }
378
+ return this;
379
+ }
380
+
381
+ // Deprecated functions
382
+
383
+ /**
384
+ * @deprecated
385
+ * @private
386
+ */
139
387
  function crop (crop) {
140
388
  this.options.canvas = 'crop';
141
389
  if (!is.defined(crop)) {
142
390
  // Default
143
- this.options.crop = gravity.center;
391
+ this.options.position = gravity.center;
144
392
  } else if (is.integer(crop) && is.inRange(crop, 0, 8)) {
145
393
  // Gravity (numeric)
146
- this.options.crop = crop;
394
+ this.options.position = crop;
147
395
  } else if (is.string(crop) && is.integer(gravity[crop])) {
148
396
  // Gravity (string)
149
- this.options.crop = gravity[crop];
397
+ this.options.position = gravity[crop];
150
398
  } else if (is.integer(crop) && crop >= strategy.entropy) {
151
399
  // Strategy
152
- this.options.crop = crop;
400
+ this.options.position = crop;
153
401
  } else if (is.string(crop) && is.integer(strategy[crop])) {
154
402
  // Strategy (string)
155
- this.options.crop = strategy[crop];
403
+ this.options.position = strategy[crop];
156
404
  } else {
157
405
  throw is.invalidParameterError('crop', 'valid crop id/name/strategy', crop);
158
406
  }
@@ -160,66 +408,29 @@ function crop (crop) {
160
408
  }
161
409
 
162
410
  /**
163
- * Preserving aspect ratio, resize the image to the maximum `width` or `height` specified
164
- * then embed on a background of the exact `width` and `height` specified.
165
- *
166
- * If the background contains an alpha value then WebP and PNG format output images will
167
- * contain an alpha channel, even when the input image does not.
168
- *
169
- * @example
170
- * sharp('input.gif')
171
- * .resize(200, 300)
172
- * .background({r: 0, g: 0, b: 0, alpha: 0})
173
- * .embed()
174
- * .toFormat(sharp.format.webp)
175
- * .toBuffer(function(err, outputBuffer) {
176
- * if (err) {
177
- * throw err;
178
- * }
179
- * // outputBuffer contains WebP image data of a 200 pixels wide and 300 pixels high
180
- * // containing a scaled version, embedded on a transparent canvas, of input.gif
181
- * });
182
- * @param {String} [embed='centre'] - A member of `sharp.gravity` to embed to an edge/corner.
183
- * @returns {Sharp}
184
- * @throws {Error} Invalid parameters
411
+ * @deprecated
412
+ * @private
185
413
  */
186
414
  function embed (embed) {
187
415
  this.options.canvas = 'embed';
188
-
189
416
  if (!is.defined(embed)) {
190
417
  // Default
191
- this.options.embed = gravity.center;
418
+ this.options.position = gravity.center;
192
419
  } else if (is.integer(embed) && is.inRange(embed, 0, 8)) {
193
420
  // Gravity (numeric)
194
- this.options.embed = embed;
421
+ this.options.position = embed;
195
422
  } else if (is.string(embed) && is.integer(gravity[embed])) {
196
423
  // Gravity (string)
197
- this.options.embed = gravity[embed];
424
+ this.options.position = gravity[embed];
198
425
  } else {
199
426
  throw is.invalidParameterError('embed', 'valid embed id/name', embed);
200
427
  }
201
-
202
428
  return this;
203
429
  }
204
430
 
205
431
  /**
206
- * Preserving aspect ratio, resize the image to be as large as possible
207
- * while ensuring its dimensions are less than or equal to the `width` and `height` specified.
208
- *
209
- * Both `width` and `height` must be provided via `resize` otherwise the behaviour will default to `crop`.
210
- *
211
- * @example
212
- * sharp(inputBuffer)
213
- * .resize(200, 200)
214
- * .max()
215
- * .toFormat('jpeg')
216
- * .toBuffer()
217
- * .then(function(outputBuffer) {
218
- * // outputBuffer contains JPEG image data no wider than 200 pixels and no higher
219
- * // than 200 pixels regardless of the inputBuffer image dimensions
220
- * });
221
- *
222
- * @returns {Sharp}
432
+ * @deprecated
433
+ * @private
223
434
  */
224
435
  function max () {
225
436
  this.options.canvas = 'max';
@@ -227,12 +438,8 @@ function max () {
227
438
  }
228
439
 
229
440
  /**
230
- * Preserving aspect ratio, resize the image to be as small as possible
231
- * while ensuring its dimensions are greater than or equal to the `width` and `height` specified.
232
- *
233
- * Both `width` and `height` must be provided via `resize` otherwise the behaviour will default to `crop`.
234
- *
235
- * @returns {Sharp}
441
+ * @deprecated
442
+ * @private
236
443
  */
237
444
  function min () {
238
445
  this.options.canvas = 'min';
@@ -240,9 +447,8 @@ function min () {
240
447
  }
241
448
 
242
449
  /**
243
- * Ignoring the aspect ratio of the input, stretch the image to
244
- * the exact `width` and/or `height` provided via `resize`.
245
- * @returns {Sharp}
450
+ * @deprecated
451
+ * @private
246
452
  */
247
453
  function ignoreAspectRatio () {
248
454
  this.options.canvas = 'ignore_aspect';
@@ -250,15 +456,8 @@ function ignoreAspectRatio () {
250
456
  }
251
457
 
252
458
  /**
253
- * Do not enlarge the output image if the input image width *or* height are already less than the required dimensions.
254
- * This is equivalent to GraphicsMagick's `>` geometry option:
255
- * "*change the dimensions of the image only if its width or height exceeds the geometry specification*".
256
- * Use with `max()` to preserve the image's aspect ratio.
257
- *
258
- * The default behaviour *before* function call is `false`, meaning the image will be enlarged.
259
- *
260
- * @param {Boolean} [withoutEnlargement=true]
261
- * @returns {Sharp}
459
+ * @deprecated
460
+ * @private
262
461
  */
263
462
  function withoutEnlargement (withoutEnlargement) {
264
463
  this.options.withoutEnlargement = is.bool(withoutEnlargement) ? withoutEnlargement : true;
@@ -270,19 +469,23 @@ function withoutEnlargement (withoutEnlargement) {
270
469
  * @private
271
470
  */
272
471
  module.exports = function (Sharp) {
273
- [
472
+ Object.assign(Sharp.prototype, {
274
473
  resize,
275
- crop,
276
- embed,
277
- max,
278
- min,
279
- ignoreAspectRatio,
280
- withoutEnlargement
281
- ].forEach(function (f) {
282
- Sharp.prototype[f.name] = f;
474
+ extend,
475
+ extract,
476
+ trim
283
477
  });
284
478
  // Class attributes
285
479
  Sharp.gravity = gravity;
286
480
  Sharp.strategy = strategy;
287
481
  Sharp.kernel = kernel;
482
+ Sharp.fit = fit;
483
+ Sharp.position = position;
484
+ // Deprecated functions, to be removed in v0.22.0
485
+ Sharp.prototype.crop = deprecate(crop, 'crop(position) is deprecated, use resize({ fit: "cover", position }) instead');
486
+ Sharp.prototype.embed = deprecate(embed, 'embed(position) is deprecated, use resize({ fit: "contain", position }) instead');
487
+ Sharp.prototype.max = deprecate(max, 'max() is deprecated, use resize({ fit: "inside" }) instead');
488
+ Sharp.prototype.min = deprecate(min, 'min() is deprecated, use resize({ fit: "outside" }) instead');
489
+ Sharp.prototype.ignoreAspectRatio = deprecate(ignoreAspectRatio, 'ignoreAspectRatio() is deprecated, use resize({ fit: "fill" }) instead');
490
+ Sharp.prototype.withoutEnlargement = deprecate(withoutEnlargement, 'withoutEnlargement() is deprecated, use resize({ withoutEnlargement: true }) instead');
288
491
  };
package/lib/utility.js CHANGED
@@ -82,23 +82,20 @@ function counters () {
82
82
  * Improves the performance of `resize`, `blur` and `sharpen` operations
83
83
  * by taking advantage of the SIMD vector unit of the CPU, e.g. Intel SSE and ARM NEON.
84
84
  *
85
- * This feature is currently off by default but future versions may reverse this.
86
- * Versions of liborc prior to 0.4.25 are known to segfault under heavy load.
87
- *
88
85
  * @example
89
86
  * const simd = sharp.simd();
90
- * // simd is `true` if SIMD is currently enabled
87
+ * // simd is `true` if the runtime use of liborc is currently enabled
91
88
  * @example
92
- * const simd = sharp.simd(true);
93
- * // attempts to enable the use of SIMD, returning true if available
89
+ * const simd = sharp.simd(false);
90
+ * // prevent libvips from using liborc at runtime
94
91
  *
95
- * @param {Boolean} [simd=false]
92
+ * @param {Boolean} [simd=true]
96
93
  * @returns {Boolean}
97
94
  */
98
95
  function simd (simd) {
99
96
  return sharp.simd(is.bool(simd) ? simd : null);
100
97
  }
101
- simd(false);
98
+ simd(true);
102
99
 
103
100
  /**
104
101
  * Decorate the Sharp class with utility-related functions.
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 and TIFF images",
4
- "version": "0.20.8",
4
+ "version": "0.21.3",
5
5
  "author": "Lovell Fuller <npm@lovell.info>",
6
6
  "homepage": "https://github.com/lovell/sharp",
7
7
  "contributors": [
@@ -54,13 +54,20 @@
54
54
  "Sylvain Dumont <sylvain.dumont35@gmail.com>",
55
55
  "Alun Davies <alun.owain.davies@googlemail.com>",
56
56
  "Aidan Hoolachan <ajhoolachan21@gmail.com>",
57
- "Axel Eirola <axel.eirola@iki.fi>"
57
+ "Axel Eirola <axel.eirola@iki.fi>",
58
+ "Freezy <freezy@xbmc.org>",
59
+ "Daiz <taneli.vatanen@gmail.com>",
60
+ "Julian Aubourg <j@ubourg.net>",
61
+ "Keith Belovay <keith@picthrive.com>",
62
+ "Michael B. Klein <mbklein@gmail.com>"
58
63
  ],
59
64
  "scripts": {
60
65
  "install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node-gyp rebuild && node install/dll-copy)",
61
- "clean": "rm -rf node_modules/ build/ vendor/ coverage/ test/fixtures/output.*",
62
- "test": "semistandard && cc && nyc --reporter=lcov --branches=99 mocha --slow=5000 --timeout=60000 ./test/unit/*.js && prebuild-ci",
63
- "coverage": "./test/coverage/report.sh",
66
+ "clean": "rm -rf node_modules/ build/ vendor/ .nyc_output/ coverage/ test/fixtures/output.*",
67
+ "test": "semistandard && cc && npm run test-unit && npm run test-licensing && prebuild-ci",
68
+ "test-unit": "nyc --reporter=lcov --branches=99 mocha --slow=5000 --timeout=60000 ./test/unit/*.js",
69
+ "test-licensing": "license-checker --production --summary --onlyAllow=\"Apache-2.0;BSD;ISC;MIT\"",
70
+ "test-coverage": "./test/coverage/report.sh",
64
71
  "test-leak": "./test/leak/leak.sh",
65
72
  "docs": "for m in constructor input resize composite operation colour channel output utility; do documentation build --shallow --format=md --markdown-toc=false lib/$m.js >docs/api-$m.md; done"
66
73
  },
@@ -86,38 +93,40 @@
86
93
  "vips"
87
94
  ],
88
95
  "dependencies": {
89
- "color": "^3.0.0",
96
+ "bindings": "^1.3.1",
97
+ "color": "^3.1.0",
90
98
  "detect-libc": "^1.0.3",
91
- "nan": "^2.11.0",
92
99
  "fs-copy-file-sync": "^1.1.1",
100
+ "nan": "^2.12.1",
93
101
  "npmlog": "^4.1.2",
94
- "prebuild-install": "^4.0.0",
95
- "semver": "^5.5.1",
96
- "simple-get": "^2.8.1",
97
- "tar": "^4.4.6",
102
+ "prebuild-install": "^5.2.2",
103
+ "semver": "^5.6.0",
104
+ "simple-get": "^3.0.3",
105
+ "tar": "^4.4.8",
98
106
  "tunnel-agent": "^0.6.0"
99
107
  },
100
108
  "devDependencies": {
101
109
  "async": "^2.6.1",
102
110
  "cc": "^1.0.2",
103
- "decompress-zip": "^0.3.1",
104
- "documentation": "^8.1.2",
111
+ "decompress-zip": "^0.3.2",
112
+ "documentation": "^9.1.1",
105
113
  "exif-reader": "^1.0.2",
106
114
  "icc": "^1.0.0",
115
+ "license-checker": "^25.0.1",
107
116
  "mocha": "^5.2.0",
108
- "mock-fs": "^4.6.0",
109
- "nyc": "^12.0.1",
110
- "prebuild": "^7.6.2",
111
- "prebuild-ci": "^2.2.3",
112
- "rimraf": "^2.6.2",
113
- "semistandard": "^12.0.1"
117
+ "mock-fs": "^4.7.0",
118
+ "nyc": "^13.1.0",
119
+ "prebuild": "^8.1.2",
120
+ "prebuild-ci": "^2.3.0",
121
+ "rimraf": "^2.6.3",
122
+ "semistandard": "^13.0.1"
114
123
  },
115
124
  "license": "Apache-2.0",
116
125
  "config": {
117
- "libvips": "8.6.1"
126
+ "libvips": "8.7.0"
118
127
  },
119
128
  "engines": {
120
- "node": ">=4.5.0"
129
+ "node": ">=6"
121
130
  },
122
131
  "semistandard": {
123
132
  "env": [