sharp 0.33.5 → 0.35.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 +12 -18
- package/dist/channel.cjs +177 -0
- package/{lib/channel.js → dist/channel.mjs} +11 -8
- package/dist/colour.cjs +195 -0
- package/{lib/colour.js → dist/colour.mjs} +38 -23
- package/dist/composite.cjs +213 -0
- package/{lib/composite.js → dist/composite.mjs} +14 -11
- package/{lib/constructor.js → dist/constructor.cjs} +102 -43
- package/dist/constructor.mjs +511 -0
- package/dist/index.cjs +25 -0
- package/dist/index.mjs +25 -0
- package/dist/input.cjs +814 -0
- package/{lib/input.js → dist/input.mjs} +224 -68
- package/{lib/is.js → dist/is.cjs} +19 -45
- package/dist/is.mjs +143 -0
- package/{lib/libvips.js → dist/libvips.cjs} +52 -43
- package/dist/libvips.mjs +212 -0
- package/dist/operation.cjs +987 -0
- package/{lib/operation.js → dist/operation.mjs} +108 -79
- package/{lib/output.js → dist/output.cjs} +243 -36
- package/dist/output.mjs +1794 -0
- package/dist/resize.cjs +613 -0
- package/{lib/resize.js → dist/resize.mjs} +38 -12
- package/dist/sharp.cjs +164 -0
- package/dist/sharp.mjs +164 -0
- package/{lib/utility.js → dist/utility.cjs} +23 -24
- package/dist/utility.mjs +295 -0
- package/install/build.js +38 -0
- package/lib/index.d.ts +347 -125
- package/package.json +75 -84
- package/src/binding.gyp +49 -26
- package/src/common.cc +203 -111
- package/src/common.h +68 -40
- package/src/metadata.cc +106 -22
- package/src/metadata.h +15 -5
- package/src/operations.cc +62 -21
- package/src/operations.h +15 -3
- package/src/pipeline.cc +374 -183
- package/src/pipeline.h +34 -7
- package/src/sharp.cc +11 -8
- package/src/stats.cc +16 -13
- package/src/stats.h +6 -3
- package/src/utilities.cc +32 -12
- package/src/utilities.h +5 -2
- package/install/check.js +0 -41
- package/lib/index.js +0 -16
- package/lib/sharp.js +0 -114
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
Copyright 2013 Lovell Fuller and others.
|
|
3
|
+
SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const is = require('./is.cjs');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Blend modes.
|
|
10
|
+
* @member
|
|
11
|
+
* @private
|
|
12
|
+
*/
|
|
13
|
+
const blend = {
|
|
14
|
+
clear: 'clear',
|
|
15
|
+
source: 'source',
|
|
16
|
+
over: 'over',
|
|
17
|
+
in: 'in',
|
|
18
|
+
out: 'out',
|
|
19
|
+
atop: 'atop',
|
|
20
|
+
dest: 'dest',
|
|
21
|
+
'dest-over': 'dest-over',
|
|
22
|
+
'dest-in': 'dest-in',
|
|
23
|
+
'dest-out': 'dest-out',
|
|
24
|
+
'dest-atop': 'dest-atop',
|
|
25
|
+
xor: 'xor',
|
|
26
|
+
add: 'add',
|
|
27
|
+
saturate: 'saturate',
|
|
28
|
+
multiply: 'multiply',
|
|
29
|
+
screen: 'screen',
|
|
30
|
+
overlay: 'overlay',
|
|
31
|
+
darken: 'darken',
|
|
32
|
+
lighten: 'lighten',
|
|
33
|
+
'colour-dodge': 'colour-dodge',
|
|
34
|
+
'color-dodge': 'colour-dodge',
|
|
35
|
+
'colour-burn': 'colour-burn',
|
|
36
|
+
'color-burn': 'colour-burn',
|
|
37
|
+
'hard-light': 'hard-light',
|
|
38
|
+
'soft-light': 'soft-light',
|
|
39
|
+
difference: 'difference',
|
|
40
|
+
exclusion: 'exclusion'
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Composite image(s) over the processed (resized, extracted etc.) image.
|
|
45
|
+
*
|
|
46
|
+
* The images to composite must be the same size or smaller than the processed image.
|
|
47
|
+
* If both `top` and `left` options are provided, they take precedence over `gravity`.
|
|
48
|
+
*
|
|
49
|
+
* Other operations in the same processing pipeline (e.g. resize, rotate, flip,
|
|
50
|
+
* flop, extract) will always be applied to the input image before composition.
|
|
51
|
+
*
|
|
52
|
+
* The `blend` option can be one of `clear`, `source`, `over`, `in`, `out`, `atop`,
|
|
53
|
+
* `dest`, `dest-over`, `dest-in`, `dest-out`, `dest-atop`,
|
|
54
|
+
* `xor`, `add`, `saturate`, `multiply`, `screen`, `overlay`, `darken`, `lighten`,
|
|
55
|
+
* `colour-dodge`, `color-dodge`, `colour-burn`,`color-burn`,
|
|
56
|
+
* `hard-light`, `soft-light`, `difference`, `exclusion`.
|
|
57
|
+
*
|
|
58
|
+
* More information about blend modes can be found at
|
|
59
|
+
* https://www.libvips.org/API/current/enum.BlendMode.html
|
|
60
|
+
* and https://www.cairographics.org/operators/
|
|
61
|
+
*
|
|
62
|
+
* @since 0.22.0
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* await sharp(background)
|
|
66
|
+
* .composite([
|
|
67
|
+
* { input: layer1, gravity: 'northwest' },
|
|
68
|
+
* { input: layer2, gravity: 'southeast' },
|
|
69
|
+
* ])
|
|
70
|
+
* .toFile('combined.png');
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* const output = await sharp('input.gif', { animated: true })
|
|
74
|
+
* .composite([
|
|
75
|
+
* { input: 'overlay.png', tile: true, blend: 'saturate' }
|
|
76
|
+
* ])
|
|
77
|
+
* .toBuffer();
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* sharp('input.png')
|
|
81
|
+
* .rotate(180)
|
|
82
|
+
* .resize(300)
|
|
83
|
+
* .flatten( { background: '#ff6600' } )
|
|
84
|
+
* .composite([{ input: 'overlay.png', gravity: 'southeast' }])
|
|
85
|
+
* .sharpen()
|
|
86
|
+
* .withMetadata()
|
|
87
|
+
* .webp( { quality: 90 } )
|
|
88
|
+
* .toBuffer()
|
|
89
|
+
* .then(function(outputBuffer) {
|
|
90
|
+
* // outputBuffer contains upside down, 300px wide, alpha channel flattened
|
|
91
|
+
* // onto orange background, composited with overlay.png with SE gravity,
|
|
92
|
+
* // sharpened, with metadata, 90% quality WebP image data. Phew!
|
|
93
|
+
* });
|
|
94
|
+
*
|
|
95
|
+
* @param {Object[]} images - Ordered list of images to composite
|
|
96
|
+
* @param {Buffer|String} [images[].input] - Buffer containing image data, String containing the path to an image file, or Create object (see below)
|
|
97
|
+
* @param {Object} [images[].input.create] - describes a blank overlay to be created.
|
|
98
|
+
* @param {Number} [images[].input.create.width]
|
|
99
|
+
* @param {Number} [images[].input.create.height]
|
|
100
|
+
* @param {Number} [images[].input.create.channels] - 3-4
|
|
101
|
+
* @param {String|Object} [images[].input.create.background] - parsed by the [color](https://www.npmjs.org/package/color) module to extract values for red, green, blue and alpha.
|
|
102
|
+
* @param {Object} [images[].input.text] - describes a new text image to be created.
|
|
103
|
+
* @param {string} [images[].input.text.text] - text to render as a UTF-8 string. It can contain Pango markup, for example `<i>Le</i>Monde`.
|
|
104
|
+
* @param {string} [images[].input.text.font] - font name to render with.
|
|
105
|
+
* @param {string} [images[].input.text.fontfile] - absolute filesystem path to a font file that can be used by `font`.
|
|
106
|
+
* @param {number} [images[].input.text.width=0] - integral number of pixels to word-wrap at. Lines of text wider than this will be broken at word boundaries.
|
|
107
|
+
* @param {number} [images[].input.text.height=0] - integral number of pixels high. When defined, `dpi` will be ignored and the text will automatically fit the pixel resolution defined by `width` and `height`. Will be ignored if `width` is not specified or set to 0.
|
|
108
|
+
* @param {string} [images[].input.text.align='left'] - text alignment (`'left'`, `'centre'`, `'center'`, `'right'`).
|
|
109
|
+
* @param {boolean} [images[].input.text.justify=false] - set this to true to apply justification to the text.
|
|
110
|
+
* @param {number} [images[].input.text.dpi=72] - the resolution (size) at which to render the text. Does not take effect if `height` is specified.
|
|
111
|
+
* @param {boolean} [images[].input.text.rgba=false] - set this to true to enable RGBA output. This is useful for colour emoji rendering, or support for Pango markup features like `<span foreground="red">Red!</span>`.
|
|
112
|
+
* @param {number} [images[].input.text.spacing=0] - text line height in points. Will use the font line height if none is specified.
|
|
113
|
+
* @param {Boolean} [images[].autoOrient=false] - set to true to use EXIF orientation data, if present, to orient the image.
|
|
114
|
+
* @param {String} [images[].blend='over'] - how to blend this image with the image below.
|
|
115
|
+
* @param {String} [images[].gravity='centre'] - gravity at which to place the overlay.
|
|
116
|
+
* @param {Number} [images[].top] - the pixel offset from the top edge.
|
|
117
|
+
* @param {Number} [images[].left] - the pixel offset from the left edge.
|
|
118
|
+
* @param {Boolean} [images[].tile=false] - set to true to repeat the overlay image across the entire image with the given `gravity`.
|
|
119
|
+
* @param {Boolean} [images[].premultiplied=false] - set to true to avoid premultiplying the image below. Equivalent to the `--premultiplied` vips option.
|
|
120
|
+
* @param {Number} [images[].density=72] - number representing the DPI for vector overlay image.
|
|
121
|
+
* @param {Object} [images[].raw] - describes overlay when using raw pixel data.
|
|
122
|
+
* @param {Number} [images[].raw.width]
|
|
123
|
+
* @param {Number} [images[].raw.height]
|
|
124
|
+
* @param {Number} [images[].raw.channels]
|
|
125
|
+
* @param {boolean} [images[].animated=false] - Set to `true` to read all frames/pages of an animated image.
|
|
126
|
+
* @param {string} [images[].failOn='warning'] - @see {@link /api-constructor/ constructor parameters}
|
|
127
|
+
* @param {number|boolean} [images[].limitInputPixels=268402689] - @see {@link /api-constructor/ constructor parameters}
|
|
128
|
+
* @param {number|boolean} [images[].limitInputChannels=5] - @see {@link /api-constructor/ constructor parameters}
|
|
129
|
+
* @returns {Sharp}
|
|
130
|
+
* @throws {Error} Invalid parameters
|
|
131
|
+
*/
|
|
132
|
+
function composite (images) {
|
|
133
|
+
if (!Array.isArray(images)) {
|
|
134
|
+
throw is.invalidParameterError('images to composite', 'array', images);
|
|
135
|
+
}
|
|
136
|
+
this.options.composite = images.map(image => {
|
|
137
|
+
if (!is.object(image)) {
|
|
138
|
+
throw is.invalidParameterError('image to composite', 'object', image);
|
|
139
|
+
}
|
|
140
|
+
const inputOptions = this._inputOptionsFromObject(image);
|
|
141
|
+
const composite = {
|
|
142
|
+
input: this._createInputDescriptor(image.input, inputOptions, { allowStream: false }),
|
|
143
|
+
blend: 'over',
|
|
144
|
+
tile: false,
|
|
145
|
+
left: 0,
|
|
146
|
+
top: 0,
|
|
147
|
+
hasOffset: false,
|
|
148
|
+
gravity: 0,
|
|
149
|
+
premultiplied: false
|
|
150
|
+
};
|
|
151
|
+
if (is.defined(image.blend)) {
|
|
152
|
+
if (is.string(blend[image.blend])) {
|
|
153
|
+
composite.blend = blend[image.blend];
|
|
154
|
+
} else {
|
|
155
|
+
throw is.invalidParameterError('blend', 'valid blend name', image.blend);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (is.defined(image.tile)) {
|
|
159
|
+
if (is.bool(image.tile)) {
|
|
160
|
+
composite.tile = image.tile;
|
|
161
|
+
} else {
|
|
162
|
+
throw is.invalidParameterError('tile', 'boolean', image.tile);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (is.defined(image.left)) {
|
|
166
|
+
if (is.integer(image.left)) {
|
|
167
|
+
composite.left = image.left;
|
|
168
|
+
} else {
|
|
169
|
+
throw is.invalidParameterError('left', 'integer', image.left);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (is.defined(image.top)) {
|
|
173
|
+
if (is.integer(image.top)) {
|
|
174
|
+
composite.top = image.top;
|
|
175
|
+
} else {
|
|
176
|
+
throw is.invalidParameterError('top', 'integer', image.top);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (is.defined(image.top) !== is.defined(image.left)) {
|
|
180
|
+
throw new Error('Expected both left and top to be set');
|
|
181
|
+
} else {
|
|
182
|
+
composite.hasOffset = is.integer(image.top) && is.integer(image.left);
|
|
183
|
+
}
|
|
184
|
+
if (is.defined(image.gravity)) {
|
|
185
|
+
if (is.integer(image.gravity) && is.inRange(image.gravity, 0, 8)) {
|
|
186
|
+
composite.gravity = image.gravity;
|
|
187
|
+
} else if (is.string(image.gravity) && is.integer(this.constructor.gravity[image.gravity])) {
|
|
188
|
+
composite.gravity = this.constructor.gravity[image.gravity];
|
|
189
|
+
} else {
|
|
190
|
+
throw is.invalidParameterError('gravity', 'valid gravity', image.gravity);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (is.defined(image.premultiplied)) {
|
|
194
|
+
if (is.bool(image.premultiplied)) {
|
|
195
|
+
composite.premultiplied = image.premultiplied;
|
|
196
|
+
} else {
|
|
197
|
+
throw is.invalidParameterError('premultiplied', 'boolean', image.premultiplied);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return composite;
|
|
201
|
+
});
|
|
202
|
+
return this;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Decorate the Sharp prototype with composite-related functions.
|
|
207
|
+
* @module Sharp
|
|
208
|
+
* @private
|
|
209
|
+
*/
|
|
210
|
+
module.exports = (Sharp) => {
|
|
211
|
+
Sharp.prototype.composite = composite;
|
|
212
|
+
Sharp.blend = blend;
|
|
213
|
+
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/*!
|
|
2
|
+
Copyright 2013 Lovell Fuller and others.
|
|
3
|
+
SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const is = require('./is');
|
|
6
|
+
import is from './is.mjs';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Blend modes.
|
|
@@ -46,8 +46,8 @@ const blend = {
|
|
|
46
46
|
* The images to composite must be the same size or smaller than the processed image.
|
|
47
47
|
* If both `top` and `left` options are provided, they take precedence over `gravity`.
|
|
48
48
|
*
|
|
49
|
-
*
|
|
50
|
-
* will always be applied to the input image before composition.
|
|
49
|
+
* Other operations in the same processing pipeline (e.g. resize, rotate, flip,
|
|
50
|
+
* flop, extract) will always be applied to the input image before composition.
|
|
51
51
|
*
|
|
52
52
|
* The `blend` option can be one of `clear`, `source`, `over`, `in`, `out`, `atop`,
|
|
53
53
|
* `dest`, `dest-over`, `dest-in`, `dest-out`, `dest-atop`,
|
|
@@ -56,7 +56,7 @@ const blend = {
|
|
|
56
56
|
* `hard-light`, `soft-light`, `difference`, `exclusion`.
|
|
57
57
|
*
|
|
58
58
|
* More information about blend modes can be found at
|
|
59
|
-
* https://www.libvips.org/API/current/
|
|
59
|
+
* https://www.libvips.org/API/current/enum.BlendMode.html
|
|
60
60
|
* and https://www.cairographics.org/operators/
|
|
61
61
|
*
|
|
62
62
|
* @since 0.22.0
|
|
@@ -110,6 +110,7 @@ const blend = {
|
|
|
110
110
|
* @param {number} [images[].input.text.dpi=72] - the resolution (size) at which to render the text. Does not take effect if `height` is specified.
|
|
111
111
|
* @param {boolean} [images[].input.text.rgba=false] - set this to true to enable RGBA output. This is useful for colour emoji rendering, or support for Pango markup features like `<span foreground="red">Red!</span>`.
|
|
112
112
|
* @param {number} [images[].input.text.spacing=0] - text line height in points. Will use the font line height if none is specified.
|
|
113
|
+
* @param {Boolean} [images[].autoOrient=false] - set to true to use EXIF orientation data, if present, to orient the image.
|
|
113
114
|
* @param {String} [images[].blend='over'] - how to blend this image with the image below.
|
|
114
115
|
* @param {String} [images[].gravity='centre'] - gravity at which to place the overlay.
|
|
115
116
|
* @param {Number} [images[].top] - the pixel offset from the top edge.
|
|
@@ -122,8 +123,9 @@ const blend = {
|
|
|
122
123
|
* @param {Number} [images[].raw.height]
|
|
123
124
|
* @param {Number} [images[].raw.channels]
|
|
124
125
|
* @param {boolean} [images[].animated=false] - Set to `true` to read all frames/pages of an animated image.
|
|
125
|
-
* @param {string} [images[].failOn='warning'] - @see {@link /api-constructor
|
|
126
|
-
* @param {number|boolean} [images[].limitInputPixels=268402689] - @see {@link /api-constructor
|
|
126
|
+
* @param {string} [images[].failOn='warning'] - @see {@link /api-constructor/ constructor parameters}
|
|
127
|
+
* @param {number|boolean} [images[].limitInputPixels=268402689] - @see {@link /api-constructor/ constructor parameters}
|
|
128
|
+
* @param {number|boolean} [images[].limitInputChannels=5] - @see {@link /api-constructor/ constructor parameters}
|
|
127
129
|
* @returns {Sharp}
|
|
128
130
|
* @throws {Error} Invalid parameters
|
|
129
131
|
*/
|
|
@@ -202,9 +204,10 @@ function composite (images) {
|
|
|
202
204
|
|
|
203
205
|
/**
|
|
204
206
|
* Decorate the Sharp prototype with composite-related functions.
|
|
207
|
+
* @module Sharp
|
|
205
208
|
* @private
|
|
206
209
|
*/
|
|
207
|
-
|
|
210
|
+
export default (Sharp) => {
|
|
208
211
|
Sharp.prototype.composite = composite;
|
|
209
212
|
Sharp.blend = blend;
|
|
210
213
|
};
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
/*!
|
|
2
|
+
Copyright 2013 Lovell Fuller and others.
|
|
3
|
+
SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
5
|
|
|
6
6
|
const util = require('node:util');
|
|
7
7
|
const stream = require('node:stream');
|
|
8
|
-
const is = require('./is');
|
|
8
|
+
const is = require('./is.cjs');
|
|
9
9
|
|
|
10
|
-
require('./sharp');
|
|
10
|
+
require('./sharp.cjs');
|
|
11
11
|
|
|
12
12
|
// Use NODE_DEBUG=sharp to enable libvips warnings
|
|
13
13
|
const debuglog = util.debuglog('sharp');
|
|
14
14
|
|
|
15
|
+
const queueListener = (queueLength) => {
|
|
16
|
+
Sharp.queue.emit('change', queueLength);
|
|
17
|
+
};
|
|
18
|
+
|
|
15
19
|
/**
|
|
16
20
|
* Constructor factory to create an instance of `sharp`, to which further methods are chained.
|
|
17
21
|
*
|
|
@@ -44,7 +48,7 @@ const debuglog = util.debuglog('sharp');
|
|
|
44
48
|
* // resize to 300 pixels wide,
|
|
45
49
|
* // emit an 'info' event with calculated dimensions
|
|
46
50
|
* // and finally write image data to writableStream
|
|
47
|
-
* const { body } = fetch('https://...');
|
|
51
|
+
* const { body } = await fetch('https://...');
|
|
48
52
|
* const readableStream = Readable.fromWeb(body);
|
|
49
53
|
* const transformer = sharp()
|
|
50
54
|
* .resize(300)
|
|
@@ -54,6 +58,17 @@ const debuglog = util.debuglog('sharp');
|
|
|
54
58
|
* readableStream.pipe(transformer).pipe(writableStream);
|
|
55
59
|
*
|
|
56
60
|
* @example
|
|
61
|
+
* // Web Streams API, requires Node.js >= 24.15.0
|
|
62
|
+
* const { Duplex } = require('node:stream');
|
|
63
|
+
*
|
|
64
|
+
* const { body } = await fetch('https://...');
|
|
65
|
+
* const transformer = Duplex.toWeb(
|
|
66
|
+
* sharp().resize(300),
|
|
67
|
+
* { readableType: 'bytes' }
|
|
68
|
+
* );
|
|
69
|
+
* body.pipeThrough(transformer).pipeTo(writable);
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
57
72
|
* // Create a blank 300x200 PNG image of semi-translucent red pixels
|
|
58
73
|
* sharp({
|
|
59
74
|
* create: {
|
|
@@ -121,24 +136,40 @@ const debuglog = util.debuglog('sharp');
|
|
|
121
136
|
* }
|
|
122
137
|
* }).toFile('text_rgba.png');
|
|
123
138
|
*
|
|
124
|
-
* @
|
|
139
|
+
* @example
|
|
140
|
+
* // Join four input images as a 2x2 grid with a 4 pixel gutter
|
|
141
|
+
* const data = await sharp(
|
|
142
|
+
* [image1, image2, image3, image4],
|
|
143
|
+
* { join: { across: 2, shim: 4 } }
|
|
144
|
+
* ).toBuffer();
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* // Generate a two-frame animated image from emoji
|
|
148
|
+
* const images = ['😀', '😛'].map(text => ({
|
|
149
|
+
* text: { text, width: 64, height: 64, channels: 4, rgba: true }
|
|
150
|
+
* }));
|
|
151
|
+
* await sharp(images, { join: { animated: true } }).toFile('out.gif');
|
|
152
|
+
*
|
|
153
|
+
* @param {(Buffer|ArrayBuffer|Uint8Array|Uint8ClampedArray|Int8Array|Uint16Array|Int16Array|Uint32Array|Int32Array|Float32Array|Float64Array|string|Array)} [input] - if present, can be
|
|
125
154
|
* a Buffer / ArrayBuffer / Uint8Array / Uint8ClampedArray containing JPEG, PNG, WebP, AVIF, GIF, SVG or TIFF image data, or
|
|
126
155
|
* a TypedArray containing raw pixel image data, or
|
|
127
156
|
* a String containing the filesystem path to an JPEG, PNG, WebP, AVIF, GIF, SVG or TIFF image file.
|
|
157
|
+
* An array of inputs can be provided, and these will be joined together.
|
|
128
158
|
* JPEG, PNG, WebP, AVIF, GIF, SVG, TIFF or raw pixel image data can be streamed into the object when not present.
|
|
129
159
|
* @param {Object} [options] - if present, is an Object with optional attributes.
|
|
130
|
-
* @param {string} [options.failOn='warning'] - When to abort processing of invalid pixel data, one of (in order of sensitivity, least to most): 'none', 'truncated', 'error', 'warning'. Higher levels imply lower levels. Invalid metadata will always abort.
|
|
160
|
+
* @param {string} [options.failOn='warning'] - When to abort processing of invalid pixel data, one of (in order of sensitivity, least to most): 'none', 'truncated', 'error', 'warning'. Higher levels imply lower levels. Invalid metadata will always abort. Use the default 'warning' level with untrusted input.
|
|
131
161
|
* @param {number|boolean} [options.limitInputPixels=268402689] - Do not process input images where the number of pixels
|
|
132
162
|
* (width x height) exceeds this limit. Assumes image dimensions contained in the input metadata can be trusted.
|
|
133
163
|
* An integral Number of pixels, zero or false to remove limit, true to use default limit of 268402689 (0x3FFF x 0x3FFF).
|
|
164
|
+
* @param {number|boolean} [options.limitInputChannels=5] - Do not process input images where the number of channels exceeds this limit. Assumes image metadata can be trusted.
|
|
165
|
+
* An integral Number of channels, zero or false to remove limit, true to use default limit of 5.
|
|
134
166
|
* @param {boolean} [options.unlimited=false] - Set this to `true` to remove safety features that help prevent memory exhaustion (JPEG, PNG, SVG, HEIF).
|
|
167
|
+
* @param {boolean} [options.autoOrient=false] - Set this to `true` to rotate/flip the image to match EXIF `Orientation`, if any.
|
|
135
168
|
* @param {boolean} [options.sequentialRead=true] - Set this to `false` to use random access rather than sequential read. Some operations will do this automatically.
|
|
136
|
-
* @param {number} [options.density=72] -
|
|
169
|
+
* @param {number} [options.density=72] - The DPI at which to render SVG and PDF images, in the range 1 to 100000.
|
|
137
170
|
* @param {number} [options.ignoreIcc=false] - should the embedded ICC profile, if any, be ignored.
|
|
138
171
|
* @param {number} [options.pages=1] - Number of pages to extract for multi-page input (GIF, WebP, TIFF), use -1 for all pages.
|
|
139
172
|
* @param {number} [options.page=0] - Page number to start extracting from for multi-page input (GIF, WebP, TIFF), zero based.
|
|
140
|
-
* @param {number} [options.subifd=-1] - subIFD (Sub Image File Directory) to extract for OME-TIFF, defaults to main image.
|
|
141
|
-
* @param {number} [options.level=0] - level to extract from a multi-level input (OpenSlide), zero based.
|
|
142
173
|
* @param {boolean} [options.animated=false] - Set to `true` to read all frames/pages of an animated image (GIF, WebP, TIFF), equivalent of setting `pages` to `-1`.
|
|
143
174
|
* @param {Object} [options.raw] - describes raw pixel input image data. See `raw()` for pixel ordering.
|
|
144
175
|
* @param {number} [options.raw.width] - integral number of pixels wide.
|
|
@@ -146,15 +177,17 @@ const debuglog = util.debuglog('sharp');
|
|
|
146
177
|
* @param {number} [options.raw.channels] - integral number of channels, between 1 and 4.
|
|
147
178
|
* @param {boolean} [options.raw.premultiplied] - specifies that the raw input has already been premultiplied, set to `true`
|
|
148
179
|
* to avoid sharp premultiplying the image. (optional, default `false`)
|
|
180
|
+
* @param {number} [options.raw.pageHeight] - The pixel height of each page/frame for animated images, must be an integral factor of `raw.height`.
|
|
149
181
|
* @param {Object} [options.create] - describes a new image to be created.
|
|
150
182
|
* @param {number} [options.create.width] - integral number of pixels wide.
|
|
151
183
|
* @param {number} [options.create.height] - integral number of pixels high.
|
|
152
184
|
* @param {number} [options.create.channels] - integral number of channels, either 3 (RGB) or 4 (RGBA).
|
|
153
185
|
* @param {string|Object} [options.create.background] - parsed by the [color](https://www.npmjs.org/package/color) module to extract values for red, green, blue and alpha.
|
|
186
|
+
* @param {number} [options.create.pageHeight] - The pixel height of each page/frame for animated images, must be an integral factor of `create.height`.
|
|
154
187
|
* @param {Object} [options.create.noise] - describes a noise to be created.
|
|
155
188
|
* @param {string} [options.create.noise.type] - type of generated noise, currently only `gaussian` is supported.
|
|
156
|
-
* @param {number} [options.create.noise.mean] -
|
|
157
|
-
* @param {number} [options.create.noise.sigma] -
|
|
189
|
+
* @param {number} [options.create.noise.mean=128] - Mean value of pixels in the generated noise.
|
|
190
|
+
* @param {number} [options.create.noise.sigma=30] - Standard deviation of pixel values in the generated noise.
|
|
158
191
|
* @param {Object} [options.text] - describes a new text image to be created.
|
|
159
192
|
* @param {string} [options.text.text] - text to render as a UTF-8 string. It can contain Pango markup, for example `<i>Le</i>Monde`.
|
|
160
193
|
* @param {string} [options.text.font] - font name to render with.
|
|
@@ -167,10 +200,29 @@ const debuglog = util.debuglog('sharp');
|
|
|
167
200
|
* @param {boolean} [options.text.rgba=false] - set this to true to enable RGBA output. This is useful for colour emoji rendering, or support for pango markup features like `<span foreground="red">Red!</span>`.
|
|
168
201
|
* @param {number} [options.text.spacing=0] - text line height in points. Will use the font line height if none is specified.
|
|
169
202
|
* @param {string} [options.text.wrap='word'] - word wrapping style when width is provided, one of: 'word', 'char', 'word-char' (prefer word, fallback to char) or 'none'.
|
|
203
|
+
* @param {Object} [options.join] - describes how an array of input images should be joined.
|
|
204
|
+
* @param {number} [options.join.across=1] - number of images to join horizontally.
|
|
205
|
+
* @param {boolean} [options.join.animated=false] - set this to `true` to join the images as an animated image.
|
|
206
|
+
* @param {number} [options.join.shim=0] - number of pixels to insert between joined images.
|
|
207
|
+
* @param {string|Object} [options.join.background] - parsed by the [color](https://www.npmjs.org/package/color) module to extract values for red, green, blue and alpha.
|
|
208
|
+
* @param {string} [options.join.halign='left'] - horizontal alignment style for images joined horizontally (`'left'`, `'centre'`, `'center'`, `'right'`).
|
|
209
|
+
* @param {string} [options.join.valign='top'] - vertical alignment style for images joined vertically (`'top'`, `'centre'`, `'center'`, `'bottom'`).
|
|
210
|
+
* @param {Object} [options.tiff] - Describes TIFF specific options.
|
|
211
|
+
* @param {number} [options.tiff.subifd=-1] - Sub Image File Directory to extract for OME-TIFF, defaults to main image.
|
|
212
|
+
* @param {Object} [options.svg] - Describes SVG specific options.
|
|
213
|
+
* @param {string} [options.svg.stylesheet] - Custom CSS for SVG input, applied with a User Origin during the CSS cascade.
|
|
214
|
+
* @param {boolean} [options.svg.highBitdepth=false] - Set to `true` to render SVG input at 32-bits per channel (128-bit) instead of 8-bits per channel (32-bit) RGBA.
|
|
215
|
+
* @param {Object} [options.pdf] - Describes PDF specific options. Requires the use of a globally-installed libvips compiled with support for PDFium, Poppler, ImageMagick or GraphicsMagick.
|
|
216
|
+
* @param {string|Object} [options.pdf.background] - Background colour to use when PDF is partially transparent. Parsed by the [color](https://www.npmjs.org/package/color) module to extract values for red, green, blue and alpha.
|
|
217
|
+
* @param {Object} [options.openSlide] - Describes OpenSlide specific options. Requires the use of a globally-installed libvips compiled with support for OpenSlide.
|
|
218
|
+
* @param {number} [options.openSlide.level=0] - Level to extract from a multi-level input, zero based.
|
|
219
|
+
* @param {Object} [options.jp2] - Describes JPEG 2000 specific options. Requires the use of a globally-installed libvips compiled with support for OpenJPEG.
|
|
220
|
+
* @param {boolean} [options.jp2.oneshot=false] - Set to `true` to decode tiled JPEG 2000 images in a single operation, improving compatibility.
|
|
170
221
|
* @returns {Sharp}
|
|
171
222
|
* @throws {Error} Invalid parameters
|
|
172
223
|
*/
|
|
173
224
|
const Sharp = function (input, options) {
|
|
225
|
+
// biome-ignore lint/complexity/noArguments: constructor factory
|
|
174
226
|
if (arguments.length === 1 && !is.defined(input)) {
|
|
175
227
|
throw new Error('Invalid input');
|
|
176
228
|
}
|
|
@@ -193,11 +245,11 @@ const Sharp = function (input, options) {
|
|
|
193
245
|
canvas: 'crop',
|
|
194
246
|
position: 0,
|
|
195
247
|
resizeBackground: [0, 0, 0, 255],
|
|
196
|
-
useExifOrientation: false,
|
|
197
248
|
angle: 0,
|
|
198
249
|
rotationAngle: 0,
|
|
199
250
|
rotationBackground: [0, 0, 0, 255],
|
|
200
|
-
|
|
251
|
+
rotateBefore: false,
|
|
252
|
+
orientBefore: false,
|
|
201
253
|
flip: false,
|
|
202
254
|
flop: false,
|
|
203
255
|
extendTop: 0,
|
|
@@ -239,6 +291,9 @@ const Sharp = function (input, options) {
|
|
|
239
291
|
trimBackground: [],
|
|
240
292
|
trimThreshold: -1,
|
|
241
293
|
trimLineArt: false,
|
|
294
|
+
trimMargin: 0,
|
|
295
|
+
dilateWidth: 0,
|
|
296
|
+
erodeWidth: 0,
|
|
242
297
|
gamma: 0,
|
|
243
298
|
gammaOut: 0,
|
|
244
299
|
greyscale: false,
|
|
@@ -265,13 +320,19 @@ const Sharp = function (input, options) {
|
|
|
265
320
|
fileOut: '',
|
|
266
321
|
formatOut: 'input',
|
|
267
322
|
streamOut: false,
|
|
323
|
+
typedArrayOut: false,
|
|
268
324
|
keepMetadata: 0,
|
|
269
325
|
withMetadataOrientation: -1,
|
|
270
326
|
withMetadataDensity: 0,
|
|
271
327
|
withIccProfile: '',
|
|
272
328
|
withExif: {},
|
|
273
329
|
withExifMerge: true,
|
|
330
|
+
withXmp: '',
|
|
331
|
+
keepGainMap: false,
|
|
332
|
+
withGainMap: false,
|
|
274
333
|
resolveWithObject: false,
|
|
334
|
+
loop: -1,
|
|
335
|
+
delay: [],
|
|
275
336
|
// output format
|
|
276
337
|
jpegQuality: 80,
|
|
277
338
|
jpegProgressive: false,
|
|
@@ -299,23 +360,27 @@ const Sharp = function (input, options) {
|
|
|
299
360
|
webpLossless: false,
|
|
300
361
|
webpNearLossless: false,
|
|
301
362
|
webpSmartSubsample: false,
|
|
363
|
+
webpSmartDeblock: false,
|
|
302
364
|
webpPreset: 'default',
|
|
303
365
|
webpEffort: 4,
|
|
304
366
|
webpMinSize: false,
|
|
305
367
|
webpMixed: false,
|
|
368
|
+
webpExact: false,
|
|
306
369
|
gifBitdepth: 8,
|
|
307
370
|
gifEffort: 7,
|
|
308
371
|
gifDither: 1,
|
|
309
372
|
gifInterFrameMaxError: 0,
|
|
310
373
|
gifInterPaletteMaxError: 3,
|
|
374
|
+
gifKeepDuplicateFrames: false,
|
|
311
375
|
gifReuse: true,
|
|
312
376
|
gifProgressive: false,
|
|
313
377
|
tiffQuality: 80,
|
|
314
378
|
tiffCompression: 'jpeg',
|
|
379
|
+
tiffBigtiff: false,
|
|
315
380
|
tiffPredictor: 'horizontal',
|
|
316
381
|
tiffPyramid: false,
|
|
317
382
|
tiffMiniswhite: false,
|
|
318
|
-
tiffBitdepth:
|
|
383
|
+
tiffBitdepth: 0,
|
|
319
384
|
tiffTile: false,
|
|
320
385
|
tiffTileHeight: 256,
|
|
321
386
|
tiffTileWidth: 256,
|
|
@@ -328,6 +393,7 @@ const Sharp = function (input, options) {
|
|
|
328
393
|
heifEffort: 4,
|
|
329
394
|
heifChromaSubsampling: '4:4:4',
|
|
330
395
|
heifBitdepth: 8,
|
|
396
|
+
heifTune: 'auto',
|
|
331
397
|
jxlDistance: 1,
|
|
332
398
|
jxlDecodingTier: 0,
|
|
333
399
|
jxlEffort: 7,
|
|
@@ -348,15 +414,14 @@ const Sharp = function (input, options) {
|
|
|
348
414
|
timeoutSeconds: 0,
|
|
349
415
|
linearA: [],
|
|
350
416
|
linearB: [],
|
|
417
|
+
pdfBackground: [255, 255, 255, 255],
|
|
351
418
|
// Function to notify of libvips warnings
|
|
352
419
|
debuglog: warning => {
|
|
353
420
|
this.emit('warning', warning);
|
|
354
421
|
debuglog(warning);
|
|
355
422
|
},
|
|
356
423
|
// Function to notify of queue length changes
|
|
357
|
-
queueListener
|
|
358
|
-
Sharp.queue.emit('change', queueLength);
|
|
359
|
-
}
|
|
424
|
+
queueListener
|
|
360
425
|
};
|
|
361
426
|
this.options.input = this._createInputDescriptor(input, options, { allowStream: true });
|
|
362
427
|
return this;
|
|
@@ -370,29 +435,33 @@ Object.setPrototypeOf(Sharp, stream.Duplex);
|
|
|
370
435
|
* This allows multiple output Streams and therefore multiple processing pipelines to share a single input Stream.
|
|
371
436
|
*
|
|
372
437
|
* @example
|
|
373
|
-
* const pipeline = sharp().rotate();
|
|
374
|
-
* pipeline.clone().resize(800, 600).pipe(firstWritableStream);
|
|
375
|
-
* pipeline.clone().extract({ left: 20, top: 20, width: 100, height: 100 }).pipe(secondWritableStream);
|
|
376
|
-
* readableStream.pipe(pipeline);
|
|
377
438
|
* // firstWritableStream receives auto-rotated, resized readableStream
|
|
378
439
|
* // secondWritableStream receives auto-rotated, extracted region of readableStream
|
|
379
440
|
*
|
|
441
|
+
* const pipeline = sharp().rotate();
|
|
442
|
+
* pipeline
|
|
443
|
+
* .clone()
|
|
444
|
+
* .resize(800, 600)
|
|
445
|
+
* .pipe(firstWritableStream);
|
|
446
|
+
* pipeline
|
|
447
|
+
* .clone()
|
|
448
|
+
* .extract({ left: 20, top: 20, width: 100, height: 100 })
|
|
449
|
+
* .pipe(secondWritableStream);
|
|
450
|
+
* readableStream.pipe(pipeline);
|
|
451
|
+
*
|
|
380
452
|
* @example
|
|
381
453
|
* // Create a pipeline that will download an image, resize it and format it to different files
|
|
382
454
|
* // Using Promises to know when the pipeline is complete
|
|
383
|
-
* const fs = require("fs");
|
|
384
|
-
* const got = require("got");
|
|
385
|
-
* const sharpStream = sharp({ failOn: 'none' });
|
|
386
455
|
*
|
|
387
|
-
* const
|
|
456
|
+
* const sharpStream = sharp();
|
|
388
457
|
*
|
|
458
|
+
* const promises = [];
|
|
389
459
|
* promises.push(
|
|
390
460
|
* sharpStream
|
|
391
461
|
* .clone()
|
|
392
462
|
* .jpeg({ quality: 100 })
|
|
393
463
|
* .toFile("originalFile.jpg")
|
|
394
464
|
* );
|
|
395
|
-
*
|
|
396
465
|
* promises.push(
|
|
397
466
|
* sharpStream
|
|
398
467
|
* .clone()
|
|
@@ -400,7 +469,6 @@ Object.setPrototypeOf(Sharp, stream.Duplex);
|
|
|
400
469
|
* .jpeg({ quality: 80 })
|
|
401
470
|
* .toFile("optimized-500.jpg")
|
|
402
471
|
* );
|
|
403
|
-
*
|
|
404
472
|
* promises.push(
|
|
405
473
|
* sharpStream
|
|
406
474
|
* .clone()
|
|
@@ -409,19 +477,9 @@ Object.setPrototypeOf(Sharp, stream.Duplex);
|
|
|
409
477
|
* .toFile("optimized-500.webp")
|
|
410
478
|
* );
|
|
411
479
|
*
|
|
412
|
-
*
|
|
413
|
-
*
|
|
414
|
-
*
|
|
415
|
-
* Promise.all(promises)
|
|
416
|
-
* .then(res => { console.log("Done!", res); })
|
|
417
|
-
* .catch(err => {
|
|
418
|
-
* console.error("Error processing files, let's clean it up", err);
|
|
419
|
-
* try {
|
|
420
|
-
* fs.unlinkSync("originalFile.jpg");
|
|
421
|
-
* fs.unlinkSync("optimized-500.jpg");
|
|
422
|
-
* fs.unlinkSync("optimized-500.webp");
|
|
423
|
-
* } catch (e) {}
|
|
424
|
-
* });
|
|
480
|
+
* const res = await fetch("https://www.example.com/some-file.jpg")
|
|
481
|
+
* Readable.fromWeb(res.body).pipe(sharpStream);
|
|
482
|
+
* await Promise.all(promises);
|
|
425
483
|
*
|
|
426
484
|
* @returns {Sharp}
|
|
427
485
|
*/
|
|
@@ -447,6 +505,7 @@ Object.assign(Sharp.prototype, { clone });
|
|
|
447
505
|
|
|
448
506
|
/**
|
|
449
507
|
* Export constructor.
|
|
508
|
+
* @module Sharp
|
|
450
509
|
* @private
|
|
451
510
|
*/
|
|
452
511
|
module.exports = Sharp;
|