sharp 0.27.0 → 0.28.1
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 +15 -14
- package/binding.gyp +3 -5
- package/install/dll-copy.js +4 -4
- package/install/libvips.js +67 -31
- package/lib/channel.js +25 -7
- package/lib/colour.js +7 -0
- package/lib/constructor.js +48 -13
- package/lib/input.js +53 -13
- package/lib/is.js +10 -0
- package/lib/libvips.js +25 -3
- package/lib/operation.js +9 -4
- package/lib/output.js +142 -47
- package/lib/resize.js +42 -15
- package/lib/utility.js +17 -10
- package/package.json +13 -13
- package/src/common.cc +86 -43
- package/src/common.h +12 -4
- package/src/metadata.cc +12 -0
- package/src/metadata.h +3 -0
- package/src/operations.cc +1 -1
- package/src/pipeline.cc +54 -14
- package/src/pipeline.h +8 -3
- package/src/sharp.cc +1 -1
- package/src/utilities.cc +16 -0
- package/src/utilities.h +1 -0
package/lib/operation.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const { flatten: flattenArray } = require('array-flatten');
|
|
4
3
|
const color = require('color');
|
|
5
4
|
const is = require('./is');
|
|
6
5
|
|
|
@@ -127,7 +126,7 @@ function flop (flop) {
|
|
|
127
126
|
* @throws {Error} Invalid parameters
|
|
128
127
|
*/
|
|
129
128
|
function affine (matrix, options) {
|
|
130
|
-
const flatMatrix =
|
|
129
|
+
const flatMatrix = [].concat(...matrix);
|
|
131
130
|
if (flatMatrix.length === 4 && flatMatrix.every(is.number)) {
|
|
132
131
|
this.options.affineMatrix = flatMatrix;
|
|
133
132
|
} else {
|
|
@@ -269,7 +268,13 @@ function blur (sigma) {
|
|
|
269
268
|
}
|
|
270
269
|
|
|
271
270
|
/**
|
|
272
|
-
* Merge alpha transparency channel, if any, with a background.
|
|
271
|
+
* Merge alpha transparency channel, if any, with a background, then remove the alpha channel.
|
|
272
|
+
*
|
|
273
|
+
* @example
|
|
274
|
+
* await sharp(rgbaInput)
|
|
275
|
+
* .flatten('#F0A703')
|
|
276
|
+
* .toBuffer();
|
|
277
|
+
*
|
|
273
278
|
* @param {Object} [options]
|
|
274
279
|
* @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.
|
|
275
280
|
* @returns {Sharp}
|
|
@@ -397,7 +402,7 @@ function convolve (kernel) {
|
|
|
397
402
|
}
|
|
398
403
|
|
|
399
404
|
/**
|
|
400
|
-
* Any pixel value
|
|
405
|
+
* Any pixel value greater than or equal to the threshold value will be set to 255, otherwise it will be set to 0.
|
|
401
406
|
* @param {number} [threshold=128] - a value in the range 0-255 representing the level at which the threshold will be applied.
|
|
402
407
|
* @param {Object} [options]
|
|
403
408
|
* @param {Boolean} [options.greyscale=true] - convert to single channel greyscale.
|
package/lib/output.js
CHANGED
|
@@ -16,6 +16,8 @@ const formats = new Map([
|
|
|
16
16
|
['gif', 'gif']
|
|
17
17
|
]);
|
|
18
18
|
|
|
19
|
+
const errMagickSave = new Error('GIF output requires libvips with support for ImageMagick');
|
|
20
|
+
|
|
19
21
|
/**
|
|
20
22
|
* Write output image data to a file.
|
|
21
23
|
*
|
|
@@ -47,25 +49,23 @@ const formats = new Map([
|
|
|
47
49
|
* @throws {Error} Invalid parameters
|
|
48
50
|
*/
|
|
49
51
|
function toFile (fileOut, callback) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
let err;
|
|
53
|
+
if (!is.string(fileOut)) {
|
|
54
|
+
err = new Error('Missing output file path');
|
|
55
|
+
} else if (this.options.input.file === fileOut) {
|
|
56
|
+
err = new Error('Cannot use same file for input and output');
|
|
57
|
+
} else if (this.options.formatOut === 'input' && fileOut.toLowerCase().endsWith('.gif') && !this.constructor.format.magick.output.file) {
|
|
58
|
+
err = errMagickSave;
|
|
59
|
+
}
|
|
60
|
+
if (err) {
|
|
52
61
|
if (is.fn(callback)) {
|
|
53
|
-
callback(
|
|
62
|
+
callback(err);
|
|
54
63
|
} else {
|
|
55
|
-
return Promise.reject(
|
|
64
|
+
return Promise.reject(err);
|
|
56
65
|
}
|
|
57
66
|
} else {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (is.fn(callback)) {
|
|
61
|
-
callback(errOutputIsInput);
|
|
62
|
-
} else {
|
|
63
|
-
return Promise.reject(errOutputIsInput);
|
|
64
|
-
}
|
|
65
|
-
} else {
|
|
66
|
-
this.options.fileOut = fileOut;
|
|
67
|
-
return this._pipeline(callback);
|
|
68
|
-
}
|
|
67
|
+
this.options.fileOut = fileOut;
|
|
68
|
+
return this._pipeline(callback);
|
|
69
69
|
}
|
|
70
70
|
return this;
|
|
71
71
|
}
|
|
@@ -104,6 +104,22 @@ function toFile (fileOut, callback) {
|
|
|
104
104
|
* .then(({ data, info }) => { ... })
|
|
105
105
|
* .catch(err => { ... });
|
|
106
106
|
*
|
|
107
|
+
* @example
|
|
108
|
+
* const { data, info } = await sharp('my-image.jpg')
|
|
109
|
+
* // output the raw pixels
|
|
110
|
+
* .raw()
|
|
111
|
+
* .toBuffer({ resolveWithObject: true });
|
|
112
|
+
*
|
|
113
|
+
* // create a more type safe way to work with the raw pixel data
|
|
114
|
+
* // this will not copy the data, instead it will change `data`s underlying ArrayBuffer
|
|
115
|
+
* // so `data` and `pixelArray` point to the same memory location
|
|
116
|
+
* const pixelArray = new Uint8ClampedArray(data.buffer);
|
|
117
|
+
*
|
|
118
|
+
* // When you are done changing the pixelArray, sharp takes the `pixelArray` as an input
|
|
119
|
+
* const { width, height, channels } = info;
|
|
120
|
+
* await sharp(pixelArray, { raw: { width, height, channels } })
|
|
121
|
+
* .toFile('my-changed-image.jpg');
|
|
122
|
+
*
|
|
107
123
|
* @param {Object} [options]
|
|
108
124
|
* @param {boolean} [options.resolveWithObject] Resolve the Promise with an Object containing `data` and `info` properties instead of resolving only with `data`.
|
|
109
125
|
* @param {Function} [callback]
|
|
@@ -132,9 +148,22 @@ function toBuffer (options, callback) {
|
|
|
132
148
|
* .toFile('output-with-metadata.jpg')
|
|
133
149
|
* .then(info => { ... });
|
|
134
150
|
*
|
|
151
|
+
* @example
|
|
152
|
+
* // Set "IFD0-Copyright" in output EXIF metadata
|
|
153
|
+
* await sharp(input)
|
|
154
|
+
* .withMetadata({
|
|
155
|
+
* exif: {
|
|
156
|
+
* IFD0: {
|
|
157
|
+
* Copyright: 'Wernham Hogg'
|
|
158
|
+
* }
|
|
159
|
+
* }
|
|
160
|
+
* })
|
|
161
|
+
* .toBuffer();
|
|
162
|
+
*
|
|
135
163
|
* @param {Object} [options]
|
|
136
164
|
* @param {number} [options.orientation] value between 1 and 8, used to update the EXIF `Orientation` tag.
|
|
137
165
|
* @param {string} [options.icc] filesystem path to output ICC profile, defaults to sRGB.
|
|
166
|
+
* @param {Object<Object>} [options.exif={}] Object keyed by IFD0, IFD1 etc. of key/value string pairs to write as EXIF data.
|
|
138
167
|
* @returns {Sharp}
|
|
139
168
|
* @throws {Error} Invalid parameters
|
|
140
169
|
*/
|
|
@@ -155,6 +184,25 @@ function withMetadata (options) {
|
|
|
155
184
|
throw is.invalidParameterError('icc', 'string filesystem path to ICC profile', options.icc);
|
|
156
185
|
}
|
|
157
186
|
}
|
|
187
|
+
if (is.defined(options.exif)) {
|
|
188
|
+
if (is.object(options.exif)) {
|
|
189
|
+
for (const [ifd, entries] of Object.entries(options.exif)) {
|
|
190
|
+
if (is.object(entries)) {
|
|
191
|
+
for (const [k, v] of Object.entries(entries)) {
|
|
192
|
+
if (is.string(v)) {
|
|
193
|
+
this.options.withMetadataStrs[`exif-${ifd.toLowerCase()}-${k}`] = v;
|
|
194
|
+
} else {
|
|
195
|
+
throw is.invalidParameterError(`exif.${ifd}.${k}`, 'string', v);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
} else {
|
|
199
|
+
throw is.invalidParameterError(`exif.${ifd}`, 'object', entries);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
} else {
|
|
203
|
+
throw is.invalidParameterError('exif', 'object', options.exif);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
158
206
|
}
|
|
159
207
|
return this;
|
|
160
208
|
}
|
|
@@ -174,7 +222,7 @@ function withMetadata (options) {
|
|
|
174
222
|
* @throws {Error} unsupported format or options
|
|
175
223
|
*/
|
|
176
224
|
function toFormat (format, options) {
|
|
177
|
-
const actualFormat = formats.get(is.object(format) && is.string(format.id) ? format.id : format);
|
|
225
|
+
const actualFormat = formats.get((is.object(format) && is.string(format.id) ? format.id : format).toLowerCase());
|
|
178
226
|
if (!actualFormat) {
|
|
179
227
|
throw is.invalidParameterError('format', `one of: ${[...formats.keys()].join(', ')}`, format);
|
|
180
228
|
}
|
|
@@ -184,8 +232,6 @@ function toFormat (format, options) {
|
|
|
184
232
|
/**
|
|
185
233
|
* Use these JPEG options for output image.
|
|
186
234
|
*
|
|
187
|
-
* Some of these options require the use of a globally-installed libvips compiled with support for mozjpeg.
|
|
188
|
-
*
|
|
189
235
|
* @example
|
|
190
236
|
* // Convert any input to very high quality JPEG output
|
|
191
237
|
* const data = await sharp(input)
|
|
@@ -195,18 +241,25 @@ function toFormat (format, options) {
|
|
|
195
241
|
* })
|
|
196
242
|
* .toBuffer();
|
|
197
243
|
*
|
|
244
|
+
* @example
|
|
245
|
+
* // Use mozjpeg to reduce output JPEG file size (slower)
|
|
246
|
+
* const data = await sharp(input)
|
|
247
|
+
* .jpeg({ mozjpeg: true })
|
|
248
|
+
* .toBuffer();
|
|
249
|
+
*
|
|
198
250
|
* @param {Object} [options] - output options
|
|
199
251
|
* @param {number} [options.quality=80] - quality, integer 1-100
|
|
200
252
|
* @param {boolean} [options.progressive=false] - use progressive (interlace) scan
|
|
201
253
|
* @param {string} [options.chromaSubsampling='4:2:0'] - set to '4:4:4' to prevent chroma subsampling otherwise defaults to '4:2:0' chroma subsampling
|
|
202
254
|
* @param {boolean} [options.optimiseCoding=true] - optimise Huffman coding tables
|
|
203
255
|
* @param {boolean} [options.optimizeCoding=true] - alternative spelling of optimiseCoding
|
|
204
|
-
* @param {boolean} [options.
|
|
205
|
-
* @param {boolean} [options.
|
|
206
|
-
* @param {boolean} [options.
|
|
207
|
-
* @param {boolean} [options.
|
|
208
|
-
* @param {
|
|
209
|
-
* @param {number} [options.
|
|
256
|
+
* @param {boolean} [options.mozjpeg=false] - use mozjpeg defaults, equivalent to `{ trellisQuantisation: true, overshootDeringing: true, optimiseScans: true, quantisationTable: 3 }`
|
|
257
|
+
* @param {boolean} [options.trellisQuantisation=false] - apply trellis quantisation
|
|
258
|
+
* @param {boolean} [options.overshootDeringing=false] - apply overshoot deringing
|
|
259
|
+
* @param {boolean} [options.optimiseScans=false] - optimise progressive scans, forces progressive
|
|
260
|
+
* @param {boolean} [options.optimizeScans=false] - alternative spelling of optimiseScans
|
|
261
|
+
* @param {number} [options.quantisationTable=0] - quantization table to use, integer 0-8
|
|
262
|
+
* @param {number} [options.quantizationTable=0] - alternative spelling of quantisationTable
|
|
210
263
|
* @param {boolean} [options.force=true] - force JPEG output, otherwise attempt to use input format
|
|
211
264
|
* @returns {Sharp}
|
|
212
265
|
* @throws {Error} Invalid options
|
|
@@ -230,6 +283,23 @@ function jpeg (options) {
|
|
|
230
283
|
throw is.invalidParameterError('chromaSubsampling', 'one of: 4:2:0, 4:4:4', options.chromaSubsampling);
|
|
231
284
|
}
|
|
232
285
|
}
|
|
286
|
+
const optimiseCoding = is.bool(options.optimizeCoding) ? options.optimizeCoding : options.optimiseCoding;
|
|
287
|
+
if (is.defined(optimiseCoding)) {
|
|
288
|
+
this._setBooleanOption('jpegOptimiseCoding', optimiseCoding);
|
|
289
|
+
}
|
|
290
|
+
if (is.defined(options.mozjpeg)) {
|
|
291
|
+
if (is.bool(options.mozjpeg)) {
|
|
292
|
+
if (options.mozjpeg) {
|
|
293
|
+
this.options.jpegTrellisQuantisation = true;
|
|
294
|
+
this.options.jpegOvershootDeringing = true;
|
|
295
|
+
this.options.jpegOptimiseScans = true;
|
|
296
|
+
this.options.jpegProgressive = true;
|
|
297
|
+
this.options.jpegQuantisationTable = 3;
|
|
298
|
+
}
|
|
299
|
+
} else {
|
|
300
|
+
throw is.invalidParameterError('mozjpeg', 'boolean', options.mozjpeg);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
233
303
|
const trellisQuantisation = is.bool(options.trellisQuantization) ? options.trellisQuantization : options.trellisQuantisation;
|
|
234
304
|
if (is.defined(trellisQuantisation)) {
|
|
235
305
|
this._setBooleanOption('jpegTrellisQuantisation', trellisQuantisation);
|
|
@@ -244,10 +314,6 @@ function jpeg (options) {
|
|
|
244
314
|
this.options.jpegProgressive = true;
|
|
245
315
|
}
|
|
246
316
|
}
|
|
247
|
-
const optimiseCoding = is.bool(options.optimizeCoding) ? options.optimizeCoding : options.optimiseCoding;
|
|
248
|
-
if (is.defined(optimiseCoding)) {
|
|
249
|
-
this._setBooleanOption('jpegOptimiseCoding', optimiseCoding);
|
|
250
|
-
}
|
|
251
317
|
const quantisationTable = is.number(options.quantizationTable) ? options.quantizationTable : options.quantisationTable;
|
|
252
318
|
if (is.defined(quantisationTable)) {
|
|
253
319
|
if (is.integer(quantisationTable) && is.inRange(quantisationTable, 0, 8)) {
|
|
@@ -263,26 +329,31 @@ function jpeg (options) {
|
|
|
263
329
|
/**
|
|
264
330
|
* Use these PNG options for output image.
|
|
265
331
|
*
|
|
266
|
-
* PNG output is
|
|
332
|
+
* By default, PNG output is full colour at 8 or 16 bits per pixel.
|
|
267
333
|
* Indexed PNG input at 1, 2 or 4 bits per pixel is converted to 8 bits per pixel.
|
|
268
|
-
*
|
|
269
|
-
* Some of these options require the use of a globally-installed libvips compiled with support for libimagequant (GPL).
|
|
334
|
+
* Set `palette` to `true` for slower, indexed PNG output.
|
|
270
335
|
*
|
|
271
336
|
* @example
|
|
272
|
-
* // Convert any input to PNG output
|
|
337
|
+
* // Convert any input to full colour PNG output
|
|
273
338
|
* const data = await sharp(input)
|
|
274
339
|
* .png()
|
|
275
340
|
* .toBuffer();
|
|
276
341
|
*
|
|
342
|
+
* @example
|
|
343
|
+
* // Convert any input to indexed PNG output (slower)
|
|
344
|
+
* const data = await sharp(input)
|
|
345
|
+
* .png({ palette: true })
|
|
346
|
+
* .toBuffer();
|
|
347
|
+
*
|
|
277
348
|
* @param {Object} [options]
|
|
278
349
|
* @param {boolean} [options.progressive=false] - use progressive (interlace) scan
|
|
279
|
-
* @param {number} [options.compressionLevel=
|
|
350
|
+
* @param {number} [options.compressionLevel=6] - zlib compression level, 0 (fastest, largest) to 9 (slowest, smallest)
|
|
280
351
|
* @param {boolean} [options.adaptiveFiltering=false] - use adaptive row filtering
|
|
281
|
-
* @param {boolean} [options.palette=false] - quantise to a palette-based image with alpha transparency support
|
|
282
|
-
* @param {number} [options.quality=100] - use the lowest number of colours needed to achieve given quality, sets `palette` to `true
|
|
283
|
-
* @param {number} [options.colours=256] - maximum number of palette entries, sets `palette` to `true
|
|
284
|
-
* @param {number} [options.colors=256] - alternative spelling of `options.colours`, sets `palette` to `true
|
|
285
|
-
* @param {number} [options.dither=1.0] - level of Floyd-Steinberg error diffusion, sets `palette` to `true
|
|
352
|
+
* @param {boolean} [options.palette=false] - quantise to a palette-based image with alpha transparency support
|
|
353
|
+
* @param {number} [options.quality=100] - use the lowest number of colours needed to achieve given quality, sets `palette` to `true`
|
|
354
|
+
* @param {number} [options.colours=256] - maximum number of palette entries, sets `palette` to `true`
|
|
355
|
+
* @param {number} [options.colors=256] - alternative spelling of `options.colours`, sets `palette` to `true`
|
|
356
|
+
* @param {number} [options.dither=1.0] - level of Floyd-Steinberg error diffusion, sets `palette` to `true`
|
|
286
357
|
* @param {boolean} [options.force=true] - force PNG output, otherwise attempt to use input format
|
|
287
358
|
* @returns {Sharp}
|
|
288
359
|
* @throws {Error} Invalid options
|
|
@@ -344,6 +415,12 @@ function png (options) {
|
|
|
344
415
|
* .webp({ lossless: true })
|
|
345
416
|
* .toBuffer();
|
|
346
417
|
*
|
|
418
|
+
* @example
|
|
419
|
+
* // Optimise the file size of an animated WebP
|
|
420
|
+
* const outputWebp = await sharp(inputWebp, { animated: true })
|
|
421
|
+
* .webp({ reductionEffort: 6 })
|
|
422
|
+
* .toBuffer();
|
|
423
|
+
*
|
|
347
424
|
* @param {Object} [options] - output options
|
|
348
425
|
* @param {number} [options.quality=80] - quality, integer 1-100
|
|
349
426
|
* @param {number} [options.alphaQuality=100] - quality of alpha layer, integer 0-100
|
|
@@ -412,7 +489,7 @@ function webp (options) {
|
|
|
412
489
|
/* istanbul ignore next */
|
|
413
490
|
function gif (options) {
|
|
414
491
|
if (!this.constructor.format.magick.output.buffer) {
|
|
415
|
-
throw
|
|
492
|
+
throw errMagickSave;
|
|
416
493
|
}
|
|
417
494
|
trySetAnimationOptions(options, this.options);
|
|
418
495
|
return this._updateFormatOut('gif', options);
|
|
@@ -472,15 +549,15 @@ function trySetAnimationOptions (source, target) {
|
|
|
472
549
|
* @param {Object} [options] - output options
|
|
473
550
|
* @param {number} [options.quality=80] - quality, integer 1-100
|
|
474
551
|
* @param {boolean} [options.force=true] - force TIFF output, otherwise attempt to use input format
|
|
475
|
-
* @param {
|
|
476
|
-
* @param {
|
|
552
|
+
* @param {string} [options.compression='jpeg'] - compression options: lzw, deflate, jpeg, ccittfax4
|
|
553
|
+
* @param {string} [options.predictor='horizontal'] - compression predictor options: none, horizontal, float
|
|
477
554
|
* @param {boolean} [options.pyramid=false] - write an image pyramid
|
|
478
555
|
* @param {boolean} [options.tile=false] - write a tiled tiff
|
|
479
|
-
* @param {
|
|
480
|
-
* @param {
|
|
556
|
+
* @param {number} [options.tileWidth=256] - horizontal tile size
|
|
557
|
+
* @param {number} [options.tileHeight=256] - vertical tile size
|
|
481
558
|
* @param {number} [options.xres=1.0] - horizontal resolution in pixels/mm
|
|
482
559
|
* @param {number} [options.yres=1.0] - vertical resolution in pixels/mm
|
|
483
|
-
* @param {
|
|
560
|
+
* @param {number} [options.bitdepth=8] - reduce bitdepth to 1, 2 or 4 bit
|
|
484
561
|
* @returns {Sharp}
|
|
485
562
|
* @throws {Error} Invalid options
|
|
486
563
|
*/
|
|
@@ -568,7 +645,8 @@ function tiff (options) {
|
|
|
568
645
|
* @param {Object} [options] - output options
|
|
569
646
|
* @param {number} [options.quality=50] - quality, integer 1-100
|
|
570
647
|
* @param {boolean} [options.lossless=false] - use lossless compression
|
|
571
|
-
* @param {
|
|
648
|
+
* @param {number} [options.speed=5] - CPU effort vs file size, 0 (slowest/smallest) to 8 (fastest/largest)
|
|
649
|
+
* @param {string} [options.chromaSubsampling='4:2:0'] - set to '4:4:4' to prevent chroma subsampling otherwise defaults to '4:2:0' chroma subsampling, requires libvips v8.11.0
|
|
572
650
|
* @returns {Sharp}
|
|
573
651
|
* @throws {Error} Invalid options
|
|
574
652
|
*/
|
|
@@ -586,9 +664,10 @@ function avif (options) {
|
|
|
586
664
|
*
|
|
587
665
|
* @param {Object} [options] - output options
|
|
588
666
|
* @param {number} [options.quality=50] - quality, integer 1-100
|
|
589
|
-
* @param {
|
|
667
|
+
* @param {string} [options.compression='av1'] - compression format: av1, hevc
|
|
590
668
|
* @param {boolean} [options.lossless=false] - use lossless compression
|
|
591
|
-
* @param {
|
|
669
|
+
* @param {number} [options.speed=5] - CPU effort vs file size, 0 (slowest/smallest) to 8 (fastest/largest)
|
|
670
|
+
* @param {string} [options.chromaSubsampling='4:2:0'] - set to '4:4:4' to prevent chroma subsampling otherwise defaults to '4:2:0' chroma subsampling, requires libvips v8.11.0
|
|
592
671
|
* @returns {Sharp}
|
|
593
672
|
* @throws {Error} Invalid options
|
|
594
673
|
*/
|
|
@@ -622,6 +701,13 @@ function heif (options) {
|
|
|
622
701
|
throw is.invalidParameterError('speed', 'integer between 0 and 8', options.speed);
|
|
623
702
|
}
|
|
624
703
|
}
|
|
704
|
+
if (is.defined(options.chromaSubsampling)) {
|
|
705
|
+
if (is.string(options.chromaSubsampling) && is.inArray(options.chromaSubsampling, ['4:2:0', '4:4:4'])) {
|
|
706
|
+
this.options.heifChromaSubsampling = options.chromaSubsampling;
|
|
707
|
+
} else {
|
|
708
|
+
throw is.invalidParameterError('chromaSubsampling', 'one of: 4:2:0, 4:4:4', options.chromaSubsampling);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
625
711
|
}
|
|
626
712
|
return this._updateFormatOut('heif', options);
|
|
627
713
|
}
|
|
@@ -681,6 +767,7 @@ function raw () {
|
|
|
681
767
|
* @param {string} [options.layout='dz'] filesystem layout, possible values are `dz`, `iiif`, `zoomify` or `google`.
|
|
682
768
|
* @param {boolean} [options.centre=false] centre image in tile.
|
|
683
769
|
* @param {boolean} [options.center=false] alternative spelling of centre.
|
|
770
|
+
* @param {string} [options.id='https://example.com/iiif'] when `layout` is `iiif`, sets the `@id` attribute of `info.json`
|
|
684
771
|
* @returns {Sharp}
|
|
685
772
|
* @throws {Error} Invalid parameters
|
|
686
773
|
*/
|
|
@@ -754,6 +841,14 @@ function tile (options) {
|
|
|
754
841
|
if (is.defined(centre)) {
|
|
755
842
|
this._setBooleanOption('tileCentre', centre);
|
|
756
843
|
}
|
|
844
|
+
// @id attribute for IIIF layout
|
|
845
|
+
if (is.defined(options.id)) {
|
|
846
|
+
if (is.string(options.id)) {
|
|
847
|
+
this.options.tileId = options.id;
|
|
848
|
+
} else {
|
|
849
|
+
throw is.invalidParameterError('id', 'string', options.id);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
757
852
|
}
|
|
758
853
|
// Format
|
|
759
854
|
if (is.inArray(this.options.formatOut, ['jpeg', 'png', 'webp'])) {
|
package/lib/resize.js
CHANGED
|
@@ -302,11 +302,20 @@ function resize (width, height, options) {
|
|
|
302
302
|
* })
|
|
303
303
|
* ...
|
|
304
304
|
*
|
|
305
|
+
* @example
|
|
306
|
+
* // Add a row of 10 red pixels to the bottom
|
|
307
|
+
* sharp(input)
|
|
308
|
+
* .extend({
|
|
309
|
+
* bottom: 10,
|
|
310
|
+
* background: 'red'
|
|
311
|
+
* })
|
|
312
|
+
* ...
|
|
313
|
+
*
|
|
305
314
|
* @param {(number|Object)} extend - single pixel count to add to all edges or an Object with per-edge counts
|
|
306
|
-
* @param {number} [extend.top]
|
|
307
|
-
* @param {number} [extend.left]
|
|
308
|
-
* @param {number} [extend.bottom]
|
|
309
|
-
* @param {number} [extend.right]
|
|
315
|
+
* @param {number} [extend.top=0]
|
|
316
|
+
* @param {number} [extend.left=0]
|
|
317
|
+
* @param {number} [extend.bottom=0]
|
|
318
|
+
* @param {number} [extend.right=0]
|
|
310
319
|
* @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.
|
|
311
320
|
* @returns {Sharp}
|
|
312
321
|
* @throws {Error} Invalid parameters
|
|
@@ -317,17 +326,35 @@ function extend (extend) {
|
|
|
317
326
|
this.options.extendBottom = extend;
|
|
318
327
|
this.options.extendLeft = extend;
|
|
319
328
|
this.options.extendRight = extend;
|
|
320
|
-
} else if (
|
|
321
|
-
is.
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
329
|
+
} else if (is.object(extend)) {
|
|
330
|
+
if (is.defined(extend.top)) {
|
|
331
|
+
if (is.integer(extend.top) && extend.top >= 0) {
|
|
332
|
+
this.options.extendTop = extend.top;
|
|
333
|
+
} else {
|
|
334
|
+
throw is.invalidParameterError('top', 'positive integer', extend.top);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
if (is.defined(extend.bottom)) {
|
|
338
|
+
if (is.integer(extend.bottom) && extend.bottom >= 0) {
|
|
339
|
+
this.options.extendBottom = extend.bottom;
|
|
340
|
+
} else {
|
|
341
|
+
throw is.invalidParameterError('bottom', 'positive integer', extend.bottom);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
if (is.defined(extend.left)) {
|
|
345
|
+
if (is.integer(extend.left) && extend.left >= 0) {
|
|
346
|
+
this.options.extendLeft = extend.left;
|
|
347
|
+
} else {
|
|
348
|
+
throw is.invalidParameterError('left', 'positive integer', extend.left);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
if (is.defined(extend.right)) {
|
|
352
|
+
if (is.integer(extend.right) && extend.right >= 0) {
|
|
353
|
+
this.options.extendRight = extend.right;
|
|
354
|
+
} else {
|
|
355
|
+
throw is.invalidParameterError('right', 'positive integer', extend.right);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
331
358
|
this._setBackgroundColourOption('extendBackground', extend.background);
|
|
332
359
|
} else {
|
|
333
360
|
throw is.invalidParameterError('extend', 'integer or object', extend);
|
package/lib/utility.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const events = require('events');
|
|
4
|
+
const detectLibc = require('detect-libc');
|
|
5
|
+
|
|
4
6
|
const is = require('./is');
|
|
5
7
|
const sharp = require('../build/Release/sharp.node');
|
|
6
8
|
|
|
@@ -84,8 +86,12 @@ cache(true);
|
|
|
84
86
|
/**
|
|
85
87
|
* Gets or, when a concurrency is provided, sets
|
|
86
88
|
* the number of threads _libvips'_ should create to process each image.
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
+
*
|
|
90
|
+
* The default value is the number of CPU cores,
|
|
91
|
+
* except when using glibc-based Linux without jemalloc,
|
|
92
|
+
* where the default is `1` to help reduce memory fragmentation.
|
|
93
|
+
*
|
|
94
|
+
* A value of `0` will reset this to the number of CPU cores.
|
|
89
95
|
*
|
|
90
96
|
* The maximum number of images that can be processed in parallel
|
|
91
97
|
* is limited by libuv's `UV_THREADPOOL_SIZE` environment variable.
|
|
@@ -103,6 +109,11 @@ cache(true);
|
|
|
103
109
|
function concurrency (concurrency) {
|
|
104
110
|
return sharp.concurrency(is.integer(concurrency) ? concurrency : null);
|
|
105
111
|
}
|
|
112
|
+
/* istanbul ignore next */
|
|
113
|
+
if (detectLibc.family === detectLibc.GLIBC && !sharp._isUsingJemalloc()) {
|
|
114
|
+
// Reduce default concurrency to 1 when using glibc memory allocator
|
|
115
|
+
sharp.concurrency(1);
|
|
116
|
+
}
|
|
106
117
|
|
|
107
118
|
/**
|
|
108
119
|
* An EventEmitter that emits a `change` event when a task is either:
|
|
@@ -157,14 +168,10 @@ simd(true);
|
|
|
157
168
|
* @private
|
|
158
169
|
*/
|
|
159
170
|
module.exports = function (Sharp) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
simd
|
|
165
|
-
].forEach(function (f) {
|
|
166
|
-
Sharp[f.name] = f;
|
|
167
|
-
});
|
|
171
|
+
Sharp.cache = cache;
|
|
172
|
+
Sharp.concurrency = concurrency;
|
|
173
|
+
Sharp.counters = counters;
|
|
174
|
+
Sharp.simd = simd;
|
|
168
175
|
Sharp.format = format;
|
|
169
176
|
Sharp.interpolators = interpolators;
|
|
170
177
|
Sharp.versions = versions;
|
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, AVIF and TIFF images",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.28.1",
|
|
5
5
|
"author": "Lovell Fuller <npm@lovell.info>",
|
|
6
6
|
"homepage": "https://github.com/lovell/sharp",
|
|
7
7
|
"contributors": [
|
|
@@ -72,17 +72,19 @@
|
|
|
72
72
|
"Robert O'Rourke <robert@o-rourke.org>",
|
|
73
73
|
"Guillermo Alfonso Varela Chouciño <guillevch@gmail.com>",
|
|
74
74
|
"Christian Flintrup <chr@gigahost.dk>",
|
|
75
|
-
"Manan Jadhav <manan@motionden.com>"
|
|
75
|
+
"Manan Jadhav <manan@motionden.com>",
|
|
76
|
+
"Leon Radley <leon@radley.se>",
|
|
77
|
+
"alza54 <alza54@thiocod.in>"
|
|
76
78
|
],
|
|
77
79
|
"scripts": {
|
|
78
80
|
"install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node-gyp rebuild && node install/dll-copy)",
|
|
79
81
|
"clean": "rm -rf node_modules/ build/ vendor/ .nyc_output/ coverage/ test/fixtures/output.*",
|
|
80
82
|
"test": "semistandard && cpplint && npm run test-unit && npm run test-licensing",
|
|
81
|
-
"test-unit": "nyc --reporter=lcov --branches=99 mocha --slow=
|
|
83
|
+
"test-unit": "nyc --reporter=lcov --branches=99 mocha --slow=1000 --timeout=60000 ./test/unit/*.js",
|
|
82
84
|
"test-licensing": "license-checker --production --summary --onlyAllow=\"Apache-2.0;BSD;ISC;MIT\"",
|
|
83
85
|
"test-coverage": "./test/coverage/report.sh",
|
|
84
86
|
"test-leak": "./test/leak/leak.sh",
|
|
85
|
-
"docs-build": "documentation lint lib &&
|
|
87
|
+
"docs-build": "documentation lint lib && node docs/build && node docs/search-index/build",
|
|
86
88
|
"docs-serve": "cd docs && npx serve",
|
|
87
89
|
"docs-publish": "cd docs && npx firebase-tools deploy --project pixelplumbing --only hosting:pixelplumbing-sharp"
|
|
88
90
|
},
|
|
@@ -115,26 +117,24 @@
|
|
|
115
117
|
"vips"
|
|
116
118
|
],
|
|
117
119
|
"dependencies": {
|
|
118
|
-
"array-flatten": "^3.0.0",
|
|
119
120
|
"color": "^3.1.3",
|
|
120
121
|
"detect-libc": "^1.0.3",
|
|
121
122
|
"node-addon-api": "^3.1.0",
|
|
122
|
-
"
|
|
123
|
-
"
|
|
124
|
-
"
|
|
125
|
-
"simple-get": "^4.0.0",
|
|
123
|
+
"prebuild-install": "^6.1.1",
|
|
124
|
+
"semver": "^7.3.5",
|
|
125
|
+
"simple-get": "^3.1.0",
|
|
126
126
|
"tar-fs": "^2.1.1",
|
|
127
127
|
"tunnel-agent": "^0.6.0"
|
|
128
128
|
},
|
|
129
129
|
"devDependencies": {
|
|
130
130
|
"async": "^3.2.0",
|
|
131
131
|
"cc": "^3.0.1",
|
|
132
|
-
"decompress-zip": "^0.3.
|
|
133
|
-
"documentation": "^13.
|
|
132
|
+
"decompress-zip": "^0.3.3",
|
|
133
|
+
"documentation": "^13.2.0",
|
|
134
134
|
"exif-reader": "^1.0.3",
|
|
135
135
|
"icc": "^2.0.0",
|
|
136
136
|
"license-checker": "^25.0.1",
|
|
137
|
-
"mocha": "^8.2
|
|
137
|
+
"mocha": "^8.3.2",
|
|
138
138
|
"mock-fs": "^4.13.0",
|
|
139
139
|
"nyc": "^15.1.0",
|
|
140
140
|
"prebuild": "^10.0.1",
|
|
@@ -143,7 +143,7 @@
|
|
|
143
143
|
},
|
|
144
144
|
"license": "Apache-2.0",
|
|
145
145
|
"config": {
|
|
146
|
-
"libvips": "8.10.
|
|
146
|
+
"libvips": "8.10.6",
|
|
147
147
|
"runtime": "napi",
|
|
148
148
|
"target": 3
|
|
149
149
|
},
|