@revizly/sharp 0.35.0-revizly54 → 0.35.0-revizly56

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.
@@ -202,7 +202,7 @@ const queueListener = (queueLength) => {
202
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
203
  * @param {Object} [options.join] - describes how an array of input images should be joined.
204
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.
205
+ * @param {boolean} [options.join.animated=false] - set this to `true` to join the images as an animated image, cannot be used with `across` or `shim`.
206
206
  * @param {number} [options.join.shim=0] - number of pixels to insert between joined images.
207
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
208
  * @param {string} [options.join.halign='left'] - horizontal alignment style for images joined horizontally (`'left'`, `'centre'`, `'center'`, `'right'`).
@@ -202,7 +202,7 @@ const queueListener = (queueLength) => {
202
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
203
  * @param {Object} [options.join] - describes how an array of input images should be joined.
204
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.
205
+ * @param {boolean} [options.join.animated=false] - set this to `true` to join the images as an animated image, cannot be used with `across` or `shim`.
206
206
  * @param {number} [options.join.shim=0] - number of pixels to insert between joined images.
207
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
208
  * @param {string} [options.join.halign='left'] - horizontal alignment style for images joined horizontally (`'left'`, `'centre'`, `'center'`, `'right'`).
package/dist/index.d.cts CHANGED
@@ -1,3 +1,4 @@
1
+ /* cspell:disable */
1
2
  /**
2
3
  * Copyright 2017 François Nguyen and others.
3
4
  *
@@ -22,6 +23,7 @@
22
23
  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23
24
  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25
  */
26
+ /* cspell:enable */
25
27
 
26
28
  // SPDX-License-Identifier: MIT
27
29
 
@@ -408,7 +410,7 @@ declare namespace sharp {
408
410
 
409
411
  /**
410
412
  * Alias for calling `rotate()` with no arguments, which orients the image based
411
- * on EXIF orientsion.
413
+ * on EXIF orientation.
412
414
  *
413
415
  * This operation is aliased to emphasize its purpose, helping to remove any
414
416
  * confusion between rotation and orientation.
@@ -580,7 +582,7 @@ declare namespace sharp {
580
582
  convolve(kernel: Kernel): Sharp;
581
583
 
582
584
  /**
583
- * Any pixel value greather than or equal to the threshold value will be set to 255, otherwise it will be set to 0.
585
+ * Any pixel value greater than or equal to the threshold value will be set to 255, otherwise it will be set to 0.
584
586
  * @param threshold a value in the range 0-255 representing the level at which the threshold will be applied. (optional, default 128)
585
587
  * @param options threshold options
586
588
  * @throws {Error} Invalid parameters
@@ -1462,8 +1464,8 @@ declare namespace sharp {
1462
1464
  interface HeifOptions extends OutputOptions {
1463
1465
  /** quality, integer 1-100 (optional, default 50) */
1464
1466
  quality?: number | undefined;
1465
- /** compression format: av1, hevc (optional, default 'av1') */
1466
- compression?: HeifCompression | undefined;
1467
+ /** compression format: av1, hevc */
1468
+ compression: HeifCompression;
1467
1469
  /** use lossless compression (optional, default false) */
1468
1470
  lossless?: boolean | undefined;
1469
1471
  /** Level of CPU effort to reduce file size, between 0 (fastest) and 9 (slowest) (optional, default 4) */
@@ -1472,7 +1474,7 @@ declare namespace sharp {
1472
1474
  chromaSubsampling?: string | undefined;
1473
1475
  /** Set bitdepth to 8, 10 or 12 bit (optional, default 8) */
1474
1476
  bitdepth?: 8 | 10 | 12 | undefined;
1475
- /** Tune output for a quality metric, one of 'auto', 'iq', 'psnr' or 'ssim' (optional, default 'auto') */
1477
+ /** Tune output for a quality metric, one of 'auto' (av1 default), 'iq' (av1 only), 'psnr' or 'ssim' (hevc default) */
1476
1478
  tune?: HeifTune | undefined;
1477
1479
  /** Which encoder libheif uses (must be compiled in) (optional, default 'auto') */
1478
1480
  encoder?: 'auto' | 'aom' | 'rav1e' | 'svt' | 'x265' | undefined;
@@ -1703,7 +1705,7 @@ declare namespace sharp {
1703
1705
  left?: number | undefined;
1704
1706
  /** set to true to repeat the overlay image across the entire image with the given gravity. (optional, default false) */
1705
1707
  tile?: boolean | undefined;
1706
- /** Set to true to avoid premultipling the image below. Equivalent to the --premultiplied vips option. */
1708
+ /** Set to true to avoid premultiplying the image below. Equivalent to the --premultiplied vips option. */
1707
1709
  premultiplied?: boolean | undefined;
1708
1710
  /** number representing the DPI for vector overlay image. (optional, default 72)*/
1709
1711
  density?: number | undefined;
package/dist/index.d.mts CHANGED
@@ -1,3 +1,4 @@
1
+ /* cspell:disable */
1
2
  /**
2
3
  * Copyright 2017 François Nguyen and others.
3
4
  *
@@ -22,6 +23,7 @@
22
23
  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23
24
  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25
  */
26
+ /* cspell:enable */
25
27
 
26
28
  // SPDX-License-Identifier: MIT
27
29
 
@@ -402,7 +404,7 @@ export interface Sharp extends Duplex {
402
404
 
403
405
  /**
404
406
  * Alias for calling `rotate()` with no arguments, which orients the image based
405
- * on EXIF orientsion.
407
+ * on EXIF orientation.
406
408
  *
407
409
  * This operation is aliased to emphasize its purpose, helping to remove any
408
410
  * confusion between rotation and orientation.
@@ -574,7 +576,7 @@ export interface Sharp extends Duplex {
574
576
  convolve(kernel: Kernel): Sharp;
575
577
 
576
578
  /**
577
- * Any pixel value greather than or equal to the threshold value will be set to 255, otherwise it will be set to 0.
579
+ * Any pixel value greater than or equal to the threshold value will be set to 255, otherwise it will be set to 0.
578
580
  * @param threshold a value in the range 0-255 representing the level at which the threshold will be applied. (optional, default 128)
579
581
  * @param options threshold options
580
582
  * @throws {Error} Invalid parameters
@@ -1456,8 +1458,8 @@ export interface AvifOptions extends OutputOptions {
1456
1458
  export interface HeifOptions extends OutputOptions {
1457
1459
  /** quality, integer 1-100 (optional, default 50) */
1458
1460
  quality?: number | undefined;
1459
- /** compression format: av1, hevc (optional, default 'av1') */
1460
- compression?: HeifCompression | undefined;
1461
+ /** compression format: av1, hevc */
1462
+ compression: HeifCompression;
1461
1463
  /** use lossless compression (optional, default false) */
1462
1464
  lossless?: boolean | undefined;
1463
1465
  /** Level of CPU effort to reduce file size, between 0 (fastest) and 9 (slowest) (optional, default 4) */
@@ -1466,7 +1468,7 @@ export interface HeifOptions extends OutputOptions {
1466
1468
  chromaSubsampling?: string | undefined;
1467
1469
  /** Set bitdepth to 8, 10 or 12 bit (optional, default 8) */
1468
1470
  bitdepth?: 8 | 10 | 12 | undefined;
1469
- /** Tune output for a quality metric, one of 'auto', 'iq', 'psnr' or 'ssim' (optional, default 'auto') */
1471
+ /** Tune output for a quality metric, one of 'auto' (av1 default), 'iq' (av1 only), 'psnr' or 'ssim' (hevc default) */
1470
1472
  tune?: HeifTune | undefined;
1471
1473
  /** Which encoder libheif uses (must be compiled in) (optional, default 'auto') */
1472
1474
  encoder?: 'auto' | 'aom' | 'rav1e' | 'svt' | 'x265' | undefined;
@@ -1697,7 +1699,7 @@ export interface OverlayOptions extends SharpOptions {
1697
1699
  left?: number | undefined;
1698
1700
  /** set to true to repeat the overlay image across the entire image with the given gravity. (optional, default false) */
1699
1701
  tile?: boolean | undefined;
1700
- /** Set to true to avoid premultipling the image below. Equivalent to the --premultiplied vips option. */
1702
+ /** Set to true to avoid premultiplying the image below. Equivalent to the --premultiplied vips option. */
1701
1703
  premultiplied?: boolean | undefined;
1702
1704
  /** number representing the DPI for vector overlay image. (optional, default 72)*/
1703
1705
  density?: number | undefined;
package/dist/input.cjs CHANGED
@@ -511,6 +511,9 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
511
511
  throw is.invalidParameterError('join.valign', 'valid alignment', inputOptions.join.valign);
512
512
  }
513
513
  }
514
+ if (inputDescriptor.joinAnimated && (inputDescriptor.joinAcross > 1 || inputDescriptor.joinShim > 0)) {
515
+ throw new Error('Expected neither join.across nor join.shim when join.animated is set');
516
+ }
514
517
  } else {
515
518
  throw new Error('Expected input to be an array of images to join');
516
519
  }
package/dist/input.mjs CHANGED
@@ -511,6 +511,9 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
511
511
  throw is.invalidParameterError('join.valign', 'valid alignment', inputOptions.join.valign);
512
512
  }
513
513
  }
514
+ if (inputDescriptor.joinAnimated && (inputDescriptor.joinAcross > 1 || inputDescriptor.joinShim > 0)) {
515
+ throw new Error('Expected neither join.across nor join.shim when join.animated is set');
516
+ }
514
517
  } else {
515
518
  throw new Error('Expected input to be an array of images to join');
516
519
  }
package/dist/is.cjs CHANGED
@@ -13,7 +13,7 @@ const defined = (val) => typeof val !== 'undefined' && val !== null;
13
13
  * Is this value an object?
14
14
  * @private
15
15
  */
16
- const object = (val) => typeof val === 'object';
16
+ const object = (val) => typeof val === 'object' && val !== null;
17
17
 
18
18
  /**
19
19
  * Is this value a plain object?
package/dist/is.mjs CHANGED
@@ -13,7 +13,7 @@ const defined = (val) => typeof val !== 'undefined' && val !== null;
13
13
  * Is this value an object?
14
14
  * @private
15
15
  */
16
- const object = (val) => typeof val === 'object';
16
+ const object = (val) => typeof val === 'object' && val !== null;
17
17
 
18
18
  /**
19
19
  * Is this value a plain object?
@@ -62,7 +62,7 @@ function rotate (angle, options) {
62
62
  this.options.rotationAngle = 0;
63
63
  }
64
64
  if (is.integer(angle) && !(angle % 90)) {
65
- this.options.angle = angle;
65
+ this.options.angle = angle % 360;
66
66
  } else if (is.number(angle)) {
67
67
  this.options.rotationAngle = angle;
68
68
  if (is.object(options) && options.background) {
@@ -62,7 +62,7 @@ function rotate (angle, options) {
62
62
  this.options.rotationAngle = 0;
63
63
  }
64
64
  if (is.integer(angle) && !(angle % 90)) {
65
- this.options.angle = angle;
65
+ this.options.angle = angle % 360;
66
66
  } else if (is.number(angle)) {
67
67
  this.options.rotationAngle = angle;
68
68
  if (is.object(options) && options.background) {
package/dist/output.cjs CHANGED
@@ -205,15 +205,15 @@ function toUint8Array () {
205
205
  * .withDensity(96)
206
206
  * .toBuffer();
207
207
  *
208
- * @param {number} density Number of pixels per inch (DPI).
208
+ * @param {number} density Number of pixels per inch (DPI), between 1 and 100000.
209
209
  * @returns {Sharp}
210
210
  * @throws {Error} Invalid parameters
211
211
  */
212
212
  function withDensity (density) {
213
- if (is.number(density) && density > 0) {
213
+ if (is.number(density) && is.inRange(density, 1, 100000)) {
214
214
  this.options.withMetadataDensity = density;
215
215
  } else {
216
- throw is.invalidParameterError('density', 'positive number', density);
216
+ throw is.invalidParameterError('density', 'number between 1 and 100000', density);
217
217
  }
218
218
  return this.keepExif();
219
219
  }
@@ -520,7 +520,7 @@ function keepMetadata () {
520
520
  *
521
521
  * @param {Object} [options]
522
522
  * @param {number} [options.orientation] Used to update the EXIF `Orientation` tag, integer between 1 and 8.
523
- * @param {number} [options.density] Number of pixels per inch (DPI).
523
+ * @param {number} [options.density] Number of pixels per inch (DPI), between 1 and 100000.
524
524
  * @returns {Sharp}
525
525
  * @throws {Error} Invalid parameters
526
526
  */
@@ -536,10 +536,10 @@ function withMetadata (options) {
536
536
  }
537
537
  }
538
538
  if (is.defined(options.density)) {
539
- if (is.number(options.density) && options.density > 0) {
539
+ if (is.number(options.density) && is.inRange(options.density, 1, 100000)) {
540
540
  this.options.withMetadataDensity = options.density;
541
541
  } else {
542
- throw is.invalidParameterError('density', 'positive number', options.density);
542
+ throw is.invalidParameterError('density', 'number between 1 and 100000', options.density);
543
543
  }
544
544
  }
545
545
  if (is.defined(options.icc)) {
@@ -1250,7 +1250,7 @@ function avif (options) {
1250
1250
  * @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 9 (slowest)
1251
1251
  * @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
1252
1252
  * @param {number} [options.bitdepth=8] - set bitdepth to 8, 10 or 12 bit
1253
- * @param {string} [options.tune='auto'] - tune output for a quality metric, one of 'auto' (default), 'iq', 'psnr' or 'ssim'
1253
+ * @param {string} [options.tune='auto'] - tune output for a quality metric, one of 'auto' (av1 default), 'iq' (av1 only), 'psnr' or 'ssim' (hevc default)
1254
1254
  * @returns {Sharp}
1255
1255
  * @throws {Error} Invalid options
1256
1256
  */
@@ -1258,6 +1258,9 @@ function heif (options) {
1258
1258
  if (is.object(options)) {
1259
1259
  if (is.string(options.compression) && is.inArray(options.compression, ['av1', 'hevc'])) {
1260
1260
  this.options.heifCompression = options.compression;
1261
+ if (options.compression === 'hevc' && this.options.heifTune === 'auto') {
1262
+ this.options.heifTune = 'ssim';
1263
+ }
1261
1264
  } else {
1262
1265
  throw is.invalidParameterError('compression', 'one of: av1, hevc', options.compression);
1263
1266
  }
@@ -1297,14 +1300,24 @@ function heif (options) {
1297
1300
  }
1298
1301
  }
1299
1302
  if (is.defined(options.tune)) {
1300
- if (is.string(options.tune) && is.inArray(options.tune, ['auto', 'iq', 'psnr', 'ssim'])) {
1301
- if (this.options.heifLossless && options.tune === 'iq') {
1302
- this.options.heifTune = 'ssim';
1303
- } else {
1303
+ if (is.string(options.tune)) {
1304
+ if (this.options.heifCompression === 'av1') {
1305
+ if (is.inArray(options.tune, ['auto', 'iq', 'psnr', 'ssim'])) {
1306
+ if (this.options.heifLossless && options.tune === 'iq') {
1307
+ this.options.heifTune = 'ssim';
1308
+ } else {
1309
+ this.options.heifTune = options.tune;
1310
+ }
1311
+ } else {
1312
+ throw is.invalidParameterError('tune', 'one of: auto, iq, psnr, ssim', options.tune);
1313
+ }
1314
+ } else if (is.inArray(options.tune, ['psnr', 'ssim'])) {
1304
1315
  this.options.heifTune = options.tune;
1316
+ } else {
1317
+ throw is.invalidParameterError('tune', 'one of: psnr, ssim', options.tune);
1305
1318
  }
1306
1319
  } else {
1307
- throw is.invalidParameterError('tune', 'one of: auto, iq, psnr, ssim', options.tune);
1320
+ throw is.invalidParameterError('tune', 'string', options.tune);
1308
1321
  }
1309
1322
  }
1310
1323
  if (is.defined(options.encoder)) {
@@ -1511,7 +1524,7 @@ function tile (options) {
1511
1524
  // Angle of rotation,
1512
1525
  if (is.defined(options.angle)) {
1513
1526
  if (is.integer(options.angle) && !(options.angle % 90)) {
1514
- this.options.tileAngle = options.angle;
1527
+ this.options.tileAngle = options.angle % 360;
1515
1528
  } else {
1516
1529
  throw is.invalidParameterError('angle', 'positive/negative multiple of 90', options.angle);
1517
1530
  }
package/dist/output.mjs CHANGED
@@ -205,15 +205,15 @@ function toUint8Array () {
205
205
  * .withDensity(96)
206
206
  * .toBuffer();
207
207
  *
208
- * @param {number} density Number of pixels per inch (DPI).
208
+ * @param {number} density Number of pixels per inch (DPI), between 1 and 100000.
209
209
  * @returns {Sharp}
210
210
  * @throws {Error} Invalid parameters
211
211
  */
212
212
  function withDensity (density) {
213
- if (is.number(density) && density > 0) {
213
+ if (is.number(density) && is.inRange(density, 1, 100000)) {
214
214
  this.options.withMetadataDensity = density;
215
215
  } else {
216
- throw is.invalidParameterError('density', 'positive number', density);
216
+ throw is.invalidParameterError('density', 'number between 1 and 100000', density);
217
217
  }
218
218
  return this.keepExif();
219
219
  }
@@ -520,7 +520,7 @@ function keepMetadata () {
520
520
  *
521
521
  * @param {Object} [options]
522
522
  * @param {number} [options.orientation] Used to update the EXIF `Orientation` tag, integer between 1 and 8.
523
- * @param {number} [options.density] Number of pixels per inch (DPI).
523
+ * @param {number} [options.density] Number of pixels per inch (DPI), between 1 and 100000.
524
524
  * @returns {Sharp}
525
525
  * @throws {Error} Invalid parameters
526
526
  */
@@ -536,10 +536,10 @@ function withMetadata (options) {
536
536
  }
537
537
  }
538
538
  if (is.defined(options.density)) {
539
- if (is.number(options.density) && options.density > 0) {
539
+ if (is.number(options.density) && is.inRange(options.density, 1, 100000)) {
540
540
  this.options.withMetadataDensity = options.density;
541
541
  } else {
542
- throw is.invalidParameterError('density', 'positive number', options.density);
542
+ throw is.invalidParameterError('density', 'number between 1 and 100000', options.density);
543
543
  }
544
544
  }
545
545
  if (is.defined(options.icc)) {
@@ -1250,7 +1250,7 @@ function avif (options) {
1250
1250
  * @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 9 (slowest)
1251
1251
  * @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
1252
1252
  * @param {number} [options.bitdepth=8] - set bitdepth to 8, 10 or 12 bit
1253
- * @param {string} [options.tune='auto'] - tune output for a quality metric, one of 'auto' (default), 'iq', 'psnr' or 'ssim'
1253
+ * @param {string} [options.tune='auto'] - tune output for a quality metric, one of 'auto' (av1 default), 'iq' (av1 only), 'psnr' or 'ssim' (hevc default)
1254
1254
  * @returns {Sharp}
1255
1255
  * @throws {Error} Invalid options
1256
1256
  */
@@ -1258,6 +1258,9 @@ function heif (options) {
1258
1258
  if (is.object(options)) {
1259
1259
  if (is.string(options.compression) && is.inArray(options.compression, ['av1', 'hevc'])) {
1260
1260
  this.options.heifCompression = options.compression;
1261
+ if (options.compression === 'hevc' && this.options.heifTune === 'auto') {
1262
+ this.options.heifTune = 'ssim';
1263
+ }
1261
1264
  } else {
1262
1265
  throw is.invalidParameterError('compression', 'one of: av1, hevc', options.compression);
1263
1266
  }
@@ -1297,14 +1300,24 @@ function heif (options) {
1297
1300
  }
1298
1301
  }
1299
1302
  if (is.defined(options.tune)) {
1300
- if (is.string(options.tune) && is.inArray(options.tune, ['auto', 'iq', 'psnr', 'ssim'])) {
1301
- if (this.options.heifLossless && options.tune === 'iq') {
1302
- this.options.heifTune = 'ssim';
1303
- } else {
1303
+ if (is.string(options.tune)) {
1304
+ if (this.options.heifCompression === 'av1') {
1305
+ if (is.inArray(options.tune, ['auto', 'iq', 'psnr', 'ssim'])) {
1306
+ if (this.options.heifLossless && options.tune === 'iq') {
1307
+ this.options.heifTune = 'ssim';
1308
+ } else {
1309
+ this.options.heifTune = options.tune;
1310
+ }
1311
+ } else {
1312
+ throw is.invalidParameterError('tune', 'one of: auto, iq, psnr, ssim', options.tune);
1313
+ }
1314
+ } else if (is.inArray(options.tune, ['psnr', 'ssim'])) {
1304
1315
  this.options.heifTune = options.tune;
1316
+ } else {
1317
+ throw is.invalidParameterError('tune', 'one of: psnr, ssim', options.tune);
1305
1318
  }
1306
1319
  } else {
1307
- throw is.invalidParameterError('tune', 'one of: auto, iq, psnr, ssim', options.tune);
1320
+ throw is.invalidParameterError('tune', 'string', options.tune);
1308
1321
  }
1309
1322
  }
1310
1323
  if (is.defined(options.encoder)) {
@@ -1511,7 +1524,7 @@ function tile (options) {
1511
1524
  // Angle of rotation,
1512
1525
  if (is.defined(options.angle)) {
1513
1526
  if (is.integer(options.angle) && !(options.angle % 90)) {
1514
- this.options.tileAngle = options.angle;
1527
+ this.options.tileAngle = options.angle % 360;
1515
1528
  } else {
1516
1529
  throw is.invalidParameterError('angle', 'positive/negative multiple of 90', options.angle);
1517
1530
  }
package/dist/resize.cjs CHANGED
@@ -52,7 +52,7 @@ const extendWith = {
52
52
  };
53
53
 
54
54
  /**
55
- * Strategies for automagic cover behaviour.
55
+ * Strategies for cover behaviour.
56
56
  * @member
57
57
  * @private
58
58
  */
package/dist/resize.mjs CHANGED
@@ -52,7 +52,7 @@ const extendWith = {
52
52
  };
53
53
 
54
54
  /**
55
- * Strategies for automagic cover behaviour.
55
+ * Strategies for cover behaviour.
56
56
  * @member
57
57
  * @private
58
58
  */
package/lib/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ /* cspell:disable */
1
2
  /**
2
3
  * Copyright 2017 François Nguyen and others.
3
4
  *
@@ -22,6 +23,7 @@
22
23
  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23
24
  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25
  */
26
+ /* cspell:enable */
25
27
 
26
28
  // SPDX-License-Identifier: MIT
27
29
 
@@ -408,7 +410,7 @@ declare namespace sharp {
408
410
 
409
411
  /**
410
412
  * Alias for calling `rotate()` with no arguments, which orients the image based
411
- * on EXIF orientsion.
413
+ * on EXIF orientation.
412
414
  *
413
415
  * This operation is aliased to emphasize its purpose, helping to remove any
414
416
  * confusion between rotation and orientation.
@@ -580,7 +582,7 @@ declare namespace sharp {
580
582
  convolve(kernel: Kernel): Sharp;
581
583
 
582
584
  /**
583
- * Any pixel value greather than or equal to the threshold value will be set to 255, otherwise it will be set to 0.
585
+ * Any pixel value greater than or equal to the threshold value will be set to 255, otherwise it will be set to 0.
584
586
  * @param threshold a value in the range 0-255 representing the level at which the threshold will be applied. (optional, default 128)
585
587
  * @param options threshold options
586
588
  * @throws {Error} Invalid parameters
@@ -1462,8 +1464,8 @@ declare namespace sharp {
1462
1464
  interface HeifOptions extends OutputOptions {
1463
1465
  /** quality, integer 1-100 (optional, default 50) */
1464
1466
  quality?: number | undefined;
1465
- /** compression format: av1, hevc (optional, default 'av1') */
1466
- compression?: HeifCompression | undefined;
1467
+ /** compression format: av1, hevc */
1468
+ compression: HeifCompression;
1467
1469
  /** use lossless compression (optional, default false) */
1468
1470
  lossless?: boolean | undefined;
1469
1471
  /** Level of CPU effort to reduce file size, between 0 (fastest) and 9 (slowest) (optional, default 4) */
@@ -1472,7 +1474,7 @@ declare namespace sharp {
1472
1474
  chromaSubsampling?: string | undefined;
1473
1475
  /** Set bitdepth to 8, 10 or 12 bit (optional, default 8) */
1474
1476
  bitdepth?: 8 | 10 | 12 | undefined;
1475
- /** Tune output for a quality metric, one of 'auto', 'iq', 'psnr' or 'ssim' (optional, default 'auto') */
1477
+ /** Tune output for a quality metric, one of 'auto' (av1 default), 'iq' (av1 only), 'psnr' or 'ssim' (hevc default) */
1476
1478
  tune?: HeifTune | undefined;
1477
1479
  /** Which encoder libheif uses (must be compiled in) (optional, default 'auto') */
1478
1480
  encoder?: 'auto' | 'aom' | 'rav1e' | 'svt' | 'x265' | undefined;
@@ -1703,7 +1705,7 @@ declare namespace sharp {
1703
1705
  left?: number | undefined;
1704
1706
  /** set to true to repeat the overlay image across the entire image with the given gravity. (optional, default false) */
1705
1707
  tile?: boolean | undefined;
1706
- /** Set to true to avoid premultipling the image below. Equivalent to the --premultiplied vips option. */
1708
+ /** Set to true to avoid premultiplying the image below. Equivalent to the --premultiplied vips option. */
1707
1709
  premultiplied?: boolean | undefined;
1708
1710
  /** number representing the DPI for vector overlay image. (optional, default 72)*/
1709
1711
  density?: number | undefined;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@revizly/sharp",
3
3
  "description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, GIF, AVIF and TIFF images",
4
- "version": "0.35.0-revizly54",
4
+ "version": "0.35.0-revizly56",
5
5
  "author": "Lovell Fuller <npm@lovell.info>",
6
6
  "homepage": "https://sharp.pixelplumbing.com",
7
7
  "contributors": [
@@ -98,10 +98,11 @@
98
98
  "build:dist": "node scripts/build.mjs",
99
99
  "clean": "rm -rf src/build/ test/fixtures/output.*",
100
100
  "test": "npm run lint && npm run test-unit",
101
- "lint": "npm run lint-cpp && npm run lint-js && npm run lint-types && npm run lint-publish",
101
+ "lint": "npm run lint-cpp && npm run lint-js && npm run lint-types && npm run lint-spell && npm run lint-publish",
102
102
  "lint-cpp": "cpplint --quiet src/*.h src/*.cc",
103
103
  "lint-js": "biome lint",
104
104
  "lint-publish": "publint --strict",
105
+ "lint-spell": "cspell --config ./test/spell/cspell.jsonc --no-progress .",
105
106
  "lint-types": "tsd --files ./test/types/sharp.test-d.{cts,mts}",
106
107
  "test-leak": "./test/leak/leak.sh",
107
108
  "test-unit": "node --experimental-test-coverage test/unit.mjs",
@@ -163,10 +164,10 @@
163
164
  "semver": "^7.8.5"
164
165
  },
165
166
  "optionalDependencies": {
166
- "@revizly/sharp-libvips-linux-arm64": "1.0.54",
167
- "@revizly/sharp-libvips-linux-x64": "1.0.54",
168
- "@revizly/sharp-linux-arm64": "0.35.0-revizly54",
169
- "@revizly/sharp-linux-x64": "0.35.0-revizly54"
167
+ "@revizly/sharp-libvips-linux-arm64": "1.0.56",
168
+ "@revizly/sharp-libvips-linux-x64": "1.0.56",
169
+ "@revizly/sharp-linux-arm64": "0.35.0-revizly56",
170
+ "@revizly/sharp-linux-x64": "0.35.0-revizly56"
170
171
  },
171
172
  "peerDependenciesMeta": {
172
173
  "@types/node": {
@@ -174,17 +175,18 @@
174
175
  }
175
176
  },
176
177
  "devDependencies": {
177
- "@biomejs/biome": "^2.5.14",
178
+ "@biomejs/biome": "^2.5.15",
178
179
  "@cpplint/cli": "^0.1.0",
179
180
  "@emnapi/runtime": "^1.11.3",
180
- "@revizly/sharp-libvips-dev": "1.0.54",
181
+ "@revizly/sharp-libvips-dev": "1.0.56",
181
182
  "@types/node": "*",
183
+ "cspell": "^10.4.0",
182
184
  "emnapi": "^1.11.3",
183
185
  "exif-reader": "^2.0.3",
184
186
  "icc": "^4.0.0",
185
187
  "node-addon-api": "^8.9.2",
186
188
  "node-gyp": "^12.4.0",
187
- "publint": "^0.3.24",
189
+ "publint": "^0.3.25",
188
190
  "tar-fs": "^3.1.3",
189
191
  "tsd": "^0.33.0",
190
192
  "yauzl": "^3.4.0"
package/src/common.cc CHANGED
@@ -198,7 +198,7 @@ namespace sharp {
198
198
  }
199
199
  descriptor->limitInputPixels = static_cast<uint64_t>(AttrAsInt64(input, "limitInputPixels"));
200
200
  descriptor->limitInputChannels = static_cast<uint64_t>(AttrAsInt64(input, "limitInputChannels"));
201
- if (HasAttr(input, "access")) {
201
+ if (HasAttr(input, "sequentialRead")) {
202
202
  descriptor->access = AttrAsBool(input, "sequentialRead") ? VIPS_ACCESS_SEQUENTIAL : VIPS_ACCESS_RANDOM;
203
203
  }
204
204
  // Remove safety features and allow unlimited input
package/src/operations.cc CHANGED
@@ -97,7 +97,7 @@ namespace sharp {
97
97
  }
98
98
 
99
99
  /*
100
- * Contrast limiting adapative histogram equalization (CLAHE)
100
+ * Contrast limiting adaptive histogram equalization (CLAHE)
101
101
  */
102
102
  VImage Clahe(VImage image, int const width, int const height, int const maxSlope) {
103
103
  return image.hist_local(width, height, VImage::option()->set("max_slope", maxSlope));
package/src/operations.h CHANGED
@@ -28,7 +28,7 @@ namespace sharp {
28
28
  VImage Normalise(VImage image, int const lower, int const upper);
29
29
 
30
30
  /*
31
- * Contrast limiting adapative histogram equalization (CLAHE)
31
+ * Contrast limiting adaptive histogram equalization (CLAHE)
32
32
  */
33
33
  VImage Clahe(VImage image, int const width, int const height, int const maxSlope);
34
34
 
package/src/pipeline.cc CHANGED
@@ -40,6 +40,7 @@ class PipelineWorker : public Napi::AsyncWorker {
40
40
  // Increment processing task counter
41
41
  sharp::counterProcess++;
42
42
 
43
+ std::pair<char*, size_t> inputProfile(nullptr, 0);
43
44
  try {
44
45
  // Open input
45
46
  vips::VImage image;
@@ -269,7 +270,12 @@ class PipelineWorker : public Napi::AsyncWorker {
269
270
  if (baton->input->buffer != nullptr) {
270
271
  // Reload JPEG buffer
271
272
  VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);
272
- image = VImage::jpegload_buffer(blob, option);
273
+ try {
274
+ image = VImage::jpegload_buffer(blob, option);
275
+ } catch (...) {
276
+ vips_area_unref(reinterpret_cast<VipsArea*>(blob));
277
+ throw;
278
+ }
273
279
  vips_area_unref(reinterpret_cast<VipsArea*>(blob));
274
280
  } else {
275
281
  // Reload JPEG file
@@ -281,7 +287,12 @@ class PipelineWorker : public Napi::AsyncWorker {
281
287
  if (baton->input->buffer != nullptr) {
282
288
  // Reload WebP buffer
283
289
  VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);
284
- image = VImage::webpload_buffer(blob, option);
290
+ try {
291
+ image = VImage::webpload_buffer(blob, option);
292
+ } catch (...) {
293
+ vips_area_unref(reinterpret_cast<VipsArea*>(blob));
294
+ throw;
295
+ }
285
296
  vips_area_unref(reinterpret_cast<VipsArea*>(blob));
286
297
  } else {
287
298
  // Reload WebP file
@@ -291,7 +302,12 @@ class PipelineWorker : public Napi::AsyncWorker {
291
302
  if (baton->input->buffer != nullptr) {
292
303
  // Reload SVG buffer
293
304
  VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);
294
- image = VImage::svgload_buffer(blob, option);
305
+ try {
306
+ image = VImage::svgload_buffer(blob, option);
307
+ } catch (...) {
308
+ vips_area_unref(reinterpret_cast<VipsArea*>(blob));
309
+ throw;
310
+ }
295
311
  vips_area_unref(reinterpret_cast<VipsArea*>(blob));
296
312
  } else {
297
313
  // Reload SVG file
@@ -305,7 +321,12 @@ class PipelineWorker : public Napi::AsyncWorker {
305
321
  if (baton->input->buffer != nullptr) {
306
322
  // Reload PDF buffer
307
323
  VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);
308
- image = VImage::pdfload_buffer(blob, option);
324
+ try {
325
+ image = VImage::pdfload_buffer(blob, option);
326
+ } catch (...) {
327
+ vips_area_unref(reinterpret_cast<VipsArea*>(blob));
328
+ throw;
329
+ }
309
330
  vips_area_unref(reinterpret_cast<VipsArea*>(blob));
310
331
  } else {
311
332
  // Reload PDF file
@@ -325,7 +346,7 @@ class PipelineWorker : public Napi::AsyncWorker {
325
346
  int gainMapScaleFactor = 1;
326
347
  if (sharp::HasGainMap(image)) {
327
348
  if (baton->keepGainMap) {
328
- gainMap = image.gainmap();
349
+ gainMap = image.gainmap().copy_memory();
329
350
  if (image.get_typeof("gainmap-scale-factor") == G_TYPE_INT) {
330
351
  gainMapScaleFactor = image.get_int("gainmap-scale-factor");
331
352
  }
@@ -378,7 +399,6 @@ class PipelineWorker : public Napi::AsyncWorker {
378
399
  }
379
400
 
380
401
  // Ensure we're using a device-independent colour space
381
- std::pair<char*, size_t> inputProfile(nullptr, 0);
382
402
  if ((baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) && baton->withIccProfile.empty()) {
383
403
  // Cache input profile for use with output
384
404
  inputProfile = sharp::GetProfile(image);
@@ -481,14 +501,14 @@ class PipelineWorker : public Napi::AsyncWorker {
481
501
  }
482
502
  image = image.rot(autoRotation);
483
503
  if (baton->keepGainMap) {
484
- gainMap = sharp::StaySequential(gainMap).rot(autoRotation);
504
+ gainMap = gainMap.rot(autoRotation);
485
505
  }
486
506
  }
487
507
  // Mirror vertically (up-down) about the x-axis
488
508
  if (baton->flip) {
489
509
  image = image.flip(VIPS_DIRECTION_VERTICAL);
490
510
  if (baton->keepGainMap) {
491
- gainMap = sharp::StaySequential(gainMap).flip(VIPS_DIRECTION_VERTICAL);
511
+ gainMap = gainMap.flip(VIPS_DIRECTION_VERTICAL);
492
512
  }
493
513
  }
494
514
  // Mirror horizontally (left-right) about the y-axis
@@ -505,7 +525,7 @@ class PipelineWorker : public Napi::AsyncWorker {
505
525
  }
506
526
  image = image.rot(rotation);
507
527
  if (baton->keepGainMap) {
508
- gainMap = sharp::StaySequential(gainMap).rot(rotation);
528
+ gainMap = gainMap.rot(rotation);
509
529
  }
510
530
  }
511
531
 
@@ -931,11 +951,8 @@ class PipelineWorker : public Napi::AsyncWorker {
931
951
  image = image.colourspace(baton->colourspace, VImage::option()->set("source_space", image.interpretation()));
932
952
  if (inputProfile.first != nullptr && baton->withIccProfile.empty()) {
933
953
  image = sharp::SetProfile(image, inputProfile);
934
- } else {
935
- g_free(inputProfile.first);
954
+ inputProfile.first = nullptr;
936
955
  }
937
- } else {
938
- g_free(inputProfile.first);
939
956
  }
940
957
 
941
958
  // Extract channel
@@ -945,10 +962,9 @@ class PipelineWorker : public Napi::AsyncWorker {
945
962
  if (baton->extractChannel == 3 && image.has_alpha()) {
946
963
  baton->extractChannel = image.bands() - 1;
947
964
  } else {
948
- (baton->err)
949
- .append("Cannot extract channel ").append(std::to_string(baton->extractChannel))
950
- .append(" from image with channels 0-").append(std::to_string(image.bands() - 1));
951
- return Error();
965
+ throw std::runtime_error(
966
+ std::string("Cannot extract channel ").append(std::to_string(baton->extractChannel))
967
+ .append(" from image with channels 0-").append(std::to_string(image.bands() - 1)));
952
968
  }
953
969
  }
954
970
  VipsInterpretation colourspace = sharp::Is16Bit(image.interpretation())
@@ -1444,6 +1460,8 @@ class PipelineWorker : public Napi::AsyncWorker {
1444
1460
  }
1445
1461
  }
1446
1462
  }
1463
+ g_free(inputProfile.first);
1464
+
1447
1465
  // Clean up libvips' per-request data and threads
1448
1466
  vips_error_clear();
1449
1467
  vips_thread_shutdown();
@@ -1869,9 +1887,9 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1869
1887
  baton->convKernelOffset = sharp::AttrAsDouble(kernel, "offset");
1870
1888
  size_t const kernelSize = static_cast<size_t>(baton->convKernelWidth * baton->convKernelHeight);
1871
1889
  baton->convKernel.resize(kernelSize);
1872
- Napi::Array kdata = kernel.Get("kernel").As<Napi::Array>();
1890
+ Napi::Array kernelData = kernel.Get("kernel").As<Napi::Array>();
1873
1891
  for (unsigned int i = 0; i < kernelSize; i++) {
1874
- baton->convKernel[i] = sharp::AttrAsDouble(kdata, i);
1892
+ baton->convKernel[i] = sharp::AttrAsDouble(kernelData, i);
1875
1893
  }
1876
1894
  }
1877
1895
  if (options.Has("recombMatrix")) {
package/src/stats.cc CHANGED
@@ -60,7 +60,7 @@ class StatsWorker : public Napi::AsyncWorker {
60
60
  static_cast<int>(stats.getpoint(STAT_MAXY_INDEX, b).front()));
61
61
  baton->channelStats.push_back(cStats);
62
62
  }
63
- // Image is not opaque when alpha layer is present and contains a non-mamixa value
63
+ // Image is not opaque when alpha layer is present and contains a non-maxima value
64
64
  if (image.has_alpha()) {
65
65
  double const minAlpha = static_cast<double>(stats.getpoint(STAT_MIN_INDEX, bands).front());
66
66
  if (minAlpha != vips_interpretation_max_alpha(image.interpretation())) {