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/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
  */
@@ -43,40 +60,137 @@ const kernel = {
43
60
  };
44
61
 
45
62
  /**
46
- * Resize image to `width` x `height`.
47
- * By default, the resized image is centre cropped to the exact size specified.
63
+ * Methods by which an image can be resized to fit the provided dimensions.
64
+ * @member
65
+ * @private
66
+ */
67
+ const fit = {
68
+ contain: 'contain',
69
+ cover: 'cover',
70
+ fill: 'fill',
71
+ inside: 'inside',
72
+ outside: 'outside'
73
+ };
74
+
75
+ /**
76
+ * Map external fit property to internal canvas property.
77
+ * @member
78
+ * @private
79
+ */
80
+ const mapFitToCanvas = {
81
+ contain: 'embed',
82
+ cover: 'crop',
83
+ fill: 'ignore_aspect',
84
+ inside: 'max',
85
+ outside: 'min'
86
+ };
87
+
88
+ /**
89
+ * Resize image to `width`, `height` or `width x height`.
90
+ *
91
+ * When both a `width` and `height` are provided, the possible methods by which the image should **fit** these are:
92
+ * - `cover`: Crop to cover both provided dimensions (the default).
93
+ * - `contain`: Embed within both provided dimensions.
94
+ * - `fill`: Ignore the aspect ratio of the input and stretch to both provided dimensions.
95
+ * - `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.
96
+ * - `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.
97
+ * Some of these values are based on the [object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) CSS property.
98
+ *
99
+ * When using a `fit` of `cover` or `contain`, the default **position** is `centre`. Other options are:
100
+ * - `sharp.position`: `top`, `right top`, `right`, `right bottom`, `bottom`, `left bottom`, `left`, `left top`.
101
+ * - `sharp.gravity`: `north`, `northeast`, `east`, `southeast`, `south`, `southwest`, `west`, `northwest`, `center` or `centre`.
102
+ * - `sharp.strategy`: `cover` only, dynamically crop using either the `entropy` or `attention` strategy.
103
+ * Some of these values are based on the [object-position](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position) CSS property.
104
+ *
105
+ * The experimental strategy-based approach resizes so one dimension is at its target length
106
+ * then repeatedly ranks edge regions, discarding the edge with the lowest score based on the selected strategy.
107
+ * - `entropy`: focus on the region with the highest [Shannon entropy](https://en.wikipedia.org/wiki/Entropy_%28information_theory%29).
108
+ * - `attention`: focus on the region with the highest luminance frequency, colour saturation and presence of skin tones.
48
109
  *
49
- * Possible kernels are:
110
+ * Possible interpolation kernels are:
50
111
  * - `nearest`: Use [nearest neighbour interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation).
51
112
  * - `cubic`: Use a [Catmull-Rom spline](https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline).
52
113
  * - `lanczos2`: Use a [Lanczos kernel](https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel) with `a=2`.
53
114
  * - `lanczos3`: Use a Lanczos kernel with `a=3` (the default).
54
115
  *
55
116
  * @example
56
- * sharp(inputBuffer)
117
+ * sharp(input)
118
+ * .resize({ width: 100 })
119
+ * .toBuffer()
120
+ * .then(data => {
121
+ * // 100 pixels wide, auto-scaled height
122
+ * });
123
+ *
124
+ * @example
125
+ * sharp(input)
126
+ * .resize({ height: 100 })
127
+ * .toBuffer()
128
+ * .then(data => {
129
+ * // 100 pixels high, auto-scaled width
130
+ * });
131
+ *
132
+ * @example
133
+ * sharp(input)
57
134
  * .resize(200, 300, {
58
- * kernel: sharp.kernel.nearest
135
+ * kernel: sharp.kernel.nearest,
136
+ * fit: 'contain',
137
+ * position: 'right top',
138
+ * background: { r: 255, g: 255, b: 255, alpha: 0.5 }
139
+ * })
140
+ * .toFile('output.png')
141
+ * .then(() => {
142
+ * // output.png is a 200 pixels wide and 300 pixels high image
143
+ * // containing a nearest-neighbour scaled version
144
+ * // contained within the north-east corner of a semi-transparent white canvas
145
+ * });
146
+ *
147
+ * @example
148
+ * const transformer = sharp()
149
+ * .resize({
150
+ * width: 200,
151
+ * height: 200,
152
+ * fit: sharp.fit.cover,
153
+ * position: sharp.strategy.entropy
154
+ * });
155
+ * // Read image data from readableStream
156
+ * // Write 200px square auto-cropped image data to writableStream
157
+ * readableStream
158
+ * .pipe(transformer)
159
+ * .pipe(writableStream);
160
+ *
161
+ * @example
162
+ * sharp(input)
163
+ * .resize(200, 200, {
164
+ * fit: sharp.fit.inside,
165
+ * withoutEnlargement: true
59
166
  * })
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
167
+ * .toFormat('jpeg')
168
+ * .toBuffer()
169
+ * .then(function(outputBuffer) {
170
+ * // outputBuffer contains JPEG image data
171
+ * // no wider and no higher than 200 pixels
172
+ * // and no larger than the input image
67
173
  * });
68
174
  *
69
175
  * @param {Number} [width] - pixels wide the resultant image should be. Use `null` or `undefined` to auto-scale the width to match the height.
70
176
  * @param {Number} [height] - pixels high the resultant image should be. Use `null` or `undefined` to auto-scale the height to match the width.
71
177
  * @param {Object} [options]
178
+ * @param {String} [options.width] - alternative means of specifying `width`. If both are present this take priority.
179
+ * @param {String} [options.height] - alternative means of specifying `height`. If both are present this take priority.
180
+ * @param {String} [options.fit='cover'] - how the image should be resized to fit both provided dimensions, one of `cover`, `contain`, `fill`, `inside` or `outside`.
181
+ * @param {String} [options.position='centre'] - position, gravity or strategy to use when `fit` is `cover` or `contain`.
182
+ * @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
183
  * @param {String} [options.kernel='lanczos3'] - the kernel to use for image reduction.
184
+ * @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
185
  * @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
186
  * @returns {Sharp}
75
187
  * @throws {Error} Invalid parameters
76
188
  */
