sharp 0.28.1 → 0.29.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 +2 -2
- package/binding.gyp +12 -9
- package/install/can-compile.js +11 -0
- package/install/dll-copy.js +6 -6
- package/install/libvips.js +24 -18
- package/lib/agent.js +1 -1
- package/lib/channel.js +13 -7
- package/lib/colour.js +42 -1
- package/lib/composite.js +2 -0
- package/lib/constructor.js +21 -30
- package/lib/input.js +52 -3
- package/lib/is.js +19 -5
- package/lib/libvips.js +9 -22
- package/lib/operation.js +74 -7
- package/lib/output.js +133 -17
- package/lib/sharp.js +24 -0
- package/lib/utility.js +1 -1
- package/package.json +23 -16
- package/src/common.cc +47 -14
- package/src/common.h +17 -5
- package/src/libvips/cplusplus/VConnection.cpp +0 -26
- package/src/libvips/cplusplus/VImage.cpp +54 -16
- package/src/libvips/cplusplus/VInterpolate.cpp +0 -13
- package/src/libvips/cplusplus/vips-operators.cpp +185 -1
- package/src/metadata.cc +14 -0
- package/src/metadata.h +1 -0
- package/src/operations.cc +36 -3
- package/src/operations.h +18 -2
- package/src/pipeline.cc +104 -34
- package/src/pipeline.h +29 -3
- package/src/utilities.cc +1 -1
package/lib/libvips.js
CHANGED
|
@@ -4,13 +4,15 @@ const fs = require('fs');
|
|
|
4
4
|
const os = require('os');
|
|
5
5
|
const path = require('path');
|
|
6
6
|
const spawnSync = require('child_process').spawnSync;
|
|
7
|
-
const
|
|
7
|
+
const semverCoerce = require('semver/functions/coerce');
|
|
8
|
+
const semverGreaterThanOrEqualTo = require('semver/functions/gte');
|
|
9
|
+
|
|
8
10
|
const platform = require('./platform');
|
|
9
11
|
|
|
10
12
|
const env = process.env;
|
|
11
13
|
const minimumLibvipsVersionLabelled = env.npm_package_config_libvips || /* istanbul ignore next */
|
|
12
14
|
require('../package.json').config.libvips;
|
|
13
|
-
const minimumLibvipsVersion =
|
|
15
|
+
const minimumLibvipsVersion = semverCoerce(minimumLibvipsVersionLabelled).version;
|
|
14
16
|
|
|
15
17
|
const spawnSyncOptions = {
|
|
16
18
|
encoding: 'utf8',
|
|
@@ -19,9 +21,9 @@ const spawnSyncOptions = {
|
|
|
19
21
|
|
|
20
22
|
const mkdirSync = function (dirPath) {
|
|
21
23
|
try {
|
|
22
|
-
fs.mkdirSync(dirPath);
|
|
24
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
23
25
|
} catch (err) {
|
|
24
|
-
/* istanbul ignore
|
|
26
|
+
/* istanbul ignore next */
|
|
25
27
|
if (err.code !== 'EEXIST') {
|
|
26
28
|
throw err;
|
|
27
29
|
}
|
|
@@ -65,23 +67,8 @@ const globalLibvipsVersion = function () {
|
|
|
65
67
|
};
|
|
66
68
|
|
|
67
69
|
const hasVendoredLibvips = function () {
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
let vendorPlatformId;
|
|
71
|
-
try {
|
|
72
|
-
vendorPlatformId = require(path.join(vendorPath, 'platform.json'));
|
|
73
|
-
} catch (err) {}
|
|
74
|
-
/* istanbul ignore else */
|
|
75
|
-
if (vendorPlatformId) {
|
|
76
|
-
/* istanbul ignore else */
|
|
77
|
-
if (currentPlatformId === vendorPlatformId) {
|
|
78
|
-
return true;
|
|
79
|
-
} else {
|
|
80
|
-
throw new Error(`'${vendorPlatformId}' binaries cannot be used on the '${currentPlatformId}' platform. Please remove the 'node_modules/sharp' directory and run 'npm install' on the '${currentPlatformId}' platform.`);
|
|
81
|
-
}
|
|
82
|
-
} else {
|
|
83
|
-
return false;
|
|
84
|
-
}
|
|
70
|
+
const vendorPath = path.join(__dirname, '..', 'vendor', minimumLibvipsVersion, platform());
|
|
71
|
+
return fs.existsSync(vendorPath);
|
|
85
72
|
};
|
|
86
73
|
|
|
87
74
|
const pkgConfigPath = function () {
|
|
@@ -105,7 +92,7 @@ const useGlobalLibvips = function () {
|
|
|
105
92
|
}
|
|
106
93
|
const globalVipsVersion = globalLibvipsVersion();
|
|
107
94
|
return !!globalVipsVersion && /* istanbul ignore next */
|
|
108
|
-
|
|
95
|
+
semverGreaterThanOrEqualTo(globalVipsVersion, minimumLibvipsVersion);
|
|
109
96
|
};
|
|
110
97
|
|
|
111
98
|
module.exports = {
|
package/lib/operation.js
CHANGED
|
@@ -270,9 +270,11 @@ function blur (sigma) {
|
|
|
270
270
|
/**
|
|
271
271
|
* Merge alpha transparency channel, if any, with a background, then remove the alpha channel.
|
|
272
272
|
*
|
|
273
|
+
* See also {@link /api-channel#removealpha|removeAlpha}.
|
|
274
|
+
*
|
|
273
275
|
* @example
|
|
274
276
|
* await sharp(rgbaInput)
|
|
275
|
-
* .flatten('#F0A703')
|
|
277
|
+
* .flatten({ background: '#F0A703' })
|
|
276
278
|
* .toBuffer();
|
|
277
279
|
*
|
|
278
280
|
* @param {Object} [options]
|
|
@@ -323,11 +325,19 @@ function gamma (gamma, gammaOut) {
|
|
|
323
325
|
|
|
324
326
|
/**
|
|
325
327
|
* Produce the "negative" of the image.
|
|
326
|
-
* @param {
|
|
328
|
+
* @param {Object} [options]
|
|
329
|
+
* @param {Boolean} [options.alpha=true] Whether or not to negate any alpha channel
|
|
327
330
|
* @returns {Sharp}
|
|
328
331
|
*/
|
|
329
|
-
function negate (
|
|
330
|
-
this.options.negate = is.bool(
|
|
332
|
+
function negate (options) {
|
|
333
|
+
this.options.negate = is.bool(options) ? options : true;
|
|
334
|
+
if (is.plainObject(options) && 'alpha' in options) {
|
|
335
|
+
if (!is.bool(options.alpha)) {
|
|
336
|
+
throw is.invalidParameterError('alpha', 'should be boolean value', options.alpha);
|
|
337
|
+
} else {
|
|
338
|
+
this.options.negateAlpha = options.alpha;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
331
341
|
return this;
|
|
332
342
|
}
|
|
333
343
|
|
|
@@ -350,6 +360,47 @@ function normalize (normalize) {
|
|
|
350
360
|
return this.normalise(normalize);
|
|
351
361
|
}
|
|
352
362
|
|
|
363
|
+
/**
|
|
364
|
+
* Perform contrast limiting adaptive histogram equalization
|
|
365
|
+
* {@link https://en.wikipedia.org/wiki/Adaptive_histogram_equalization#Contrast_Limited_AHE|CLAHE}.
|
|
366
|
+
*
|
|
367
|
+
* This will, in general, enhance the clarity of the image by bringing out darker details.
|
|
368
|
+
*
|
|
369
|
+
* @since 0.28.3
|
|
370
|
+
*
|
|
371
|
+
* @param {Object} options
|
|
372
|
+
* @param {number} options.width - integer width of the region in pixels.
|
|
373
|
+
* @param {number} options.height - integer height of the region in pixels.
|
|
374
|
+
* @param {number} [options.maxSlope=3] - maximum value for the slope of the
|
|
375
|
+
* cumulative histogram. A value of 0 disables contrast limiting. Valid values
|
|
376
|
+
* are integers in the range 0-100 (inclusive)
|
|
377
|
+
* @returns {Sharp}
|
|
378
|
+
* @throws {Error} Invalid parameters
|
|
379
|
+
*/
|
|
380
|
+
function clahe (options) {
|
|
381
|
+
if (!is.plainObject(options)) {
|
|
382
|
+
throw is.invalidParameterError('options', 'plain object', options);
|
|
383
|
+
}
|
|
384
|
+
if (!('width' in options) || !is.integer(options.width) || options.width <= 0) {
|
|
385
|
+
throw is.invalidParameterError('width', 'integer above zero', options.width);
|
|
386
|
+
} else {
|
|
387
|
+
this.options.claheWidth = options.width;
|
|
388
|
+
}
|
|
389
|
+
if (!('height' in options) || !is.integer(options.height) || options.height <= 0) {
|
|
390
|
+
throw is.invalidParameterError('height', 'integer above zero', options.height);
|
|
391
|
+
} else {
|
|
392
|
+
this.options.claheHeight = options.height;
|
|
393
|
+
}
|
|
394
|
+
if (!is.defined(options.maxSlope)) {
|
|
395
|
+
this.options.claheMaxSlope = 3;
|
|
396
|
+
} else if (!is.integer(options.maxSlope) || options.maxSlope < 0 || options.maxSlope > 100) {
|
|
397
|
+
throw is.invalidParameterError('maxSlope', 'integer 0-100', options.maxSlope);
|
|
398
|
+
} else {
|
|
399
|
+
this.options.claheMaxSlope = options.maxSlope;
|
|
400
|
+
}
|
|
401
|
+
return this;
|
|
402
|
+
}
|
|
403
|
+
|
|
353
404
|
/**
|
|
354
405
|
* Convolve the image with the specified kernel.
|
|
355
406
|
*
|
|
@@ -368,7 +419,7 @@ function normalize (normalize) {
|
|
|
368
419
|
*
|
|
369
420
|
* @param {Object} kernel
|
|
370
421
|
* @param {number} kernel.width - width of the kernel in pixels.
|
|
371
|
-
* @param {number} kernel.height -
|
|
422
|
+
* @param {number} kernel.height - height of the kernel in pixels.
|
|
372
423
|
* @param {Array<number>} kernel.kernel - Array of length `width*height` containing the kernel values.
|
|
373
424
|
* @param {number} [kernel.scale=sum] - the scale of the kernel in pixels.
|
|
374
425
|
* @param {number} [kernel.offset=0] - the offset of the kernel in pixels.
|
|
@@ -519,14 +570,16 @@ function recomb (inputMatrix) {
|
|
|
519
570
|
}
|
|
520
571
|
|
|
521
572
|
/**
|
|
522
|
-
* Transforms the image using brightness, saturation
|
|
573
|
+
* Transforms the image using brightness, saturation, hue rotation, and lightness.
|
|
574
|
+
* Brightness and lightness both operate on luminance, with the difference being that
|
|
575
|
+
* brightness is multiplicative whereas lightness is additive.
|
|
523
576
|
*
|
|
524
577
|
* @since 0.22.1
|
|
525
578
|
*
|
|
526
579
|
* @example
|
|
527
580
|
* sharp(input)
|
|
528
581
|
* .modulate({
|
|
529
|
-
* brightness: 2 // increase
|
|
582
|
+
* brightness: 2 // increase brightness by a factor of 2
|
|
530
583
|
* });
|
|
531
584
|
*
|
|
532
585
|
* sharp(input)
|
|
@@ -534,6 +587,11 @@ function recomb (inputMatrix) {
|
|
|
534
587
|
* hue: 180 // hue-rotate by 180 degrees
|
|
535
588
|
* });
|
|
536
589
|
*
|
|
590
|
+
* sharp(input)
|
|
591
|
+
* .modulate({
|
|
592
|
+
* lightness: 50 // increase lightness by +50
|
|
593
|
+
* });
|
|
594
|
+
*
|
|
537
595
|
* // decreate brightness and saturation while also hue-rotating by 90 degrees
|
|
538
596
|
* sharp(input)
|
|
539
597
|
* .modulate({
|
|
@@ -546,6 +604,7 @@ function recomb (inputMatrix) {
|
|
|
546
604
|
* @param {number} [options.brightness] Brightness multiplier
|
|
547
605
|
* @param {number} [options.saturation] Saturation multiplier
|
|
548
606
|
* @param {number} [options.hue] Degrees for hue rotation
|
|
607
|
+
* @param {number} [options.lightness] Lightness addend
|
|
549
608
|
* @returns {Sharp}
|
|
550
609
|
*/
|
|
551
610
|
function modulate (options) {
|
|
@@ -573,6 +632,13 @@ function modulate (options) {
|
|
|
573
632
|
throw is.invalidParameterError('hue', 'number', options.hue);
|
|
574
633
|
}
|
|
575
634
|
}
|
|
635
|
+
if ('lightness' in options) {
|
|
636
|
+
if (is.number(options.lightness)) {
|
|
637
|
+
this.options.lightness = options.lightness;
|
|
638
|
+
} else {
|
|
639
|
+
throw is.invalidParameterError('lightness', 'number', options.lightness);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
576
642
|
return this;
|
|
577
643
|
}
|
|
578
644
|
|
|
@@ -594,6 +660,7 @@ module.exports = function (Sharp) {
|
|
|
594
660
|
negate,
|
|
595
661
|
normalise,
|
|
596
662
|
normalize,
|
|
663
|
+
clahe,
|
|
597
664
|
convolve,
|
|
598
665
|
threshold,
|
|
599
666
|
boolean,
|
package/lib/output.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const path = require('path');
|
|
3
4
|
const is = require('./is');
|
|
4
|
-
const sharp = require('
|
|
5
|
+
const sharp = require('./sharp');
|
|
5
6
|
|
|
6
7
|
const formats = new Map([
|
|
7
8
|
['heic', 'heif'],
|
|
@@ -13,10 +14,15 @@ const formats = new Map([
|
|
|
13
14
|
['raw', 'raw'],
|
|
14
15
|
['tiff', 'tiff'],
|
|
15
16
|
['webp', 'webp'],
|
|
16
|
-
['gif', 'gif']
|
|
17
|
+
['gif', 'gif'],
|
|
18
|
+
['jp2', 'jp2'],
|
|
19
|
+
['jpx', 'jp2'],
|
|
20
|
+
['j2k', 'jp2'],
|
|
21
|
+
['j2c', 'jp2']
|
|
17
22
|
]);
|
|
18
23
|
|
|
19
24
|
const errMagickSave = new Error('GIF output requires libvips with support for ImageMagick');
|
|
25
|
+
const errJp2Save = new Error('JP2 output requires libvips with support for OpenJPEG');
|
|
20
26
|
|
|
21
27
|
/**
|
|
22
28
|
* Write output image data to a file.
|
|
@@ -28,6 +34,8 @@ const errMagickSave = new Error('GIF output requires libvips with support for Im
|
|
|
28
34
|
* By default all metadata will be removed, which includes EXIF-based orientation.
|
|
29
35
|
* See {@link withMetadata} for control over this.
|
|
30
36
|
*
|
|
37
|
+
* The caller is responsible for ensuring directory structures and permissions exist.
|
|
38
|
+
*
|
|
31
39
|
* A `Promise` is returned when `callback` is not provided.
|
|
32
40
|
*
|
|
33
41
|
* @example
|
|
@@ -52,7 +60,7 @@ function toFile (fileOut, callback) {
|
|
|
52
60
|
let err;
|
|
53
61
|
if (!is.string(fileOut)) {
|
|
54
62
|
err = new Error('Missing output file path');
|
|
55
|
-
} else if (this.options.input.file === fileOut) {
|
|
63
|
+
} else if (is.string(this.options.input.file) && path.resolve(this.options.input.file) === path.resolve(fileOut)) {
|
|
56
64
|
err = new Error('Cannot use same file for input and output');
|
|
57
65
|
} else if (this.options.formatOut === 'input' && fileOut.toLowerCase().endsWith('.gif') && !this.constructor.format.magick.output.file) {
|
|
58
66
|
err = errMagickSave;
|
|
@@ -150,7 +158,7 @@ function toBuffer (options, callback) {
|
|
|
150
158
|
*
|
|
151
159
|
* @example
|
|
152
160
|
* // Set "IFD0-Copyright" in output EXIF metadata
|
|
153
|
-
* await sharp(input)
|
|
161
|
+
* const data = await sharp(input)
|
|
154
162
|
* .withMetadata({
|
|
155
163
|
* exif: {
|
|
156
164
|
* IFD0: {
|
|
@@ -160,10 +168,17 @@ function toBuffer (options, callback) {
|
|
|
160
168
|
* })
|
|
161
169
|
* .toBuffer();
|
|
162
170
|
*
|
|
171
|
+
* * @example
|
|
172
|
+
* // Set output metadata to 96 DPI
|
|
173
|
+
* const data = await sharp(input)
|
|
174
|
+
* .withMetadata({ density: 96 })
|
|
175
|
+
* .toBuffer();
|
|
176
|
+
*
|
|
163
177
|
* @param {Object} [options]
|
|
164
178
|
* @param {number} [options.orientation] value between 1 and 8, used to update the EXIF `Orientation` tag.
|
|
165
179
|
* @param {string} [options.icc] filesystem path to output ICC profile, defaults to sRGB.
|
|
166
180
|
* @param {Object<Object>} [options.exif={}] Object keyed by IFD0, IFD1 etc. of key/value string pairs to write as EXIF data.
|
|
181
|
+
* @param {number} [options.density] Number of pixels per inch (DPI).
|
|
167
182
|
* @returns {Sharp}
|
|
168
183
|
* @throws {Error} Invalid parameters
|
|
169
184
|
*/
|
|
@@ -177,6 +192,13 @@ function withMetadata (options) {
|
|
|
177
192
|
throw is.invalidParameterError('orientation', 'integer between 1 and 8', options.orientation);
|
|
178
193
|
}
|
|
179
194
|
}
|
|
195
|
+
if (is.defined(options.density)) {
|
|
196
|
+
if (is.number(options.density) && options.density > 0) {
|
|
197
|
+
this.options.withMetadataDensity = options.density;
|
|
198
|
+
} else {
|
|
199
|
+
throw is.invalidParameterError('density', 'positive number', options.density);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
180
202
|
if (is.defined(options.icc)) {
|
|
181
203
|
if (is.string(options.icc)) {
|
|
182
204
|
this.options.withMetadataIcc = options.icc;
|
|
@@ -389,7 +411,7 @@ function png (options) {
|
|
|
389
411
|
const colours = options.colours || options.colors;
|
|
390
412
|
if (is.defined(colours)) {
|
|
391
413
|
if (is.integer(colours) && is.inRange(colours, 2, 256)) {
|
|
392
|
-
this.options.
|
|
414
|
+
this.options.pngBitdepth = 1 << 31 - Math.clz32(Math.ceil(Math.log2(colours)));
|
|
393
415
|
} else {
|
|
394
416
|
throw is.invalidParameterError('colours', 'integer between 2 and 256', colours);
|
|
395
417
|
}
|
|
@@ -495,6 +517,84 @@ function gif (options) {
|
|
|
495
517
|
return this._updateFormatOut('gif', options);
|
|
496
518
|
}
|
|
497
519
|
|
|
520
|
+
/**
|
|
521
|
+
* Use these JP2 options for output image.
|
|
522
|
+
*
|
|
523
|
+
* Requires libvips compiled with support for OpenJPEG.
|
|
524
|
+
* The prebuilt binaries do not include this - see
|
|
525
|
+
* {@link https://sharp.pixelplumbing.com/install#custom-libvips installing a custom libvips}.
|
|
526
|
+
*
|
|
527
|
+
* @example
|
|
528
|
+
* // Convert any input to lossless JP2 output
|
|
529
|
+
* const data = await sharp(input)
|
|
530
|
+
* .jp2({ lossless: true })
|
|
531
|
+
* .toBuffer();
|
|
532
|
+
*
|
|
533
|
+
* @example
|
|
534
|
+
* // Convert any input to very high quality JP2 output
|
|
535
|
+
* const data = await sharp(input)
|
|
536
|
+
* .jp2({
|
|
537
|
+
* quality: 100,
|
|
538
|
+
* chromaSubsampling: '4:4:4'
|
|
539
|
+
* })
|
|
540
|
+
* .toBuffer();
|
|
541
|
+
*
|
|
542
|
+
* @since 0.29.1
|
|
543
|
+
*
|
|
544
|
+
* @param {Object} [options] - output options
|
|
545
|
+
* @param {number} [options.quality=80] - quality, integer 1-100
|
|
546
|
+
* @param {boolean} [options.lossless=false] - use lossless compression mode
|
|
547
|
+
* @param {number} [options.tileWidth=512] - horizontal tile size
|
|
548
|
+
* @param {number} [options.tileHeight=512] - vertical tile size
|
|
549
|
+
* @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
|
|
550
|
+
* @returns {Sharp}
|
|
551
|
+
* @throws {Error} Invalid options
|
|
552
|
+
*/
|
|
553
|
+
/* istanbul ignore next */
|
|
554
|
+
function jp2 (options) {
|
|
555
|
+
if (!this.constructor.format.jp2k.output.buffer) {
|
|
556
|
+
throw errJp2Save;
|
|
557
|
+
}
|
|
558
|
+
if (is.object(options)) {
|
|
559
|
+
if (is.defined(options.quality)) {
|
|
560
|
+
if (is.integer(options.quality) && is.inRange(options.quality, 1, 100)) {
|
|
561
|
+
this.options.jp2Quality = options.quality;
|
|
562
|
+
} else {
|
|
563
|
+
throw is.invalidParameterError('quality', 'integer between 1 and 100', options.quality);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
if (is.defined(options.lossless)) {
|
|
567
|
+
if (is.bool(options.lossless)) {
|
|
568
|
+
this.options.jp2Lossless = options.lossless;
|
|
569
|
+
} else {
|
|
570
|
+
throw is.invalidParameterError('lossless', 'boolean', options.lossless);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
if (is.defined(options.tileWidth)) {
|
|
574
|
+
if (is.integer(options.tileWidth) && is.inRange(options.tileWidth, 1, 32768)) {
|
|
575
|
+
this.options.jp2TileWidth = options.tileWidth;
|
|
576
|
+
} else {
|
|
577
|
+
throw is.invalidParameterError('tileWidth', 'integer between 1 and 32768', options.tileWidth);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
if (is.defined(options.tileHeight)) {
|
|
581
|
+
if (is.integer(options.tileHeight) && is.inRange(options.tileHeight, 1, 32768)) {
|
|
582
|
+
this.options.jp2TileHeight = options.tileHeight;
|
|
583
|
+
} else {
|
|
584
|
+
throw is.invalidParameterError('tileHeight', 'integer between 1 and 32768', options.tileHeight);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
if (is.defined(options.chromaSubsampling)) {
|
|
588
|
+
if (is.string(options.chromaSubsampling) && is.inArray(options.chromaSubsampling, ['4:2:0', '4:4:4'])) {
|
|
589
|
+
this.options.heifChromaSubsampling = options.chromaSubsampling;
|
|
590
|
+
} else {
|
|
591
|
+
throw is.invalidParameterError('chromaSubsampling', 'one of: 4:2:0, 4:4:4', options.chromaSubsampling);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
return this._updateFormatOut('jp2', options);
|
|
596
|
+
}
|
|
597
|
+
|
|
498
598
|
/**
|
|
499
599
|
* Set animation options if available.
|
|
500
600
|
* @private
|
|
@@ -640,13 +740,15 @@ function tiff (options) {
|
|
|
640
740
|
* Whilst it is possible to create AVIF images smaller than 16x16 pixels,
|
|
641
741
|
* most web browsers do not display these properly.
|
|
642
742
|
*
|
|
743
|
+
* AVIF image sequences are not supported.
|
|
744
|
+
*
|
|
643
745
|
* @since 0.27.0
|
|
644
746
|
*
|
|
645
747
|
* @param {Object} [options] - output options
|
|
646
748
|
* @param {number} [options.quality=50] - quality, integer 1-100
|
|
647
749
|
* @param {boolean} [options.lossless=false] - use lossless compression
|
|
648
|
-
* @param {number} [options.speed=5] - CPU effort vs file size, 0 (slowest/smallest) to
|
|
649
|
-
* @param {string} [options.chromaSubsampling='4:
|
|
750
|
+
* @param {number} [options.speed=5] - CPU effort vs file size, 0 (slowest/smallest) to 9 (fastest/largest)
|
|
751
|
+
* @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
|
|
650
752
|
* @returns {Sharp}
|
|
651
753
|
* @throws {Error} Invalid options
|
|
652
754
|
*/
|
|
@@ -666,8 +768,8 @@ function avif (options) {
|
|
|
666
768
|
* @param {number} [options.quality=50] - quality, integer 1-100
|
|
667
769
|
* @param {string} [options.compression='av1'] - compression format: av1, hevc
|
|
668
770
|
* @param {boolean} [options.lossless=false] - use lossless compression
|
|
669
|
-
* @param {number} [options.speed=5] - CPU effort vs file size, 0 (slowest/smallest) to
|
|
670
|
-
* @param {string} [options.chromaSubsampling='4:
|
|
771
|
+
* @param {number} [options.speed=5] - CPU effort vs file size, 0 (slowest/smallest) to 9 (fastest/largest)
|
|
772
|
+
* @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
|
|
671
773
|
* @returns {Sharp}
|
|
672
774
|
* @throws {Error} Invalid options
|
|
673
775
|
*/
|
|
@@ -695,10 +797,10 @@ function heif (options) {
|
|
|
695
797
|
}
|
|
696
798
|
}
|
|
697
799
|
if (is.defined(options.speed)) {
|
|
698
|
-
if (is.integer(options.speed) && is.inRange(options.speed, 0,
|
|
800
|
+
if (is.integer(options.speed) && is.inRange(options.speed, 0, 9)) {
|
|
699
801
|
this.options.heifSpeed = options.speed;
|
|
700
802
|
} else {
|
|
701
|
-
throw is.invalidParameterError('speed', 'integer between 0 and
|
|
803
|
+
throw is.invalidParameterError('speed', 'integer between 0 and 9', options.speed);
|
|
702
804
|
}
|
|
703
805
|
}
|
|
704
806
|
if (is.defined(options.chromaSubsampling)) {
|
|
@@ -713,28 +815,41 @@ function heif (options) {
|
|
|
713
815
|
}
|
|
714
816
|
|
|
715
817
|
/**
|
|
716
|
-
* Force output to be raw, uncompressed
|
|
818
|
+
* Force output to be raw, uncompressed pixel data.
|
|
717
819
|
* Pixel ordering is left-to-right, top-to-bottom, without padding.
|
|
718
820
|
* Channel ordering will be RGB or RGBA for non-greyscale colourspaces.
|
|
719
821
|
*
|
|
720
822
|
* @example
|
|
721
|
-
* // Extract raw RGB pixel data from JPEG input
|
|
823
|
+
* // Extract raw, unsigned 8-bit RGB pixel data from JPEG input
|
|
722
824
|
* const { data, info } = await sharp('input.jpg')
|
|
723
825
|
* .raw()
|
|
724
826
|
* .toBuffer({ resolveWithObject: true });
|
|
725
827
|
*
|
|
726
828
|
* @example
|
|
727
|
-
* // Extract alpha channel as raw pixel data from PNG input
|
|
829
|
+
* // Extract alpha channel as raw, unsigned 16-bit pixel data from PNG input
|
|
728
830
|
* const data = await sharp('input.png')
|
|
729
831
|
* .ensureAlpha()
|
|
730
832
|
* .extractChannel(3)
|
|
731
833
|
* .toColourspace('b-w')
|
|
732
|
-
* .raw()
|
|
834
|
+
* .raw({ depth: 'ushort' })
|
|
733
835
|
* .toBuffer();
|
|
734
836
|
*
|
|
735
|
-
* @
|
|
837
|
+
* @param {Object} [options] - output options
|
|
838
|
+
* @param {string} [options.depth='uchar'] - bit depth, one of: char, uchar (default), short, ushort, int, uint, float, complex, double, dpcomplex
|
|
839
|
+
* @throws {Error} Invalid options
|
|
736
840
|
*/
|
|
737
|
-
function raw () {
|
|
841
|
+
function raw (options) {
|
|
842
|
+
if (is.object(options)) {
|
|
843
|
+
if (is.defined(options.depth)) {
|
|
844
|
+
if (is.string(options.depth) && is.inArray(options.depth,
|
|
845
|
+
['char', 'uchar', 'short', 'ushort', 'int', 'uint', 'float', 'complex', 'double', 'dpcomplex']
|
|
846
|
+
)) {
|
|
847
|
+
this.options.rawDepth = options.depth;
|
|
848
|
+
} else {
|
|
849
|
+
throw is.invalidParameterError('depth', 'one of: char, uchar, short, ushort, int, uint, float, complex, double, dpcomplex', options.depth);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
}
|
|
738
853
|
return this._updateFormatOut('raw');
|
|
739
854
|
}
|
|
740
855
|
|
|
@@ -1004,6 +1119,7 @@ module.exports = function (Sharp) {
|
|
|
1004
1119
|
withMetadata,
|
|
1005
1120
|
toFormat,
|
|
1006
1121
|
jpeg,
|
|
1122
|
+
jp2,
|
|
1007
1123
|
png,
|
|
1008
1124
|
webp,
|
|
1009
1125
|
tiff,
|
package/lib/sharp.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const platformAndArch = require('./platform')();
|
|
4
|
+
|
|
5
|
+
/* istanbul ignore next */
|
|
6
|
+
try {
|
|
7
|
+
module.exports = require(`../build/Release/sharp-${platformAndArch}.node`);
|
|
8
|
+
} catch (err) {
|
|
9
|
+
// Bail early if bindings aren't available
|
|
10
|
+
const help = ['', 'Something went wrong installing the "sharp" module', '', err.message, '', 'Possible solutions:'];
|
|
11
|
+
if (/dylib/.test(err.message) && /Incompatible library version/.test(err.message)) {
|
|
12
|
+
help.push('- Update Homebrew: "brew update && brew upgrade vips"');
|
|
13
|
+
} else {
|
|
14
|
+
help.push(
|
|
15
|
+
'- Install with the --verbose flag and look for errors: "npm install --ignore-scripts=false --verbose sharp"',
|
|
16
|
+
`- Install for the current runtime: "npm install --platform=${process.platform} --arch=${process.arch} sharp"`
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
help.push(
|
|
20
|
+
'- Consult the installation documentation: https://sharp.pixelplumbing.com/install'
|
|
21
|
+
);
|
|
22
|
+
console.error(help.join('\n'));
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
package/lib/utility.js
CHANGED
|
@@ -4,7 +4,7 @@ const events = require('events');
|
|
|
4
4
|
const detectLibc = require('detect-libc');
|
|
5
5
|
|
|
6
6
|
const is = require('./is');
|
|
7
|
-
const sharp = require('
|
|
7
|
+
const sharp = require('./sharp');
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* An Object containing nested boolean values representing the available input and output formats/methods.
|
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.29.1",
|
|
5
5
|
"author": "Lovell Fuller <npm@lovell.info>",
|
|
6
6
|
"homepage": "https://github.com/lovell/sharp",
|
|
7
7
|
"contributors": [
|
|
@@ -74,12 +74,18 @@
|
|
|
74
74
|
"Christian Flintrup <chr@gigahost.dk>",
|
|
75
75
|
"Manan Jadhav <manan@motionden.com>",
|
|
76
76
|
"Leon Radley <leon@radley.se>",
|
|
77
|
-
"alza54 <alza54@thiocod.in>"
|
|
77
|
+
"alza54 <alza54@thiocod.in>",
|
|
78
|
+
"Jacob Smith <jacob@frende.me>",
|
|
79
|
+
"Michael Nutt <michael@nutt.im>",
|
|
80
|
+
"Brad Parham <baparham@gmail.com>",
|
|
81
|
+
"Taneli Vatanen <taneli.vatanen@gmail.com>",
|
|
82
|
+
"Joris Dugué <zaruike10@gmail.com>"
|
|
78
83
|
],
|
|
79
84
|
"scripts": {
|
|
80
|
-
"install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node-gyp rebuild && node install/dll-copy)",
|
|
85
|
+
"install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node install/can-compile && node-gyp rebuild && node install/dll-copy)",
|
|
81
86
|
"clean": "rm -rf node_modules/ build/ vendor/ .nyc_output/ coverage/ test/fixtures/output.*",
|
|
82
|
-
"test": "
|
|
87
|
+
"test": "npm run test-lint && npm run test-unit && npm run test-licensing",
|
|
88
|
+
"test-lint": "semistandard && cpplint",
|
|
83
89
|
"test-unit": "nyc --reporter=lcov --branches=99 mocha --slow=1000 --timeout=60000 ./test/unit/*.js",
|
|
84
90
|
"test-licensing": "license-checker --production --summary --onlyAllow=\"Apache-2.0;BSD;ISC;MIT\"",
|
|
85
91
|
"test-coverage": "./test/coverage/report.sh",
|
|
@@ -107,6 +113,7 @@
|
|
|
107
113
|
"tiff",
|
|
108
114
|
"gif",
|
|
109
115
|
"svg",
|
|
116
|
+
"jp2",
|
|
110
117
|
"dzi",
|
|
111
118
|
"image",
|
|
112
119
|
"resize",
|
|
@@ -117,45 +124,45 @@
|
|
|
117
124
|
"vips"
|
|
118
125
|
],
|
|
119
126
|
"dependencies": {
|
|
120
|
-
"color": "^
|
|
127
|
+
"color": "^4.0.1",
|
|
121
128
|
"detect-libc": "^1.0.3",
|
|
122
|
-
"node-addon-api": "^
|
|
123
|
-
"prebuild-install": "^6.1.
|
|
129
|
+
"node-addon-api": "^4.1.0",
|
|
130
|
+
"prebuild-install": "^6.1.4",
|
|
124
131
|
"semver": "^7.3.5",
|
|
125
132
|
"simple-get": "^3.1.0",
|
|
126
133
|
"tar-fs": "^2.1.1",
|
|
127
134
|
"tunnel-agent": "^0.6.0"
|
|
128
135
|
},
|
|
129
136
|
"devDependencies": {
|
|
130
|
-
"async": "^3.2.
|
|
137
|
+
"async": "^3.2.1",
|
|
131
138
|
"cc": "^3.0.1",
|
|
132
139
|
"decompress-zip": "^0.3.3",
|
|
133
|
-
"documentation": "^13.2.
|
|
140
|
+
"documentation": "^13.2.5",
|
|
134
141
|
"exif-reader": "^1.0.3",
|
|
135
142
|
"icc": "^2.0.0",
|
|
136
143
|
"license-checker": "^25.0.1",
|
|
137
|
-
"mocha": "^
|
|
138
|
-
"mock-fs": "^
|
|
144
|
+
"mocha": "^9.1.1",
|
|
145
|
+
"mock-fs": "^5.0.0",
|
|
139
146
|
"nyc": "^15.1.0",
|
|
140
147
|
"prebuild": "^10.0.1",
|
|
141
148
|
"rimraf": "^3.0.2",
|
|
142
|
-
"semistandard": "^16.0.
|
|
149
|
+
"semistandard": "^16.0.1"
|
|
143
150
|
},
|
|
144
151
|
"license": "Apache-2.0",
|
|
145
152
|
"config": {
|
|
146
|
-
"libvips": "8.
|
|
153
|
+
"libvips": "8.11.3",
|
|
147
154
|
"runtime": "napi",
|
|
148
|
-
"target":
|
|
155
|
+
"target": 5
|
|
149
156
|
},
|
|
150
157
|
"engines": {
|
|
151
|
-
"node": ">=
|
|
158
|
+
"node": ">=12.13.0"
|
|
152
159
|
},
|
|
153
160
|
"funding": {
|
|
154
161
|
"url": "https://opencollective.com/libvips"
|
|
155
162
|
},
|
|
156
163
|
"binary": {
|
|
157
164
|
"napi_versions": [
|
|
158
|
-
|
|
165
|
+
5
|
|
159
166
|
]
|
|
160
167
|
},
|
|
161
168
|
"semistandard": {
|