@revizly/sharp 0.35.0-revizly4 → 0.35.0-revizly41

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.
Files changed (46) hide show
  1. package/README.md +12 -18
  2. package/{lib/channel.js → dist/channel.cjs} +1 -1
  3. package/dist/channel.mjs +177 -0
  4. package/{lib/colour.js → dist/colour.cjs} +11 -7
  5. package/dist/colour.mjs +199 -0
  6. package/{lib/composite.js → dist/composite.cjs} +2 -1
  7. package/dist/composite.mjs +213 -0
  8. package/{lib/constructor.js → dist/constructor.cjs} +42 -29
  9. package/dist/constructor.mjs +512 -0
  10. package/dist/index.cjs +25 -0
  11. package/dist/index.d.cts +2001 -0
  12. package/dist/index.d.mts +2048 -0
  13. package/dist/index.mjs +25 -0
  14. package/{lib/input.js → dist/input.cjs} +26 -21
  15. package/dist/input.mjs +814 -0
  16. package/{lib/is.js → dist/is.cjs} +1 -1
  17. package/dist/is.mjs +143 -0
  18. package/{lib/libvips.js → dist/libvips.cjs} +35 -30
  19. package/dist/libvips.mjs +212 -0
  20. package/{lib/operation.js → dist/operation.cjs} +33 -51
  21. package/dist/operation.mjs +998 -0
  22. package/{lib/output.js → dist/output.cjs} +161 -28
  23. package/dist/output.mjs +1799 -0
  24. package/{lib/resize.js → dist/resize.cjs} +46 -24
  25. package/dist/resize.mjs +617 -0
  26. package/dist/sharp.cjs +125 -0
  27. package/dist/sharp.mjs +125 -0
  28. package/{lib/utility.js → dist/utility.cjs} +18 -8
  29. package/dist/utility.mjs +301 -0
  30. package/install/build.js +3 -3
  31. package/lib/index.d.ts +105 -75
  32. package/package.json +46 -27
  33. package/src/binding.gyp +18 -13
  34. package/src/common.cc +70 -17
  35. package/src/common.h +22 -3
  36. package/src/metadata.cc +66 -8
  37. package/src/metadata.h +6 -1
  38. package/src/operations.cc +25 -8
  39. package/src/operations.h +1 -1
  40. package/src/pipeline.cc +206 -69
  41. package/src/pipeline.h +16 -1
  42. package/src/stats.cc +6 -6
  43. package/src/utilities.cc +7 -6
  44. package/install/check.js +0 -14
  45. package/lib/index.js +0 -16
  46. package/lib/sharp.js +0 -121
