sharp 0.25.3 → 0.26.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/lib/output.js CHANGED
@@ -11,7 +11,8 @@ const formats = new Map([
11
11
  ['png', 'png'],
12
12
  ['raw', 'raw'],
13
13
  ['tiff', 'tiff'],
14
- ['webp', 'webp']
14
+ ['webp', 'webp'],
15
+ ['gif', 'gif']
15
16
  ]);
16
17
 
17
18
  /**
@@ -118,7 +119,8 @@ function toBuffer (options, callback) {
118
119
 
119
120
  /**
120
121
  * Include all metadata (EXIF, XMP, IPTC) from the input image in the output image.
121
- * This will also convert to and add a web-friendly sRGB ICC profile.
122
+ * This will also convert to and add a web-friendly sRGB ICC profile unless a custom
123
+ * output profile is provided.
122
124
  *
123
125
  * The default behaviour, when `withMetadata` is not used, is to convert to the device-independent
124
126
  * sRGB colour space and strip all metadata, including the removal of any ICC profile.
@@ -131,6 +133,7 @@ function toBuffer (options, callback) {
131
133
  *
132
134
  * @param {Object} [options]
133
135
  * @param {number} [options.orientation] value between 1 and 8, used to update the EXIF `Orientation` tag.
136
+ * @param {string} [options.icc] filesystem path to output ICC profile, defaults to sRGB.
134
137
  * @returns {Sharp}
135
138
  * @throws {Error} Invalid parameters
136
139
  */
@@ -144,6 +147,13 @@ function withMetadata (options) {
144
147
  throw is.invalidParameterError('orientation', 'integer between 1 and 8', options.orientation);
145
148
  }
146
149
  }
150
+ if (is.defined(options.icc)) {
151
+ if (is.string(options.icc)) {
152
+ this.options.withMetadataIcc = options.icc;
153
+ } else {
154
+ throw is.invalidParameterError('icc', 'string filesystem path to ICC profile', options.icc);
155
+ }
156
+ }
147
157
  }
148
158
  return this;
149
159
  }
