sharp 0.29.3 → 0.30.2
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 +5 -5
- package/install/libvips.js +39 -8
- package/lib/composite.js +0 -1
- package/lib/constructor.js +10 -3
- package/lib/input.js +21 -4
- package/lib/libvips.js +24 -5
- package/lib/operation.js +14 -1
- package/lib/output.js +129 -69
- package/lib/platform.js +1 -1
- package/lib/resize.js +19 -0
- package/lib/sharp.js +2 -1
- package/lib/utility.js +22 -4
- package/package.json +27 -12
- package/src/common.cc +102 -19
- package/src/common.h +29 -5
- package/src/libvips/cplusplus/VImage.cpp +34 -16
- package/src/libvips/cplusplus/vips-operators.cpp +29 -1
- package/src/metadata.cc +6 -0
- package/src/metadata.h +1 -0
- package/src/operations.cc +94 -0
- package/src/operations.h +12 -0
- package/src/pipeline.cc +296 -270
- package/src/pipeline.h +17 -19
package/lib/output.js
CHANGED
|
@@ -22,14 +22,15 @@ const formats = new Map([
|
|
|
22
22
|
['j2c', 'jp2']
|
|
23
23
|
]);
|
|
24
24
|
|
|
25
|
-
const errMagickSave = new Error('GIF output requires libvips with support for ImageMagick');
|
|
26
25
|
const errJp2Save = new Error('JP2 output requires libvips with support for OpenJPEG');
|
|
27
26
|
|
|
27
|
+
const bitdepthFromColourCount = (colours) => 1 << 31 - Math.clz32(Math.ceil(Math.log2(colours)));
|
|
28
|
+
|
|
28
29
|
/**
|
|
29
30
|
* Write output image data to a file.
|
|
30
31
|
*
|
|
31
32
|
* If an explicit output format is not selected, it will be inferred from the extension,
|
|
32
|
-
* with JPEG, PNG, WebP, AVIF, TIFF, DZI, and libvips' V format supported.
|
|
33
|
+
* with JPEG, PNG, WebP, AVIF, TIFF, GIF, DZI, and libvips' V format supported.
|
|
33
34
|
* Note that raw pixel data is only supported for buffer output.
|
|
34
35
|
*
|
|
35
36
|
* By default all metadata will be removed, which includes EXIF-based orientation.
|
|
@@ -63,8 +64,6 @@ function toFile (fileOut, callback) {
|
|
|
63
64
|
err = new Error('Missing output file path');
|
|
64
65
|
} else if (is.string(this.options.input.file) && path.resolve(this.options.input.file) === path.resolve(fileOut)) {
|
|
65
66
|
err = new Error('Cannot use same file for input and output');
|
|
66
|
-
} else if (this.options.formatOut === 'input' && fileOut.toLowerCase().endsWith('.gif') && !this.constructor.format.magick.output.file) {
|
|
67
|
-
err = errMagickSave;
|
|
68
67
|
}
|
|
69
68
|
if (err) {
|
|
70
69
|
if (is.fn(callback)) {
|
|
@@ -81,9 +80,9 @@ function toFile (fileOut, callback) {
|
|
|
81
80
|
|
|
82
81
|
/**
|
|
83
82
|
* Write output to a Buffer.
|
|
84
|
-
* JPEG, PNG, WebP, AVIF, TIFF and raw pixel data output are supported.
|
|
83
|
+
* JPEG, PNG, WebP, AVIF, TIFF, GIF and raw pixel data output are supported.
|
|
85
84
|
*
|
|
86
|
-
* If no explicit format is set, the output format will match the input image, except
|
|
85
|
+
* If no explicit format is set, the output format will match the input image, except SVG input which becomes PNG output.
|
|
87
86
|
*
|
|
88
87
|
* By default all metadata will be removed, which includes EXIF-based orientation.
|
|
89
88
|
* See {@link withMetadata} for control over this.
|
|
@@ -140,6 +139,7 @@ function toBuffer (options, callback) {
|
|
|
140
139
|
} else if (this.options.resolveWithObject) {
|
|
141
140
|
this.options.resolveWithObject = false;
|
|
142
141
|
}
|
|
142
|
+
this.options.fileOut = '';
|
|
143
143
|
return this._pipeline(is.fn(options) ? options : callback);
|
|
144
144
|
}
|
|
145
145
|
|
|
@@ -169,7 +169,7 @@ function toBuffer (options, callback) {
|
|
|
169
169
|
* })
|
|
170
170
|
* .toBuffer();
|
|
171
171
|
*
|
|
172
|
-
*
|
|
172
|
+
* @example
|
|
173
173
|
* // Set output metadata to 96 DPI
|
|
174
174
|
* const data = await sharp(input)
|
|
175
175
|
* .withMetadata({ density: 96 })
|
|
@@ -374,6 +374,7 @@ function jpeg (options) {
|
|
|
374
374
|
* @param {boolean} [options.adaptiveFiltering=false] - use adaptive row filtering
|
|
375
375
|
* @param {boolean} [options.palette=false] - quantise to a palette-based image with alpha transparency support
|
|
376
376
|
* @param {number} [options.quality=100] - use the lowest number of colours needed to achieve given quality, sets `palette` to `true`
|
|
377
|
+
* @param {number} [options.effort=7] - CPU effort, between 1 (fastest) and 10 (slowest), sets `palette` to `true`
|
|
377
378
|
* @param {number} [options.colours=256] - maximum number of palette entries, sets `palette` to `true`
|
|
378
379
|
* @param {number} [options.colors=256] - alternative spelling of `options.colours`, sets `palette` to `true`
|
|
379
380
|
* @param {number} [options.dither=1.0] - level of Floyd-Steinberg error diffusion, sets `palette` to `true`
|
|
@@ -398,7 +399,7 @@ function png (options) {
|
|
|
398
399
|
}
|
|
399
400
|
if (is.defined(options.palette)) {
|
|
400
401
|
this._setBooleanOption('pngPalette', options.palette);
|
|
401
|
-
} else if (
|
|
402
|
+
} else if ([options.quality, options.effort, options.colours, options.colors, options.dither].some(is.defined)) {
|
|
402
403
|
this._setBooleanOption('pngPalette', true);
|
|
403
404
|
}
|
|
404
405
|
if (this.options.pngPalette) {
|
|
@@ -409,10 +410,17 @@ function png (options) {
|
|
|
409
410
|
throw is.invalidParameterError('quality', 'integer between 0 and 100', options.quality);
|
|
410
411
|
}
|
|
411
412
|
}
|
|
413
|
+
if (is.defined(options.effort)) {
|
|
414
|
+
if (is.integer(options.effort) && is.inRange(options.effort, 1, 10)) {
|
|
415
|
+
this.options.pngEffort = options.effort;
|
|
416
|
+
} else {
|
|
417
|
+
throw is.invalidParameterError('effort', 'integer between 1 and 10', options.effort);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
412
420
|
const colours = options.colours || options.colors;
|
|
413
421
|
if (is.defined(colours)) {
|
|
414
422
|
if (is.integer(colours) && is.inRange(colours, 2, 256)) {
|
|
415
|
-
this.options.pngBitdepth =
|
|
423
|
+
this.options.pngBitdepth = bitdepthFromColourCount(colours);
|
|
416
424
|
} else {
|
|
417
425
|
throw is.invalidParameterError('colours', 'integer between 2 and 256', colours);
|
|
418
426
|
}
|
|
@@ -441,7 +449,7 @@ function png (options) {
|
|
|
441
449
|
* @example
|
|
442
450
|
* // Optimise the file size of an animated WebP
|
|
443
451
|
* const outputWebp = await sharp(inputWebp, { animated: true })
|
|
444
|
-
* .webp({
|
|
452
|
+
* .webp({ effort: 6 })
|
|
445
453
|
* .toBuffer();
|
|
446
454
|
*
|
|
447
455
|
* @param {Object} [options] - output options
|
|
@@ -450,69 +458,111 @@ function png (options) {
|
|
|
450
458
|
* @param {boolean} [options.lossless=false] - use lossless compression mode
|
|
451
459
|
* @param {boolean} [options.nearLossless=false] - use near_lossless compression mode
|
|
452
460
|
* @param {boolean} [options.smartSubsample=false] - use high quality chroma subsampling
|
|
453
|
-
* @param {number} [options.
|
|
454
|
-
* @param {number} [options.pageHeight] - page height for animated output
|
|
461
|
+
* @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 6 (slowest)
|
|
455
462
|
* @param {number} [options.loop=0] - number of animation iterations, use 0 for infinite animation
|
|
456
|
-
* @param {number[]} [options.delay] -
|
|
463
|
+
* @param {number|number[]} [options.delay] - delay(s) between animation frames (in milliseconds)
|
|
457
464
|
* @param {boolean} [options.force=true] - force WebP output, otherwise attempt to use input format
|
|
458
465
|
* @returns {Sharp}
|
|
459
466
|
* @throws {Error} Invalid options
|
|
460
467
|
*/
|
|
461
468
|
function webp (options) {
|
|
462
|
-
if (is.object(options)
|
|
463
|
-
if (is.
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
469
|
+
if (is.object(options)) {
|
|
470
|
+
if (is.defined(options.quality)) {
|
|
471
|
+
if (is.integer(options.quality) && is.inRange(options.quality, 1, 100)) {
|
|
472
|
+
this.options.webpQuality = options.quality;
|
|
473
|
+
} else {
|
|
474
|
+
throw is.invalidParameterError('quality', 'integer between 1 and 100', options.quality);
|
|
475
|
+
}
|
|
467
476
|
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
477
|
+
if (is.defined(options.alphaQuality)) {
|
|
478
|
+
if (is.integer(options.alphaQuality) && is.inRange(options.alphaQuality, 0, 100)) {
|
|
479
|
+
this.options.webpAlphaQuality = options.alphaQuality;
|
|
480
|
+
} else {
|
|
481
|
+
throw is.invalidParameterError('alphaQuality', 'integer between 0 and 100', options.alphaQuality);
|
|
482
|
+
}
|
|
474
483
|
}
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
484
|
+
if (is.defined(options.lossless)) {
|
|
485
|
+
this._setBooleanOption('webpLossless', options.lossless);
|
|
486
|
+
}
|
|
487
|
+
if (is.defined(options.nearLossless)) {
|
|
488
|
+
this._setBooleanOption('webpNearLossless', options.nearLossless);
|
|
489
|
+
}
|
|
490
|
+
if (is.defined(options.smartSubsample)) {
|
|
491
|
+
this._setBooleanOption('webpSmartSubsample', options.smartSubsample);
|
|
492
|
+
}
|
|
493
|
+
const effort = options.effort || options.reductionEffort;
|
|
494
|
+
if (is.defined(effort)) {
|
|
495
|
+
if (is.integer(effort) && is.inRange(effort, 0, 6)) {
|
|
496
|
+
this.options.webpEffort = effort;
|
|
497
|
+
} else {
|
|
498
|
+
throw is.invalidParameterError('effort', 'integer between 0 and 6', effort);
|
|
499
|
+
}
|
|
490
500
|
}
|
|
491
501
|
}
|
|
492
|
-
|
|
493
502
|
trySetAnimationOptions(options, this.options);
|
|
494
503
|
return this._updateFormatOut('webp', options);
|
|
495
504
|
}
|
|
496
505
|
|
|
497
506
|
/**
|
|
498
|
-
* Use these GIF options for output image.
|
|
507
|
+
* Use these GIF options for the output image.
|
|
499
508
|
*
|
|
500
|
-
*
|
|
501
|
-
*
|
|
502
|
-
*
|
|
509
|
+
* The first entry in the palette is reserved for transparency.
|
|
510
|
+
*
|
|
511
|
+
* @since 0.30.0
|
|
512
|
+
*
|
|
513
|
+
* @example
|
|
514
|
+
* // Convert PNG to GIF
|
|
515
|
+
* await sharp(pngBuffer)
|
|
516
|
+
* .gif()
|
|
517
|
+
* .toBuffer());
|
|
518
|
+
*
|
|
519
|
+
* @example
|
|
520
|
+
* // Convert animated WebP to animated GIF
|
|
521
|
+
* await sharp('animated.webp', { animated: true })
|
|
522
|
+
* .toFile('animated.gif');
|
|
523
|
+
*
|
|
524
|
+
* @example
|
|
525
|
+
* // Create a 128x128, cropped, non-dithered, animated thumbnail of an animated GIF
|
|
526
|
+
* const out = await sharp('in.gif', { animated: true })
|
|
527
|
+
* .resize({ width: 128, height: 128 })
|
|
528
|
+
* .gif({ dither: 0 })
|
|
529
|
+
* .toBuffer();
|
|
503
530
|
*
|
|
504
531
|
* @param {Object} [options] - output options
|
|
505
|
-
* @param {number} [options.
|
|
532
|
+
* @param {number} [options.colours=256] - maximum number of palette entries, including transparency, between 2 and 256
|
|
533
|
+
* @param {number} [options.colors=256] - alternative spelling of `options.colours`
|
|
534
|
+
* @param {number} [options.effort=7] - CPU effort, between 1 (fastest) and 10 (slowest)
|
|
535
|
+
* @param {number} [options.dither=1.0] - level of Floyd-Steinberg error diffusion, between 0 (least) and 1 (most)
|
|
506
536
|
* @param {number} [options.loop=0] - number of animation iterations, use 0 for infinite animation
|
|
507
|
-
* @param {number[]} [options.delay] -
|
|
537
|
+
* @param {number|number[]} [options.delay] - delay(s) between animation frames (in milliseconds)
|
|
508
538
|
* @param {boolean} [options.force=true] - force GIF output, otherwise attempt to use input format
|
|
509
539
|
* @returns {Sharp}
|
|
510
540
|
* @throws {Error} Invalid options
|
|
511
541
|
*/
|
|
512
|
-
/* istanbul ignore next */
|
|
513
542
|
function gif (options) {
|
|
514
|
-
if (
|
|
515
|
-
|
|
543
|
+
if (is.object(options)) {
|
|
544
|
+
const colours = options.colours || options.colors;
|
|
545
|
+
if (is.defined(colours)) {
|
|
546
|
+
if (is.integer(colours) && is.inRange(colours, 2, 256)) {
|
|
547
|
+
this.options.gifBitdepth = bitdepthFromColourCount(colours);
|
|
548
|
+
} else {
|
|
549
|
+
throw is.invalidParameterError('colours', 'integer between 2 and 256', colours);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
if (is.defined(options.effort)) {
|
|
553
|
+
if (is.number(options.effort) && is.inRange(options.effort, 1, 10)) {
|
|
554
|
+
this.options.gifEffort = options.effort;
|
|
555
|
+
} else {
|
|
556
|
+
throw is.invalidParameterError('effort', 'integer between 1 and 10', options.effort);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
if (is.defined(options.dither)) {
|
|
560
|
+
if (is.number(options.dither) && is.inRange(options.dither, 0, 1)) {
|
|
561
|
+
this.options.gifDither = options.dither;
|
|
562
|
+
} else {
|
|
563
|
+
throw is.invalidParameterError('dither', 'number between 0.0 and 1.0', options.dither);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
516
566
|
}
|
|
517
567
|
trySetAnimationOptions(options, this.options);
|
|
518
568
|
return this._updateFormatOut('gif', options);
|
|
@@ -601,20 +651,12 @@ function jp2 (options) {
|
|
|
601
651
|
* @private
|
|
602
652
|
*
|
|
603
653
|
* @param {Object} [source] - output options
|
|
604
|
-
* @param {number} [source.pageHeight] - page height for animated output
|
|
605
654
|
* @param {number} [source.loop=0] - number of animation iterations, use 0 for infinite animation
|
|
606
655
|
* @param {number[]} [source.delay] - list of delays between animation frames (in milliseconds)
|
|
607
656
|
* @param {Object} [target] - target object for valid options
|
|
608
657
|
* @throws {Error} Invalid options
|
|
609
658
|
*/
|
|
610
659
|
function trySetAnimationOptions (source, target) {
|
|
611
|
-
if (is.object(source) && is.defined(source.pageHeight)) {
|
|
612
|
-
if (is.integer(source.pageHeight) && source.pageHeight > 0) {
|
|
613
|
-
target.pageHeight = source.pageHeight;
|
|
614
|
-
} else {
|
|
615
|
-
throw is.invalidParameterError('pageHeight', 'integer larger than 0', source.pageHeight);
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
660
|
if (is.object(source) && is.defined(source.loop)) {
|
|
619
661
|
if (is.integer(source.loop) && is.inRange(source.loop, 0, 65535)) {
|
|
620
662
|
target.loop = source.loop;
|
|
@@ -623,13 +665,16 @@ function trySetAnimationOptions (source, target) {
|
|
|
623
665
|
}
|
|
624
666
|
}
|
|
625
667
|
if (is.object(source) && is.defined(source.delay)) {
|
|
626
|
-
|
|
668
|
+
// We allow singular values as well
|
|
669
|
+
if (is.integer(source.delay) && is.inRange(source.delay, 0, 65535)) {
|
|
670
|
+
target.delay = [source.delay];
|
|
671
|
+
} else if (
|
|
627
672
|
Array.isArray(source.delay) &&
|
|
628
673
|
source.delay.every(is.integer) &&
|
|
629
674
|
source.delay.every(v => is.inRange(v, 0, 65535))) {
|
|
630
675
|
target.delay = source.delay;
|
|
631
676
|
} else {
|
|
632
|
-
throw is.invalidParameterError('delay', 'array of integers between 0 and 65535', source.delay);
|
|
677
|
+
throw is.invalidParameterError('delay', 'integer or an array of integers between 0 and 65535', source.delay);
|
|
633
678
|
}
|
|
634
679
|
}
|
|
635
680
|
}
|
|
@@ -660,6 +705,7 @@ function trySetAnimationOptions (source, target) {
|
|
|
660
705
|
* @param {number} [options.tileHeight=256] - vertical tile size
|
|
661
706
|
* @param {number} [options.xres=1.0] - horizontal resolution in pixels/mm
|
|
662
707
|
* @param {number} [options.yres=1.0] - vertical resolution in pixels/mm
|
|
708
|
+
* @param {string} [options.resolutionUnit='inch'] - resolution unit options: inch, cm
|
|
663
709
|
* @param {number} [options.bitdepth=8] - reduce bitdepth to 1, 2 or 4 bit
|
|
664
710
|
* @returns {Sharp}
|
|
665
711
|
* @throws {Error} Invalid options
|
|
@@ -733,6 +779,14 @@ function tiff (options) {
|
|
|
733
779
|
throw is.invalidParameterError('predictor', 'one of: none, horizontal, float', options.predictor);
|
|
734
780
|
}
|
|
735
781
|
}
|
|
782
|
+
// resolutionUnit
|
|
783
|
+
if (is.defined(options.resolutionUnit)) {
|
|
784
|
+
if (is.string(options.resolutionUnit) && is.inArray(options.resolutionUnit, ['inch', 'cm'])) {
|
|
785
|
+
this.options.tiffResolutionUnit = options.resolutionUnit;
|
|
786
|
+
} else {
|
|
787
|
+
throw is.invalidParameterError('resolutionUnit', 'one of: inch, cm', options.resolutionUnit);
|
|
788
|
+
}
|
|
789
|
+
}
|
|
736
790
|
}
|
|
737
791
|
return this._updateFormatOut('tiff', options);
|
|
738
792
|
}
|
|
@@ -750,7 +804,7 @@ function tiff (options) {
|
|
|
750
804
|
* @param {Object} [options] - output options
|
|
751
805
|
* @param {number} [options.quality=50] - quality, integer 1-100
|
|
752
806
|
* @param {boolean} [options.lossless=false] - use lossless compression
|
|
753
|
-
* @param {number} [options.
|
|
807
|
+
* @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 9 (slowest)
|
|
754
808
|
* @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
|
|
755
809
|
* @returns {Sharp}
|
|
756
810
|
* @throws {Error} Invalid options
|
|
@@ -771,7 +825,7 @@ function avif (options) {
|
|
|
771
825
|
* @param {number} [options.quality=50] - quality, integer 1-100
|
|
772
826
|
* @param {string} [options.compression='av1'] - compression format: av1, hevc
|
|
773
827
|
* @param {boolean} [options.lossless=false] - use lossless compression
|
|
774
|
-
* @param {number} [options.
|
|
828
|
+
* @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 9 (slowest)
|
|
775
829
|
* @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
|
|
776
830
|
* @returns {Sharp}
|
|
777
831
|
* @throws {Error} Invalid options
|
|
@@ -799,9 +853,15 @@ function heif (options) {
|
|
|
799
853
|
throw is.invalidParameterError('compression', 'one of: av1, hevc', options.compression);
|
|
800
854
|
}
|
|
801
855
|
}
|
|
802
|
-
if (is.defined(options.
|
|
856
|
+
if (is.defined(options.effort)) {
|
|
857
|
+
if (is.integer(options.effort) && is.inRange(options.effort, 0, 9)) {
|
|
858
|
+
this.options.heifEffort = options.effort;
|
|
859
|
+
} else {
|
|
860
|
+
throw is.invalidParameterError('effort', 'integer between 0 and 9', options.effort);
|
|
861
|
+
}
|
|
862
|
+
} else if (is.defined(options.speed)) {
|
|
803
863
|
if (is.integer(options.speed) && is.inRange(options.speed, 0, 9)) {
|
|
804
|
-
this.options.
|
|
864
|
+
this.options.heifEffort = 9 - options.speed;
|
|
805
865
|
} else {
|
|
806
866
|
throw is.invalidParameterError('speed', 'integer between 0 and 9', options.speed);
|
|
807
867
|
}
|
|
@@ -861,8 +921,6 @@ function raw (options) {
|
|
|
861
921
|
* Set the format and options for tile images via the `toFormat`, `jpeg`, `png` or `webp` functions.
|
|
862
922
|
* Use a `.zip` or `.szi` file extension with `toFile` to write to a compressed archive file format.
|
|
863
923
|
*
|
|
864
|
-
* Warning: multiple sharp instances concurrently producing tile output can expose a possible race condition in some versions of libgsf.
|
|
865
|
-
*
|
|
866
924
|
* @example
|
|
867
925
|
* sharp('input.tiff')
|
|
868
926
|
* .png()
|
|
@@ -882,10 +940,10 @@ function raw (options) {
|
|
|
882
940
|
* @param {string} [options.depth] how deep to make the pyramid, possible values are `onepixel`, `onetile` or `one`, default based on layout.
|
|
883
941
|
* @param {number} [options.skipBlanks=-1] threshold to skip tile generation, a value 0 - 255 for 8-bit images or 0 - 65535 for 16-bit images
|
|
884
942
|
* @param {string} [options.container='fs'] tile container, with value `fs` (filesystem) or `zip` (compressed file).
|
|
885
|
-
* @param {string} [options.layout='dz'] filesystem layout, possible values are `dz`, `iiif`, `zoomify` or `google`.
|
|
943
|
+
* @param {string} [options.layout='dz'] filesystem layout, possible values are `dz`, `iiif`, `iiif3`, `zoomify` or `google`.
|
|
886
944
|
* @param {boolean} [options.centre=false] centre image in tile.
|
|
887
945
|
* @param {boolean} [options.center=false] alternative spelling of centre.
|
|
888
|
-
* @param {string} [options.id='https://example.com/iiif'] when `layout` is `iiif`, sets the `@id` attribute of `info.json`
|
|
946
|
+
* @param {string} [options.id='https://example.com/iiif'] when `layout` is `iiif`/`iiif3`, sets the `@id`/`id` attribute of `info.json`
|
|
889
947
|
* @returns {Sharp}
|
|
890
948
|
* @throws {Error} Invalid parameters
|
|
891
949
|
*/
|
|
@@ -920,10 +978,10 @@ function tile (options) {
|
|
|
920
978
|
}
|
|
921
979
|
// Layout
|
|
922
980
|
if (is.defined(options.layout)) {
|
|
923
|
-
if (is.string(options.layout) && is.inArray(options.layout, ['dz', 'google', 'iiif', 'zoomify'])) {
|
|
981
|
+
if (is.string(options.layout) && is.inArray(options.layout, ['dz', 'google', 'iiif', 'iiif3', 'zoomify'])) {
|
|
924
982
|
this.options.tileLayout = options.layout;
|
|
925
983
|
} else {
|
|
926
|
-
throw is.invalidParameterError('layout', 'one of: dz, google, iiif, zoomify', options.layout);
|
|
984
|
+
throw is.invalidParameterError('layout', 'one of: dz, google, iiif, iiif3, zoomify', options.layout);
|
|
927
985
|
}
|
|
928
986
|
}
|
|
929
987
|
// Angle of rotation,
|
|
@@ -1078,6 +1136,7 @@ function _pipeline (callback) {
|
|
|
1078
1136
|
this.push(data);
|
|
1079
1137
|
}
|
|
1080
1138
|
this.push(null);
|
|
1139
|
+
this.emit('close');
|
|
1081
1140
|
});
|
|
1082
1141
|
});
|
|
1083
1142
|
if (this.streamInFinished) {
|
|
@@ -1093,6 +1152,7 @@ function _pipeline (callback) {
|
|
|
1093
1152
|
this.push(data);
|
|
1094
1153
|
}
|
|
1095
1154
|
this.push(null);
|
|
1155
|
+
this.emit('close');
|
|
1096
1156
|
});
|
|
1097
1157
|
}
|
|
1098
1158
|
return this;
|
package/lib/platform.js
CHANGED
|
@@ -8,7 +8,7 @@ module.exports = function () {
|
|
|
8
8
|
const arch = env.npm_config_arch || process.arch;
|
|
9
9
|
const platform = env.npm_config_platform || process.platform;
|
|
10
10
|
/* istanbul ignore next */
|
|
11
|
-
const libc = (platform === 'linux' && detectLibc.
|
|
11
|
+
const libc = (platform === 'linux' && detectLibc.isNonGlibcLinuxSync()) ? detectLibc.familySync() : '';
|
|
12
12
|
|
|
13
13
|
const platformId = [`${platform}${libc}`];
|
|
14
14
|
|
package/lib/resize.js
CHANGED
|
@@ -183,6 +183,20 @@ function isRotationExpected (options) {
|
|
|
183
183
|
* });
|
|
184
184
|
*
|
|
185
185
|
* @example
|
|
186
|
+
* sharp(input)
|
|
187
|
+
* .resize(200, 200, {
|
|
188
|
+
* fit: sharp.fit.outside,
|
|
189
|
+
* withoutReduction: true
|
|
190
|
+
* })
|
|
191
|
+
* .toFormat('jpeg')
|
|
192
|
+
* .toBuffer()
|
|
193
|
+
* .then(function(outputBuffer) {
|
|
194
|
+
* // outputBuffer contains JPEG image data
|
|
195
|
+
* // of at least 200 pixels wide and 200 pixels high while maintaining aspect ratio
|
|
196
|
+
* // and no smaller than the input image
|
|
197
|
+
* });
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
186
200
|
* const scaleByHalf = await sharp(input)
|
|
187
201
|
* .metadata()
|
|
188
202
|
* .then(({ width }) => sharp(input)
|
|
@@ -200,6 +214,7 @@ function isRotationExpected (options) {
|
|
|
200
214
|
* @param {String|Object} [options.background={r: 0, g: 0, b: 0, alpha: 1}] - background colour when using a `fit` of `contain`, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to black without transparency.
|
|
201
215
|
* @param {String} [options.kernel='lanczos3'] - the kernel to use for image reduction.
|
|
202
216
|
* @param {Boolean} [options.withoutEnlargement=false] - do not enlarge if the width *or* height are already less than the specified dimensions, equivalent to GraphicsMagick's `>` geometry option.
|
|
217
|
+
* @param {Boolean} [options.withoutReduction=false] - do not reduce if the width *or* height are already greater than the specified dimensions, equivalent to GraphicsMagick's `<` geometry option.
|
|
203
218
|
* @param {Boolean} [options.fastShrinkOnLoad=true] - take greater advantage of the JPEG and WebP shrink-on-load feature, which can lead to a slight moiré pattern on some images.
|
|
204
219
|
* @returns {Sharp}
|
|
205
220
|
* @throws {Error} Invalid parameters
|
|
@@ -276,6 +291,10 @@ function resize (width, height, options) {
|
|
|
276
291
|
if (is.defined(options.withoutEnlargement)) {
|
|
277
292
|
this._setBooleanOption('withoutEnlargement', options.withoutEnlargement);
|
|
278
293
|
}
|
|
294
|
+
// Without reduction
|
|
295
|
+
if (is.defined(options.withoutReduction)) {
|
|
296
|
+
this._setBooleanOption('withoutReduction', options.withoutReduction);
|
|
297
|
+
}
|
|
279
298
|
// Shrink on load
|
|
280
299
|
if (is.defined(options.fastShrinkOnLoad)) {
|
|
281
300
|
this._setBooleanOption('fastShrinkOnLoad', options.fastShrinkOnLoad);
|
package/lib/sharp.js
CHANGED
|
@@ -11,9 +11,10 @@ try {
|
|
|
11
11
|
if (/dylib/.test(err.message) && /Incompatible library version/.test(err.message)) {
|
|
12
12
|
help.push('- Update Homebrew: "brew update && brew upgrade vips"');
|
|
13
13
|
} else {
|
|
14
|
+
const [platform, arch] = platformAndArch.split('-');
|
|
14
15
|
help.push(
|
|
15
16
|
'- Install with the --verbose flag and look for errors: "npm install --ignore-scripts=false --verbose sharp"',
|
|
16
|
-
`- Install for the current runtime: "npm install --platform=${
|
|
17
|
+
`- Install for the current ${platformAndArch} runtime: "npm install --platform=${platform} --arch=${arch} sharp"`
|
|
17
18
|
);
|
|
18
19
|
}
|
|
19
20
|
help.push(
|
package/lib/utility.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
3
5
|
const events = require('events');
|
|
4
6
|
const detectLibc = require('detect-libc');
|
|
5
7
|
|
|
@@ -28,11 +30,11 @@ const interpolators = {
|
|
|
28
30
|
bilinear: 'bilinear',
|
|
29
31
|
/** [Bicubic interpolation](http://en.wikipedia.org/wiki/Bicubic_interpolation) (the default). */
|
|
30
32
|
bicubic: 'bicubic',
|
|
31
|
-
/** [LBB interpolation](https://github.com/
|
|
33
|
+
/** [LBB interpolation](https://github.com/libvips/libvips/blob/master/libvips/resample/lbb.cpp#L100). Prevents some "[acutance](http://en.wikipedia.org/wiki/Acutance)" but typically reduces performance by a factor of 2. */
|
|
32
34
|
locallyBoundedBicubic: 'lbb',
|
|
33
35
|
/** [Nohalo interpolation](http://eprints.soton.ac.uk/268086/). Prevents acutance but typically reduces performance by a factor of 3. */
|
|
34
36
|
nohalo: 'nohalo',
|
|
35
|
-
/** [VSQBS interpolation](https://github.com/
|
|
37
|
+
/** [VSQBS interpolation](https://github.com/libvips/libvips/blob/master/libvips/resample/vsqbs.cpp#L48). Prevents "staircasing" when enlarging. */
|
|
36
38
|
vertexSplitQuadraticBasisSpline: 'vsqbs'
|
|
37
39
|
};
|
|
38
40
|
|
|
@@ -47,7 +49,22 @@ let versions = {
|
|
|
47
49
|
};
|
|
48
50
|
try {
|
|
49
51
|
versions = require(`../vendor/${versions.vips}/${platformAndArch}/versions.json`);
|
|
50
|
-
} catch (
|
|
52
|
+
} catch (_err) { /* ignore */ }
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* An Object containing the platform and architecture
|
|
56
|
+
* of the current and installed vendored binaries.
|
|
57
|
+
* @member
|
|
58
|
+
* @example
|
|
59
|
+
* console.log(sharp.vendor);
|
|
60
|
+
*/
|
|
61
|
+
const vendor = {
|
|
62
|
+
current: platformAndArch,
|
|
63
|
+
installed: []
|
|
64
|
+
};
|
|
65
|
+
try {
|
|
66
|
+
vendor.installed = fs.readdirSync(path.join(__dirname, `../vendor/${versions.vips}`));
|
|
67
|
+
} catch (_err) { /* ignore */ }
|
|
51
68
|
|
|
52
69
|
/**
|
|
53
70
|
* Gets or, when options are provided, sets the limits of _libvips'_ operation cache.
|
|
@@ -111,7 +128,7 @@ function concurrency (concurrency) {
|
|
|
111
128
|
return sharp.concurrency(is.integer(concurrency) ? concurrency : null);
|
|
112
129
|
}
|
|
113
130
|
/* istanbul ignore next */
|
|
114
|
-
if (detectLibc.
|
|
131
|
+
if (detectLibc.familySync() === detectLibc.GLIBC && !sharp._isUsingJemalloc()) {
|
|
115
132
|
// Reduce default concurrency to 1 when using glibc memory allocator
|
|
116
133
|
sharp.concurrency(1);
|
|
117
134
|
}
|
|
@@ -176,5 +193,6 @@ module.exports = function (Sharp) {
|
|
|
176
193
|
Sharp.format = format;
|
|
177
194
|
Sharp.interpolators = interpolators;
|
|
178
195
|
Sharp.versions = versions;
|
|
196
|
+
Sharp.vendor = vendor;
|
|
179
197
|
Sharp.queue = queue;
|
|
180
198
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sharp",
|
|
3
|
-
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, AVIF and TIFF images",
|
|
4
|
-
"version": "0.
|
|
3
|
+
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, GIF, AVIF and TIFF images",
|
|
4
|
+
"version": "0.30.2",
|
|
5
5
|
"author": "Lovell Fuller <npm@lovell.info>",
|
|
6
6
|
"homepage": "https://github.com/lovell/sharp",
|
|
7
7
|
"contributors": [
|
|
@@ -79,7 +79,9 @@
|
|
|
79
79
|
"Michael Nutt <michael@nutt.im>",
|
|
80
80
|
"Brad Parham <baparham@gmail.com>",
|
|
81
81
|
"Taneli Vatanen <taneli.vatanen@gmail.com>",
|
|
82
|
-
"Joris Dugué <zaruike10@gmail.com>"
|
|
82
|
+
"Joris Dugué <zaruike10@gmail.com>",
|
|
83
|
+
"Chris Banks <christopher.bradley.banks@gmail.com>",
|
|
84
|
+
"Ompal Singh <ompal.hitm09@gmail.com>"
|
|
83
85
|
],
|
|
84
86
|
"scripts": {
|
|
85
87
|
"install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node install/can-compile && node-gyp rebuild && node install/dll-copy)",
|
|
@@ -124,33 +126,46 @@
|
|
|
124
126
|
"vips"
|
|
125
127
|
],
|
|
126
128
|
"dependencies": {
|
|
127
|
-
"color": "^4.
|
|
128
|
-
"detect-libc": "^
|
|
129
|
-
"node-addon-api": "^4.
|
|
130
|
-
"prebuild-install": "^7.0.
|
|
129
|
+
"color": "^4.2.1",
|
|
130
|
+
"detect-libc": "^2.0.1",
|
|
131
|
+
"node-addon-api": "^4.3.0",
|
|
132
|
+
"prebuild-install": "^7.0.1",
|
|
131
133
|
"semver": "^7.3.5",
|
|
132
|
-
"simple-get": "^4.0.
|
|
134
|
+
"simple-get": "^4.0.1",
|
|
133
135
|
"tar-fs": "^2.1.1",
|
|
134
136
|
"tunnel-agent": "^0.6.0"
|
|
135
137
|
},
|
|
136
138
|
"devDependencies": {
|
|
137
|
-
"async": "^3.2.
|
|
139
|
+
"async": "^3.2.3",
|
|
138
140
|
"cc": "^3.0.1",
|
|
139
141
|
"decompress-zip": "^0.3.3",
|
|
140
142
|
"documentation": "^13.2.5",
|
|
141
143
|
"exif-reader": "^1.0.3",
|
|
142
144
|
"icc": "^2.0.0",
|
|
143
145
|
"license-checker": "^25.0.1",
|
|
144
|
-
"mocha": "^9.1
|
|
146
|
+
"mocha": "^9.2.1",
|
|
145
147
|
"mock-fs": "^5.1.2",
|
|
146
148
|
"nyc": "^15.1.0",
|
|
147
|
-
"prebuild": "^11.0.
|
|
149
|
+
"prebuild": "^11.0.3",
|
|
148
150
|
"rimraf": "^3.0.2",
|
|
149
151
|
"semistandard": "^16.0.1"
|
|
150
152
|
},
|
|
151
153
|
"license": "Apache-2.0",
|
|
152
154
|
"config": {
|
|
153
|
-
"libvips": "8.
|
|
155
|
+
"libvips": "8.12.2",
|
|
156
|
+
"integrity": {
|
|
157
|
+
"darwin-arm64v8": "sha512-p46s/bbJAjkOXzPISZt9HUpG9GWjwQkYnLLRLKzsBJHLtB3X6C6Y/zXI5Hd0DOojcFkks9a0kTN+uDQ/XJY19g==",
|
|
158
|
+
"darwin-x64": "sha512-6vOHVZnvXwe6EXRsy29jdkUzBE6ElNpXUwd+m8vV7qy32AnXu7B9YemHsZ44vWviIwPZeXF6Nhd9EFLM0wWohw==",
|
|
159
|
+
"linux-arm64v8": "sha512-XwZdS63yhqLtbFtx/0eoLF/Agf5qtTrI11FMnMRpuBJWd4jHB60RAH+uzYUgoChCmKIS+AeXYMLm4d8Ns2QX8w==",
|
|
160
|
+
"linux-armv6": "sha512-Rh0Q0kqwPG2MjXWOkPCuPEyiUKFgKJYWLgS835D4MrXgdKr8Tft/eVrc2iGIxt2re30VpDiZ1h0Rby1aCZt2zw==",
|
|
161
|
+
"linux-armv7": "sha512-heTS/MsmRvu4JljINxP+vDiS9ZZfuGhr3IStb5F7Gc0/QLRhllYAg4rcO8L1eTK9sIIzG5ARvI19+YUZe7WbzA==",
|
|
162
|
+
"linux-x64": "sha512-SSWAwBFi0hx8V/h/v82tTFGKWTFv9FiCK3Timz5OExuI+sX1Ngrd0PVQaWXOThGNdel/fcD3Bz9YjSt4feBR1g==",
|
|
163
|
+
"linuxmusl-arm64v8": "sha512-Rhks+5C7p7aO6AucLT1uvzo8ohlqcqCUPgZmN+LZjsPWob/Iix3MfiDYtv/+gTvdeEfXxbCU6/YuPBwHQ7/crA==",
|
|
164
|
+
"linuxmusl-x64": "sha512-IOyjSQqpWVntqOUpCHVWuQwACwmmjdi15H8Pc+Ma1JkhPogTfVsFQWyL7DuOTD3Yr23EuYGzovUX00duOtfy/g==",
|
|
165
|
+
"win32-arm64v8": "sha512-A+Qe8Ipewtvw9ldvF6nWed2J8kphzrUE04nFeKCtNx6pfGQ/MAlCKMjt/U8VgUKNjB01zJDUW9XE0+FhGZ/UpQ==",
|
|
166
|
+
"win32-ia32": "sha512-cMrAvwFdDeAVnLJt0IPMPRKaIFhyXYGTprsM0DND9VUHE8F7dJMR44tS5YkXsGh1QNDtjKT6YuxAVUglmiXtpA==",
|
|
167
|
+
"win32-x64": "sha512-vLFIfw6aW2zABa8jpgzWDhljnE6glktrddErVyazAIoHl6BFFe/Da+LK1DbXvIYHz7fyOoKhSfCJHCiJG1Vg6w=="
|
|
168
|
+
},
|
|
154
169
|
"runtime": "napi",
|
|
155
170
|
"target": 5
|
|
156
171
|
},
|