77
189
  function resize (width, height, options) {
78
190
  if (is.defined(width)) {
79
- if (is.integer(width) && width > 0) {
191
+ if (is.object(width) && !is.defined(options)) {
192
+ options = width;
193
+ } else if (is.integer(width) && width > 0) {
80
194
  this.options.width = width;
81
195
  } else {
82
196
  throw is.invalidParameterError('width', 'positive integer', width);
@@ -94,6 +208,38 @@ function resize (width, height, options) {
94
208
  this.options.height = -1;
95
209
  }
96
210
  if (is.object(options)) {
211
+ // Width
212
+ if (is.integer(options.width) && options.width > 0) {
213
+ this.options.width = options.width;
214
+ }
215
+ // Height
216
+ if (is.integer(options.height) && options.height > 0) {
217
+ this.options.height = options.height;
218
+ }
219
+ // Fit
220
+ if (is.defined(options.fit)) {
221
+ const canvas = mapFitToCanvas[options.fit];
222
+ if (is.string(canvas)) {
223
+ this.options.canvas = canvas;
224
+ } else {
225
+ throw is.invalidParameterError('fit', 'valid fit', options.fit);
226
+ }
227
+ }
228
+ // Position
229
+ if (is.defined(options.position)) {
230
+ const pos = is.integer(options.position)
231
+ ? options.position
232
+ : strategy[options.position] || position[options.position] || gravity[options.position];
233
+ if (is.integer(pos) && (is.inRange(pos, 0, 8) || is.inRange(pos, 16, 17))) {
234
+ this.options.position = pos;
235
+ } else {
236
+ throw is.invalidParameterError('position', 'valid position/gravity/strategy', options.position);
237
+ }
238
+ }
239
+ // Background
240
+ if (is.defined(options.background)) {
241
+ this._setColourOption('resizeBackground', options.background);
242
+ }
97
243
  // Kernel
98
244
  if (is.defined(options.kernel)) {
99
245
  if (is.string(kernel[options.kernel])) {
@@ -102,6 +248,10 @@ function resize (width, height, options) {
102
248
  throw is.invalidParameterError('kernel', 'valid kernel name', options.kernel);
103
249
  }
104
250
  }
251
+ // Without enlargement
252
+ if (is.defined(options.withoutEnlargement)) {
253
+ this._setBooleanOption('withoutEnlargement', options.withoutEnlargement);
254
+ }
105
255
  // Shrink on load
106
256
  if (is.defined(options.fastShrinkOnLoad)) {
107
257
  this._setBooleanOption('fastShrinkOnLoad', options.fastShrinkOnLoad);
@@ -111,48 +261,145 @@ function resize (width, height, options) {
111
261
  }
112
262
 
113
263
  /**
114
- * Crop the resized image to the exact size specified, the default behaviour.
264
+ * Extends/pads the edges of the image with the provided background colour.
265
+ * This operation will always occur after resizing and extraction, if any.
115
266
  *
116
- * Possible attributes of the optional `sharp.gravity` are `north`, `northeast`, `east`, `southeast`, `south`,
117
- * `southwest`, `west`, `northwest`, `center` and `centre`.
267
+ * @example
268
+ * // Resize to 140 pixels wide, then add 10 transparent pixels
269
+ * // to the top, left and right edges and 20 to the bottom edge
270
+ * sharp(input)
271
+ * .resize(140)
272
+ * .)
273
+ * .extend({
274
+ * top: 10,
275
+ * bottom: 20,
276
+ * left: 10,
277
+ * right: 10
278
+ * background: { r: 0, g: 0, b: 0, alpha: 0 }
279
+ * })
280
+ * ...
118
281
  *
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.
282
+ * @param {(Number|Object)} extend - single pixel count to add to all edges or an Object with per-edge counts
283
+ * @param {Number} [extend.top]
284
+ * @param {Number} [extend.left]
285
+ * @param {Number} [extend.bottom]
286
+ * @param {Number} [extend.right]
287
+ * @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.
288
+ * @returns {Sharp}
289
+ * @throws {Error} Invalid parameters
290
+ */
291
+ function extend (extend) {
292
+ if (is.integer(extend) && extend > 0) {
293
+ this.options.extendTop = extend;
294
+ this.options.extendBottom = extend;
295
+ this.options.extendLeft = extend;
296
+ this.options.extendRight = extend;
297
+ } else if (
298
+ is.object(extend) &&
299
+ is.integer(extend.top) && extend.top >= 0 &&
300
+ is.integer(extend.bottom) && extend.bottom >= 0 &&
301
+ is.integer(extend.left) && extend.left >= 0 &&
302
+ is.integer(extend.right) && extend.right >= 0
303
+ ) {
304
+ this.options.extendTop = extend.top;
305
+ this.options.extendBottom = extend.bottom;
306
+ this.options.extendLeft = extend.left;
307
+ this.options.extendRight = extend.right;
308
+ this._setColourOption('extendBackground', extend.background);
309
+ } else {
310
+ throw new Error('Invalid edge extension ' + extend);
311
+ }
312
+ return this;
313
+ }
314
+
315
+ /**
316
+ * Extract a region of the image.
317
+ *
318
+ * - Use `extract` before `resize` for pre-resize extraction.
319
+ * - Use `extract` after `resize` for post-resize extraction.
320
+ * - Use `extract` before and after for both.
123
321
  *
124
322
  * @example
125
- * const transformer = sharp()
126
- * .resize(200, 200)
127
- * .crop(sharp.strategy.entropy)
128
- * .on('error', function(err) {
129
- * console.log(err);
323
+ * sharp(input)
324
+ * .extract({ left: left, top: top, width: width, height: height })
325
+ * .toFile(output, function(err) {
326
+ * // Extract a region of the input image, saving in the same format.
327
+ * });
328
+ * @example
329
+ * sharp(input)
330
+ * .extract({ left: leftOffsetPre, top: topOffsetPre, width: widthPre, height: heightPre })
331
+ * .resize(width, height)
332
+ * .extract({ left: leftOffsetPost, top: topOffsetPost, width: widthPost, height: heightPost })
333
+ * .toFile(output, function(err) {
334
+ * // Extract a region, resize, then extract from the resized image
130
335
  * });
131
- * // Read image data from readableStream
132
- * // Write 200px square auto-cropped image data to writableStream
133
- * readableStream.pipe(transformer).pipe(writableStream);
134
336
  *
135
- * @param {String} [crop='centre'] - A member of `sharp.gravity` to crop to an edge/corner or `sharp.strategy` to crop dynamically.
337
+ * @param {Object} options
338
+ * @param {Number} options.left - zero-indexed offset from left edge
339
+ * @param {Number} options.top - zero-indexed offset from top edge
340
+ * @param {Number} options.width - dimension of extracted image
341
+ * @param {Number} options.height - dimension of extracted image
136
342
  * @returns {Sharp}
137
343
  * @throws {Error} Invalid parameters
138
344
  */
345
+ function extract (options) {
346
+ const suffix = this.options.width === -1 && this.options.height === -1 ? 'Pre' : 'Post';
347
+ ['left', 'top', 'width', 'height'].forEach(function (name) {
348
+ const value = options[name];
349
+ if (is.integer(value) && value >= 0) {
350
+ this.options[name + (name === 'left' || name === 'top' ? 'Offset' : '') + suffix] = value;
351
+ } else {
352
+ throw new Error('Non-integer value for ' + name + ' of ' + value);
353
+ }
354
+ }, this);
355
+ // Ensure existing rotation occurs before pre-resize extraction
356
+ if (suffix === 'Pre' && ((this.options.angle % 360) !== 0 || this.options.useExifOrientation === true)) {
357
+ this.options.rotateBeforePreExtract = true;
358
+ }
359
+ return this;
360
+ }
361
+
362
+ /**
363
+ * Trim "boring" pixels from all edges that contain values similar to the top-left pixel.
364
+ * The `info` response Object will contain `trimOffsetLeft` and `trimOffsetTop` properties.
365
+ * @param {Number} [threshold=10] the allowed difference from the top-left pixel, a number greater than zero.
366
+ * @returns {Sharp}
367
+ * @throws {Error} Invalid parameters
368
+ */
369
+ function trim (threshold) {
370
+ if (!is.defined(threshold)) {
371
+ this.options.trimThreshold = 10;
372
+ } else if (is.number(threshold) && threshold > 0) {
373
+ this.options.trimThreshold = threshold;
374
+ } else {
375
+ throw is.invalidParameterError('threshold', 'number greater than zero', threshold);
376
+ }
377
+ return this;
378
+ }
379
+
380
+ // Deprecated functions
381
+
382
+ /**
383
+ * @deprecated
384
+ * @private
385
+ */
139
386
  function crop (crop) {
140
387
  this.options.canvas = 'crop';
141
388
  if (!is.defined(crop)) {
142
389
  // Default
143
- this.options.crop = gravity.center;
390
+ this.options.position = gravity.center;
144
391
  } else if (is.integer(crop) && is.inRange(crop, 0, 8)) {
145
392
  // Gravity (numeric)
146
- this.options.crop = crop;
393
+ this.options.position = crop;
147
394
  } else if (is.string(crop) && is.integer(gravity[crop])) {
148
395
  // Gravity (string)
149
- this.options.crop = gravity[crop];
396
+ this.options.position = gravity[crop];
150
397
  } else if (is.integer(crop) && crop >= strategy.entropy) {
151
398
  // Strategy
152
- this.options.crop = crop;
399
+ this.options.position = crop;
153
400
  } else if (is.string(crop) && is.integer(strategy[crop])) {
154
401
  // Strategy (string)
155
- this.options.crop = strategy[crop];
402
+ this.options.position = strategy[crop];
156
403
  } else {
157
404
  throw is.invalidParameterError('crop', 'valid crop id/name/strategy', crop);
158
405
  }
@@ -160,66 +407,29 @@ function crop (crop) {
160
407
  }
161
408
 
162
409
  /**
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
410
+ * @deprecated
411
+ * @private
185
412
  */
186
413
  function embed (embed) {
187
414
  this.options.canvas = 'embed';
188
-
189
415
  if (!is.defined(embed)) {
190
416
  // Default
191
- this.options.embed = gravity.center;
417
+ this.options.position = gravity.center;
192
418
  } else if (is.integer(embed) && is.inRange(embed, 0, 8)) {
193
419
  // Gravity (numeric)
194
- this.options.embed = embed;
420
+ this.options.position = embed;
195
421
  } else if (is.string(embed) && is.integer(gravity[embed])) {
196
422
  // Gravity (string)
197
- this.options.embed = gravity[embed];
423
+ this.options.position = gravity[embed];
198
424
  } else {
199
425
  throw is.invalidParameterError('embed', 'valid embed id/name', embed);
200
426
  }
201
-
202
427
  return this;
203
428
  }
204
429
 
205
430
  /**
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}
431
+ * @deprecated
432
+ * @private
223
433
  */
224
434
  function max () {
225
435
  this.options.canvas = 'max';
@@ -227,12 +437,8 @@ function max () {
227
437
  }
228
438
 
229
439
  /**
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}
440
+ * @deprecated
441
+ * @private
236
442
  */
237
443
  function min () {
238
444
  this.options.canvas = 'min';
@@ -240,9 +446,8 @@ function min () {
240
446
  }
241
447
 
242
448
  /**
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}
449
+ * @deprecated
450
+ * @private
246
451
  */
247
452
  function ignoreAspectRatio () {
248
453
  this.options.canvas = 'ignore_aspect';
@@ -250,15 +455,8 @@ function ignoreAspectRatio () {
250
455
  }
251
456
 
252
457
  /**
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}
458
+ * @deprecated
459
+ * @private
262
460
  */
263
461
  function withoutEnlargement (withoutEnlargement) {
264
462
  this.options.withoutEnlargement = is.bool(withoutEnlargement) ? withoutEnlargement : true;
@@ -272,12 +470,9 @@ function withoutEnlargement (withoutEnlargement) {
272
470
  module.exports = function (Sharp) {
273
471
  [
274
472
  resize,
275
- crop,
276
- embed,
277
- max,
278
- min,
279
- ignoreAspectRatio,
280
- withoutEnlargement
473
+ extend,
474
+ extract,
475
+ trim
281
476
  ].forEach(function (f) {
282
477
  Sharp.prototype[f.name] = f;
283
478
  });
@@ -285,4 +480,13 @@ module.exports = function (Sharp) {
285
480
  Sharp.gravity = gravity;
286
481
  Sharp.strategy = strategy;
287
482
  Sharp.kernel = kernel;
483
+ Sharp.fit = fit;
484
+ Sharp.position = position;
485
+ // Deprecated functions, to be removed in v0.22.0
486
+ Sharp.prototype.crop = deprecate(crop, 'crop(position) is deprecated, use resize({ fit: "cover", position }) instead');
487
+ Sharp.prototype.embed = deprecate(embed, 'embed(position) is deprecated, use resize({ fit: "contain", position }) instead');
488
+ Sharp.prototype.max = deprecate(max, 'max() is deprecated, use resize({ fit: "inside" }) instead');
489
+ Sharp.prototype.min = deprecate(min, 'min() is deprecated, use resize({ fit: "outside" }) instead');
490
+ Sharp.prototype.ignoreAspectRatio = deprecate(ignoreAspectRatio, 'ignoreAspectRatio() is deprecated, use resize({ fit: "fill" }) instead');
491
+ Sharp.prototype.withoutEnlargement = deprecate(withoutEnlargement, 'withoutEnlargement() is deprecated, use resize({ withoutEnlargement: true }) instead');
288
492
  };
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.5",
4
+ "version": "0.21.0",
5
5
  "author": "Lovell Fuller <npm@lovell.info>",
6
6
  "homepage": "https://github.com/lovell/sharp",
7
7
  "contributors": [
@@ -49,11 +49,17 @@
49
49
  "Rik Heywood <rik@rik.org>",
50
50
  "Thomas Parisot <hi@oncletom.io>",
51
51
  "Nathan Graves <nathanrgraves+github@gmail.com>",
52
- "Tom Lokhorst <tom@lokhorst.eu>"
52
+ "Tom Lokhorst <tom@lokhorst.eu>",
53
+ "Espen Hovlandsdal <espen@hovlandsdal.com>",
54
+ "Sylvain Dumont <sylvain.dumont35@gmail.com>",
55
+ "Alun Davies <alun.owain.davies@googlemail.com>",
56
+ "Aidan Hoolachan <ajhoolachan21@gmail.com>",
57
+ "Axel Eirola <axel.eirola@iki.fi>",
58
+ "Freezy <freezy@xbmc.org>"
53
59
  ],
54
60
  "scripts": {
55
61
  "install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node-gyp rebuild && node install/dll-copy)",
56
- "clean": "rm -rf node_modules/ build/ vendor/ coverage/ test/fixtures/output.*",
62
+ "clean": "rm -rf node_modules/ build/ vendor/ .nyc_output/ coverage/ test/fixtures/output.*",
57
63
  "test": "semistandard && cc && nyc --reporter=lcov --branches=99 mocha --slow=5000 --timeout=60000 ./test/unit/*.js && prebuild-ci",
58
64
  "coverage": "./test/coverage/report.sh",
59
65
  "test-leak": "./test/leak/leak.sh",
@@ -83,35 +89,36 @@
83
89
  "dependencies": {
84
90
  "color": "^3.0.0",
85
91
  "detect-libc": "^1.0.3",
86
- "nan": "^2.10.0",
92
+ "nan": "^2.11.1",
87
93
  "fs-copy-file-sync": "^1.1.1",
88
94
  "npmlog": "^4.1.2",
89
- "prebuild-install": "^4.0.0",
90
- "semver": "^5.5.0",
91
- "simple-get": "^2.8.1",
92
- "tar": "^4.4.4",
95
+ "prebuild-install": "^5.2.0",
96
+ "semver": "^5.5.1",
97
+ "simple-get": "^3.0.3",
98
+ "tar": "^4.4.6",
93
99
  "tunnel-agent": "^0.6.0"
94
100
  },
95
101
  "devDependencies": {
96
102
  "async": "^2.6.1",
97
103
  "cc": "^1.0.2",
98
104
  "decompress-zip": "^0.3.1",
99
- "documentation": "^8.0.0",
105
+ "documentation": "^8.1.2",
100
106
  "exif-reader": "^1.0.2",
101
107
  "icc": "^1.0.0",
102
108
  "mocha": "^5.2.0",
103
- "nyc": "^12.0.2",
104
- "prebuild": "^7.6.0",
109
+ "mock-fs": "^4.7.0",
110
+ "nyc": "^13.1.0",
111
+ "prebuild": "^8.1.0",
105
112
  "prebuild-ci": "^2.2.3",
106
113
  "rimraf": "^2.6.2",
107
114
  "semistandard": "^12.0.1"
108
115
  },
109
116
  "license": "Apache-2.0",
110
117
  "config": {
111
- "libvips": "8.6.1"
118
+ "libvips": "8.7.0"
112
119
  },
113
120
  "engines": {
114
- "node": ">=4.5.0"
121
+ "node": ">=6"
115
122
  },
116
123
  "semistandard": {
117
124
  "env": [