sharp 0.27.1 → 0.30.5
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 +19 -18
- package/binding.gyp +15 -14
- package/install/can-compile.js +11 -0
- package/install/dll-copy.js +10 -10
- package/install/libvips.js +128 -47
- package/lib/agent.js +1 -1
- package/lib/channel.js +38 -14
- package/lib/colour.js +51 -1
- package/lib/composite.js +19 -2
- package/lib/constructor.js +47 -46
- package/lib/input.js +112 -18
- package/lib/is.js +19 -5
- package/lib/libvips.js +64 -29
- package/lib/operation.js +239 -35
- package/lib/output.js +398 -116
- package/lib/platform.js +5 -3
- package/lib/resize.js +61 -15
- package/lib/sharp.js +32 -0
- package/lib/utility.js +58 -19
- package/package.json +46 -24
- package/src/common.cc +202 -52
- package/src/common.h +59 -10
- package/src/libvips/cplusplus/VConnection.cpp +0 -26
- package/src/libvips/cplusplus/VImage.cpp +88 -32
- package/src/libvips/cplusplus/VInterpolate.cpp +0 -13
- package/src/libvips/cplusplus/vips-operators.cpp +213 -1
- package/src/metadata.cc +26 -0
- package/src/metadata.h +4 -0
- package/src/operations.cc +141 -7
- package/src/operations.h +32 -3
- package/src/pipeline.cc +454 -306
- package/src/pipeline.h +64 -29
- package/src/sharp.cc +1 -0
- package/src/utilities.cc +17 -1
- package/src/utilities.h +1 -0
package/lib/composite.js
CHANGED
|
@@ -50,12 +50,27 @@ const blend = {
|
|
|
50
50
|
* `hard-light`, `soft-light`, `difference`, `exclusion`.
|
|
51
51
|
*
|
|
52
52
|
* More information about blend modes can be found at
|
|
53
|
-
* https://libvips.
|
|
53
|
+
* https://www.libvips.org/API/current/libvips-conversion.html#VipsBlendMode
|
|
54
54
|
* and https://www.cairographics.org/operators/
|
|
55
55
|
*
|
|
56
56
|
* @since 0.22.0
|
|
57
57
|
*
|
|
58
58
|
* @example
|
|
59
|
+
* await sharp(background)
|
|
60
|
+
* .composite([
|
|
61
|
+
* { input: layer1, gravity: 'northwest' },
|
|
62
|
+
* { input: layer2, gravity: 'southeast' },
|
|
63
|
+
* ])
|
|
64
|
+
* .toFile('combined.png');
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* const output = await sharp('input.gif', { animated: true })
|
|
68
|
+
* .composite([
|
|
69
|
+
* { input: 'overlay.png', tile: true, blend: 'saturate' }
|
|
70
|
+
* ])
|
|
71
|
+
* .toBuffer();
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
59
74
|
* sharp('input.png')
|
|
60
75
|
* .rotate(180)
|
|
61
76
|
* .resize(300)
|
|
@@ -89,6 +104,9 @@ const blend = {
|
|
|
89
104
|
* @param {Number} [images[].raw.width]
|
|
90
105
|
* @param {Number} [images[].raw.height]
|
|
91
106
|
* @param {Number} [images[].raw.channels]
|
|
107
|
+
* @param {boolean} [images[].animated=false] - Set to `true` to read all frames/pages of an animated image.
|
|
108
|
+
* @param {string} [images[].failOn='warning'] - @see {@link /api-constructor#parameters|constructor parameters}
|
|
109
|
+
* @param {number|boolean} [images[].limitInputPixels=268402689] - @see {@link /api-constructor#parameters|constructor parameters}
|
|
92
110
|
* @returns {Sharp}
|
|
93
111
|
* @throws {Error} Invalid parameters
|
|
94
112
|
*/
|
|
@@ -160,7 +178,6 @@ function composite (images) {
|
|
|
160
178
|
throw is.invalidParameterError('premultiplied', 'boolean', image.premultiplied);
|
|
161
179
|
}
|
|
162
180
|
}
|
|
163
|
-
|
|
164
181
|
return composite;
|
|
165
182
|
});
|
|
166
183
|
return this;
|
package/lib/constructor.js
CHANGED
|
@@ -5,34 +5,7 @@ const stream = require('stream');
|
|
|
5
5
|
const is = require('./is');
|
|
6
6
|
|
|
7
7
|
require('./libvips').hasVendoredLibvips();
|
|
8
|
-
|
|
9
|
-
/* istanbul ignore next */
|
|
10
|
-
try {
|
|
11
|
-
require('../build/Release/sharp.node');
|
|
12
|
-
} catch (err) {
|
|
13
|
-
// Bail early if bindings aren't available
|
|
14
|
-
const help = ['', 'Something went wrong installing the "sharp" module', '', err.message, ''];
|
|
15
|
-
if (/NODE_MODULE_VERSION/.test(err.message)) {
|
|
16
|
-
help.push('- Ensure the version of Node.js used at install time matches that used at runtime');
|
|
17
|
-
} else if (/invalid ELF header/.test(err.message)) {
|
|
18
|
-
help.push(`- Ensure "${process.platform}" is used at install time as well as runtime`);
|
|
19
|
-
} else if (/dylib/.test(err.message) && /Incompatible library version/.test(err.message)) {
|
|
20
|
-
help.push('- Run "brew update && brew upgrade vips"');
|
|
21
|
-
} else if (/Cannot find module/.test(err.message)) {
|
|
22
|
-
help.push('- Run "npm rebuild --verbose sharp" and look for errors');
|
|
23
|
-
} else {
|
|
24
|
-
help.push(
|
|
25
|
-
'- Remove the "node_modules/sharp" directory then run',
|
|
26
|
-
' "npm install --ignore-scripts=false --verbose" and look for errors'
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
help.push(
|
|
30
|
-
'- Consult the installation documentation at https://sharp.pixelplumbing.com/install',
|
|
31
|
-
'- Search for this error at https://github.com/lovell/sharp/issues', ''
|
|
32
|
-
);
|
|
33
|
-
const error = help.join('\n');
|
|
34
|
-
throw new Error(error);
|
|
35
|
-
}
|
|
8
|
+
require('./sharp');
|
|
36
9
|
|
|
37
10
|
// Use NODE_DEBUG=sharp to enable libvips warnings
|
|
38
11
|
const debuglog = util.debuglog('sharp');
|
|
@@ -40,7 +13,7 @@ const debuglog = util.debuglog('sharp');
|
|
|
40
13
|
/**
|
|
41
14
|
* Constructor factory to create an instance of `sharp`, to which further methods are chained.
|
|
42
15
|
*
|
|
43
|
-
* JPEG, PNG, WebP, AVIF or TIFF format image data can be streamed out from this object.
|
|
16
|
+
* JPEG, PNG, WebP, GIF, AVIF or TIFF format image data can be streamed out from this object.
|
|
44
17
|
* When using Stream based output, derived attributes are available from the `info` event.
|
|
45
18
|
*
|
|
46
19
|
* Non-critical problems encountered during processing are emitted as `warning` events.
|
|
@@ -117,29 +90,33 @@ const debuglog = util.debuglog('sharp');
|
|
|
117
90
|
* sigma: 30
|
|
118
91
|
* }
|
|
119
92
|
* }
|
|
120
|
-
* }.toFile('noise.png');
|
|
93
|
+
* }).toFile('noise.png');
|
|
121
94
|
*
|
|
122
|
-
* @param {(Buffer|Uint8Array|Uint8ClampedArray|string)} [input] - if present, can be
|
|
123
|
-
* a Buffer / Uint8Array / Uint8ClampedArray containing JPEG, PNG, WebP, AVIF, GIF, SVG
|
|
95
|
+
* @param {(Buffer|Uint8Array|Uint8ClampedArray|Int8Array|Uint16Array|Int16Array|Uint32Array|Int32Array|Float32Array|Float64Array|string)} [input] - if present, can be
|
|
96
|
+
* a Buffer / Uint8Array / Uint8ClampedArray containing JPEG, PNG, WebP, AVIF, GIF, SVG or TIFF image data, or
|
|
97
|
+
* a TypedArray containing raw pixel image data, or
|
|
124
98
|
* a String containing the filesystem path to an JPEG, PNG, WebP, AVIF, GIF, SVG or TIFF image file.
|
|
125
99
|
* JPEG, PNG, WebP, AVIF, GIF, SVG, TIFF or raw pixel image data can be streamed into the object when not present.
|
|
126
100
|
* @param {Object} [options] - if present, is an Object with optional attributes.
|
|
127
|
-
* @param {
|
|
128
|
-
* Set this flag to `false` if you'd rather apply a "best effort" to decode images, even if the data is corrupt or invalid.
|
|
101
|
+
* @param {string} [options.failOn='warning'] - level of sensitivity to invalid images, one of (in order of sensitivity): 'none' (least), 'truncated', 'error' or 'warning' (most), highers level imply lower levels.
|
|
129
102
|
* @param {number|boolean} [options.limitInputPixels=268402689] - Do not process input images where the number of pixels
|
|
130
103
|
* (width x height) exceeds this limit. Assumes image dimensions contained in the input metadata can be trusted.
|
|
131
104
|
* An integral Number of pixels, zero or false to remove limit, true to use default limit of 268402689 (0x3FFF x 0x3FFF).
|
|
105
|
+
* @param {boolean} [options.unlimited=false] - Set this to `true` to remove safety features that help prevent memory exhaustion (SVG, PNG).
|
|
132
106
|
* @param {boolean} [options.sequentialRead=false] - Set this to `true` to use sequential rather than random access where possible.
|
|
133
107
|
* This can reduce memory usage and might improve performance on some systems.
|
|
134
108
|
* @param {number} [options.density=72] - number representing the DPI for vector images in the range 1 to 100000.
|
|
135
109
|
* @param {number} [options.pages=1] - number of pages to extract for multi-page input (GIF, WebP, AVIF, TIFF, PDF), use -1 for all pages.
|
|
136
110
|
* @param {number} [options.page=0] - page number to start extracting from for multi-page input (GIF, WebP, AVIF, TIFF, PDF), zero based.
|
|
111
|
+
* @param {number} [options.subifd=-1] - subIFD (Sub Image File Directory) to extract for OME-TIFF, defaults to main image.
|
|
137
112
|
* @param {number} [options.level=0] - level to extract from a multi-level input (OpenSlide), zero based.
|
|
138
113
|
* @param {boolean} [options.animated=false] - Set to `true` to read all frames/pages of an animated image (equivalent of setting `pages` to `-1`).
|
|
139
114
|
* @param {Object} [options.raw] - describes raw pixel input image data. See `raw()` for pixel ordering.
|
|
140
115
|
* @param {number} [options.raw.width] - integral number of pixels wide.
|
|
141
116
|
* @param {number} [options.raw.height] - integral number of pixels high.
|
|
142
117
|
* @param {number} [options.raw.channels] - integral number of channels, between 1 and 4.
|
|
118
|
+
* @param {boolean} [options.raw.premultiplied] - specifies that the raw input has already been premultiplied, set to `true`
|
|
119
|
+
* to avoid sharp premultiplying the image. (optional, default `false`)
|
|
143
120
|
* @param {Object} [options.create] - describes a new image to be created.
|
|
144
121
|
* @param {number} [options.create.width] - integral number of pixels wide.
|
|
145
122
|
* @param {number} [options.create.height] - integral number of pixels high.
|
|
@@ -188,6 +165,7 @@ const Sharp = function (input, options) {
|
|
|
188
165
|
extendRight: 0,
|
|
189
166
|
extendBackground: [0, 0, 0, 255],
|
|
190
167
|
withoutEnlargement: false,
|
|
168
|
+
withoutReduction: false,
|
|
191
169
|
affineMatrix: [],
|
|
192
170
|
affineBackground: [0, 0, 0, 255],
|
|
193
171
|
affineIdx: 0,
|
|
@@ -203,11 +181,15 @@ const Sharp = function (input, options) {
|
|
|
203
181
|
flatten: false,
|
|
204
182
|
flattenBackground: [0, 0, 0],
|
|
205
183
|
negate: false,
|
|
184
|
+
negateAlpha: true,
|
|
206
185
|
medianSize: 0,
|
|
207
186
|
blurSigma: 0,
|
|
208
187
|
sharpenSigma: 0,
|
|
209
|
-
|
|
210
|
-
|
|
188
|
+
sharpenM1: 1,
|
|
189
|
+
sharpenM2: 2,
|
|
190
|
+
sharpenX1: 2,
|
|
191
|
+
sharpenY2: 10,
|
|
192
|
+
sharpenY3: 20,
|
|
211
193
|
threshold: 0,
|
|
212
194
|
thresholdGrayscale: true,
|
|
213
195
|
trimThreshold: 0,
|
|
@@ -215,16 +197,21 @@ const Sharp = function (input, options) {
|
|
|
215
197
|
gammaOut: 0,
|
|
216
198
|
greyscale: false,
|
|
217
199
|
normalise: false,
|
|
200
|
+
claheWidth: 0,
|
|
201
|
+
claheHeight: 0,
|
|
202
|
+
claheMaxSlope: 3,
|
|
218
203
|
brightness: 1,
|
|
219
204
|
saturation: 1,
|
|
220
205
|
hue: 0,
|
|
206
|
+
lightness: 0,
|
|
221
207
|
booleanBufferIn: null,
|
|
222
208
|
booleanFileIn: '',
|
|
223
209
|
joinChannelIn: [],
|
|
224
210
|
extractChannel: -1,
|
|
225
211
|
removeAlpha: false,
|
|
226
|
-
ensureAlpha:
|
|
212
|
+
ensureAlpha: -1,
|
|
227
213
|
colourspace: 'srgb',
|
|
214
|
+
colourspaceInput: 'last',
|
|
228
215
|
composite: [],
|
|
229
216
|
// output
|
|
230
217
|
fileOut: '',
|
|
@@ -232,7 +219,9 @@ const Sharp = function (input, options) {
|
|
|
232
219
|
streamOut: false,
|
|
233
220
|
withMetadata: false,
|
|
234
221
|
withMetadataOrientation: -1,
|
|
222
|
+
withMetadataDensity: 0,
|
|
235
223
|
withMetadataIcc: '',
|
|
224
|
+
withMetadataStrs: {},
|
|
236
225
|
resolveWithObject: false,
|
|
237
226
|
// output format
|
|
238
227
|
jpegQuality: 80,
|
|
@@ -244,18 +233,27 @@ const Sharp = function (input, options) {
|
|
|
244
233
|
jpegOptimiseCoding: true,
|
|
245
234
|
jpegQuantisationTable: 0,
|
|
246
235
|
pngProgressive: false,
|
|
247
|
-
pngCompressionLevel:
|
|
236
|
+
pngCompressionLevel: 6,
|
|
248
237
|
pngAdaptiveFiltering: false,
|
|
249
238
|
pngPalette: false,
|
|
250
239
|
pngQuality: 100,
|
|
251
|
-
|
|
240
|
+
pngEffort: 7,
|
|
241
|
+
pngBitdepth: 8,
|
|
252
242
|
pngDither: 1,
|
|
243
|
+
jp2Quality: 80,
|
|
244
|
+
jp2TileHeight: 512,
|
|
245
|
+
jp2TileWidth: 512,
|
|
246
|
+
jp2Lossless: false,
|
|
247
|
+
jp2ChromaSubsampling: '4:4:4',
|
|
253
248
|
webpQuality: 80,
|
|
254
249
|
webpAlphaQuality: 100,
|
|
255
250
|
webpLossless: false,
|
|
256
251
|
webpNearLossless: false,
|
|
257
252
|
webpSmartSubsample: false,
|
|
258
|
-
|
|
253
|
+
webpEffort: 4,
|
|
254
|
+
gifBitdepth: 8,
|
|
255
|
+
gifEffort: 7,
|
|
256
|
+
gifDither: 1,
|
|
259
257
|
tiffQuality: 80,
|
|
260
258
|
tiffCompression: 'jpeg',
|
|
261
259
|
tiffPredictor: 'horizontal',
|
|
@@ -266,11 +264,13 @@ const Sharp = function (input, options) {
|
|
|
266
264
|
tiffTileWidth: 256,
|
|
267
265
|
tiffXres: 1.0,
|
|
268
266
|
tiffYres: 1.0,
|
|
267
|
+
tiffResolutionUnit: 'inch',
|
|
269
268
|
heifQuality: 50,
|
|
270
269
|
heifLossless: false,
|
|
271
270
|
heifCompression: 'av1',
|
|
272
|
-
|
|
273
|
-
heifChromaSubsampling: '4:
|
|
271
|
+
heifEffort: 4,
|
|
272
|
+
heifChromaSubsampling: '4:4:4',
|
|
273
|
+
rawDepth: 'uchar',
|
|
274
274
|
tileSize: 256,
|
|
275
275
|
tileOverlap: 0,
|
|
276
276
|
tileContainer: 'fs',
|
|
@@ -281,6 +281,8 @@ const Sharp = function (input, options) {
|
|
|
281
281
|
tileSkipBlanks: -1,
|
|
282
282
|
tileBackground: [255, 255, 255, 255],
|
|
283
283
|
tileCentre: false,
|
|
284
|
+
tileId: 'https://example.com/iiif',
|
|
285
|
+
timeoutSeconds: 0,
|
|
284
286
|
linearA: 1,
|
|
285
287
|
linearB: 0,
|
|
286
288
|
// Function to notify of libvips warnings
|
|
@@ -296,7 +298,8 @@ const Sharp = function (input, options) {
|
|
|
296
298
|
this.options.input = this._createInputDescriptor(input, options, { allowStream: true });
|
|
297
299
|
return this;
|
|
298
300
|
};
|
|
299
|
-
|
|
301
|
+
Object.setPrototypeOf(Sharp.prototype, stream.Duplex.prototype);
|
|
302
|
+
Object.setPrototypeOf(Sharp, stream.Duplex);
|
|
300
303
|
|
|
301
304
|
/**
|
|
302
305
|
* Take a "snapshot" of the Sharp instance, returning a new instance.
|
|
@@ -316,9 +319,7 @@ util.inherits(Sharp, stream.Duplex);
|
|
|
316
319
|
* // Using Promises to know when the pipeline is complete
|
|
317
320
|
* const fs = require("fs");
|
|
318
321
|
* const got = require("got");
|
|
319
|
-
* const sharpStream = sharp({
|
|
320
|
-
* failOnError: false
|
|
321
|
-
* });
|
|
322
|
+
* const sharpStream = sharp({ failOn: 'none' });
|
|
322
323
|
*
|
|
323
324
|
* const promises = [];
|
|
324
325
|
*
|
package/lib/input.js
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
const color = require('color');
|
|
4
4
|
const is = require('./is');
|
|
5
|
-
const sharp = require('
|
|
5
|
+
const sharp = require('./sharp');
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Extract input options, if any, from an object.
|
|
9
9
|
* @private
|
|
10
10
|
*/
|
|
11
11
|
function _inputOptionsFromObject (obj) {
|
|
12
|
-
const { raw, density, limitInputPixels, sequentialRead, failOnError, animated, page, pages } = obj;
|
|
13
|
-
return [raw, density, limitInputPixels, sequentialRead, failOnError, animated, page, pages].some(is.defined)
|
|
14
|
-
? { raw, density, limitInputPixels, sequentialRead, failOnError, animated, page, pages }
|
|
12
|
+
const { raw, density, limitInputPixels, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd } = obj;
|
|
13
|
+
return [raw, density, limitInputPixels, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd].some(is.defined)
|
|
14
|
+
? { raw, density, limitInputPixels, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd }
|
|
15
15
|
: undefined;
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -21,8 +21,9 @@ function _inputOptionsFromObject (obj) {
|
|
|
21
21
|
*/
|
|
22
22
|
function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
23
23
|
const inputDescriptor = {
|
|
24
|
-
|
|
24
|
+
failOn: 'warning',
|
|
25
25
|
limitInputPixels: Math.pow(0x3FFF, 2),
|
|
26
|
+
unlimited: false,
|
|
26
27
|
sequentialRead: false
|
|
27
28
|
};
|
|
28
29
|
if (is.string(input)) {
|
|
@@ -30,10 +31,15 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
30
31
|
inputDescriptor.file = input;
|
|
31
32
|
} else if (is.buffer(input)) {
|
|
32
33
|
// Buffer
|
|
34
|
+
if (input.length === 0) {
|
|
35
|
+
throw Error('Input Buffer is empty');
|
|
36
|
+
}
|
|
33
37
|
inputDescriptor.buffer = input;
|
|
34
|
-
} else if (is.
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
} else if (is.typedArray(input)) {
|
|
39
|
+
if (input.length === 0) {
|
|
40
|
+
throw Error('Input Bit Array is empty');
|
|
41
|
+
}
|
|
42
|
+
inputDescriptor.buffer = Buffer.from(input.buffer, input.byteOffset, input.byteLength);
|
|
37
43
|
} else if (is.plainObject(input) && !is.defined(inputOptions)) {
|
|
38
44
|
// Plain Object descriptor, e.g. create
|
|
39
45
|
inputOptions = input;
|
|
@@ -50,14 +56,22 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
50
56
|
}`);
|
|
51
57
|
}
|
|
52
58
|
if (is.object(inputOptions)) {
|
|
53
|
-
//
|
|
59
|
+
// Deprecated: failOnError
|
|
54
60
|
if (is.defined(inputOptions.failOnError)) {
|
|
55
61
|
if (is.bool(inputOptions.failOnError)) {
|
|
56
|
-
inputDescriptor.
|
|
62
|
+
inputDescriptor.failOn = inputOptions.failOnError ? 'warning' : 'none';
|
|
57
63
|
} else {
|
|
58
64
|
throw is.invalidParameterError('failOnError', 'boolean', inputOptions.failOnError);
|
|
59
65
|
}
|
|
60
66
|
}
|
|
67
|
+
// failOn
|
|
68
|
+
if (is.defined(inputOptions.failOn)) {
|
|
69
|
+
if (is.string(inputOptions.failOn) && is.inArray(inputOptions.failOn, ['none', 'truncated', 'error', 'warning'])) {
|
|
70
|
+
inputDescriptor.failOn = inputOptions.failOn;
|
|
71
|
+
} else {
|
|
72
|
+
throw is.invalidParameterError('failOn', 'one of: none, truncated, error, warning', inputOptions.failOn);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
61
75
|
// Density
|
|
62
76
|
if (is.defined(inputOptions.density)) {
|
|
63
77
|
if (is.inRange(inputOptions.density, 1, 100000)) {
|
|
@@ -78,6 +92,14 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
78
92
|
throw is.invalidParameterError('limitInputPixels', 'integer >= 0', inputOptions.limitInputPixels);
|
|
79
93
|
}
|
|
80
94
|
}
|
|
95
|
+
// unlimited
|
|
96
|
+
if (is.defined(inputOptions.unlimited)) {
|
|
97
|
+
if (is.bool(inputOptions.unlimited)) {
|
|
98
|
+
inputDescriptor.unlimited = inputOptions.unlimited;
|
|
99
|
+
} else {
|
|
100
|
+
throw is.invalidParameterError('unlimited', 'boolean', inputOptions.unlimited);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
81
103
|
// sequentialRead
|
|
82
104
|
if (is.defined(inputOptions.sequentialRead)) {
|
|
83
105
|
if (is.bool(inputOptions.sequentialRead)) {
|
|
@@ -97,6 +119,38 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
97
119
|
inputDescriptor.rawWidth = inputOptions.raw.width;
|
|
98
120
|
inputDescriptor.rawHeight = inputOptions.raw.height;
|
|
99
121
|
inputDescriptor.rawChannels = inputOptions.raw.channels;
|
|
122
|
+
inputDescriptor.rawPremultiplied = !!inputOptions.raw.premultiplied;
|
|
123
|
+
|
|
124
|
+
switch (input.constructor) {
|
|
125
|
+
case Uint8Array:
|
|
126
|
+
case Uint8ClampedArray:
|
|
127
|
+
inputDescriptor.rawDepth = 'uchar';
|
|
128
|
+
break;
|
|
129
|
+
case Int8Array:
|
|
130
|
+
inputDescriptor.rawDepth = 'char';
|
|
131
|
+
break;
|
|
132
|
+
case Uint16Array:
|
|
133
|
+
inputDescriptor.rawDepth = 'ushort';
|
|
134
|
+
break;
|
|
135
|
+
case Int16Array:
|
|
136
|
+
inputDescriptor.rawDepth = 'short';
|
|
137
|
+
break;
|
|
138
|
+
case Uint32Array:
|
|
139
|
+
inputDescriptor.rawDepth = 'uint';
|
|
140
|
+
break;
|
|
141
|
+
case Int32Array:
|
|
142
|
+
inputDescriptor.rawDepth = 'int';
|
|
143
|
+
break;
|
|
144
|
+
case Float32Array:
|
|
145
|
+
inputDescriptor.rawDepth = 'float';
|
|
146
|
+
break;
|
|
147
|
+
case Float64Array:
|
|
148
|
+
inputDescriptor.rawDepth = 'double';
|
|
149
|
+
break;
|
|
150
|
+
default:
|
|
151
|
+
inputDescriptor.rawDepth = 'uchar';
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
100
154
|
} else {
|
|
101
155
|
throw new Error('Expected width, height and channels for raw pixel input');
|
|
102
156
|
}
|
|
@@ -131,6 +185,14 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
131
185
|
throw is.invalidParameterError('level', 'integer between 0 and 256', inputOptions.level);
|
|
132
186
|
}
|
|
133
187
|
}
|
|
188
|
+
// Sub Image File Directory (TIFF)
|
|
189
|
+
if (is.defined(inputOptions.subifd)) {
|
|
190
|
+
if (is.integer(inputOptions.subifd) && is.inRange(inputOptions.subifd, -1, 100000)) {
|
|
191
|
+
inputDescriptor.subifd = inputOptions.subifd;
|
|
192
|
+
} else {
|
|
193
|
+
throw is.invalidParameterError('subifd', 'integer between -1 and 100000', inputOptions.subifd);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
134
196
|
// Create new image
|
|
135
197
|
if (is.defined(inputOptions.create)) {
|
|
136
198
|
if (
|
|
@@ -236,16 +298,20 @@ function _isStreamInput () {
|
|
|
236
298
|
}
|
|
237
299
|
|
|
238
300
|
/**
|
|
239
|
-
* Fast access to (uncached) image metadata without decoding any compressed
|
|
301
|
+
* Fast access to (uncached) image metadata without decoding any compressed pixel data.
|
|
302
|
+
*
|
|
303
|
+
* This is taken from the header of the input image.
|
|
304
|
+
* It does not include operations, such as resize, to be applied to the output image.
|
|
305
|
+
*
|
|
240
306
|
* A `Promise` is returned when `callback` is not provided.
|
|
241
307
|
*
|
|
242
308
|
* - `format`: Name of decoder used to decompress image data e.g. `jpeg`, `png`, `webp`, `gif`, `svg`
|
|
243
309
|
* - `size`: Total size of image in bytes, for Stream and Buffer input only
|
|
244
|
-
* - `width`: Number of pixels wide (EXIF orientation is not taken into consideration)
|
|
245
|
-
* - `height`: Number of pixels high (EXIF orientation is not taken into consideration)
|
|
246
|
-
* - `space`: Name of colour space interpretation e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://libvips.
|
|
310
|
+
* - `width`: Number of pixels wide (EXIF orientation is not taken into consideration, see example below)
|
|
311
|
+
* - `height`: Number of pixels high (EXIF orientation is not taken into consideration, see example below)
|
|
312
|
+
* - `space`: Name of colour space interpretation e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://www.libvips.org/API/current/VipsImage.html#VipsInterpretation)
|
|
247
313
|
* - `channels`: Number of bands e.g. `3` for sRGB, `4` for CMYK
|
|
248
|
-
* - `depth`: Name of pixel depth format e.g. `uchar`, `char`, `ushort`, `float` [...](https://libvips.
|
|
314
|
+
* - `depth`: Name of pixel depth format e.g. `uchar`, `char`, `ushort`, `float` [...](https://www.libvips.org/API/current/VipsImage.html#VipsBandFormat)
|
|
249
315
|
* - `density`: Number of pixels per inch (DPI), if present
|
|
250
316
|
* - `chromaSubsampling`: String containing JPEG chroma subsampling, `4:2:0` or `4:4:4` for RGB, `4:2:0:4` or `4:4:4:4` for CMYK
|
|
251
317
|
* - `isProgressive`: Boolean indicating whether the image is interlaced using a progressive scan
|
|
@@ -255,6 +321,10 @@ function _isStreamInput () {
|
|
|
255
321
|
* - `delay`: Delay in ms between each page in an animated image, provided as an array of integers.
|
|
256
322
|
* - `pagePrimary`: Number of the primary page in a HEIF image
|
|
257
323
|
* - `levels`: Details of each level in a multi-level image provided as an array of objects, requires libvips compiled with support for OpenSlide
|
|
324
|
+
* - `subifds`: Number of Sub Image File Directories in an OME-TIFF image
|
|
325
|
+
* - `background`: Default background colour, if present, for PNG (bKGD) and GIF images, either an RGB Object or a single greyscale value
|
|
326
|
+
* - `compression`: The encoder used to compress an HEIF file, `av1` (AVIF) or `hevc` (HEIC)
|
|
327
|
+
* - `resolutionUnit`: The unit of resolution (density), either `inch` or `cm`, if present
|
|
258
328
|
* - `hasProfile`: Boolean indicating the presence of an embedded ICC profile
|
|
259
329
|
* - `hasAlpha`: Boolean indicating the presence of an alpha transparency channel
|
|
260
330
|
* - `orientation`: Number value of the EXIF Orientation header, if present
|
|
@@ -265,6 +335,9 @@ function _isStreamInput () {
|
|
|
265
335
|
* - `tifftagPhotoshop`: Buffer containing raw TIFFTAG_PHOTOSHOP data, if present
|
|
266
336
|
*
|
|
267
337
|
* @example
|
|
338
|
+
* const metadata = await sharp(input).metadata();
|
|
339
|
+
*
|
|
340
|
+
* @example
|
|
268
341
|
* const image = sharp(inputJpg);
|
|
269
342
|
* image
|
|
270
343
|
* .metadata()
|
|
@@ -278,6 +351,17 @@ function _isStreamInput () {
|
|
|
278
351
|
* // data contains a WebP image half the width and height of the original JPEG
|
|
279
352
|
* });
|
|
280
353
|
*
|
|
354
|
+
* @example
|
|
355
|
+
* // Based on EXIF rotation metadata, get the right-side-up width and height:
|
|
356
|
+
*
|
|
357
|
+
* const size = getNormalSize(await sharp(input).metadata());
|
|
358
|
+
*
|
|
359
|
+
* function getNormalSize({ width, height, orientation }) {
|
|
360
|
+
* return orientation || 0 >= 5
|
|
361
|
+
* ? { width: height, height: width }
|
|
362
|
+
* : { width, height };
|
|
363
|
+
* }
|
|
364
|
+
*
|
|
281
365
|
* @param {Function} [callback] - called with the arguments `(err, metadata)`
|
|
282
366
|
* @returns {Promise<Object>|Sharp}
|
|
283
367
|
*/
|
|
@@ -336,9 +420,12 @@ function metadata (callback) {
|
|
|
336
420
|
* - `maxX` (x-coordinate of one of the pixel where the maximum lies)
|
|
337
421
|
* - `maxY` (y-coordinate of one of the pixel where the maximum lies)
|
|
338
422
|
* - `isOpaque`: Is the image fully opaque? Will be `true` if the image has no alpha channel or if every pixel is fully opaque.
|
|
339
|
-
* - `entropy`: Histogram-based estimation of greyscale entropy, discarding alpha channel if any
|
|
340
|
-
* - `sharpness`: Estimation of greyscale sharpness based on the standard deviation of a Laplacian convolution, discarding alpha channel if any
|
|
341
|
-
* - `dominant`: Object containing most dominant sRGB colour based on a 4096-bin 3D histogram
|
|
423
|
+
* - `entropy`: Histogram-based estimation of greyscale entropy, discarding alpha channel if any.
|
|
424
|
+
* - `sharpness`: Estimation of greyscale sharpness based on the standard deviation of a Laplacian convolution, discarding alpha channel if any.
|
|
425
|
+
* - `dominant`: Object containing most dominant sRGB colour based on a 4096-bin 3D histogram.
|
|
426
|
+
*
|
|
427
|
+
* **Note**: Statistics are derived from the original input image. Any operations performed on the image must first be
|
|
428
|
+
* written to a buffer in order to run `stats` on the result (see third example).
|
|
342
429
|
*
|
|
343
430
|
* @example
|
|
344
431
|
* const image = sharp(inputJpg);
|
|
@@ -352,6 +439,13 @@ function metadata (callback) {
|
|
|
352
439
|
* const { entropy, sharpness, dominant } = await sharp(input).stats();
|
|
353
440
|
* const { r, g, b } = dominant;
|
|
354
441
|
*
|
|
442
|
+
* @example
|
|
443
|
+
* const image = sharp(input);
|
|
444
|
+
* // store intermediate result
|
|
445
|
+
* const part = await image.extract(region).toBuffer();
|
|
446
|
+
* // create new instance to obtain statistics of extracted region
|
|
447
|
+
* const stats = await sharp(part).stats();
|
|
448
|
+
*
|
|
355
449
|
* @param {Function} [callback] - called with the arguments `(err, stats)`
|
|
356
450
|
* @returns {Promise<Object>}
|
|
357
451
|
*/
|
package/lib/is.js
CHANGED
|
@@ -49,12 +49,26 @@ const buffer = function (val) {
|
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
|
-
* Is this value a Uint8Array or Uint8ClampedArray
|
|
52
|
+
* Is this value a typed array object?. E.g. Uint8Array or Uint8ClampedArray?
|
|
53
53
|
* @private
|
|
54
54
|
*/
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
const typedArray = function (val) {
|
|
56
|
+
if (defined(val)) {
|
|
57
|
+
switch (val.constructor) {
|
|
58
|
+
case Uint8Array:
|
|
59
|
+
case Uint8ClampedArray:
|
|
60
|
+
case Int8Array:
|
|
61
|
+
case Uint16Array:
|
|
62
|
+
case Int16Array:
|
|
63
|
+
case Uint32Array:
|
|
64
|
+
case Int32Array:
|
|
65
|
+
case Float32Array:
|
|
66
|
+
case Float64Array:
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return false;
|
|
58
72
|
};
|
|
59
73
|
|
|
60
74
|
/**
|
|
@@ -119,7 +133,7 @@ module.exports = {
|
|
|
119
133
|
fn: fn,
|
|
120
134
|
bool: bool,
|
|
121
135
|
buffer: buffer,
|
|
122
|
-
|
|
136
|
+
typedArray: typedArray,
|
|
123
137
|
string: string,
|
|
124
138
|
number: number,
|
|
125
139
|
integer: integer,
|