@@ -0,0 +1,213 @@
1
+ /*!
2
+ Copyright 2013 Lovell Fuller and others.
3
+ SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ import is from './is.mjs';
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
+ export default (Sharp) => {
211
+ Sharp.prototype.composite = composite;
212
+ Sharp.blend = blend;
213
+ };
@@ -5,9 +5,9 @@
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');
@@ -48,7 +48,7 @@ const queueListener = (queueLength) => {
48
48
  * // resize to 300 pixels wide,
49
49
  * // emit an 'info' event with calculated dimensions
50
50
  * // and finally write image data to writableStream
51
- * const { body } = fetch('https://...');
51
+ * const { body } = await fetch('https://...');
52
52
  * const readableStream = Readable.fromWeb(body);
53
53
  * const transformer = sharp()
54
54
  * .resize(300)
@@ -58,6 +58,17 @@ const queueListener = (queueLength) => {
58
58
  * readableStream.pipe(transformer).pipe(writableStream);
59
59
  *
60
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
61
72
  * // Create a blank 300x200 PNG image of semi-translucent red pixels
62
73
  * sharp({
63
74
  * create: {
@@ -146,14 +157,16 @@ const queueListener = (queueLength) => {
146
157
  * An array of inputs can be provided, and these will be joined together.
147
158
  * JPEG, PNG, WebP, AVIF, GIF, SVG, TIFF or raw pixel image data can be streamed into the object when not present.
148
159
  * @param {Object} [options] - if present, is an Object with optional attributes.
149
- * @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.
150
161
  * @param {number|boolean} [options.limitInputPixels=268402689] - Do not process input images where the number of pixels
151
162
  * (width x height) exceeds this limit. Assumes image dimensions contained in the input metadata can be trusted.
152
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.
153
166
  * @param {boolean} [options.unlimited=false] - Set this to `true` to remove safety features that help prevent memory exhaustion (JPEG, PNG, SVG, HEIF).
154
167
  * @param {boolean} [options.autoOrient=false] - Set this to `true` to rotate/flip the image to match EXIF `Orientation`, if any.
155
168
  * @param {boolean} [options.sequentialRead=true] - Set this to `false` to use random access rather than sequential read. Some operations will do this automatically.
156
- * @param {number} [options.density=72] - number representing the DPI for vector images in the range 1 to 100000.
169
+ * @param {number} [options.density=72] - The DPI at which to render SVG and PDF images, in the range 1 to 100000.
157
170
  * @param {number} [options.ignoreIcc=false] - should the embedded ICC profile, if any, be ignored.
158
171
  * @param {number} [options.pages=1] - Number of pages to extract for multi-page input (GIF, WebP, TIFF), use -1 for all pages.
159
172
  * @param {number} [options.page=0] - Page number to start extracting from for multi-page input (GIF, WebP, TIFF), zero based.
@@ -278,6 +291,7 @@ const Sharp = function (input, options) {
278
291
  trimBackground: [],
279
292
  trimThreshold: -1,
280
293
  trimLineArt: false,
294
+ trimMargin: 0,
281
295
  dilateWidth: 0,
282
296
  erodeWidth: 0,
283
297
  gamma: 0,
@@ -306,6 +320,7 @@ const Sharp = function (input, options) {
306
320
  fileOut: '',
307
321
  formatOut: 'input',
308
322
  streamOut: false,
323
+ typedArrayOut: false,
309
324
  keepMetadata: 0,
310
325
  withMetadataOrientation: -1,
311
326
  withMetadataDensity: 0,
@@ -313,6 +328,8 @@ const Sharp = function (input, options) {
313
328
  withExif: {},
314
329
  withExifMerge: true,
315
330
  withXmp: '',
331
+ keepGainMap: false,
332
+ withGainMap: false,
316
333
  resolveWithObject: false,
317
334
  loop: -1,
318
335
  delay: [],
@@ -348,6 +365,7 @@ const Sharp = function (input, options) {
348
365
  webpEffort: 4,
349
366
  webpMinSize: false,
350
367
  webpMixed: false,
368
+ webpExact: false,
351
369
  gifBitdepth: 8,
352
370
  gifEffort: 7,
353
371
  gifDither: 1,
@@ -362,7 +380,7 @@ const Sharp = function (input, options) {
362
380
  tiffPredictor: 'horizontal',
363
381
  tiffPyramid: false,
364
382
  tiffMiniswhite: false,
365
- tiffBitdepth: 8,
383
+ tiffBitdepth: 0,
366
384
  tiffTile: false,
367
385
  tiffTileHeight: 256,
368
386
  tiffTileWidth: 256,
@@ -375,6 +393,8 @@ const Sharp = function (input, options) {
375
393
  heifEffort: 4,
376
394
  heifChromaSubsampling: '4:4:4',
377
395
  heifBitdepth: 8,
396
+ heifTune: 'auto',
397
+ heifEncoder: 'auto',
378
398
  jxlDistance: 1,
379
399
  jxlDecodingTier: 0,
380
400
  jxlEffort: 7,
@@ -416,29 +436,33 @@ Object.setPrototypeOf(Sharp, stream.Duplex);
416
436
  * This allows multiple output Streams and therefore multiple processing pipelines to share a single input Stream.
417
437
  *
418
438
  * @example
419
- * const pipeline = sharp().rotate();
420
- * pipeline.clone().resize(800, 600).pipe(firstWritableStream);
421
- * pipeline.clone().extract({ left: 20, top: 20, width: 100, height: 100 }).pipe(secondWritableStream);
422
- * readableStream.pipe(pipeline);
423
439
  * // firstWritableStream receives auto-rotated, resized readableStream
424
440
  * // secondWritableStream receives auto-rotated, extracted region of readableStream
425
441
  *
442
+ * const pipeline = sharp().rotate();
443
+ * pipeline
444
+ * .clone()
445
+ * .resize(800, 600)
446
+ * .pipe(firstWritableStream);
447
+ * pipeline
448
+ * .clone()
449
+ * .extract({ left: 20, top: 20, width: 100, height: 100 })
450
+ * .pipe(secondWritableStream);
451
+ * readableStream.pipe(pipeline);
452
+ *
426
453
  * @example
427
454
  * // Create a pipeline that will download an image, resize it and format it to different files
428
455
  * // Using Promises to know when the pipeline is complete
429
- * const fs = require("fs");
430
- * const got = require("got");
431
- * const sharpStream = sharp({ failOn: 'none' });
432
456
  *
433
- * const promises = [];
457
+ * const sharpStream = sharp();
434
458
  *
459
+ * const promises = [];
435
460
  * promises.push(
436
461
  * sharpStream
437
462
  * .clone()
438
463
  * .jpeg({ quality: 100 })
439
464
  * .toFile("originalFile.jpg")
440
465
  * );
441
- *
442
466
  * promises.push(
443
467
  * sharpStream
444
468
  * .clone()
@@ -446,7 +470,6 @@ Object.setPrototypeOf(Sharp, stream.Duplex);
446
470
  * .jpeg({ quality: 80 })
447
471
  * .toFile("optimized-500.jpg")
448
472
  * );
449
- *
450
473
  * promises.push(
451
474
  * sharpStream
452
475
  * .clone()
@@ -455,19 +478,9 @@ Object.setPrototypeOf(Sharp, stream.Duplex);
455
478
  * .toFile("optimized-500.webp")
456
479
  * );
457
480
  *
458
- * // https://github.com/sindresorhus/got/blob/main/documentation/3-streams.md
459
- * got.stream("https://www.example.com/some-file.jpg").pipe(sharpStream);
460
- *
461
- * Promise.all(promises)
462
- * .then(res => { console.log("Done!", res); })
463
- * .catch(err => {
464
- * console.error("Error processing files, let's clean it up", err);
465
- * try {
466
- * fs.unlinkSync("originalFile.jpg");
467
- * fs.unlinkSync("optimized-500.jpg");
468
- * fs.unlinkSync("optimized-500.webp");
469
- * } catch (e) {}
470
- * });
481
+ * const res = await fetch("https://www.example.com/some-file.jpg")
482
+ * Readable.fromWeb(res.body).pipe(sharpStream);
483
+ * await Promise.all(promises);
471
484
  *
472
485
  * @returns {Sharp}
473
486
  */