sharp 0.31.3 → 0.32.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/README.md +1 -1
- package/binding.gyp +1 -1
- package/install/can-compile.js +3 -0
- package/install/dll-copy.js +3 -0
- package/install/libvips.js +3 -4
- package/lib/agent.js +3 -0
- package/lib/channel.js +3 -0
- package/lib/colour.js +3 -0
- package/lib/composite.js +3 -0
- package/lib/constructor.js +16 -8
- package/lib/index.d.ts +1614 -0
- package/lib/index.js +3 -0
- package/lib/input.js +32 -6
- package/lib/is.js +12 -0
- package/lib/libvips.js +4 -0
- package/lib/operation.js +75 -35
- package/lib/output.js +17 -8
- package/lib/platform.js +3 -0
- package/lib/resize.js +52 -19
- package/lib/sharp.js +3 -0
- package/lib/utility.js +5 -1
- package/package.json +28 -21
- package/src/common.cc +29 -14
- package/src/common.h +19 -16
- package/src/libvips/cplusplus/vips-operators.cpp +7 -0
- package/src/metadata.cc +12 -17
- package/src/metadata.h +3 -13
- package/src/operations.cc +11 -21
- package/src/operations.h +4 -15
- package/src/pipeline.cc +72 -49
- package/src/pipeline.h +18 -15
- package/src/sharp.cc +2 -13
- package/src/stats.cc +6 -17
- package/src/stats.h +2 -13
- package/src/utilities.cc +16 -27
- package/src/utilities.h +2 -13
package/lib/index.js
CHANGED
package/lib/input.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// Copyright 2013 Lovell Fuller and others.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
1
4
|
'use strict';
|
|
2
5
|
|
|
3
6
|
const color = require('color');
|
|
@@ -21,9 +24,9 @@ const align = {
|
|
|
21
24
|
* @private
|
|
22
25
|
*/
|
|
23
26
|
function _inputOptionsFromObject (obj) {
|
|
24
|
-
const { raw, density, limitInputPixels, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd } = obj;
|
|
25
|
-
return [raw, density, limitInputPixels, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd].some(is.defined)
|
|
26
|
-
? { raw, density, limitInputPixels, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd }
|
|
27
|
+
const { raw, density, limitInputPixels, ignoreIcc, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd } = obj;
|
|
28
|
+
return [raw, density, limitInputPixels, ignoreIcc, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd].some(is.defined)
|
|
29
|
+
? { raw, density, limitInputPixels, ignoreIcc, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd }
|
|
27
30
|
: undefined;
|
|
28
31
|
}
|
|
29
32
|
|
|
@@ -35,8 +38,9 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
35
38
|
const inputDescriptor = {
|
|
36
39
|
failOn: 'warning',
|
|
37
40
|
limitInputPixels: Math.pow(0x3FFF, 2),
|
|
41
|
+
ignoreIcc: false,
|
|
38
42
|
unlimited: false,
|
|
39
|
-
sequentialRead:
|
|
43
|
+
sequentialRead: true
|
|
40
44
|
};
|
|
41
45
|
if (is.string(input)) {
|
|
42
46
|
// filesystem
|
|
@@ -47,6 +51,11 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
47
51
|
throw Error('Input Buffer is empty');
|
|
48
52
|
}
|
|
49
53
|
inputDescriptor.buffer = input;
|
|
54
|
+
} else if (is.arrayBuffer(input)) {
|
|
55
|
+
if (input.byteLength === 0) {
|
|
56
|
+
throw Error('Input bit Array is empty');
|
|
57
|
+
}
|
|
58
|
+
inputDescriptor.buffer = Buffer.from(input, 0, input.byteLength);
|
|
50
59
|
} else if (is.typedArray(input)) {
|
|
51
60
|
if (input.length === 0) {
|
|
52
61
|
throw Error('Input Bit Array is empty');
|
|
@@ -92,6 +101,14 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
92
101
|
throw is.invalidParameterError('density', 'number between 1 and 100000', inputOptions.density);
|
|
93
102
|
}
|
|
94
103
|
}
|
|
104
|
+
// Ignore embeddded ICC profile
|
|
105
|
+
if (is.defined(inputOptions.ignoreIcc)) {
|
|
106
|
+
if (is.bool(inputOptions.ignoreIcc)) {
|
|
107
|
+
inputDescriptor.ignoreIcc = inputOptions.ignoreIcc;
|
|
108
|
+
} else {
|
|
109
|
+
throw is.invalidParameterError('ignoreIcc', 'boolean', inputOptions.ignoreIcc);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
95
112
|
// limitInputPixels
|
|
96
113
|
if (is.defined(inputOptions.limitInputPixels)) {
|
|
97
114
|
if (is.bool(inputOptions.limitInputPixels)) {
|
|
@@ -327,6 +344,13 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
327
344
|
throw is.invalidParameterError('text.spacing', 'number', inputOptions.text.spacing);
|
|
328
345
|
}
|
|
329
346
|
}
|
|
347
|
+
if (is.defined(inputOptions.text.wrap)) {
|
|
348
|
+
if (is.string(inputOptions.text.wrap) && is.inArray(inputOptions.text.wrap, ['word', 'char', 'wordChar', 'none'])) {
|
|
349
|
+
inputDescriptor.textWrap = inputOptions.text.wrap;
|
|
350
|
+
} else {
|
|
351
|
+
throw is.invalidParameterError('text.wrap', 'one of: word, char, wordChar, none', inputOptions.text.wrap);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
330
354
|
delete inputDescriptor.buffer;
|
|
331
355
|
} else {
|
|
332
356
|
throw new Error('Expected a valid string to create an image with text.');
|
|
@@ -387,8 +411,9 @@ function _isStreamInput () {
|
|
|
387
411
|
/**
|
|
388
412
|
* Fast access to (uncached) image metadata without decoding any compressed pixel data.
|
|
389
413
|
*
|
|
390
|
-
* This is
|
|
391
|
-
* It does not
|
|
414
|
+
* This is read from the header of the input image.
|
|
415
|
+
* It does not take into consideration any operations to be applied to the output image,
|
|
416
|
+
* such as resize or rotate.
|
|
392
417
|
*
|
|
393
418
|
* Dimensions in the response will respect the `page` and `pages` properties of the
|
|
394
419
|
* {@link /api-constructor#parameters|constructor parameters}.
|
|
@@ -423,6 +448,7 @@ function _isStreamInput () {
|
|
|
423
448
|
* - `iptc`: Buffer containing raw IPTC data, if present
|
|
424
449
|
* - `xmp`: Buffer containing raw XMP data, if present
|
|
425
450
|
* - `tifftagPhotoshop`: Buffer containing raw TIFFTAG_PHOTOSHOP data, if present
|
|
451
|
+
* - `formatMagick`: String containing format for images loaded via *magick
|
|
426
452
|
*
|
|
427
453
|
* @example
|
|
428
454
|
* const metadata = await sharp(input).metadata();
|
package/lib/is.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// Copyright 2013 Lovell Fuller and others.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
1
4
|
'use strict';
|
|
2
5
|
|
|
3
6
|
/**
|
|
@@ -71,6 +74,14 @@ const typedArray = function (val) {
|
|
|
71
74
|
return false;
|
|
72
75
|
};
|
|
73
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Is this value an ArrayBuffer object?
|
|
79
|
+
* @private
|
|
80
|
+
*/
|
|
81
|
+
const arrayBuffer = function (val) {
|
|
82
|
+
return val instanceof ArrayBuffer;
|
|
83
|
+
};
|
|
84
|
+
|
|
74
85
|
/**
|
|
75
86
|
* Is this value a non-empty string?
|
|
76
87
|
* @private
|
|
@@ -134,6 +145,7 @@ module.exports = {
|
|
|
134
145
|
bool: bool,
|
|
135
146
|
buffer: buffer,
|
|
136
147
|
typedArray: typedArray,
|
|
148
|
+
arrayBuffer: arrayBuffer,
|
|
137
149
|
string: string,
|
|
138
150
|
number: number,
|
|
139
151
|
integer: integer,
|
package/lib/libvips.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// Copyright 2013 Lovell Fuller and others.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
1
4
|
'use strict';
|
|
2
5
|
|
|
3
6
|
const fs = require('fs');
|
|
@@ -115,6 +118,7 @@ const useGlobalLibvips = function () {
|
|
|
115
118
|
}
|
|
116
119
|
/* istanbul ignore next */
|
|
117
120
|
if (isRosetta()) {
|
|
121
|
+
log('Detected Rosetta, skipping search for globally-installed libvips');
|
|
118
122
|
return false;
|
|
119
123
|
}
|
|
120
124
|
const globalVipsVersion = globalLibvipsVersion();
|
package/lib/operation.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// Copyright 2013 Lovell Fuller and others.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
1
4
|
'use strict';
|
|
2
5
|
|
|
3
6
|
const color = require('color');
|
|
@@ -232,7 +235,7 @@ function affine (matrix, options) {
|
|
|
232
235
|
* .toBuffer();
|
|
233
236
|
*
|
|
234
237
|
* @param {Object|number} [options] - if present, is an Object with attributes
|
|
235
|
-
* @param {number} [options.sigma] - the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`, between 0.000001 and
|
|
238
|
+
* @param {number} [options.sigma] - the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`, between 0.000001 and 10
|
|
236
239
|
* @param {number} [options.m1=1.0] - the level of sharpening to apply to "flat" areas, between 0 and 1000000
|
|
237
240
|
* @param {number} [options.m2=2.0] - the level of sharpening to apply to "jagged" areas, between 0 and 1000000
|
|
238
241
|
* @param {number} [options.x1=2.0] - threshold between "flat" and "jagged", between 0 and 1000000
|
|
@@ -270,10 +273,10 @@ function sharpen (options, flat, jagged) {
|
|
|
270
273
|
}
|
|
271
274
|
}
|
|
272
275
|
} else if (is.plainObject(options)) {
|
|
273
|
-
if (is.number(options.sigma) && is.inRange(options.sigma, 0.000001,
|
|
276
|
+
if (is.number(options.sigma) && is.inRange(options.sigma, 0.000001, 10)) {
|
|
274
277
|
this.options.sharpenSigma = options.sigma;
|
|
275
278
|
} else {
|
|
276
|
-
throw is.invalidParameterError('options.sigma', 'number between 0.000001 and
|
|
279
|
+
throw is.invalidParameterError('options.sigma', 'number between 0.000001 and 10', options.sigma);
|
|
277
280
|
}
|
|
278
281
|
if (is.defined(options.m1)) {
|
|
279
282
|
if (is.number(options.m1) && is.inRange(options.m1, 0, 1000000)) {
|
|
@@ -466,16 +469,50 @@ function negate (options) {
|
|
|
466
469
|
}
|
|
467
470
|
|
|
468
471
|
/**
|
|
469
|
-
* Enhance output image contrast by stretching its luminance to cover
|
|
472
|
+
* Enhance output image contrast by stretching its luminance to cover a full dynamic range.
|
|
473
|
+
*
|
|
474
|
+
* Uses a histogram-based approach, taking a default range of 1% to 99% to reduce sensitivity to noise at the extremes.
|
|
475
|
+
*
|
|
476
|
+
* Luminance values below the `lower` percentile will be underexposed by clipping to zero.
|
|
477
|
+
* Luminance values above the `upper` percentile will be overexposed by clipping to the max pixel value.
|
|
470
478
|
*
|
|
471
479
|
* @example
|
|
472
|
-
* const output = await sharp(input)
|
|
480
|
+
* const output = await sharp(input)
|
|
481
|
+
* .normalise()
|
|
482
|
+
* .toBuffer();
|
|
483
|
+
*
|
|
484
|
+
* @example
|
|
485
|
+
* const output = await sharp(input)
|
|
486
|
+
* .normalise({ lower: 0, upper: 100 })
|
|
487
|
+
* .toBuffer();
|
|
473
488
|
*
|
|
474
|
-
* @param {
|
|
489
|
+
* @param {Object} [options]
|
|
490
|
+
* @param {number} [options.lower=1] - Percentile below which luminance values will be underexposed.
|
|
491
|
+
* @param {number} [options.upper=99] - Percentile above which luminance values will be overexposed.
|
|
475
492
|
* @returns {Sharp}
|
|
476
493
|
*/
|
|
477
|
-
function normalise (
|
|
478
|
-
|
|
494
|
+
function normalise (options) {
|
|
495
|
+
if (is.plainObject(options)) {
|
|
496
|
+
if (is.defined(options.lower)) {
|
|
497
|
+
if (is.number(options.lower) && is.inRange(options.lower, 0, 99)) {
|
|
498
|
+
this.options.normaliseLower = options.lower;
|
|
499
|
+
} else {
|
|
500
|
+
throw is.invalidParameterError('lower', 'number between 0 and 99', options.lower);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
if (is.defined(options.upper)) {
|
|
504
|
+
if (is.number(options.upper) && is.inRange(options.upper, 1, 100)) {
|
|
505
|
+
this.options.normaliseUpper = options.upper;
|
|
506
|
+
} else {
|
|
507
|
+
throw is.invalidParameterError('upper', 'number between 1 and 100', options.upper);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
if (this.options.normaliseLower >= this.options.normaliseUpper) {
|
|
512
|
+
throw is.invalidParameterError('range', 'lower to be less than upper',
|
|
513
|
+
`${this.options.normaliseLower} >= ${this.options.normaliseUpper}`);
|
|
514
|
+
}
|
|
515
|
+
this.options.normalise = true;
|
|
479
516
|
return this;
|
|
480
517
|
}
|
|
481
518
|
|
|
@@ -483,13 +520,17 @@ function normalise (normalise) {
|
|
|
483
520
|
* Alternative spelling of normalise.
|
|
484
521
|
*
|
|
485
522
|
* @example
|
|
486
|
-
* const output = await sharp(input)
|
|
523
|
+
* const output = await sharp(input)
|
|
524
|
+
* .normalize()
|
|
525
|
+
* .toBuffer();
|
|
487
526
|
*
|
|
488
|
-
* @param {
|
|
527
|
+
* @param {Object} [options]
|
|
528
|
+
* @param {number} [options.lower=1] - Percentile below which luminance values will be underexposed.
|
|
529
|
+
* @param {number} [options.upper=99] - Percentile above which luminance values will be overexposed.
|
|
489
530
|
* @returns {Sharp}
|
|
490
531
|
*/
|
|
491
|
-
function normalize (
|
|
492
|
-
return this.normalise(
|
|
532
|
+
function normalize (options) {
|
|
533
|
+
return this.normalise(options);
|
|
493
534
|
}
|
|
494
535
|
|
|
495
536
|
/**
|
|
@@ -509,34 +550,33 @@ function normalize (normalize) {
|
|
|
509
550
|
* .toBuffer();
|
|
510
551
|
*
|
|
511
552
|
* @param {Object} options
|
|
512
|
-
* @param {number} options.width -
|
|
513
|
-
* @param {number} options.height -
|
|
514
|
-
* @param {number} [options.maxSlope=3] -
|
|
515
|
-
* cumulative histogram. A value of 0 disables contrast limiting. Valid values
|
|
516
|
-
* are integers in the range 0-100 (inclusive)
|
|
553
|
+
* @param {number} options.width - Integral width of the search window, in pixels.
|
|
554
|
+
* @param {number} options.height - Integral height of the search window, in pixels.
|
|
555
|
+
* @param {number} [options.maxSlope=3] - Integral level of brightening, between 0 and 100, where 0 disables contrast limiting.
|
|
517
556
|
* @returns {Sharp}
|
|
518
557
|
* @throws {Error} Invalid parameters
|
|
519
558
|
*/
|
|
520
559
|
function clahe (options) {
|
|
521
|
-
if (
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
560
|
+
if (is.plainObject(options)) {
|
|
561
|
+
if (is.integer(options.width) && options.width > 0) {
|
|
562
|
+
this.options.claheWidth = options.width;
|
|
563
|
+
} else {
|
|
564
|
+
throw is.invalidParameterError('width', 'integer greater than zero', options.width);
|
|
565
|
+
}
|
|
566
|
+
if (is.integer(options.height) && options.height > 0) {
|
|
567
|
+
this.options.claheHeight = options.height;
|
|
568
|
+
} else {
|
|
569
|
+
throw is.invalidParameterError('height', 'integer greater than zero', options.height);
|
|
570
|
+
}
|
|
571
|
+
if (is.defined(options.maxSlope)) {
|
|
572
|
+
if (is.integer(options.maxSlope) && is.inRange(options.maxSlope, 0, 100)) {
|
|
573
|
+
this.options.claheMaxSlope = options.maxSlope;
|
|
574
|
+
} else {
|
|
575
|
+
throw is.invalidParameterError('maxSlope', 'integer between 0 and 100', options.maxSlope);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
538
578
|
} else {
|
|
539
|
-
|
|
579
|
+
throw is.invalidParameterError('options', 'plain object', options);
|
|
540
580
|
}
|
|
541
581
|
return this;
|
|
542
582
|
}
|
package/lib/output.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// Copyright 2013 Lovell Fuller and others.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
1
4
|
'use strict';
|
|
2
5
|
|
|
3
6
|
const path = require('path');
|
|
@@ -61,6 +64,7 @@ const bitdepthFromColourCount = (colours) => 1 << 31 - Math.clz32(Math.ceil(Math
|
|
|
61
64
|
* `info` contains the output image `format`, `size` (bytes), `width`, `height`,
|
|
62
65
|
* `channels` and `premultiplied` (indicating if premultiplication was used).
|
|
63
66
|
* When using a crop strategy also contains `cropOffsetLeft` and `cropOffsetTop`.
|
|
67
|
+
* When using the attention crop strategy also contains `attentionX` and `attentionY`, the focal point of the cropped region.
|
|
64
68
|
* May also contain `textAutofitDpi` (dpi the font was rendered at) if image was created from text.
|
|
65
69
|
* @returns {Promise<Object>} - when no callback is provided
|
|
66
70
|
* @throws {Error} Invalid parameters
|
|
@@ -192,7 +196,7 @@ function toBuffer (options, callback) {
|
|
|
192
196
|
*
|
|
193
197
|
* @param {Object} [options]
|
|
194
198
|
* @param {number} [options.orientation] value between 1 and 8, used to update the EXIF `Orientation` tag.
|
|
195
|
-
* @param {string} [options.icc]
|
|
199
|
+
* @param {string} [options.icc='srgb'] Filesystem path to output ICC profile, relative to `process.cwd()`, defaults to built-in sRGB.
|
|
196
200
|
* @param {Object<Object>} [options.exif={}] Object keyed by IFD0, IFD1 etc. of key/value string pairs to write as EXIF data.
|
|
197
201
|
* @param {number} [options.density] Number of pixels per inch (DPI).
|
|
198
202
|
* @returns {Sharp}
|
|
@@ -559,8 +563,8 @@ function webp (options) {
|
|
|
559
563
|
* .toFile('optim.gif');
|
|
560
564
|
*
|
|
561
565
|
* @param {Object} [options] - output options
|
|
562
|
-
* @param {boolean} [options.
|
|
563
|
-
* @param {boolean} [options.
|
|
566
|
+
* @param {boolean} [options.reuse=true] - re-use existing palette, otherwise generate new (slow)
|
|
567
|
+
* @param {boolean} [options.progressive=false] - use progressive (interlace) scan
|
|
564
568
|
* @param {number} [options.colours=256] - maximum number of palette entries, including transparency, between 2 and 256
|
|
565
569
|
* @param {number} [options.colors=256] - alternative spelling of `options.colours`
|
|
566
570
|
* @param {number} [options.effort=7] - CPU effort, between 1 (fastest) and 10 (slowest)
|
|
@@ -575,10 +579,11 @@ function webp (options) {
|
|
|
575
579
|
*/
|
|
576
580
|
function gif (options) {
|
|
577
581
|
if (is.object(options)) {
|
|
578
|
-
if (is.defined(options.
|
|
579
|
-
this._setBooleanOption('
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
+
if (is.defined(options.reuse)) {
|
|
583
|
+
this._setBooleanOption('gifReuse', options.reuse);
|
|
584
|
+
}
|
|
585
|
+
if (is.defined(options.progressive)) {
|
|
586
|
+
this._setBooleanOption('gifProgressive', options.progressive);
|
|
582
587
|
}
|
|
583
588
|
const colours = options.colours || options.colors;
|
|
584
589
|
if (is.defined(colours)) {
|
|
@@ -690,7 +695,7 @@ function jp2 (options) {
|
|
|
690
695
|
}
|
|
691
696
|
if (is.defined(options.chromaSubsampling)) {
|
|
692
697
|
if (is.string(options.chromaSubsampling) && is.inArray(options.chromaSubsampling, ['4:2:0', '4:4:4'])) {
|
|
693
|
-
this.options.
|
|
698
|
+
this.options.jp2ChromaSubsampling = options.chromaSubsampling;
|
|
694
699
|
} else {
|
|
695
700
|
throw is.invalidParameterError('chromaSubsampling', 'one of: 4:2:0, 4:4:4', options.chromaSubsampling);
|
|
696
701
|
}
|
|
@@ -1051,6 +1056,10 @@ function raw (options) {
|
|
|
1051
1056
|
*
|
|
1052
1057
|
* The container will be set to `zip` when the output is a Buffer or Stream, otherwise it will default to `fs`.
|
|
1053
1058
|
*
|
|
1059
|
+
* Requires libvips compiled with support for libgsf.
|
|
1060
|
+
* The prebuilt binaries do not include this - see
|
|
1061
|
+
* {@link https://sharp.pixelplumbing.com/install#custom-libvips installing a custom libvips}.
|
|
1062
|
+
*
|
|
1054
1063
|
* @example
|
|
1055
1064
|
* sharp('input.tiff')
|
|
1056
1065
|
* .png()
|
package/lib/platform.js
CHANGED
package/lib/resize.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// Copyright 2013 Lovell Fuller and others.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
1
4
|
'use strict';
|
|
2
5
|
|
|
3
6
|
const is = require('./is');
|
|
@@ -36,6 +39,18 @@ const position = {
|
|
|
36
39
|
'left top': 8
|
|
37
40
|
};
|
|
38
41
|
|
|
42
|
+
/**
|
|
43
|
+
* How to extend the image.
|
|
44
|
+
* @member
|
|
45
|
+
* @private
|
|
46
|
+
*/
|
|
47
|
+
const extendWith = {
|
|
48
|
+
background: 'background',
|
|
49
|
+
copy: 'copy',
|
|
50
|
+
repeat: 'repeat',
|
|
51
|
+
mirror: 'mirror'
|
|
52
|
+
};
|
|
53
|
+
|
|
39
54
|
/**
|
|
40
55
|
* Strategies for automagic cover behaviour.
|
|
41
56
|
* @member
|
|
@@ -103,7 +118,7 @@ function isResizeExpected (options) {
|
|
|
103
118
|
* Resize image to `width`, `height` or `width x height`.
|
|
104
119
|
*
|
|
105
120
|
* When both a `width` and `height` are provided, the possible methods by which the image should **fit** these are:
|
|
106
|
-
* - `cover`: (default) Preserving aspect ratio, ensure the image covers both provided dimensions by cropping/clipping to fit.
|
|
121
|
+
* - `cover`: (default) Preserving aspect ratio, attempt to ensure the image covers both provided dimensions by cropping/clipping to fit.
|
|
107
122
|
* - `contain`: Preserving aspect ratio, contain within both provided dimensions using "letterboxing" where necessary.
|
|
108
123
|
* - `fill`: Ignore the aspect ratio of the input and stretch to both provided dimensions.
|
|
109
124
|
* - `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.
|
|
@@ -216,32 +231,32 @@ function isResizeExpected (options) {
|
|
|
216
231
|
* .toBuffer()
|
|
217
232
|
* );
|
|
218
233
|
*
|
|
219
|
-
* @param {number} [width] - pixels wide the resultant image should be. Use `null` or `undefined` to auto-scale the width to match the height.
|
|
220
|
-
* @param {number} [height] - pixels high the resultant image should be. Use `null` or `undefined` to auto-scale the height to match the width.
|
|
234
|
+
* @param {number} [width] - How many pixels wide the resultant image should be. Use `null` or `undefined` to auto-scale the width to match the height.
|
|
235
|
+
* @param {number} [height] - How many pixels high the resultant image should be. Use `null` or `undefined` to auto-scale the height to match the width.
|
|
221
236
|
* @param {Object} [options]
|
|
222
|
-
* @param {
|
|
223
|
-
* @param {
|
|
224
|
-
* @param {String} [options.fit='cover'] -
|
|
225
|
-
* @param {String} [options.position='centre'] - position, gravity or strategy to use when `fit` is `cover` or `contain`.
|
|
237
|
+
* @param {number} [options.width] - An alternative means of specifying `width`. If both are present this takes priority.
|
|
238
|
+
* @param {number} [options.height] - An alternative means of specifying `height`. If both are present this takes priority.
|
|
239
|
+
* @param {String} [options.fit='cover'] - How the image should be resized/cropped to fit the target dimension(s), one of `cover`, `contain`, `fill`, `inside` or `outside`.
|
|
240
|
+
* @param {String} [options.position='centre'] - A position, gravity or strategy to use when `fit` is `cover` or `contain`.
|
|
226
241
|
* @param {String|Object} [options.background={r: 0, g: 0, b: 0, alpha: 1}] - background colour when `fit` is `contain`, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to black without transparency.
|
|
227
|
-
* @param {String} [options.kernel='lanczos3'] -
|
|
228
|
-
* @param {Boolean} [options.withoutEnlargement=false] -
|
|
229
|
-
* @param {Boolean} [options.withoutReduction=false] -
|
|
230
|
-
* @param {Boolean} [options.fastShrinkOnLoad=true] -
|
|
242
|
+
* @param {String} [options.kernel='lanczos3'] - The kernel to use for image reduction. Use the `fastShrinkOnLoad` option to control kernel vs shrink-on-load.
|
|
243
|
+
* @param {Boolean} [options.withoutEnlargement=false] - Do not scale up if the width *or* height are already less than the target dimensions, equivalent to GraphicsMagick's `>` geometry option. This may result in output dimensions smaller than the target dimensions.
|
|
244
|
+
* @param {Boolean} [options.withoutReduction=false] - Do not scale down if the width *or* height are already greater than the target dimensions, equivalent to GraphicsMagick's `<` geometry option. This may still result in a crop to reach the target dimensions.
|
|
245
|
+
* @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 or round-down of an auto-scaled dimension.
|
|
231
246
|
* @returns {Sharp}
|
|
232
247
|
* @throws {Error} Invalid parameters
|
|
233
248
|
*/
|
|
234
|
-
function resize (
|
|
249
|
+
function resize (widthOrOptions, height, options) {
|
|
235
250
|
if (isResizeExpected(this.options)) {
|
|
236
251
|
this.options.debuglog('ignoring previous resize options');
|
|
237
252
|
}
|
|
238
|
-
if (is.defined(
|
|
239
|
-
if (is.object(
|
|
240
|
-
options =
|
|
241
|
-
} else if (is.integer(
|
|
242
|
-
this.options.width =
|
|
253
|
+
if (is.defined(widthOrOptions)) {
|
|
254
|
+
if (is.object(widthOrOptions) && !is.defined(options)) {
|
|
255
|
+
options = widthOrOptions;
|
|
256
|
+
} else if (is.integer(widthOrOptions) && widthOrOptions > 0) {
|
|
257
|
+
this.options.width = widthOrOptions;
|
|
243
258
|
} else {
|
|
244
|
-
throw is.invalidParameterError('width', 'positive integer',
|
|
259
|
+
throw is.invalidParameterError('width', 'positive integer', widthOrOptions);
|
|
245
260
|
}
|
|
246
261
|
} else {
|
|
247
262
|
this.options.width = -1;
|
|
@@ -322,7 +337,8 @@ function resize (width, height, options) {
|
|
|
322
337
|
}
|
|
323
338
|
|
|
324
339
|
/**
|
|
325
|
-
*
|
|
340
|
+
* Extend / pad / extrude one or more edges of the image with either
|
|
341
|
+
* the provided background colour or pixels derived from the image.
|
|
326
342
|
* This operation will always occur after resizing and extraction, if any.
|
|
327
343
|
*
|
|
328
344
|
* @example
|
|
@@ -348,11 +364,21 @@ function resize (width, height, options) {
|
|
|
348
364
|
* })
|
|
349
365
|
* ...
|
|
350
366
|
*
|
|
367
|
+
* @example
|
|
368
|
+
* // Extrude image by 8 pixels to the right, mirroring existing right hand edge
|
|
369
|
+
* sharp(input)
|
|
370
|
+
* .extend({
|
|
371
|
+
* right: 8,
|
|
372
|
+
* background: 'mirror'
|
|
373
|
+
* })
|
|
374
|
+
* ...
|
|
375
|
+
*
|
|
351
376
|
* @param {(number|Object)} extend - single pixel count to add to all edges or an Object with per-edge counts
|
|
352
377
|
* @param {number} [extend.top=0]
|
|
353
378
|
* @param {number} [extend.left=0]
|
|
354
379
|
* @param {number} [extend.bottom=0]
|
|
355
380
|
* @param {number} [extend.right=0]
|
|
381
|
+
* @param {String} [extend.extendWith='background'] - populate new pixels using this method, one of: background, copy, repeat, mirror.
|
|
356
382
|
* @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.
|
|
357
383
|
* @returns {Sharp}
|
|
358
384
|
* @throws {Error} Invalid parameters
|
|
@@ -393,6 +419,13 @@ function extend (extend) {
|
|
|
393
419
|
}
|
|
394
420
|
}
|
|
395
421
|
this._setBackgroundColourOption('extendBackground', extend.background);
|
|
422
|
+
if (is.defined(extend.extendWith)) {
|
|
423
|
+
if (is.string(extendWith[extend.extendWith])) {
|
|
424
|
+
this.options.extendWith = extendWith[extend.extendWith];
|
|
425
|
+
} else {
|
|
426
|
+
throw is.invalidParameterError('extendWith', 'one of: background, copy, repeat, mirror', extend.extendWith);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
396
429
|
} else {
|
|
397
430
|
throw is.invalidParameterError('extend', 'integer or object', extend);
|
|
398
431
|
}
|
package/lib/sharp.js
CHANGED
package/lib/utility.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// Copyright 2013 Lovell Fuller and others.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
1
4
|
'use strict';
|
|
2
5
|
|
|
3
6
|
const fs = require('fs');
|
|
@@ -43,7 +46,7 @@ const interpolators = {
|
|
|
43
46
|
};
|
|
44
47
|
|
|
45
48
|
/**
|
|
46
|
-
* An Object containing the version numbers of libvips and its dependencies.
|
|
49
|
+
* An Object containing the version numbers of sharp, libvips and its dependencies.
|
|
47
50
|
* @member
|
|
48
51
|
* @example
|
|
49
52
|
* console.log(sharp.versions);
|
|
@@ -54,6 +57,7 @@ let versions = {
|
|
|
54
57
|
try {
|
|
55
58
|
versions = require(`../vendor/${versions.vips}/${platformAndArch}/versions.json`);
|
|
56
59
|
} catch (_err) { /* ignore */ }
|
|
60
|
+
versions.sharp = require('../package.json').version;
|
|
57
61
|
|
|
58
62
|
/**
|
|
59
63
|
* An Object containing the platform and architecture
|
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, GIF, AVIF and TIFF images",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.32.0",
|
|
5
5
|
"author": "Lovell Fuller <npm@lovell.info>",
|
|
6
6
|
"homepage": "https://github.com/lovell/sharp",
|
|
7
7
|
"contributors": [
|
|
@@ -85,21 +85,24 @@
|
|
|
85
85
|
"Brodan <christopher.hranj@gmail.com",
|
|
86
86
|
"Ankur Parihar <ankur.github@gmail.com>",
|
|
87
87
|
"Brahim Ait elhaj <brahima@gmail.com>",
|
|
88
|
-
"Mart Jansink <m.jansink@gmail.com>"
|
|
88
|
+
"Mart Jansink <m.jansink@gmail.com>",
|
|
89
|
+
"Lachlan Newman <lachnewman007@gmail.com>"
|
|
89
90
|
],
|
|
90
91
|
"scripts": {
|
|
91
92
|
"install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node install/can-compile && node-gyp rebuild && node install/dll-copy)",
|
|
92
93
|
"clean": "rm -rf node_modules/ build/ vendor/ .nyc_output/ coverage/ test/fixtures/output.*",
|
|
93
|
-
"test": "npm run test-lint && npm run test-unit && npm run test-licensing",
|
|
94
|
+
"test": "npm run test-lint && npm run test-unit && npm run test-licensing && npm run test-types",
|
|
94
95
|
"test-lint": "semistandard && cpplint",
|
|
95
96
|
"test-unit": "nyc --reporter=lcov --reporter=text --check-coverage --branches=100 mocha",
|
|
96
97
|
"test-licensing": "license-checker --production --summary --onlyAllow=\"Apache-2.0;BSD;ISC;MIT\"",
|
|
97
98
|
"test-leak": "./test/leak/leak.sh",
|
|
98
|
-
"
|
|
99
|
+
"test-types": "tsd",
|
|
100
|
+
"docs-build": "node docs/build && node docs/search-index/build",
|
|
99
101
|
"docs-serve": "cd docs && npx serve",
|
|
100
102
|
"docs-publish": "cd docs && npx firebase-tools deploy --project pixelplumbing --only hosting:pixelplumbing-sharp"
|
|
101
103
|
},
|
|
102
104
|
"main": "lib/index.js",
|
|
105
|
+
"types": "lib/index.d.ts",
|
|
103
106
|
"files": [
|
|
104
107
|
"binding.gyp",
|
|
105
108
|
"install/**",
|
|
@@ -131,7 +134,7 @@
|
|
|
131
134
|
"dependencies": {
|
|
132
135
|
"color": "^4.2.3",
|
|
133
136
|
"detect-libc": "^2.0.1",
|
|
134
|
-
"node-addon-api": "^
|
|
137
|
+
"node-addon-api": "^6.0.0",
|
|
135
138
|
"prebuild-install": "^7.1.1",
|
|
136
139
|
"semver": "^7.3.8",
|
|
137
140
|
"simple-get": "^4.0.1",
|
|
@@ -139,35 +142,36 @@
|
|
|
139
142
|
"tunnel-agent": "^0.6.0"
|
|
140
143
|
},
|
|
141
144
|
"devDependencies": {
|
|
145
|
+
"@types/node": "*",
|
|
142
146
|
"async": "^3.2.4",
|
|
143
147
|
"cc": "^3.0.1",
|
|
144
|
-
"
|
|
145
|
-
"exif-reader": "^1.0.3",
|
|
148
|
+
"exif-reader": "^1.2.0",
|
|
146
149
|
"extract-zip": "^2.0.1",
|
|
147
150
|
"icc": "^2.0.0",
|
|
151
|
+
"jsdoc-to-markdown": "^8.0.0",
|
|
148
152
|
"license-checker": "^25.0.1",
|
|
149
153
|
"mocha": "^10.2.0",
|
|
150
154
|
"mock-fs": "^5.2.0",
|
|
151
155
|
"nyc": "^15.1.0",
|
|
152
156
|
"prebuild": "^11.0.4",
|
|
153
|
-
"
|
|
154
|
-
"
|
|
157
|
+
"semistandard": "^16.0.1",
|
|
158
|
+
"tsd": "^0.28.0"
|
|
155
159
|
},
|
|
156
160
|
"license": "Apache-2.0",
|
|
157
161
|
"config": {
|
|
158
|
-
"libvips": "8.
|
|
162
|
+
"libvips": "8.14.2",
|
|
159
163
|
"integrity": {
|
|
160
|
-
"darwin-arm64v8": "sha512-
|
|
161
|
-
"darwin-x64": "sha512-
|
|
162
|
-
"linux-arm64v8": "sha512-
|
|
163
|
-
"linux-armv6": "sha512-
|
|
164
|
-
"linux-armv7": "sha512
|
|
165
|
-
"linux-x64": "sha512-
|
|
166
|
-
"linuxmusl-arm64v8": "sha512-
|
|
167
|
-
"linuxmusl-x64": "sha512-
|
|
168
|
-
"win32-arm64v8": "sha512-
|
|
169
|
-
"win32-ia32": "sha512-
|
|
170
|
-
"win32-x64": "sha512-
|
|
164
|
+
"darwin-arm64v8": "sha512-eUuxg6H0tXgX4z2lsaGtZ4cbPAm7yoFgkvPDd4csxoiVt+QUB25pEJwiXw7oB53VlBFIp3O8lbydSFS5zH8MQQ==",
|
|
165
|
+
"darwin-x64": "sha512-cMT4v76IgzSR0VoXqLk/yftRyzMEZ+SBVMLzXCgqP/lmnYisrpmHHNqrWnoZbUUBXbPXLn6KMultYOJHe/c9ZQ==",
|
|
166
|
+
"linux-arm64v8": "sha512-OcDJ/ly80pxwaKnw0W91sSvZczPtWsjmzrY/+6NMiQZT84LkmeaRuwErbHhorKDxnl7iZuNn9Uj5V25Xmj+LDQ==",
|
|
167
|
+
"linux-armv6": "sha512-hk2ohSOYTJEtVQxEQFyQ+tuayKpYqx6NiXa7AE+8MF+yscxt+g+mLJ7TjDqtmb4ttFGH4IVfsEfU2YXIqWqkpg==",
|
|
168
|
+
"linux-armv7": "sha512-/5Ci2Cd+yLZmTaEt9lVJ89elxX3RMJpps0ESjj43X40yrwka51QfXeg1QV38uNzZpCDIZkrbXZK0lyKldjpLuA==",
|
|
169
|
+
"linux-x64": "sha512-wjCKmWfBb0uz1UB7rPDLvO0s+VWuoAY/Vv/YGCRFEQUkdSLQUgHExrOMMbOM3FleuYfQqznDYCXXphkl7X44+w==",
|
|
170
|
+
"linuxmusl-arm64v8": "sha512-QtD2n90yi+rLE65C0gksFUU5uMUFPICI/pS3A0bgthpIcoCejAOYs3ZjVWpZbHQuV/lWahIUYO78MB9CzY860A==",
|
|
171
|
+
"linuxmusl-x64": "sha512-TokQ/ETCJAsPYuxIMOPYDp25rlcwtpmIMtRUR9PB75TmZEJe7abRfCEInIPYeD8F/HxxnJSLiEdlbn1z1Jfzng==",
|
|
172
|
+
"win32-arm64v8": "sha512-IIuj4EAgLqEVAoOuYH79C61a7TcJXlU/RBwk+5JsGWc2mr4J/Ar5J01e6XBvU4Lu3eqcU+3GPaACZEa1511buA==",
|
|
173
|
+
"win32-ia32": "sha512-CsZi7lrReX3B6tmYgOGJ0IiAfcN5APDC6l+3gdosxfTfwpLLO+jXaSmyNwIGeMqrdgckG/gwwc+IrUZmkmjJ/A==",
|
|
174
|
+
"win32-x64": "sha512-J7znmNKUK4ZKo6SnSnEtzT1xRAwvkGXxIx9/QihAadu1TFdS06yNhcENmwC4973+KZBlAdVpWbZ8sLrEoWkdCA=="
|
|
171
175
|
},
|
|
172
176
|
"runtime": "napi",
|
|
173
177
|
"target": 7
|
|
@@ -193,5 +197,8 @@
|
|
|
193
197
|
"filter": [
|
|
194
198
|
"build/include"
|
|
195
199
|
]
|
|
200
|
+
},
|
|
201
|
+
"tsd": {
|
|
202
|
+
"directory": "test/types/"
|
|
196
203
|
}
|
|
197
204
|
}
|