sharp 0.29.1 → 0.30.1
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/binding.gyp +2 -0
- package/install/libvips.js +39 -8
- package/lib/constructor.js +13 -4
- package/lib/input.js +21 -4
- package/lib/libvips.js +16 -2
- package/lib/operation.js +14 -1
- package/lib/output.js +158 -69
- package/lib/platform.js +1 -1
- package/lib/resize.js +19 -0
- package/lib/sharp.js +11 -3
- package/lib/utility.js +24 -5
- package/package.json +28 -13
- package/src/common.cc +125 -19
- package/src/common.h +39 -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 +291 -255
- package/src/pipeline.h +19 -19
- package/src/sharp.cc +16 -0
package/lib/output.js
CHANGED
|
@@ -13,6 +13,7 @@ const formats = new Map([
|
|
|
13
13
|
['png', 'png'],
|
|
14
14
|
['raw', 'raw'],
|
|
15
15
|
['tiff', 'tiff'],
|
|
16
|
+
['tif', 'tiff'],
|
|
16
17
|
['webp', 'webp'],
|
|
17
18
|
['gif', 'gif'],
|
|
18
19
|
['jp2', 'jp2'],
|
|
@@ -21,14 +22,15 @@ const formats = new Map([
|
|
|
21
22
|
['j2c', 'jp2']
|
|
22
23
|
]);
|
|
23
24
|
|
|
24
|
-
const errMagickSave = new Error('GIF output requires libvips with support for ImageMagick');
|
|
25
25
|
const errJp2Save = new Error('JP2 output requires libvips with support for OpenJPEG');
|
|
26
26
|
|
|
27
|
+
const bitdepthFromColourCount = (colours) => 1 << 31 - Math.clz32(Math.ceil(Math.log2(colours)));
|
|
28
|
+
|
|
27
29
|
/**
|
|
28
30
|
* Write output image data to a file.
|
|
29
31
|
*
|
|
30
32
|
* If an explicit output format is not selected, it will be inferred from the extension,
|
|
31
|
-
* 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.
|
|
32
34
|
* Note that raw pixel data is only supported for buffer output.
|
|
33
35
|
*
|
|
34
36
|
* By default all metadata will be removed, which includes EXIF-based orientation.
|
|
@@ -62,8 +64,6 @@ function toFile (fileOut, callback) {
|
|
|
62
64
|
err = new Error('Missing output file path');
|
|
63
65
|
} else if (is.string(this.options.input.file) && path.resolve(this.options.input.file) === path.resolve(fileOut)) {
|
|
64
66
|
err = new Error('Cannot use same file for input and output');
|
|
65
|
-
} else if (this.options.formatOut === 'input' && fileOut.toLowerCase().endsWith('.gif') && !this.constructor.format.magick.output.file) {
|
|
66
|
-
err = errMagickSave;
|
|
67
67
|
}
|
|
68
68
|
if (err) {
|
|
69
69
|
if (is.fn(callback)) {
|
|
@@ -80,9 +80,9 @@ function toFile (fileOut, callback) {
|
|
|
80
80
|
|
|
81
81
|
/**
|
|
82
82
|
* Write output to a Buffer.
|
|
83
|
-
* 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.
|
|
84
84
|
*
|
|
85
|
-
* 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.
|
|
86
86
|
*
|
|
87
87
|
* By default all metadata will be removed, which includes EXIF-based orientation.
|
|
88
88
|
* See {@link withMetadata} for control over this.
|
|
@@ -139,6 +139,7 @@ function toBuffer (options, callback) {
|
|
|
139
139
|
} else if (this.options.resolveWithObject) {
|
|
140
140
|
this.options.resolveWithObject = false;
|
|
141
141
|
}
|
|
142
|
+
this.options.fileOut = '';
|
|
142
143
|
return this._pipeline(is.fn(options) ? options : callback);
|
|
143
144
|
}
|
|
144
145
|
|
|
@@ -168,7 +169,7 @@ function toBuffer (options, callback) {
|
|
|
168
169
|
* })
|
|
169
170
|
* .toBuffer();
|
|
170
171
|
*
|
|
171
|
-
*
|
|
172
|
+
* @example
|
|
172
173
|
* // Set output metadata to 96 DPI
|
|
173
174
|
* const data = await sharp(input)
|
|
174
175
|
* .withMetadata({ density: 96 })
|
|
@@ -373,6 +374,7 @@ function jpeg (options) {
|
|
|
373
374
|
* @param {boolean} [options.adaptiveFiltering=false] - use adaptive row filtering
|
|
374
375
|
* @param {boolean} [options.palette=false] - quantise to a palette-based image with alpha transparency support
|
|
375
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`
|
|
376
378
|
* @param {number} [options.colours=256] - maximum number of palette entries, sets `palette` to `true`
|
|
377
379
|
* @param {number} [options.colors=256] - alternative spelling of `options.colours`, sets `palette` to `true`
|
|
378
380
|
* @param {number} [options.dither=1.0] - level of Floyd-Steinberg error diffusion, sets `palette` to `true`
|
|
@@ -397,7 +399,7 @@ function png (options) {
|
|
|
397
399
|
}
|
|
398
400
|
if (is.defined(options.palette)) {
|
|
399
401
|
this._setBooleanOption('pngPalette', options.palette);
|
|
400
|
-
} else if (
|
|
402
|
+
} else if ([options.quality, options.effort, options.colours, options.colors, options.dither].some(is.defined)) {
|
|
401
403
|
this._setBooleanOption('pngPalette', true);
|
|
402
404
|
}
|
|
403
405
|
if (this.options.pngPalette) {
|
|
@@ -408,10 +410,17 @@ function png (options) {
|
|
|
408
410
|
throw is.invalidParameterError('quality', 'integer between 0 and 100', options.quality);
|
|
409
411
|
}
|
|
410
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
|
+
}
|
|
411
420
|
const colours = options.colours || options.colors;
|
|
412
421
|
if (is.defined(colours)) {
|
|
413
422
|
if (is.integer(colours) && is.inRange(colours, 2, 256)) {
|
|
414
|
-
this.options.pngBitdepth =
|
|
423
|
+
this.options.pngBitdepth = bitdepthFromColourCount(colours);
|
|
415
424
|
} else {
|
|
416
425
|
throw is.invalidParameterError('colours', 'integer between 2 and 256', colours);
|
|
417
426
|
}
|
|
@@ -440,7 +449,7 @@ function png (options) {
|
|
|
440
449
|
* @example
|
|
441
450
|
* // Optimise the file size of an animated WebP
|
|
442
451
|
* const outputWebp = await sharp(inputWebp, { animated: true })
|
|
443
|
-
* .webp({
|
|
452
|
+
* .webp({ effort: 6 })
|
|
444
453
|
* .toBuffer();
|
|
445
454
|
*
|
|
446
455
|
* @param {Object} [options] - output options
|
|
@@ -449,69 +458,111 @@ function png (options) {
|
|
|
449
458
|
* @param {boolean} [options.lossless=false] - use lossless compression mode
|
|
450
459
|
* @param {boolean} [options.nearLossless=false] - use near_lossless compression mode
|
|
451
460
|
* @param {boolean} [options.smartSubsample=false] - use high quality chroma subsampling
|
|
452
|
-
* @param {number} [options.
|
|
453
|
-
* @param {number} [options.pageHeight] - page height for animated output
|
|
461
|
+
* @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 6 (slowest)
|
|
454
462
|
* @param {number} [options.loop=0] - number of animation iterations, use 0 for infinite animation
|
|
455
|
-
* @param {number[]} [options.delay] -
|
|
463
|
+
* @param {number|number[]} [options.delay] - delay(s) between animation frames (in milliseconds)
|
|
456
464
|
* @param {boolean} [options.force=true] - force WebP output, otherwise attempt to use input format
|
|
457
465
|
* @returns {Sharp}
|
|
458
466
|
* @throws {Error} Invalid options
|
|
459
467
|
*/
|
|
460
468
|
function webp (options) {
|
|
461
|
-
if (is.object(options)
|
|
462
|
-
if (is.
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
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
|
+
}
|
|
466
476
|
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
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
|
+
}
|
|
473
483
|
}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
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
|
+
}
|
|
489
500
|
}
|
|
490
501
|
}
|
|
491
|
-
|
|
492
502
|
trySetAnimationOptions(options, this.options);
|
|
493
503
|
return this._updateFormatOut('webp', options);
|
|
494
504
|
}
|
|
495
505
|
|
|
496
506
|
/**
|
|
497
|
-
* Use these GIF options for output image.
|
|
507
|
+
* Use these GIF options for the output image.
|
|
498
508
|
*
|
|
499
|
-
*
|
|
500
|
-
*
|
|
501
|
-
*
|
|
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();
|
|
502
530
|
*
|
|
503
531
|
* @param {Object} [options] - output options
|
|
504
|
-
* @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)
|
|
505
536
|
* @param {number} [options.loop=0] - number of animation iterations, use 0 for infinite animation
|
|
506
|
-
* @param {number[]} [options.delay] -
|
|
537
|
+
* @param {number|number[]} [options.delay] - delay(s) between animation frames (in milliseconds)
|
|
507
538
|
* @param {boolean} [options.force=true] - force GIF output, otherwise attempt to use input format
|
|
508
539
|
* @returns {Sharp}
|
|
509
540
|
* @throws {Error} Invalid options
|
|
510
541
|
*/
|
|
511
|
-
/* istanbul ignore next */
|
|
512
542
|
function gif (options) {
|
|
513
|
-
if (
|
|
514
|
-
|
|
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
|
+
}
|
|
515
566
|
}
|
|
516
567
|
trySetAnimationOptions(options, this.options);
|
|
517
568
|
return this._updateFormatOut('gif', options);
|
|
@@ -600,20 +651,12 @@ function jp2 (options) {
|
|
|
600
651
|
* @private
|
|
601
652
|
*
|
|
602
653
|
* @param {Object} [source] - output options
|
|
603
|
-
* @param {number} [source.pageHeight] - page height for animated output
|
|
604
654
|
* @param {number} [source.loop=0] - number of animation iterations, use 0 for infinite animation
|
|
605
655
|
* @param {number[]} [source.delay] - list of delays between animation frames (in milliseconds)
|
|
606
656
|
* @param {Object} [target] - target object for valid options
|
|
607
657
|
* @throws {Error} Invalid options
|
|
608
658
|
*/
|
|
609
659
|
function trySetAnimationOptions (source, target) {
|
|
610
|
-
if (is.object(source) && is.defined(source.pageHeight)) {
|
|
611
|
-
if (is.integer(source.pageHeight) && source.pageHeight > 0) {
|
|
612
|
-
target.pageHeight = source.pageHeight;
|
|
613
|
-
} else {
|
|
614
|
-
throw is.invalidParameterError('pageHeight', 'integer larger than 0', source.pageHeight);
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
660
|
if (is.object(source) && is.defined(source.loop)) {
|
|
618
661
|
if (is.integer(source.loop) && is.inRange(source.loop, 0, 65535)) {
|
|
619
662
|
target.loop = source.loop;
|
|
@@ -622,13 +665,16 @@ function trySetAnimationOptions (source, target) {
|
|
|
622
665
|
}
|
|
623
666
|
}
|
|
624
667
|
if (is.object(source) && is.defined(source.delay)) {
|
|
625
|
-
|
|
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 (
|
|
626
672
|
Array.isArray(source.delay) &&
|
|
627
673
|
source.delay.every(is.integer) &&
|
|
628
674
|
source.delay.every(v => is.inRange(v, 0, 65535))) {
|
|
629
675
|
target.delay = source.delay;
|
|
630
676
|
} else {
|
|
631
|
-
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);
|
|
632
678
|
}
|
|
633
679
|
}
|
|
634
680
|
}
|
|
@@ -636,6 +682,8 @@ function trySetAnimationOptions (source, target) {
|
|
|
636
682
|
/**
|
|
637
683
|
* Use these TIFF options for output image.
|
|
638
684
|
*
|
|
685
|
+
* The `density` can be set in pixels/inch via {@link withMetadata} instead of providing `xres` and `yres` in pixels/mm.
|
|
686
|
+
*
|
|
639
687
|
* @example
|
|
640
688
|
* // Convert SVG input to LZW-compressed, 1 bit per pixel TIFF output
|
|
641
689
|
* sharp('input.svg')
|
|
@@ -657,6 +705,7 @@ function trySetAnimationOptions (source, target) {
|
|
|
657
705
|
* @param {number} [options.tileHeight=256] - vertical tile size
|
|
658
706
|
* @param {number} [options.xres=1.0] - horizontal resolution in pixels/mm
|
|
659
707
|
* @param {number} [options.yres=1.0] - vertical resolution in pixels/mm
|
|
708
|
+
* @param {string} [options.resolutionUnit='inch'] - resolution unit options: inch, cm
|
|
660
709
|
* @param {number} [options.bitdepth=8] - reduce bitdepth to 1, 2 or 4 bit
|
|
661
710
|
* @returns {Sharp}
|
|
662
711
|
* @throws {Error} Invalid options
|
|
@@ -730,6 +779,14 @@ function tiff (options) {
|
|
|
730
779
|
throw is.invalidParameterError('predictor', 'one of: none, horizontal, float', options.predictor);
|
|
731
780
|
}
|
|
732
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
|
+
}
|
|
733
790
|
}
|
|
734
791
|
return this._updateFormatOut('tiff', options);
|
|
735
792
|
}
|
|
@@ -747,7 +804,7 @@ function tiff (options) {
|
|
|
747
804
|
* @param {Object} [options] - output options
|
|
748
805
|
* @param {number} [options.quality=50] - quality, integer 1-100
|
|
749
806
|
* @param {boolean} [options.lossless=false] - use lossless compression
|
|
750
|
-
* @param {number} [options.
|
|
807
|
+
* @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 9 (slowest)
|
|
751
808
|
* @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
|
|
752
809
|
* @returns {Sharp}
|
|
753
810
|
* @throws {Error} Invalid options
|
|
@@ -768,7 +825,7 @@ function avif (options) {
|
|
|
768
825
|
* @param {number} [options.quality=50] - quality, integer 1-100
|
|
769
826
|
* @param {string} [options.compression='av1'] - compression format: av1, hevc
|
|
770
827
|
* @param {boolean} [options.lossless=false] - use lossless compression
|
|
771
|
-
* @param {number} [options.
|
|
828
|
+
* @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 9 (slowest)
|
|
772
829
|
* @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
|
|
773
830
|
* @returns {Sharp}
|
|
774
831
|
* @throws {Error} Invalid options
|
|
@@ -796,9 +853,15 @@ function heif (options) {
|
|
|
796
853
|
throw is.invalidParameterError('compression', 'one of: av1, hevc', options.compression);
|
|
797
854
|
}
|
|
798
855
|
}
|
|
799
|
-
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)) {
|
|
800
863
|
if (is.integer(options.speed) && is.inRange(options.speed, 0, 9)) {
|
|
801
|
-
this.options.
|
|
864
|
+
this.options.heifEffort = 9 - options.speed;
|
|
802
865
|
} else {
|
|
803
866
|
throw is.invalidParameterError('speed', 'integer between 0 and 9', options.speed);
|
|
804
867
|
}
|
|
@@ -858,8 +921,6 @@ function raw (options) {
|
|
|
858
921
|
* Set the format and options for tile images via the `toFormat`, `jpeg`, `png` or `webp` functions.
|
|
859
922
|
* Use a `.zip` or `.szi` file extension with `toFile` to write to a compressed archive file format.
|
|
860
923
|
*
|
|
861
|
-
* Warning: multiple sharp instances concurrently producing tile output can expose a possible race condition in some versions of libgsf.
|
|
862
|
-
*
|
|
863
924
|
* @example
|
|
864
925
|
* sharp('input.tiff')
|
|
865
926
|
* .png()
|
|
@@ -879,10 +940,10 @@ function raw (options) {
|
|
|
879
940
|
* @param {string} [options.depth] how deep to make the pyramid, possible values are `onepixel`, `onetile` or `one`, default based on layout.
|
|
880
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
|
|
881
942
|
* @param {string} [options.container='fs'] tile container, with value `fs` (filesystem) or `zip` (compressed file).
|
|
882
|
-
* @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`.
|
|
883
944
|
* @param {boolean} [options.centre=false] centre image in tile.
|
|
884
945
|
* @param {boolean} [options.center=false] alternative spelling of centre.
|
|
885
|
-
* @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`
|
|
886
947
|
* @returns {Sharp}
|
|
887
948
|
* @throws {Error} Invalid parameters
|
|
888
949
|
*/
|
|
@@ -917,10 +978,10 @@ function tile (options) {
|
|
|
917
978
|
}
|
|
918
979
|
// Layout
|
|
919
980
|
if (is.defined(options.layout)) {
|
|
920
|
-
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'])) {
|
|
921
982
|
this.options.tileLayout = options.layout;
|
|
922
983
|
} else {
|
|
923
|
-
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);
|
|
924
985
|
}
|
|
925
986
|
}
|
|
926
987
|
// Angle of rotation,
|
|
@@ -974,6 +1035,31 @@ function tile (options) {
|
|
|
974
1035
|
return this._updateFormatOut('dz');
|
|
975
1036
|
}
|
|
976
1037
|
|
|
1038
|
+
/**
|
|
1039
|
+
* Set a timeout for processing, in seconds.
|
|
1040
|
+
* Use a value of zero to continue processing indefinitely, the default behaviour.
|
|
1041
|
+
*
|
|
1042
|
+
* The clock starts when libvips opens an input image for processing.
|
|
1043
|
+
* Time spent waiting for a libuv thread to become available is not included.
|
|
1044
|
+
*
|
|
1045
|
+
* @since 0.29.2
|
|
1046
|
+
*
|
|
1047
|
+
* @param {Object} options
|
|
1048
|
+
* @param {number} options.seconds - Number of seconds after which processing will be stopped
|
|
1049
|
+
* @returns {Sharp}
|
|
1050
|
+
*/
|
|
1051
|
+
function timeout (options) {
|
|
1052
|
+
if (!is.plainObject(options)) {
|
|
1053
|
+
throw is.invalidParameterError('options', 'object', options);
|
|
1054
|
+
}
|
|
1055
|
+
if (is.integer(options.seconds) && is.inRange(options.seconds, 0, 3600)) {
|
|
1056
|
+
this.options.timeoutSeconds = options.seconds;
|
|
1057
|
+
} else {
|
|
1058
|
+
throw is.invalidParameterError('seconds', 'integer between 0 and 3600', options.seconds);
|
|
1059
|
+
}
|
|
1060
|
+
return this;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
977
1063
|
/**
|
|
978
1064
|
* Update the output format unless options.force is false,
|
|
979
1065
|
* in which case revert to input format.
|
|
@@ -1050,6 +1136,7 @@ function _pipeline (callback) {
|
|
|
1050
1136
|
this.push(data);
|
|
1051
1137
|
}
|
|
1052
1138
|
this.push(null);
|
|
1139
|
+
this.emit('close');
|
|
1053
1140
|
});
|
|
1054
1141
|
});
|
|
1055
1142
|
if (this.streamInFinished) {
|
|
@@ -1065,6 +1152,7 @@ function _pipeline (callback) {
|
|
|
1065
1152
|
this.push(data);
|
|
1066
1153
|
}
|
|
1067
1154
|
this.push(null);
|
|
1155
|
+
this.emit('close');
|
|
1068
1156
|
});
|
|
1069
1157
|
}
|
|
1070
1158
|
return this;
|
|
@@ -1128,6 +1216,7 @@ module.exports = function (Sharp) {
|
|
|
1128
1216
|
gif,
|
|
1129
1217
|
raw,
|
|
1130
1218
|
tile,
|
|
1219
|
+
timeout,
|
|
1131
1220
|
// Private
|
|
1132
1221
|
_updateFormatOut,
|
|
1133
1222
|
_setBooleanOption,
|
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,14 +11,22 @@ 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(
|
|
20
21
|
'- Consult the installation documentation: https://sharp.pixelplumbing.com/install'
|
|
21
22
|
);
|
|
22
|
-
|
|
23
|
-
process.
|
|
23
|
+
// Check loaded
|
|
24
|
+
if (process.platform === 'win32') {
|
|
25
|
+
const loadedModule = Object.keys(require.cache).find((i) => /[\\/]build[\\/]Release[\\/]sharp(.*)\.node$/.test(i));
|
|
26
|
+
if (loadedModule) {
|
|
27
|
+
const [, loadedPackage] = loadedModule.match(/node_modules[\\/]([^\\/]+)[\\/]/);
|
|
28
|
+
help.push(`- Ensure the version of sharp aligns with the ${loadedPackage} package: "npm ls sharp"`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
throw new Error(help.join('\n'));
|
|
24
32
|
}
|
package/lib/utility.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
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
|
|
|
6
8
|
const is = require('./is');
|
|
9
|
+
const platformAndArch = require('./platform')();
|
|
7
10
|
const sharp = require('./sharp');
|
|
8
11
|
|
|
9
12
|
/**
|
|
@@ -27,11 +30,11 @@ const interpolators = {
|
|
|
27
30
|
bilinear: 'bilinear',
|
|
28
31
|
/** [Bicubic interpolation](http://en.wikipedia.org/wiki/Bicubic_interpolation) (the default). */
|
|
29
32
|
bicubic: 'bicubic',
|
|
30
|
-
/** [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. */
|
|
31
34
|
locallyBoundedBicubic: 'lbb',
|
|
32
35
|
/** [Nohalo interpolation](http://eprints.soton.ac.uk/268086/). Prevents acutance but typically reduces performance by a factor of 3. */
|
|
33
36
|
nohalo: 'nohalo',
|
|
34
|
-
/** [VSQBS interpolation](https://github.com/
|
|
37
|
+
/** [VSQBS interpolation](https://github.com/libvips/libvips/blob/master/libvips/resample/vsqbs.cpp#L48). Prevents "staircasing" when enlarging. */
|
|
35
38
|
vertexSplitQuadraticBasisSpline: 'vsqbs'
|
|
36
39
|
};
|
|
37
40
|
|
|
@@ -45,8 +48,23 @@ let versions = {
|
|
|
45
48
|
vips: sharp.libvipsVersion()
|
|
46
49
|
};
|
|
47
50
|
try {
|
|
48
|
-
versions = require(`../vendor/${versions.vips}/versions.json`);
|
|
49
|
-
} catch (
|
|
51
|
+
versions = require(`../vendor/${versions.vips}/${platformAndArch}/versions.json`);
|
|
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 */ }
|
|
50
68
|
|
|
51
69
|
/**
|
|
52
70
|
* Gets or, when options are provided, sets the limits of _libvips'_ operation cache.
|
|
@@ -110,7 +128,7 @@ function concurrency (concurrency) {
|
|
|
110
128
|
return sharp.concurrency(is.integer(concurrency) ? concurrency : null);
|
|
111
129
|
}
|
|
112
130
|
/* istanbul ignore next */
|
|
113
|
-
if (detectLibc.
|
|
131
|
+
if (detectLibc.familySync() === detectLibc.GLIBC && !sharp._isUsingJemalloc()) {
|
|
114
132
|
// Reduce default concurrency to 1 when using glibc memory allocator
|
|
115
133
|
sharp.concurrency(1);
|
|
116
134
|
}
|
|
@@ -175,5 +193,6 @@ module.exports = function (Sharp) {
|
|
|
175
193
|
Sharp.format = format;
|
|
176
194
|
Sharp.interpolators = interpolators;
|
|
177
195
|
Sharp.versions = versions;
|
|
196
|
+
Sharp.vendor = vendor;
|
|
178
197
|
Sharp.queue = queue;
|
|
179
198
|
};
|