@@ -173,6 +183,8 @@ function toFormat (format, options) {
173
183
  /**
174
184
  * Use these JPEG options for output image.
175
185
  *
186
+ * Some of these options require the use of a globally-installed libvips compiled with support for mozjpeg.
187
+ *
176
188
  * @example
177
189
  * // Convert any input to very high quality JPEG output
178
190
  * const data = await sharp(input)
@@ -185,15 +197,15 @@ function toFormat (format, options) {
185
197
  * @param {Object} [options] - output options
186
198
  * @param {number} [options.quality=80] - quality, integer 1-100
187
199
  * @param {boolean} [options.progressive=false] - use progressive (interlace) scan
188
- * @param {string} [options.chromaSubsampling='4:2:0'] - for quality < 90, set to '4:4:4' to prevent chroma subsampling otherwise defaults to '4:2:0' (use chroma subsampling); for quality >= 90 chroma is never subsampled
200
+ * @param {string} [options.chromaSubsampling='4:2:0'] - set to '4:4:4' to prevent chroma subsampling otherwise defaults to '4:2:0' chroma subsampling
201
+ * @param {boolean} [options.optimiseCoding=true] - optimise Huffman coding tables
202
+ * @param {boolean} [options.optimizeCoding=true] - alternative spelling of optimiseCoding
189
203
  * @param {boolean} [options.trellisQuantisation=false] - apply trellis quantisation, requires libvips compiled with support for mozjpeg
190
204
  * @param {boolean} [options.overshootDeringing=false] - apply overshoot deringing, requires libvips compiled with support for mozjpeg
191
205
  * @param {boolean} [options.optimiseScans=false] - optimise progressive scans, forces progressive, requires libvips compiled with support for mozjpeg
192
- * @param {boolean} [options.optimizeScans=false] - alternative spelling of optimiseScans
193
- * @param {boolean} [options.optimiseCoding=true] - optimise Huffman coding tables
194
- * @param {boolean} [options.optimizeCoding=true] - alternative spelling of optimiseCoding
206
+ * @param {boolean} [options.optimizeScans=false] - alternative spelling of optimiseScans, requires libvips compiled with support for mozjpeg
195
207
  * @param {number} [options.quantisationTable=0] - quantization table to use, integer 0-8, requires libvips compiled with support for mozjpeg
196
- * @param {number} [options.quantizationTable=0] - alternative spelling of quantisationTable
208
+ * @param {number} [options.quantizationTable=0] - alternative spelling of quantisationTable, requires libvips compiled with support for mozjpeg
197
209
  * @param {boolean} [options.force=true] - force JPEG output, otherwise attempt to use input format
198
210
  * @returns {Sharp}
199
211
  * @throws {Error} Invalid options
@@ -253,6 +265,8 @@ function jpeg (options) {
253
265
  * PNG output is always full colour at 8 or 16 bits per pixel.
254
266
  * Indexed PNG input at 1, 2 or 4 bits per pixel is converted to 8 bits per pixel.
255
267
  *
268
+ * Some of these options require the use of a globally-installed libvips compiled with support for libimagequant (GPL).
269
+ *
256
270
  * @example
257
271
  * // Convert any input to PNG output
258
272
  * const data = await sharp(input)
@@ -264,10 +278,10 @@ function jpeg (options) {
264
278
  * @param {number} [options.compressionLevel=9] - zlib compression level, 0-9
265
279
  * @param {boolean} [options.adaptiveFiltering=false] - use adaptive row filtering
266
280
  * @param {boolean} [options.palette=false] - quantise to a palette-based image with alpha transparency support, requires libvips compiled with support for libimagequant
267
- * @param {number} [options.quality=100] - use the lowest number of colours needed to achieve given quality, requires libvips compiled with support for libimagequant
268
- * @param {number} [options.colours=256] - maximum number of palette entries, requires libvips compiled with support for libimagequant
269
- * @param {number} [options.colors=256] - alternative spelling of `options.colours`, requires libvips compiled with support for libimagequant
270
- * @param {number} [options.dither=1.0] - level of Floyd-Steinberg error diffusion, requires libvips compiled with support for libimagequant
281
+ * @param {number} [options.quality=100] - use the lowest number of colours needed to achieve given quality, sets `palette` to `true`, requires libvips compiled with support for libimagequant
282
+ * @param {number} [options.colours=256] - maximum number of palette entries, sets `palette` to `true`, requires libvips compiled with support for libimagequant
283
+ * @param {number} [options.colors=256] - alternative spelling of `options.colours`, sets `palette` to `true`, requires libvips compiled with support for libimagequant
284
+ * @param {number} [options.dither=1.0] - level of Floyd-Steinberg error diffusion, sets `palette` to `true`, requires libvips compiled with support for libimagequant
271
285
  * @param {boolean} [options.force=true] - force PNG output, otherwise attempt to use input format
272
286
  * @returns {Sharp}
273
287
  * @throws {Error} Invalid options
@@ -289,28 +303,30 @@ function png (options) {
289
303
  }
290
304
  if (is.defined(options.palette)) {
291
305
  this._setBooleanOption('pngPalette', options.palette);
292
- if (this.options.pngPalette) {
293
- if (is.defined(options.quality)) {
294
- if (is.integer(options.quality) && is.inRange(options.quality, 0, 100)) {
295
- this.options.pngQuality = options.quality;
296
- } else {
297
- throw is.invalidParameterError('quality', 'integer between 0 and 100', options.quality);
298
- }
306
+ } else if (is.defined(options.quality) || is.defined(options.colours || options.colors) || is.defined(options.dither)) {
307
+ this._setBooleanOption('pngPalette', true);
308
+ }
309
+ if (this.options.pngPalette) {
310
+ if (is.defined(options.quality)) {
311
+ if (is.integer(options.quality) && is.inRange(options.quality, 0, 100)) {
312
+ this.options.pngQuality = options.quality;
313
+ } else {
314
+ throw is.invalidParameterError('quality', 'integer between 0 and 100', options.quality);
299
315
  }
300
- const colours = options.colours || options.colors;
301
- if (is.defined(colours)) {
302
- if (is.integer(colours) && is.inRange(colours, 2, 256)) {
303
- this.options.pngColours = colours;
304
- } else {
305
- throw is.invalidParameterError('colours', 'integer between 2 and 256', colours);
306
- }
316
+ }
317
+ const colours = options.colours || options.colors;
318
+ if (is.defined(colours)) {
319
+ if (is.integer(colours) && is.inRange(colours, 2, 256)) {
320
+ this.options.pngColours = colours;
321
+ } else {
322
+ throw is.invalidParameterError('colours', 'integer between 2 and 256', colours);
307
323
  }
308
- if (is.defined(options.dither)) {
309
- if (is.number(options.dither) && is.inRange(options.dither, 0, 1)) {
310
- this.options.pngDither = options.dither;
311
- } else {
312
- throw is.invalidParameterError('dither', 'number between 0.0 and 1.0', options.dither);
313
- }
324
+ }
325
+ if (is.defined(options.dither)) {
326
+ if (is.number(options.dither) && is.inRange(options.dither, 0, 1)) {
327
+ this.options.pngDither = options.dither;
328
+ } else {
329
+ throw is.invalidParameterError('dither', 'number between 0.0 and 1.0', options.dither);
314
330
  }
315
331
  }
316
332
  }
@@ -334,6 +350,9 @@ function png (options) {
334
350
  * @param {boolean} [options.nearLossless=false] - use near_lossless compression mode
335
351
  * @param {boolean} [options.smartSubsample=false] - use high quality chroma subsampling
336
352
  * @param {number} [options.reductionEffort=4] - level of CPU effort to reduce file size, integer 0-6
353
+ * @param {number} [options.pageHeight] - page height for animated output
354
+ * @param {number} [options.loop=0] - number of animation iterations, use 0 for infinite animation
355
+ * @param {number[]} [options.delay] - list of delays between animation frames (in milliseconds)
337
356
  * @param {boolean} [options.force=true] - force WebP output, otherwise attempt to use input format
338
357
  * @returns {Sharp}
339
358
  * @throws {Error} Invalid options
@@ -369,9 +388,73 @@ function webp (options) {
369
388
  throw is.invalidParameterError('reductionEffort', 'integer between 0 and 6', options.reductionEffort);
370
389
  }
371
390
  }
391
+
392
+ trySetAnimationOptions(options, this.options);
372
393
  return this._updateFormatOut('webp', options);
373
394
  }
374
395
 
396
+ /**
397
+ * Use these GIF options for output image.
398
+ *
399
+ * Requires libvips compiled with support for ImageMagick or GraphicsMagick.
400
+ * The prebuilt binaries do not include this - see
401
+ * {@link https://sharp.pixelplumbing.com/install#custom-libvips installing a custom libvips}.
402
+ *
403
+ * @param {Object} [options] - output options
404
+ * @param {number} [options.pageHeight] - page height for animated output
405
+ * @param {number} [options.loop=0] - number of animation iterations, use 0 for infinite animation
406
+ * @param {number[]} [options.delay] - list of delays between animation frames (in milliseconds)
407
+ * @param {boolean} [options.force=true] - force GIF output, otherwise attempt to use input format
408
+ * @returns {Sharp}
409
+ * @throws {Error} Invalid options
410
+ */
411
+ /* istanbul ignore next */
412
+ function gif (options) {
413
+ if (!this.constructor.format.magick.output.buffer) {
414
+ throw new Error('The gif operation requires libvips to have been installed with support for ImageMagick');
415
+ }
416
+ trySetAnimationOptions(options, this.options);
417
+ return this._updateFormatOut('gif', options);
418
+ }
419
+
420
+ /**
421
+ * Set animation options if available.
422
+ * @private
423
+ *
424
+ * @param {Object} [source] - output options
425
+ * @param {number} [source.pageHeight] - page height for animated output
426
+ * @param {number} [source.loop=0] - number of animation iterations, use 0 for infinite animation
427
+ * @param {number[]} [source.delay] - list of delays between animation frames (in milliseconds)
428
+ * @param {Object} [target] - target object for valid options
429
+ * @throws {Error} Invalid options
430
+ */
431
+ function trySetAnimationOptions (source, target) {
432
+ if (is.object(source) && is.defined(source.pageHeight)) {
433
+ if (is.integer(source.pageHeight) && source.pageHeight > 0) {
434
+ target.pageHeight = source.pageHeight;
435
+ } else {
436
+ throw is.invalidParameterError('pageHeight', 'integer larger than 0', source.pageHeight);
437
+ }
438
+ }
439
+ if (is.object(source) && is.defined(source.loop)) {
440
+ if (is.integer(source.loop) && is.inRange(source.loop, 0, 65535)) {
441
+ target.loop = source.loop;
442
+ } else {
443
+ throw is.invalidParameterError('loop', 'integer between 0 and 65535', source.loop);
444
+ }
445
+ }
446
+ if (is.object(source) && is.defined(source.delay)) {
447
+ if (
448
+ Array.isArray(source.delay) &&
449
+ source.delay.every(is.integer) &&
450
+ source.delay.every(v => is.inRange(v, 0, 65535))) {
451
+ target.delay = source.delay;
452
+ } else {
453
+ throw is.invalidParameterError('delay', 'array of integers between 0 and 65535', source.delay);
454
+ }
455
+ }
456
+ }
457
+
375
458
  /**
376
459
  * Use these TIFF options for output image.
377
460
  *
@@ -380,7 +463,7 @@ function webp (options) {
380
463
  * sharp('input.svg')
381
464
  * .tiff({
382
465
  * compression: 'lzw',
383
- * squash: true
466
+ * bitdepth: 1
384
467
  * })
385
468
  * .toFile('1-bpp-output.tiff')
386
469
  * .then(info => { ... });
@@ -396,7 +479,7 @@ function webp (options) {
396
479
  * @param {boolean} [options.tileHeight=256] - vertical tile size
397
480
  * @param {number} [options.xres=1.0] - horizontal resolution in pixels/mm
398
481
  * @param {number} [options.yres=1.0] - vertical resolution in pixels/mm
399
- * @param {boolean} [options.squash=false] - squash 8-bit images down to 1 bit
482
+ * @param {boolean} [options.bitdepth=8] - reduce bitdepth to 1, 2 or 4 bit
400
483
  * @returns {Sharp}
401
484
  * @throws {Error} Invalid options
402
485
  */
@@ -409,8 +492,12 @@ function tiff (options) {
409
492
  throw is.invalidParameterError('quality', 'integer between 1 and 100', options.quality);
410
493
  }
411
494
  }
