@revizly/sharp 0.34.1-revizly9 → 0.34.4-revizly10
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/install/check.js +2 -4
- package/lib/channel.js +2 -2
- package/lib/colour.js +1 -3
- package/lib/composite.js +0 -2
- package/lib/constructor.js +20 -9
- package/lib/index.d.ts +116 -21
- package/lib/index.js +0 -2
- package/lib/input.js +117 -31
- package/lib/is.js +0 -2
- package/lib/libvips.js +22 -22
- package/lib/operation.js +0 -2
- package/lib/output.js +67 -4
- package/lib/resize.js +10 -7
- package/lib/sharp.js +3 -6
- package/lib/utility.js +6 -14
- package/package.json +28 -48
- package/src/binding.gyp +8 -4
- package/src/common.cc +84 -73
- package/src/common.h +23 -23
- package/src/metadata.cc +9 -3
- package/src/metadata.h +1 -0
- package/src/operations.cc +2 -2
- package/src/operations.h +1 -0
- package/src/pipeline.cc +64 -73
- package/src/pipeline.h +6 -2
- package/src/sharp.cc +6 -6
- package/src/stats.cc +5 -4
- package/src/stats.h +2 -1
- package/src/utilities.cc +5 -5
package/lib/input.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
// Copyright 2013 Lovell Fuller and others.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
|
-
'use strict';
|
|
5
|
-
|
|
6
4
|
const is = require('./is');
|
|
7
5
|
const sharp = require('./sharp');
|
|
8
6
|
|
|
@@ -22,14 +20,27 @@ const align = {
|
|
|
22
20
|
high: 'high'
|
|
23
21
|
};
|
|
24
22
|
|
|
23
|
+
const inputStreamParameters = [
|
|
24
|
+
// Limits and error handling
|
|
25
|
+
'failOn', 'limitInputPixels', 'unlimited',
|
|
26
|
+
// Format-generic
|
|
27
|
+
'animated', 'autoOrient', 'density', 'ignoreIcc', 'page', 'pages', 'sequentialRead',
|
|
28
|
+
// Format-specific
|
|
29
|
+
'jp2', 'openSlide', 'pdf', 'raw', 'svg', 'tiff',
|
|
30
|
+
// Deprecated
|
|
31
|
+
'failOnError', 'openSlideLevel', 'pdfBackground', 'tiffSubifd'
|
|
32
|
+
];
|
|
33
|
+
|
|
25
34
|
/**
|
|
26
35
|
* Extract input options, if any, from an object.
|
|
27
36
|
* @private
|
|
28
37
|
*/
|
|
29
38
|
function _inputOptionsFromObject (obj) {
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
const params = inputStreamParameters
|
|
40
|
+
.filter(p => is.defined(obj[p]))
|
|
41
|
+
.map(p => ([p, obj[p]]));
|
|
42
|
+
return params.length
|
|
43
|
+
? Object.fromEntries(params)
|
|
33
44
|
: undefined;
|
|
34
45
|
}
|
|
35
46
|
|
|
@@ -41,7 +52,7 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
41
52
|
const inputDescriptor = {
|
|
42
53
|
autoOrient: false,
|
|
43
54
|
failOn: 'warning',
|
|
44
|
-
limitInputPixels:
|
|
55
|
+
limitInputPixels: 0x3FFF ** 2,
|
|
45
56
|
ignoreIcc: false,
|
|
46
57
|
unlimited: false,
|
|
47
58
|
sequentialRead: true
|
|
@@ -137,7 +148,7 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
137
148
|
if (is.defined(inputOptions.limitInputPixels)) {
|
|
138
149
|
if (is.bool(inputOptions.limitInputPixels)) {
|
|
139
150
|
inputDescriptor.limitInputPixels = inputOptions.limitInputPixels
|
|
140
|
-
?
|
|
151
|
+
? 0x3FFF ** 2
|
|
141
152
|
: 0;
|
|
142
153
|
} else if (is.integer(inputOptions.limitInputPixels) && is.inRange(inputOptions.limitInputPixels, 0, Number.MAX_SAFE_INTEGER)) {
|
|
143
154
|
inputDescriptor.limitInputPixels = inputOptions.limitInputPixels;
|
|
@@ -172,8 +183,6 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
172
183
|
inputDescriptor.rawWidth = inputOptions.raw.width;
|
|
173
184
|
inputDescriptor.rawHeight = inputOptions.raw.height;
|
|
174
185
|
inputDescriptor.rawChannels = inputOptions.raw.channels;
|
|
175
|
-
inputDescriptor.rawPremultiplied = !!inputOptions.raw.premultiplied;
|
|
176
|
-
|
|
177
186
|
switch (input.constructor) {
|
|
178
187
|
case Uint8Array:
|
|
179
188
|
case Uint8ClampedArray:
|
|
@@ -207,6 +216,25 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
207
216
|
} else {
|
|
208
217
|
throw new Error('Expected width, height and channels for raw pixel input');
|
|
209
218
|
}
|
|
219
|
+
inputDescriptor.rawPremultiplied = false;
|
|
220
|
+
if (is.defined(inputOptions.raw.premultiplied)) {
|
|
221
|
+
if (is.bool(inputOptions.raw.premultiplied)) {
|
|
222
|
+
inputDescriptor.rawPremultiplied = inputOptions.raw.premultiplied;
|
|
223
|
+
} else {
|
|
224
|
+
throw is.invalidParameterError('raw.premultiplied', 'boolean', inputOptions.raw.premultiplied);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
inputDescriptor.rawPageHeight = 0;
|
|
228
|
+
if (is.defined(inputOptions.raw.pageHeight)) {
|
|
229
|
+
if (is.integer(inputOptions.raw.pageHeight) && inputOptions.raw.pageHeight > 0 && inputOptions.raw.pageHeight <= inputOptions.raw.height) {
|
|
230
|
+
if (inputOptions.raw.height % inputOptions.raw.pageHeight !== 0) {
|
|
231
|
+
throw new Error(`Expected raw.height ${inputOptions.raw.height} to be a multiple of raw.pageHeight ${inputOptions.raw.pageHeight}`);
|
|
232
|
+
}
|
|
233
|
+
inputDescriptor.rawPageHeight = inputOptions.raw.pageHeight;
|
|
234
|
+
} else {
|
|
235
|
+
throw is.invalidParameterError('raw.pageHeight', 'positive integer', inputOptions.raw.pageHeight);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
210
238
|
}
|
|
211
239
|
// Multi-page input (GIF, TIFF, PDF)
|
|
212
240
|
if (is.defined(inputOptions.animated)) {
|
|
@@ -230,26 +258,68 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
230
258
|
throw is.invalidParameterError('page', 'integer between 0 and 100000', inputOptions.page);
|
|
231
259
|
}
|
|
232
260
|
}
|
|
233
|
-
//
|
|
234
|
-
if (is.defined(inputOptions.level)) {
|
|
261
|
+
// OpenSlide specific options
|
|
262
|
+
if (is.object(inputOptions.openSlide) && is.defined(inputOptions.openSlide.level)) {
|
|
263
|
+
if (is.integer(inputOptions.openSlide.level) && is.inRange(inputOptions.openSlide.level, 0, 256)) {
|
|
264
|
+
inputDescriptor.openSlideLevel = inputOptions.openSlide.level;
|
|
265
|
+
} else {
|
|
266
|
+
throw is.invalidParameterError('openSlide.level', 'integer between 0 and 256', inputOptions.openSlide.level);
|
|
267
|
+
}
|
|
268
|
+
} else if (is.defined(inputOptions.level)) {
|
|
269
|
+
// Deprecated
|
|
235
270
|
if (is.integer(inputOptions.level) && is.inRange(inputOptions.level, 0, 256)) {
|
|
236
|
-
inputDescriptor.
|
|
271
|
+
inputDescriptor.openSlideLevel = inputOptions.level;
|
|
237
272
|
} else {
|
|
238
273
|
throw is.invalidParameterError('level', 'integer between 0 and 256', inputOptions.level);
|
|
239
274
|
}
|
|
240
275
|
}
|
|
241
|
-
//
|
|
242
|
-
if (is.defined(inputOptions.subifd)) {
|
|
276
|
+
// TIFF specific options
|
|
277
|
+
if (is.object(inputOptions.tiff) && is.defined(inputOptions.tiff.subifd)) {
|
|
278
|
+
if (is.integer(inputOptions.tiff.subifd) && is.inRange(inputOptions.tiff.subifd, -1, 100000)) {
|
|
279
|
+
inputDescriptor.tiffSubifd = inputOptions.tiff.subifd;
|
|
280
|
+
} else {
|
|
281
|
+
throw is.invalidParameterError('tiff.subifd', 'integer between -1 and 100000', inputOptions.tiff.subifd);
|
|
282
|
+
}
|
|
283
|
+
} else if (is.defined(inputOptions.subifd)) {
|
|
284
|
+
// Deprecated
|
|
243
285
|
if (is.integer(inputOptions.subifd) && is.inRange(inputOptions.subifd, -1, 100000)) {
|
|
244
|
-
inputDescriptor.
|
|
286
|
+
inputDescriptor.tiffSubifd = inputOptions.subifd;
|
|
245
287
|
} else {
|
|
246
288
|
throw is.invalidParameterError('subifd', 'integer between -1 and 100000', inputOptions.subifd);
|
|
247
289
|
}
|
|
248
290
|
}
|
|
249
|
-
//
|
|
250
|
-
if (is.
|
|
291
|
+
// SVG specific options
|
|
292
|
+
if (is.object(inputOptions.svg)) {
|
|
293
|
+
if (is.defined(inputOptions.svg.stylesheet)) {
|
|
294
|
+
if (is.string(inputOptions.svg.stylesheet)) {
|
|
295
|
+
inputDescriptor.svgStylesheet = inputOptions.svg.stylesheet;
|
|
296
|
+
} else {
|
|
297
|
+
throw is.invalidParameterError('svg.stylesheet', 'string', inputOptions.svg.stylesheet);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (is.defined(inputOptions.svg.highBitdepth)) {
|
|
301
|
+
if (is.bool(inputOptions.svg.highBitdepth)) {
|
|
302
|
+
inputDescriptor.svgHighBitdepth = inputOptions.svg.highBitdepth;
|
|
303
|
+
} else {
|
|
304
|
+
throw is.invalidParameterError('svg.highBitdepth', 'boolean', inputOptions.svg.highBitdepth);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
// PDF specific options
|
|
309
|
+
if (is.object(inputOptions.pdf) && is.defined(inputOptions.pdf.background)) {
|
|
310
|
+
inputDescriptor.pdfBackground = this._getBackgroundColourOption(inputOptions.pdf.background);
|
|
311
|
+
} else if (is.defined(inputOptions.pdfBackground)) {
|
|
312
|
+
// Deprecated
|
|
251
313
|
inputDescriptor.pdfBackground = this._getBackgroundColourOption(inputOptions.pdfBackground);
|
|
252
314
|
}
|
|
315
|
+
// JPEG 2000 specific options
|
|
316
|
+
if (is.object(inputOptions.jp2) && is.defined(inputOptions.jp2.oneshot)) {
|
|
317
|
+
if (is.bool(inputOptions.jp2.oneshot)) {
|
|
318
|
+
inputDescriptor.jp2Oneshot = inputOptions.jp2.oneshot;
|
|
319
|
+
} else {
|
|
320
|
+
throw is.invalidParameterError('jp2.oneshot', 'boolean', inputOptions.jp2.oneshot);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
253
323
|
// Create new image
|
|
254
324
|
if (is.defined(inputOptions.create)) {
|
|
255
325
|
if (
|
|
@@ -261,27 +331,44 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
261
331
|
inputDescriptor.createWidth = inputOptions.create.width;
|
|
262
332
|
inputDescriptor.createHeight = inputOptions.create.height;
|
|
263
333
|
inputDescriptor.createChannels = inputOptions.create.channels;
|
|
334
|
+
inputDescriptor.createPageHeight = 0;
|
|
335
|
+
if (is.defined(inputOptions.create.pageHeight)) {
|
|
336
|
+
if (is.integer(inputOptions.create.pageHeight) && inputOptions.create.pageHeight > 0 && inputOptions.create.pageHeight <= inputOptions.create.height) {
|
|
337
|
+
if (inputOptions.create.height % inputOptions.create.pageHeight !== 0) {
|
|
338
|
+
throw new Error(`Expected create.height ${inputOptions.create.height} to be a multiple of create.pageHeight ${inputOptions.create.pageHeight}`);
|
|
339
|
+
}
|
|
340
|
+
inputDescriptor.createPageHeight = inputOptions.create.pageHeight;
|
|
341
|
+
} else {
|
|
342
|
+
throw is.invalidParameterError('create.pageHeight', 'positive integer', inputOptions.create.pageHeight);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
264
345
|
// Noise
|
|
265
346
|
if (is.defined(inputOptions.create.noise)) {
|
|
266
347
|
if (!is.object(inputOptions.create.noise)) {
|
|
267
348
|
throw new Error('Expected noise to be an object');
|
|
268
349
|
}
|
|
269
|
-
if (
|
|
350
|
+
if (inputOptions.create.noise.type !== 'gaussian') {
|
|
270
351
|
throw new Error('Only gaussian noise is supported at the moment');
|
|
271
352
|
}
|
|
353
|
+
inputDescriptor.createNoiseType = inputOptions.create.noise.type;
|
|
272
354
|
if (!is.inRange(inputOptions.create.channels, 1, 4)) {
|
|
273
355
|
throw is.invalidParameterError('create.channels', 'number between 1 and 4', inputOptions.create.channels);
|
|
274
356
|
}
|
|
275
|
-
inputDescriptor.
|
|
276
|
-
if (is.
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
357
|
+
inputDescriptor.createNoiseMean = 128;
|
|
358
|
+
if (is.defined(inputOptions.create.noise.mean)) {
|
|
359
|
+
if (is.number(inputOptions.create.noise.mean) && is.inRange(inputOptions.create.noise.mean, 0, 10000)) {
|
|
360
|
+
inputDescriptor.createNoiseMean = inputOptions.create.noise.mean;
|
|
361
|
+
} else {
|
|
362
|
+
throw is.invalidParameterError('create.noise.mean', 'number between 0 and 10000', inputOptions.create.noise.mean);
|
|
363
|
+
}
|
|
280
364
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
365
|
+
inputDescriptor.createNoiseSigma = 30;
|
|
366
|
+
if (is.defined(inputOptions.create.noise.sigma)) {
|
|
367
|
+
if (is.number(inputOptions.create.noise.sigma) && is.inRange(inputOptions.create.noise.sigma, 0, 10000)) {
|
|
368
|
+
inputDescriptor.createNoiseSigma = inputOptions.create.noise.sigma;
|
|
369
|
+
} else {
|
|
370
|
+
throw is.invalidParameterError('create.noise.sigma', 'number between 0 and 10000', inputOptions.create.noise.sigma);
|
|
371
|
+
}
|
|
285
372
|
}
|
|
286
373
|
} else if (is.defined(inputOptions.create.background)) {
|
|
287
374
|
if (!is.inRange(inputOptions.create.channels, 3, 4)) {
|
|
@@ -424,7 +511,7 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
424
511
|
}
|
|
425
512
|
}
|
|
426
513
|
} else if (is.defined(inputOptions)) {
|
|
427
|
-
throw new Error(
|
|
514
|
+
throw new Error(`Invalid input options ${inputOptions}`);
|
|
428
515
|
}
|
|
429
516
|
return inputDescriptor;
|
|
430
517
|
}
|
|
@@ -436,10 +523,8 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
436
523
|
* @param {string} encoding - unused
|
|
437
524
|
* @param {Function} callback
|
|
438
525
|
*/
|
|
439
|
-
function _write (chunk,
|
|
440
|
-
/* istanbul ignore else */
|
|
526
|
+
function _write (chunk, _encoding, callback) {
|
|
441
527
|
if (Array.isArray(this.options.input.buffer)) {
|
|
442
|
-
/* istanbul ignore else */
|
|
443
528
|
if (is.buffer(chunk)) {
|
|
444
529
|
if (this.options.input.buffer.length === 0) {
|
|
445
530
|
this.on('finish', () => {
|
|
@@ -516,6 +601,7 @@ function _isStreamInput () {
|
|
|
516
601
|
* - `icc`: Buffer containing raw [ICC](https://www.npmjs.com/package/icc) profile data, if present
|
|
517
602
|
* - `iptc`: Buffer containing raw IPTC data, if present
|
|
518
603
|
* - `xmp`: Buffer containing raw XMP data, if present
|
|
604
|
+
* - `xmpAsString`: String containing XMP data, if valid UTF-8.
|
|
519
605
|
* - `tifftagPhotoshop`: Buffer containing raw TIFFTAG_PHOTOSHOP data, if present
|
|
520
606
|
* - `formatMagick`: String containing format for images loaded via *magick
|
|
521
607
|
* - `comments`: Array of keyword/text pairs representing PNG text blocks, if present.
|
package/lib/is.js
CHANGED
package/lib/libvips.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
// Copyright 2013 Lovell Fuller and others.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
|
-
'use strict';
|
|
5
|
-
|
|
6
4
|
const { spawnSync } = require('node:child_process');
|
|
7
5
|
const { createHash } = require('node:crypto');
|
|
8
6
|
const semverCoerce = require('semver/functions/coerce');
|
|
@@ -12,15 +10,15 @@ const detectLibc = require('detect-libc');
|
|
|
12
10
|
|
|
13
11
|
const { config, engines, optionalDependencies } = require('../package.json');
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
/* node:coverage ignore next */
|
|
14
|
+
const minimumLibvipsVersionLabelled = process.env.npm_package_config_libvips || config.libvips;
|
|
17
15
|
const minimumLibvipsVersion = semverCoerce(minimumLibvipsVersionLabelled).version;
|
|
18
16
|
|
|
19
17
|
const prebuiltPlatforms = [
|
|
20
18
|
'darwin-arm64', 'darwin-x64',
|
|
21
|
-
'linux-arm', 'linux-arm64', 'linux-s390x', 'linux-x64',
|
|
19
|
+
'linux-arm', 'linux-arm64', 'linux-ppc64', 'linux-s390x', 'linux-x64',
|
|
22
20
|
'linuxmusl-arm64', 'linuxmusl-x64',
|
|
23
|
-
'win32-ia32', 'win32-x64'
|
|
21
|
+
'win32-arm64', 'win32-ia32', 'win32-x64'
|
|
24
22
|
];
|
|
25
23
|
|
|
26
24
|
const spawnSyncOptions = {
|
|
@@ -36,17 +34,16 @@ const log = (item) => {
|
|
|
36
34
|
}
|
|
37
35
|
};
|
|
38
36
|
|
|
39
|
-
/*
|
|
37
|
+
/* node:coverage ignore next */
|
|
40
38
|
const runtimeLibc = () => detectLibc.isNonGlibcLinuxSync() ? detectLibc.familySync() : '';
|
|
41
39
|
|
|
42
40
|
const runtimePlatformArch = () => `${process.platform}${runtimeLibc()}-${process.arch}`;
|
|
43
41
|
|
|
44
|
-
/* istanbul ignore next */
|
|
45
42
|
const buildPlatformArch = () => {
|
|
43
|
+
/* node:coverage ignore next 3 */
|
|
46
44
|
if (isEmscripten()) {
|
|
47
45
|
return 'wasm32';
|
|
48
46
|
}
|
|
49
|
-
/* eslint camelcase: ["error", { allow: ["^npm_config_"] }] */
|
|
50
47
|
const { npm_config_arch, npm_config_platform, npm_config_libc } = process.env;
|
|
51
48
|
const libc = typeof npm_config_libc === 'string' ? npm_config_libc : runtimeLibc();
|
|
52
49
|
return `${npm_config_platform || process.platform}${libc}-${npm_config_arch || process.arch}`;
|
|
@@ -56,19 +53,19 @@ const buildSharpLibvipsIncludeDir = () => {
|
|
|
56
53
|
try {
|
|
57
54
|
return require(`@revizly/sharp-libvips-dev-${buildPlatformArch()}/include`);
|
|
58
55
|
} catch {
|
|
56
|
+
/* node:coverage ignore next 5 */
|
|
59
57
|
try {
|
|
60
58
|
return require('@revizly/sharp-libvips-dev/include');
|
|
61
59
|
} catch {}
|
|
62
60
|
}
|
|
63
|
-
/* istanbul ignore next */
|
|
64
61
|
return '';
|
|
65
62
|
};
|
|
66
63
|
|
|
67
64
|
const buildSharpLibvipsCPlusPlusDir = () => {
|
|
65
|
+
/* node:coverage ignore next 4 */
|
|
68
66
|
try {
|
|
69
67
|
return require('@revizly/sharp-libvips-dev/cplusplus');
|
|
70
68
|
} catch {}
|
|
71
|
-
/* istanbul ignore next */
|
|
72
69
|
return '';
|
|
73
70
|
};
|
|
74
71
|
|
|
@@ -76,16 +73,17 @@ const buildSharpLibvipsLibDir = () => {
|
|
|
76
73
|
try {
|
|
77
74
|
return require(`@revizly/sharp-libvips-dev-${buildPlatformArch()}/lib`);
|
|
78
75
|
} catch {
|
|
76
|
+
/* node:coverage ignore next 5 */
|
|
79
77
|
try {
|
|
80
78
|
return require(`@revizly/sharp-libvips-${buildPlatformArch()}/lib`);
|
|
81
79
|
} catch {}
|
|
82
80
|
}
|
|
83
|
-
/* istanbul ignore next */
|
|
84
81
|
return '';
|
|
85
82
|
};
|
|
86
83
|
|
|
84
|
+
/* node:coverage disable */
|
|
85
|
+
|
|
87
86
|
const isUnsupportedNodeRuntime = () => {
|
|
88
|
-
/* istanbul ignore next */
|
|
89
87
|
if (process.release?.name === 'node' && process.versions) {
|
|
90
88
|
if (!semverSatisfies(process.versions.node, engines.node)) {
|
|
91
89
|
return { found: process.versions.node, expected: engines.node };
|
|
@@ -93,14 +91,12 @@ const isUnsupportedNodeRuntime = () => {
|
|
|
93
91
|
}
|
|
94
92
|
};
|
|
95
93
|
|
|
96
|
-
/* istanbul ignore next */
|
|
97
94
|
const isEmscripten = () => {
|
|
98
95
|
const { CC } = process.env;
|
|
99
|
-
return Boolean(CC
|
|
96
|
+
return Boolean(CC?.endsWith('/emcc'));
|
|
100
97
|
};
|
|
101
98
|
|
|
102
99
|
const isRosetta = () => {
|
|
103
|
-
/* istanbul ignore next */
|
|
104
100
|
if (process.platform === 'darwin' && process.arch === 'x64') {
|
|
105
101
|
const translated = spawnSync('sysctl sysctl.proc_translated', spawnSyncOptions).stdout;
|
|
106
102
|
return (translated || '').trim() === 'sysctl.proc_translated: 1';
|
|
@@ -108,6 +104,8 @@ const isRosetta = () => {
|
|
|
108
104
|
return false;
|
|
109
105
|
};
|
|
110
106
|
|
|
107
|
+
/* node:coverage enable */
|
|
108
|
+
|
|
111
109
|
const sha512 = (s) => createHash('sha512').update(s).digest('hex');
|
|
112
110
|
|
|
113
111
|
const yarnLocator = () => {
|
|
@@ -121,7 +119,8 @@ const yarnLocator = () => {
|
|
|
121
119
|
return '';
|
|
122
120
|
};
|
|
123
121
|
|
|
124
|
-
/*
|
|
122
|
+
/* node:coverage disable */
|
|
123
|
+
|
|
125
124
|
const spawnRebuild = () =>
|
|
126
125
|
spawnSync(`node-gyp rebuild --directory=src ${isEmscripten() ? '--nodedir=emscripten' : ''}`, {
|
|
127
126
|
...spawnSyncOptions,
|
|
@@ -137,16 +136,17 @@ const globalLibvipsVersion = () => {
|
|
|
137
136
|
PKG_CONFIG_PATH: pkgConfigPath()
|
|
138
137
|
}
|
|
139
138
|
}).stdout;
|
|
140
|
-
/* istanbul ignore next */
|
|
141
139
|
return (globalLibvipsVersion || '').trim();
|
|
142
140
|
} else {
|
|
143
141
|
return '';
|
|
144
142
|
}
|
|
145
143
|
};
|
|
146
144
|
|
|
147
|
-
/*
|
|
145
|
+
/* node:coverage enable */
|
|
146
|
+
|
|
148
147
|
const pkgConfigPath = () => {
|
|
149
148
|
if (process.platform !== 'win32') {
|
|
149
|
+
/* node:coverage ignore next 4 */
|
|
150
150
|
const brewPkgConfigPath = spawnSync(
|
|
151
151
|
'which brew >/dev/null 2>&1 && brew environment --plain | grep PKG_CONFIG_LIBDIR | cut -d" " -f2',
|
|
152
152
|
spawnSyncOptions
|
|
@@ -178,13 +178,13 @@ const useGlobalLibvips = (logger) => {
|
|
|
178
178
|
if (Boolean(process.env.SHARP_FORCE_GLOBAL_LIBVIPS) === true) {
|
|
179
179
|
return skipSearch(true, 'SHARP_FORCE_GLOBAL_LIBVIPS', logger);
|
|
180
180
|
}
|
|
181
|
-
/*
|
|
181
|
+
/* node:coverage ignore next 3 */
|
|
182
182
|
if (isRosetta()) {
|
|
183
183
|
return skipSearch(false, 'Rosetta', logger);
|
|
184
184
|
}
|
|
185
185
|
const globalVipsVersion = globalLibvipsVersion();
|
|
186
|
-
|
|
187
|
-
|
|
186
|
+
/* node:coverage ignore next */
|
|
187
|
+
return !!globalVipsVersion && semverGreaterThanOrEqualTo(globalVipsVersion, minimumLibvipsVersion);
|
|
188
188
|
};
|
|
189
189
|
|
|
190
190
|
module.exports = {
|
package/lib/operation.js
CHANGED
package/lib/output.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
// Copyright 2013 Lovell Fuller and others.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
|
-
'use strict';
|
|
5
|
-
|
|
6
4
|
const path = require('node:path');
|
|
7
5
|
const is = require('./is');
|
|
8
6
|
const sharp = require('./sharp');
|
|
@@ -312,6 +310,59 @@ function withIccProfile (icc, options) {
|
|
|
312
310
|
return this;
|
|
313
311
|
}
|
|
314
312
|
|
|
313
|
+
/**
|
|
314
|
+
* Keep XMP metadata from the input image in the output image.
|
|
315
|
+
*
|
|
316
|
+
* @since 0.34.3
|
|
317
|
+
*
|
|
318
|
+
* @example
|
|
319
|
+
* const outputWithXmp = await sharp(inputWithXmp)
|
|
320
|
+
* .keepXmp()
|
|
321
|
+
* .toBuffer();
|
|
322
|
+
*
|
|
323
|
+
* @returns {Sharp}
|
|
324
|
+
*/
|
|
325
|
+
function keepXmp () {
|
|
326
|
+
this.options.keepMetadata |= 0b00010;
|
|
327
|
+
return this;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Set XMP metadata in the output image.
|
|
332
|
+
*
|
|
333
|
+
* Supported by PNG, JPEG, WebP, and TIFF output.
|
|
334
|
+
*
|
|
335
|
+
* @since 0.34.3
|
|
336
|
+
*
|
|
337
|
+
* @example
|
|
338
|
+
* const xmpString = `
|
|
339
|
+
* <?xml version="1.0"?>
|
|
340
|
+
* <x:xmpmeta xmlns:x="adobe:ns:meta/">
|
|
341
|
+
* <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
|
342
|
+
* <rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
|
343
|
+
* <dc:creator><rdf:Seq><rdf:li>John Doe</rdf:li></rdf:Seq></dc:creator>
|
|
344
|
+
* </rdf:Description>
|
|
345
|
+
* </rdf:RDF>
|
|
346
|
+
* </x:xmpmeta>`;
|
|
347
|
+
*
|
|
348
|
+
* const data = await sharp(input)
|
|
349
|
+
* .withXmp(xmpString)
|
|
350
|
+
* .toBuffer();
|
|
351
|
+
*
|
|
352
|
+
* @param {string} xmp String containing XMP metadata to be embedded in the output image.
|
|
353
|
+
* @returns {Sharp}
|
|
354
|
+
* @throws {Error} Invalid parameters
|
|
355
|
+
*/
|
|
356
|
+
function withXmp (xmp) {
|
|
357
|
+
if (is.string(xmp) && xmp.length > 0) {
|
|
358
|
+
this.options.withXmp = xmp;
|
|
359
|
+
this.options.keepMetadata |= 0b00010;
|
|
360
|
+
} else {
|
|
361
|
+
throw is.invalidParameterError('xmp', 'non-empty string', xmp);
|
|
362
|
+
}
|
|
363
|
+
return this;
|
|
364
|
+
}
|
|
365
|
+
|
|
315
366
|
/**
|
|
316
367
|
* Keep all metadata (EXIF, ICC, XMP, IPTC) from the input image in the output image.
|
|
317
368
|
*
|
|
@@ -729,6 +780,7 @@ function webp (options) {
|
|
|
729
780
|
* @param {number} [options.dither=1.0] - level of Floyd-Steinberg error diffusion, between 0 (least) and 1 (most)
|
|
730
781
|
* @param {number} [options.interFrameMaxError=0] - maximum inter-frame error for transparency, between 0 (lossless) and 32
|
|
731
782
|
* @param {number} [options.interPaletteMaxError=3] - maximum inter-palette error for palette reuse, between 0 and 256
|
|
783
|
+
* @param {boolean} [options.keepDuplicateFrames=false] - keep duplicate frames in the output instead of combining them
|
|
732
784
|
* @param {number} [options.loop=0] - number of animation iterations, use 0 for infinite animation
|
|
733
785
|
* @param {number|number[]} [options.delay] - delay(s) between animation frames (in milliseconds)
|
|
734
786
|
* @param {boolean} [options.force=true] - force GIF output, otherwise attempt to use input format
|
|
@@ -779,12 +831,18 @@ function gif (options) {
|
|
|
779
831
|
throw is.invalidParameterError('interPaletteMaxError', 'number between 0.0 and 256.0', options.interPaletteMaxError);
|
|
780
832
|
}
|
|
781
833
|
}
|
|
834
|
+
if (is.defined(options.keepDuplicateFrames)) {
|
|
835
|
+
if (is.bool(options.keepDuplicateFrames)) {
|
|
836
|
+
this._setBooleanOption('gifKeepDuplicateFrames', options.keepDuplicateFrames);
|
|
837
|
+
} else {
|
|
838
|
+
throw is.invalidParameterError('keepDuplicateFrames', 'boolean', options.keepDuplicateFrames);
|
|
839
|
+
}
|
|
840
|
+
}
|
|
782
841
|
}
|
|
783
842
|
trySetAnimationOptions(options, this.options);
|
|
784
843
|
return this._updateFormatOut('gif', options);
|
|
785
844
|
}
|
|
786
845
|
|
|
787
|
-
/* istanbul ignore next */
|
|
788
846
|
/**
|
|
789
847
|
* Use these JP2 options for output image.
|
|
790
848
|
*
|
|
@@ -819,6 +877,7 @@ function gif (options) {
|
|
|
819
877
|
* @throws {Error} Invalid options
|
|
820
878
|
*/
|
|
821
879
|
function jp2 (options) {
|
|
880
|
+
/* node:coverage ignore next 41 */
|
|
822
881
|
if (!this.constructor.format.jp2k.output.buffer) {
|
|
823
882
|
throw errJp2Save();
|
|
824
883
|
}
|
|
@@ -1019,6 +1078,9 @@ function tiff (options) {
|
|
|
1019
1078
|
* AVIF image sequences are not supported.
|
|
1020
1079
|
* Prebuilt binaries support a bitdepth of 8 only.
|
|
1021
1080
|
*
|
|
1081
|
+
* This feature is experimental on the Windows ARM64 platform
|
|
1082
|
+
* and requires a CPU with ARM64v8.4 or later.
|
|
1083
|
+
*
|
|
1022
1084
|
* @example
|
|
1023
1085
|
* const data = await sharp(input)
|
|
1024
1086
|
* .avif({ effort: 2 })
|
|
@@ -1438,7 +1500,6 @@ function _setBooleanOption (key, val) {
|
|
|
1438
1500
|
* @private
|
|
1439
1501
|
*/
|
|
1440
1502
|
function _read () {
|
|
1441
|
-
/* istanbul ignore else */
|
|
1442
1503
|
if (!this.options.streamOut) {
|
|
1443
1504
|
this.options.streamOut = true;
|
|
1444
1505
|
const stack = Error();
|
|
@@ -1565,6 +1626,8 @@ module.exports = function (Sharp) {
|
|
|
1565
1626
|
withExifMerge,
|
|
1566
1627
|
keepIccProfile,
|
|
1567
1628
|
withIccProfile,
|
|
1629
|
+
keepXmp,
|
|
1630
|
+
withXmp,
|
|
1568
1631
|
keepMetadata,
|
|
1569
1632
|
withMetadata,
|
|
1570
1633
|
toFormat,
|
package/lib/resize.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
// Copyright 2013 Lovell Fuller and others.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
|
-
'use strict';
|
|
5
|
-
|
|
6
4
|
const is = require('./is');
|
|
7
5
|
|
|
8
6
|
/**
|
|
@@ -107,7 +105,7 @@ const mapFitToCanvas = {
|
|
|
107
105
|
* @private
|
|
108
106
|
*/
|
|
109
107
|
function isRotationExpected (options) {
|
|
110
|
-
return (options.angle % 360) !== 0 || options.
|
|
108
|
+
return (options.angle % 360) !== 0 || options.rotationAngle !== 0;
|
|
111
109
|
}
|
|
112
110
|
|
|
113
111
|
/**
|
|
@@ -129,7 +127,7 @@ function isResizeExpected (options) {
|
|
|
129
127
|
*
|
|
130
128
|
* Some of these values are based on the [object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) CSS property.
|
|
131
129
|
*
|
|
132
|
-
* <img alt="Examples of various values for the fit property when resizing" width="100%" style="aspect-ratio: 998/243" src="
|
|
130
|
+
* <img alt="Examples of various values for the fit property when resizing" width="100%" style="aspect-ratio: 998/243" src="/api-resize-fit.svg">
|
|
133
131
|
*
|
|
134
132
|
* When using a **fit** of `cover` or `contain`, the default **position** is `centre`. Other options are:
|
|
135
133
|
* - `sharp.position`: `top`, `right top`, `right`, `right bottom`, `bottom`, `left bottom`, `left`, `left top`.
|
|
@@ -150,6 +148,8 @@ function isResizeExpected (options) {
|
|
|
150
148
|
* - `mitchell`: Use a [Mitchell-Netravali spline](https://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf).
|
|
151
149
|
* - `lanczos2`: Use a [Lanczos kernel](https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel) with `a=2`.
|
|
152
150
|
* - `lanczos3`: Use a Lanczos kernel with `a=3` (the default).
|
|
151
|
+
* - `mks2013`: Use a [Magic Kernel Sharp](https://johncostella.com/magic/mks.pdf) 2013 kernel, as adopted by Facebook.
|
|
152
|
+
* - `mks2021`: Use a Magic Kernel Sharp 2021 kernel, with more accurate (reduced) sharpening than the 2013 version.
|
|
153
153
|
*
|
|
154
154
|
* When upsampling, these kernels map to `nearest`, `linear` and `cubic` interpolators.
|
|
155
155
|
* Downsampling kernels without a matching upsampling interpolator map to `cubic`.
|
|
@@ -341,7 +341,7 @@ function resize (widthOrOptions, height, options) {
|
|
|
341
341
|
}
|
|
342
342
|
}
|
|
343
343
|
if (isRotationExpected(this.options) && isResizeExpected(this.options)) {
|
|
344
|
-
this.options.
|
|
344
|
+
this.options.rotateBefore = true;
|
|
345
345
|
}
|
|
346
346
|
return this;
|
|
347
347
|
}
|
|
@@ -488,9 +488,12 @@ function extract (options) {
|
|
|
488
488
|
// Ensure existing rotation occurs before pre-resize extraction
|
|
489
489
|
if (isRotationExpected(this.options) && !isResizeExpected(this.options)) {
|
|
490
490
|
if (this.options.widthPre === -1 || this.options.widthPost === -1) {
|
|
491
|
-
this.options.
|
|
491
|
+
this.options.rotateBefore = true;
|
|
492
492
|
}
|
|
493
493
|
}
|
|
494
|
+
if (this.options.input.autoOrient) {
|
|
495
|
+
this.options.orientBefore = true;
|
|
496
|
+
}
|
|
494
497
|
return this;
|
|
495
498
|
}
|
|
496
499
|
|
|
@@ -564,7 +567,7 @@ function trim (options) {
|
|
|
564
567
|
}
|
|
565
568
|
}
|
|
566
569
|
if (isRotationExpected(this.options)) {
|
|
567
|
-
this.options.
|
|
570
|
+
this.options.rotateBefore = true;
|
|
568
571
|
}
|
|
569
572
|
return this;
|
|
570
573
|
}
|
package/lib/sharp.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
// Copyright 2013 Lovell Fuller and others.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
|
-
'use strict';
|
|
5
|
-
|
|
6
4
|
// Inspects the runtime environment and exports the relevant sharp.node binary
|
|
7
5
|
|
|
8
6
|
const { familySync, versionSync } = require('detect-libc');
|
|
@@ -17,6 +15,8 @@ const paths = [
|
|
|
17
15
|
'@revizly/sharp-wasm32/sharp.node'
|
|
18
16
|
];
|
|
19
17
|
|
|
18
|
+
/* node:coverage disable */
|
|
19
|
+
|
|
20
20
|
let path, sharp;
|
|
21
21
|
const errors = [];
|
|
22
22
|
for (path of paths) {
|
|
@@ -24,12 +24,10 @@ for (path of paths) {
|
|
|
24
24
|
sharp = require(path);
|
|
25
25
|
break;
|
|
26
26
|
} catch (err) {
|
|
27
|
-
/* istanbul ignore next */
|
|
28
27
|
errors.push(err);
|
|
29
28
|
}
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
/* istanbul ignore next */
|
|
33
31
|
if (sharp && path.startsWith('@img/sharp-linux-x64') && !sharp._isUsingX64V2()) {
|
|
34
32
|
const err = new Error('Prebuilt binaries for linux-x64 require v2 microarchitecture');
|
|
35
33
|
err.code = 'Unsupported CPU';
|
|
@@ -37,7 +35,6 @@ if (sharp && path.startsWith('@img/sharp-linux-x64') && !sharp._isUsingX64V2())
|
|
|
37
35
|
sharp = null;
|
|
38
36
|
}
|
|
39
37
|
|
|
40
|
-
/* istanbul ignore next */
|
|
41
38
|
if (sharp) {
|
|
42
39
|
module.exports = sharp;
|
|
43
40
|
} else {
|
|
@@ -88,7 +85,7 @@ if (sharp) {
|
|
|
88
85
|
` Found ${libcFound}`,
|
|
89
86
|
` Requires ${libcRequires}`
|
|
90
87
|
);
|
|
91
|
-
} catch (
|
|
88
|
+
} catch (_errEngines) {}
|
|
92
89
|
}
|
|
93
90
|
if (isLinux && /\/snap\/core[0-9]{2}/.test(messages)) {
|
|
94
91
|
help.push(
|