sharp 0.33.0-alpha.8 → 0.33.0-rc.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 CHANGED
@@ -2,10 +2,14 @@
2
2
 
3
3
  <img src="https://cdn.jsdelivr.net/gh/lovell/sharp@main/docs/image/sharp-logo.svg" width="160" height="160" alt="sharp logo" align="right">
4
4
 
5
- The typical use case for this high speed Node.js module
5
+ The typical use case for this high speed Node-API module
6
6
  is to convert large images in common formats to
7
7
  smaller, web-friendly JPEG, PNG, WebP, GIF and AVIF images of varying dimensions.
8
8
 
9
+ It can be used with all JavaScript runtimes
10
+ that provide support for Node-API v9, including
11
+ Node.js >= 18.17.0, Deno and Bun.
12
+
9
13
  Resizing an image is typically 4x-5x faster than using the
10
14
  quickest ImageMagick and GraphicsMagick settings
11
15
  due to its use of [libvips](https://github.com/libvips/libvips).
@@ -16,7 +20,7 @@ Lanczos resampling ensures quality is not sacrificed for speed.
16
20
  As well as image resizing, operations such as
17
21
  rotation, extraction, compositing and gamma correction are available.
18
22
 
19
- Most modern macOS, Windows and Linux systems running Node.js >= 18.17.0
23
+ Most modern macOS, Windows and Linux systems
20
24
  do not require any additional install or runtime dependencies.
21
25
 
22
26
  ## Documentation
package/lib/colour.js CHANGED
@@ -19,7 +19,7 @@ const colourspace = {
19
19
  };
20
20
 
21
21
  /**
22
- * Tint the image using the provided chroma while preserving the image luminance.
22
+ * Tint the image using the provided colour.
23
23
  * An alpha channel may be present and will be unchanged by the operation.
24
24
  *
25
25
  * @example
@@ -27,14 +27,12 @@ const colourspace = {
27
27
  * .tint({ r: 255, g: 240, b: 16 })
28
28
  * .toBuffer();
29
29
  *
30
- * @param {string|Object} rgb - parsed by the [color](https://www.npmjs.org/package/color) module to extract chroma values.
30
+ * @param {string|Object} tint - Parsed by the [color](https://www.npmjs.org/package/color) module.
31
31
  * @returns {Sharp}
32
32
  * @throws {Error} Invalid parameter
33
33
  */
34
- function tint (rgb) {
35
- const colour = color(rgb);
36
- this.options.tintA = colour.a();
37
- this.options.tintB = colour.b();
34
+ function tint (tint) {
35
+ this._setBackgroundColourOption('tint', tint);
38
36
  return this;
39
37
  }
40
38
 
@@ -121,7 +121,7 @@ const debuglog = util.debuglog('sharp');
121
121
  * a String containing the filesystem path to an JPEG, PNG, WebP, AVIF, GIF, SVG or TIFF image file.
122
122
  * JPEG, PNG, WebP, AVIF, GIF, SVG, TIFF or raw pixel image data can be streamed into the object when not present.
123
123
  * @param {Object} [options] - if present, is an Object with optional attributes.
124
- * @param {string} [options.failOn='warning'] - when to abort processing of invalid pixel data, one of (in order of sensitivity): 'none' (least), 'truncated', 'error' or 'warning' (most), higher levels imply lower levels, invalid metadata will always abort.
124
+ * @param {string} [options.failOn='warning'] - When to abort processing of invalid pixel data, one of (in order of sensitivity, least to most): 'none', 'truncated', 'error', 'warning'. Higher levels imply lower levels. Invalid metadata will always abort.
125
125
  * @param {number|boolean} [options.limitInputPixels=268402689] - Do not process input images where the number of pixels
126
126
  * (width x height) exceeds this limit. Assumes image dimensions contained in the input metadata can be trusted.
127
127
  * An integral Number of pixels, zero or false to remove limit, true to use default limit of 268402689 (0x3FFF x 0x3FFF).
@@ -212,8 +212,7 @@ const Sharp = function (input, options) {
212
212
  kernel: 'lanczos3',
213
213
  fastShrinkOnLoad: true,
214
214
  // operations
215
- tintA: 128,
216
- tintB: 128,
215
+ tint: [-1, 0, 0, 0],
217
216
  flatten: false,
218
217
  flattenBackground: [0, 0, 0],
219
218
  unflatten: false,
@@ -230,7 +229,8 @@ const Sharp = function (input, options) {
230
229
  threshold: 0,
231
230
  thresholdGrayscale: true,
232
231
  trimBackground: [],
233
- trimThreshold: 0,
232
+ trimThreshold: -1,
233
+ trimLineArt: false,
234
234
  gamma: 0,
235
235
  gammaOut: 0,
236
236
  greyscale: false,
@@ -257,11 +257,12 @@ const Sharp = function (input, options) {
257
257
  fileOut: '',
258
258
  formatOut: 'input',
259
259
  streamOut: false,
260
- withMetadata: false,
260
+ keepMetadata: 0,
261
261
  withMetadataOrientation: -1,
262
262
  withMetadataDensity: 0,
263
- withMetadataIcc: '',
264
- withMetadataStrs: {},
263
+ withIccProfile: '',
264
+ withExif: {},
265
+ withExifMerge: true,
265
266
  resolveWithObject: false,
266
267
  // output format
267
268
  jpegQuality: 80,
@@ -305,6 +306,7 @@ const Sharp = function (input, options) {
305
306
  tiffCompression: 'jpeg',
306
307
  tiffPredictor: 'horizontal',
307
308
  tiffPyramid: false,
309
+ tiffMiniswhite: false,
308
310
  tiffBitdepth: 8,
309
311
  tiffTile: false,
310
312
  tiffTileHeight: 256,
package/lib/index.d.ts CHANGED
@@ -239,12 +239,12 @@ declare namespace sharp {
239
239
  //#region Color functions
240
240
 
241
241
  /**
242
- * Tint the image using the provided chroma while preserving the image luminance.
242
+ * Tint the image using the provided colour.
243
243
  * An alpha channel may be present and will be unchanged by the operation.
244
- * @param rgb Parsed by the color module to extract chroma values.
244
+ * @param tint Parsed by the color module.
245
245
  * @returns A sharp instance that can be used to chain operations
246
246
  */
247
- tint(rgb: Color): Sharp;
247
+ tint(tint: Color): Sharp;
248
248
 
249
249
  /**
250
250
  * Convert to 8-bit greyscale; 256 shades of grey.
@@ -633,6 +633,43 @@ declare namespace sharp {
633
633
  */
634
634
  toBuffer(options: { resolveWithObject: true }): Promise<{ data: Buffer; info: OutputInfo }>;
635
635
 
636
+ /**
637
+ * Keep all EXIF metadata from the input image in the output image.
638
+ * EXIF metadata is unsupported for TIFF output.
639
+ * @returns A sharp instance that can be used to chain operations
640
+ */
641
+ keepExif(): Sharp;
642
+
643
+ /**
644
+ * Set EXIF metadata in the output image, ignoring any EXIF in the input image.
645
+ * @param {Exif} exif Object keyed by IFD0, IFD1 etc. of key/value string pairs to write as EXIF data.
646
+ * @returns A sharp instance that can be used to chain operations
647
+ * @throws {Error} Invalid parameters
648
+ */
649
+ withExif(exif: Exif): Sharp;
650
+
651
+ /**
652
+ * Update EXIF metadata from the input image in the output image.
653
+ * @param {Exif} exif Object keyed by IFD0, IFD1 etc. of key/value string pairs to write as EXIF data.
654
+ * @returns A sharp instance that can be used to chain operations
655
+ * @throws {Error} Invalid parameters
656
+ */
657
+ withExifMerge(exif: Exif): Sharp;
658
+
659
+ /**
660
+ * Keep ICC profile from the input image in the output image where possible.
661
+ * @returns A sharp instance that can be used to chain operations
662
+ */
663
+ keepIccProfile(): Sharp;
664
+
665
+ /**
666
+ * Transform using an ICC profile and attach to the output image.
667
+ * @param {string} icc - Absolute filesystem path to output ICC profile or built-in profile name (srgb, p3, cmyk).
668
+ * @returns A sharp instance that can be used to chain operations
669
+ * @throws {Error} Invalid parameters
670
+ */
671
+ withIccProfile(icc: string, options?: WithIccProfileOptions): Sharp;
672
+
636
673
  /**
637
674
  * Include all metadata (EXIF, XMP, IPTC) from the input image in the output image.
638
675
  * The default behaviour, when withMetadata is not used, is to strip all metadata and convert to the device-independent sRGB colour space.
@@ -847,11 +884,11 @@ declare namespace sharp {
847
884
  * Trim pixels from all edges that contain values similar to the given background colour, which defaults to that of the top-left pixel.
848
885
  * Images with an alpha channel will use the combined bounding box of alpha and non-alpha channels.
849
886
  * The info response Object will contain trimOffsetLeft and trimOffsetTop properties.
850
- * @param trim The specific background colour to trim, the threshold for doing so or an Object with both.
887
+ * @param options trim options
851
888
  * @throws {Error} Invalid parameters
852
889
  * @returns A sharp instance that can be used to chain operations
853
890
  */
854
- trim(trim?: string | number | TrimOptions): Sharp;
891
+ trim(options?: TrimOptions): Sharp;
855
892
 
856
893
  //#endregion
857
894
  }
@@ -978,15 +1015,32 @@ declare namespace sharp {
978
1015
  wrap?: TextWrap;
979
1016
  }
980
1017
 
1018
+ interface ExifDir {
1019
+ [k: string]: string;
1020
+ }
1021
+
1022
+ interface Exif {
1023
+ 'IFD0'?: ExifDir;
1024
+ 'IFD1'?: ExifDir;
1025
+ 'IFD2'?: ExifDir;
1026
+ 'IFD3'?: ExifDir;
1027
+ }
1028
+
981
1029
  interface WriteableMetadata {
1030
+ /** Number of pixels per inch (DPI) */
1031
+ density?: number | undefined;
982
1032
  /** Value between 1 and 8, used to update the EXIF Orientation tag. */
983
1033
  orientation?: number | undefined;
984
- /** Filesystem path to output ICC profile, defaults to sRGB. */
1034
+ /**
1035
+ * Filesystem path to output ICC profile, defaults to sRGB.
1036
+ * @deprecated Use `withIccProfile()` instead.
1037
+ */
985
1038
  icc?: string | undefined;
986
- /** Object keyed by IFD0, IFD1 etc. of key/value string pairs to write as EXIF data. (optional, default {}) */
987
- exif?: Record<string, any> | undefined;
988
- /** Number of pixels per inch (DPI) */
989
- density?: number | undefined;
1039
+ /**
1040
+ * Object keyed by IFD0, IFD1 etc. of key/value string pairs to write as EXIF data.
1041
+ * @deprecated Use `withExif()` or `withExifMerge()` instead.
1042
+ */
1043
+ exif?: Exif | undefined;
990
1044
  }
991
1045
 
992
1046
  interface Metadata {
@@ -1096,6 +1150,11 @@ declare namespace sharp {
1096
1150
  force?: boolean | undefined;
1097
1151
  }
1098
1152
 
1153
+ interface WithIccProfileOptions {
1154
+ /** Should the ICC profile be included in the output image metadata? (optional, default true) */
1155
+ attach?: boolean | undefined;
1156
+ }
1157
+
1099
1158
  interface JpegOptions extends OutputOptions {
1100
1159
  /** Quality, integer 1-100 (optional, default 80) */
1101
1160
  quality?: number | undefined;
@@ -1234,6 +1293,8 @@ declare namespace sharp {
1234
1293
  yres?: number | undefined;
1235
1294
  /** Reduce bitdepth to 1, 2 or 4 bit (optional, default 8) */
1236
1295
  bitdepth?: 1 | 2 | 4 | 8 | undefined;
1296
+ /** Write 1-bit images as miniswhite (optional, default false) */
1297
+ miniswhite?: boolean | undefined;
1237
1298
  /** Resolution unit options: inch, cm (optional, default 'inch') */
1238
1299
  resolutionUnit?: 'inch' | 'cm' | undefined;
1239
1300
  }
@@ -1275,10 +1336,10 @@ declare namespace sharp {
1275
1336
  }
1276
1337
 
1277
1338
  interface NormaliseOptions {
1278
- /** Percentile below which luminance values will be underexposed. */
1279
- lower?: number | undefined;
1280
- /** Percentile above which luminance values will be overexposed. */
1281
- upper?: number | undefined;
1339
+ /** Percentile below which luminance values will be underexposed. */
1340
+ lower?: number | undefined;
1341
+ /** Percentile above which luminance values will be overexposed. */
1342
+ upper?: number | undefined;
1282
1343
  }
1283
1344
 
1284
1345
  interface ResizeOptions {
@@ -1340,10 +1401,12 @@ declare namespace sharp {
1340
1401
  }
1341
1402
 
1342
1403
  interface TrimOptions {
1343
- /** background colour, parsed by the color module, defaults to that of the top-left pixel. (optional) */
1404
+ /** Background colour, parsed by the color module, defaults to that of the top-left pixel. (optional) */
1344
1405
  background?: Color | undefined;
1345
- /** the allowed difference from the above colour, a positive number. (optional, default `10`) */
1406
+ /** Allowed difference from the above colour, a positive number. (optional, default 10) */
1346
1407
  threshold?: number | undefined;
1408
+ /** Does the input more closely resemble line art (e.g. vector) rather than being photographic? (optional, default false) */
1409
+ lineArt?: boolean | undefined;
1347
1410
  }
1348
1411
 
1349
1412
  interface RawOptions {
package/lib/input.js CHANGED
@@ -483,14 +483,27 @@ function _isStreamInput () {
483
483
  * @returns {Promise<Object>|Sharp}
484
484
  */
485
485
  function metadata (callback) {
486
+ const stack = Error();
486
487
  if (is.fn(callback)) {
487
488
  if (this._isStreamInput()) {
488
489
  this.on('finish', () => {
489
490
  this._flattenBufferIn();
490
- sharp.metadata(this.options, callback);
491
+ sharp.metadata(this.options, (err, metadata) => {
492
+ if (err) {
493
+ callback(is.nativeError(err, stack));
494
+ } else {
495
+ callback(null, metadata);
496
+ }
497
+ });
491
498
  });
492
499
  } else {
493
- sharp.metadata(this.options, callback);
500
+ sharp.metadata(this.options, (err, metadata) => {
501
+ if (err) {
502
+ callback(is.nativeError(err, stack));
503
+ } else {
504
+ callback(null, metadata);
505
+ }
506
+ });
494
507
  }
495
508
  return this;
496
509
  } else {
@@ -500,7 +513,7 @@ function metadata (callback) {
500
513
  this._flattenBufferIn();
501
514
  sharp.metadata(this.options, (err, metadata) => {
502
515
  if (err) {
503
- reject(err);
516
+ reject(is.nativeError(err, stack));
504
517
  } else {
505
518
  resolve(metadata);
506
519
  }
@@ -516,7 +529,7 @@ function metadata (callback) {
516
529
  return new Promise((resolve, reject) => {
517
530
  sharp.metadata(this.options, (err, metadata) => {
518
531
  if (err) {
519
- reject(err);
532
+ reject(is.nativeError(err, stack));
520
533
  } else {
521
534
  resolve(metadata);
522
535
  }
@@ -572,14 +585,27 @@ function metadata (callback) {
572
585
  * @returns {Promise<Object>}
573
586
  */
574
587
  function stats (callback) {
588
+ const stack = Error();
575
589
  if (is.fn(callback)) {
576
590
  if (this._isStreamInput()) {
577
591
  this.on('finish', () => {
578
592
  this._flattenBufferIn();
579
- sharp.stats(this.options, callback);
593
+ sharp.stats(this.options, (err, stats) => {
594
+ if (err) {
595
+ callback(is.nativeError(err, stack));
596
+ } else {
597
+ callback(null, stats);
598
+ }
599
+ });
580
600
  });
581
601
  } else {
582
- sharp.stats(this.options, callback);
602
+ sharp.stats(this.options, (err, stats) => {
603
+ if (err) {
604
+ callback(is.nativeError(err, stack));
605
+ } else {
606
+ callback(null, stats);
607
+ }
608
+ });
583
609
  }
584
610
  return this;
585
611
  } else {
@@ -589,7 +615,7 @@ function stats (callback) {
589
615
  this._flattenBufferIn();
590
616
  sharp.stats(this.options, (err, stats) => {
591
617
  if (err) {
592
- reject(err);
618
+ reject(is.nativeError(err, stack));
593
619
  } else {
594
620
  resolve(stats);
595
621
  }
@@ -600,7 +626,7 @@ function stats (callback) {
600
626
  return new Promise((resolve, reject) => {
601
627
  sharp.stats(this.options, (err, stats) => {
602
628
  if (err) {
603
- reject(err);
629
+ reject(is.nativeError(err, stack));
604
630
  } else {
605
631
  resolve(stats);
606
632
  }
package/lib/is.js CHANGED
@@ -137,6 +137,19 @@ const invalidParameterError = function (name, expected, actual) {
137
137
  );
138
138
  };
139
139
 
140
+ /**
141
+ * Ensures an Error from C++ contains a JS stack.
142
+ *
143
+ * @param {Error} native - Error with message from C++.
144
+ * @param {Error} context - Error with stack from JS.
145
+ * @returns {Error} Error with message and stack.
146
+ * @private
147
+ */
148
+ const nativeError = function (native, context) {
149
+ context.message = native.message;
150
+ return context;
151
+ };
152
+
140
153
  module.exports = {
141
154
  defined,
142
155
  object,
@@ -151,5 +164,6 @@ module.exports = {
151
164
  integer,
152
165
  inRange,
153
166
  inArray,
154
- invalidParameterError
167
+ invalidParameterError,
168
+ nativeError
155
169
  };
package/lib/libvips.js CHANGED
@@ -16,7 +16,7 @@ const minimumLibvipsVersion = semverCoerce(minimumLibvipsVersionLabelled).versio
16
16
 
17
17
  const prebuiltPlatforms = [
18
18
  'darwin-arm64', 'darwin-x64',
19
- 'linux-arm', 'linux-arm64', 'linux-x64',
19
+ 'linux-arm', 'linux-arm64', 'linux-s390x', 'linux-x64',
20
20
  'linuxmusl-arm64', 'linuxmusl-x64',
21
21
  'win32-ia32', 'win32-x64'
22
22
  ];
@@ -41,22 +41,30 @@ const runtimePlatformArch = () => `${process.platform}${runtimeLibc()}-${process
41
41
 
42
42
  /* istanbul ignore next */
43
43
  const buildPlatformArch = () => {
44
+ if (isEmscripten()) {
45
+ return 'wasm32';
46
+ }
44
47
  /* eslint camelcase: ["error", { allow: ["^npm_config_"] }] */
45
48
  const { npm_config_arch, npm_config_platform, npm_config_libc } = process.env;
46
- return `${npm_config_platform || process.platform}${npm_config_libc || runtimeLibc()}-${npm_config_arch || process.arch}`;
49
+ const libc = typeof npm_config_libc === 'string' ? npm_config_libc : runtimeLibc();
50
+ return `${npm_config_platform || process.platform}${libc}-${npm_config_arch || process.arch}`;
47
51
  };
48
52
 
49
53
  const buildSharpLibvipsIncludeDir = () => {
50
54
  try {
51
- return require('@sharpen/sharp-libvips-dev/include');
52
- } catch {}
55
+ return require(`@img/sharp-libvips-dev-${buildPlatformArch()}/include`);
56
+ } catch {
57
+ try {
58
+ return require('@img/sharp-libvips-dev/include');
59
+ } catch {}
60
+ }
53
61
  /* istanbul ignore next */
54
62
  return '';
55
63
  };
56
64
 
57
65
  const buildSharpLibvipsCPlusPlusDir = () => {
58
66
  try {
59
- return require('@sharpen/sharp-libvips-dev/cplusplus');
67
+ return require('@img/sharp-libvips-dev/cplusplus');
60
68
  } catch {}
61
69
  /* istanbul ignore next */
62
70
  return '';
@@ -64,12 +72,22 @@ const buildSharpLibvipsCPlusPlusDir = () => {
64
72
 
65
73
  const buildSharpLibvipsLibDir = () => {
66
74
  try {
67
- return require(`@sharpen/sharp-libvips-${buildPlatformArch()}/lib`);
68
- } catch {}
75
+ return require(`@img/sharp-libvips-dev-${buildPlatformArch()}/lib`);
76
+ } catch {
77
+ try {
78
+ return require(`@img/sharp-libvips-${buildPlatformArch()}/lib`);
79
+ } catch {}
80
+ }
69
81
  /* istanbul ignore next */
70
82
  return '';
71
83
  };
72
84
 
85
+ /* istanbul ignore next */
86
+ const isEmscripten = () => {
87
+ const { CC } = process.env;
88
+ return Boolean(CC && CC.endsWith('/emcc'));
89
+ };
90
+
73
91
  const isRosetta = () => {
74
92
  /* istanbul ignore next */
75
93
  if (process.platform === 'darwin' && process.arch === 'x64') {
@@ -81,7 +99,7 @@ const isRosetta = () => {
81
99
 
82
100
  /* istanbul ignore next */
83
101
  const spawnRebuild = () =>
84
- spawnSync('node-gyp rebuild --directory=src', {
102
+ spawnSync(`node-gyp rebuild --directory=src ${isEmscripten() ? '--nodedir=emscripten' : ''}`, {
85
103
  ...spawnSyncOptions,
86
104
  stdio: 'inherit'
87
105
  }).status;