412
- if (is.defined(options.squash)) {
413
- this._setBooleanOption('tiffSquash', options.squash);
495
+ if (is.defined(options.bitdepth)) {
496
+ if (is.integer(options.bitdepth) && is.inArray(options.bitdepth, [1, 2, 4, 8])) {
497
+ this.options.tiffBitdepth = options.bitdepth;
498
+ } else {
499
+ throw is.invalidParameterError('bitdepth', '1, 2, 4 or 8', options.bitdepth);
500
+ }
414
501
  }
415
502
  // tiling
416
503
  if (is.defined(options.tile)) {
@@ -571,6 +658,8 @@ function raw () {
571
658
  * @param {number} [options.skipBlanks=-1] threshold to skip tile generation, a value 0 - 255 for 8-bit images or 0 - 65535 for 16-bit images
572
659
  * @param {string} [options.container='fs'] tile container, with value `fs` (filesystem) or `zip` (compressed file).
573
660
  * @param {string} [options.layout='dz'] filesystem layout, possible values are `dz`, `iiif`, `zoomify` or `google`.
661
+ * @param {boolean} [options.centre=false] centre image in tile.
662
+ * @param {boolean} [options.center=false] alternative spelling of centre.
574
663
  * @returns {Sharp}
575
664
  * @throws {Error} Invalid parameters
576
665
  */
@@ -639,6 +728,11 @@ function tile (options) {
639
728
  } else if (is.defined(options.layout) && options.layout === 'google') {
640
729
  this.options.tileSkipBlanks = 5;
641
730
  }
731
+ // Center image in tile
732
+ const centre = is.bool(options.center) ? options.center : options.centre;
733
+ if (is.defined(centre)) {
734
+ this._setBooleanOption('tileCentre', centre);
735
+ }
642
736
  }
643
737
  // Format
644
738
  if (is.inArray(this.options.formatOut, ['jpeg', 'png', 'webp'])) {
@@ -798,6 +892,7 @@ module.exports = function (Sharp) {
798
892
  webp,
799
893
  tiff,
800
894
  heif,
895
+ gif,
801
896
  raw,
802
897
  tile,
803
898
  // Private
package/lib/platform.js CHANGED
@@ -13,7 +13,8 @@ module.exports = function () {
13
13
  const platformId = [`${platform}${libc}`];
14
14
 
15
15
  if (arch === 'arm') {
16
- platformId.push(`armv${env.npm_config_arm_version || process.config.variables.arm_version || '6'}`);
16
+ const fallback = process.versions.electron ? '7' : '6';
17
+ platformId.push(`armv${env.npm_config_arm_version || process.config.variables.arm_version || fallback}`);
17
18
  } else if (arch === 'arm64') {
18
19
  platformId.push(`arm64v${env.npm_config_arm_version || '8'}`);
19
20
  } else {
package/lib/resize.js CHANGED
@@ -386,7 +386,8 @@ function extract (options) {
386
386
  * Trim "boring" pixels from all edges that contain values similar to the top-left pixel.
387
387
  * Images consisting entirely of a single colour will calculate "boring" using the alpha channel, if any.
388
388
  *
389
- * The `info` response Object will contain `trimOffsetLeft` and `trimOffsetTop` properties.
389
+ * The `info` response Object, obtained from callback of `.toFile()` or `.toBuffer()`,
390
+ * will contain `trimOffsetLeft` and `trimOffsetTop` properties.
390
391
  *
391
392
  * @param {number} [threshold=10] the allowed difference from the top-left pixel, a number greater than zero.
392
393
  * @returns {Sharp}
package/lib/utility.js CHANGED
@@ -23,7 +23,7 @@ let versions = {
23
23
  vips: sharp.libvipsVersion()
24
24
  };
25
25
  try {
26
- versions = require('../vendor/versions.json');
26
+ versions = require(`../vendor/${versions.vips}/versions.json`);
27
27
  } catch (err) {}
28
28
 
29
29
  /**
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.25.3",
4
+ "version": "0.26.2",
5
5
  "author": "Lovell Fuller <npm@lovell.info>",
6
6
  "homepage": "https://github.com/lovell/sharp",
7
7
  "contributors": [
@@ -66,12 +66,15 @@
66
66
  "Paul Neave <paul.neave@gmail.com>",
67
67
  "Brendan Kennedy <brenwken@gmail.com>",
68
68
  "Brychan Bennett-Odlum <git@brychan.io>",
69
- "Edward Silverton <e.silverton@gmail.com>"
69
+ "Edward Silverton <e.silverton@gmail.com>",
70
+ "Roman Malieiev <aromaleev@gmail.com>",
71
+ "Tomas Szabo <tomas.szabo@deftomat.com>",
72
+ "Robert O'Rourke <robert@o-rourke.org>"
70
73
  ],
71
74
  "scripts": {
72
- "install": "(node install/libvips && node install/dll-copy && prebuild-install --runtime=napi) || (node-gyp rebuild && node install/dll-copy)",
75
+ "install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node-gyp rebuild && node install/dll-copy)",
73
76
  "clean": "rm -rf node_modules/ build/ vendor/ .nyc_output/ coverage/ test/fixtures/output.*",
74
- "test": "semistandard && cpplint && npm run test-unit && npm run test-licensing && prebuild-ci",
77
+ "test": "semistandard && cpplint && npm run test-unit && npm run test-licensing && node install/prebuild-ci",
75
78
  "test-unit": "nyc --reporter=lcov --branches=99 mocha --slow=5000 --timeout=60000 ./test/unit/*.js",
76
79
  "test-licensing": "license-checker --production --summary --onlyAllow=\"Apache-2.0;BSD;ISC;MIT\"",
77
80
  "test-coverage": "./test/coverage/report.sh",
@@ -84,6 +87,7 @@
84
87
  "files": [
85
88
  "binding.gyp",
86
89
  "install/**",
90
+ "!install/prebuild-ci.js",
87
91
  "lib/**",
88
92
  "src/**"
89
93
  ],
@@ -110,36 +114,37 @@
110
114
  "dependencies": {
111
115
  "color": "^3.1.2",
112
116
  "detect-libc": "^1.0.3",
113
- "node-addon-api": "^3.0.0",
117
+ "node-addon-api": "^3.0.2",
114
118
  "npmlog": "^4.1.2",
115
- "prebuild-install": "^5.3.3",
119
+ "prebuild-install": "^5.3.5",
116
120
  "semver": "^7.3.2",
117
121
  "simple-get": "^4.0.0",
118
- "tar": "^6.0.2",
122
+ "tar-fs": "^2.1.0",
119
123
  "tunnel-agent": "^0.6.0"
120
124
  },
121
125
  "devDependencies": {
122
126
  "async": "^3.2.0",
123
127
  "cc": "^2.0.1",
124
128
  "decompress-zip": "^0.3.2",
125
- "documentation": "^13.0.0",
129
+ "documentation": "^13.0.2",
126
130
  "exif-reader": "^1.0.3",
127
- "icc": "^1.0.0",
131
+ "icc": "^2.0.0",
128
132
  "license-checker": "^25.0.1",
129
- "mocha": "^7.1.2",
130
- "mock-fs": "^4.12.0",
131
- "nyc": "^15.0.1",
132
- "prebuild": "^10.0.0",
133
- "prebuild-ci": "^3.1.0",
133
+ "mocha": "^8.1.1",
134
+ "mock-fs": "^4.13.0",
135
+ "nyc": "^15.1.0",
136
+ "prebuild": "^10.0.1",
134
137
  "rimraf": "^3.0.2",
135
- "semistandard": "^14.2.0"
138
+ "semistandard": "^14.2.3"
136
139
  },
137
140
  "license": "Apache-2.0",
138
141
  "config": {
139
- "libvips": "8.9.1"
142
+ "libvips": "8.10.0",
143
+ "runtime": "napi",
144
+ "target": 3
140
145
  },
141
146
  "engines": {
142
- "node": ">=10"
147
+ "node": ">=10.16.0"
143
148
  },
144
149
  "funding": {
145
150
  "url": "https://opencollective.com/libvips"