@revizly/sharp 0.35.0-revizly6 → 0.35.0-revizly8

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
@@ -8,7 +8,7 @@ smaller, web-friendly JPEG, PNG, WebP, GIF and AVIF images of varying dimensions
8
8
 
9
9
  It can be used with all JavaScript runtimes
10
10
  that provide support for Node-API v9, including
11
- Node.js (^18.17.0 or >= 20.3.0), Deno and Bun.
11
+ Node.js (>= 20.9.0), Deno and Bun.
12
12
 
13
13
  Resizing an image is typically 4x-5x faster than using the
14
14
  quickest ImageMagick and GraphicsMagick settings
package/install/build.js CHANGED
@@ -10,7 +10,7 @@ const {
10
10
  spawnRebuild,
11
11
  } = require('../lib/libvips');
12
12
 
13
- log('Attempting to build from source via node-gyp');
13
+ log('Building from source');
14
14
  log('See https://sharp.pixelplumbing.com/install#building-from-source');
15
15
 
16
16
  try {
@@ -29,7 +29,7 @@ try {
29
29
  }
30
30
 
31
31
  if (useGlobalLibvips(log)) {
32
- log(`Detected globally-installed libvips v${globalLibvipsVersion()}`);
32
+ log(`Found globally-installed libvips v${globalLibvipsVersion()}`);
33
33
  }
34
34
 
35
35
  const status = spawnRebuild();
@@ -278,6 +278,7 @@ const Sharp = function (input, options) {
278
278
  trimBackground: [],
279
279
  trimThreshold: -1,
280
280
  trimLineArt: false,
281
+ trimMargin: 0,
281
282
  dilateWidth: 0,
282
283
  erodeWidth: 0,
283
284
  gamma: 0,
@@ -306,6 +307,7 @@ const Sharp = function (input, options) {
306
307
  fileOut: '',
307
308
  formatOut: 'input',
308
309
  streamOut: false,
310
+ typedArrayOut: false,
309
311
  keepMetadata: 0,
310
312
  withMetadataOrientation: -1,
311
313
  withMetadataDensity: 0,
@@ -313,6 +315,7 @@ const Sharp = function (input, options) {
313
315
  withExif: {},
314
316
  withExifMerge: true,
315
317
  withXmp: '',
318
+ withGainMap: false,
316
319
  resolveWithObject: false,
317
320
  loop: -1,
318
321
  delay: [],
@@ -348,6 +351,7 @@ const Sharp = function (input, options) {
348
351
  webpEffort: 4,
349
352
  webpMinSize: false,
350
353
  webpMixed: false,
354
+ webpExact: false,
351
355
  gifBitdepth: 8,
352
356
  gifEffort: 7,
353
357
  gifDither: 1,
@@ -362,7 +366,7 @@ const Sharp = function (input, options) {
362
366
  tiffPredictor: 'horizontal',
363
367
  tiffPyramid: false,
364
368
  tiffMiniswhite: false,
365
- tiffBitdepth: 8,
369
+ tiffBitdepth: 0,
366
370
  tiffTile: false,
367
371
  tiffTileHeight: 256,
368
372
  tiffTileWidth: 256,
@@ -375,6 +379,7 @@ const Sharp = function (input, options) {
375
379
  heifEffort: 4,
376
380
  heifChromaSubsampling: '4:4:4',
377
381
  heifBitdepth: 8,
382
+ heifTune: 'ssim',
378
383
  jxlDistance: 1,
379
384
  jxlDecodingTier: 0,
380
385
  jxlEffort: 7,
package/lib/index.d.ts CHANGED
@@ -259,7 +259,6 @@ declare namespace sharp {
259
259
  * Set the pipeline colourspace.
260
260
  * The input image will be converted to the provided colourspace at the start of the pipeline.
261
261
  * All operations will use this colourspace before converting to the output colourspace, as defined by toColourspace.
262
- * This feature is experimental and has not yet been fully-tested with all operations.
263
262
  *
264
263
  * @param colourspace pipeline colourspace e.g. rgb16, scrgb, lab, grey16 ...
265
264
  * @throws {Error} Invalid parameters
@@ -470,21 +469,6 @@ declare namespace sharp {
470
469
  */
471
470
  sharpen(options?: SharpenOptions): Sharp;
472
471
 
473
- /**
474
- * Sharpen the image.
475
- * When used without parameters, performs a fast, mild sharpen of the output image.
476
- * When a sigma is provided, performs a slower, more accurate sharpen of the L channel in the LAB colour space.
477
- * Fine-grained control over the level of sharpening in "flat" (m1) and "jagged" (m2) areas is available.
478
- * @param sigma the sigma of the Gaussian mask, where sigma = 1 + radius / 2.
479
- * @param flat the level of sharpening to apply to "flat" areas. (optional, default 1.0)
480
- * @param jagged the level of sharpening to apply to "jagged" areas. (optional, default 2.0)
481
- * @throws {Error} Invalid parameters
482
- * @returns A sharp instance that can be used to chain operations
483
- *
484
- * @deprecated Use the object parameter `sharpen({sigma, m1, m2, x1, y2, y3})` instead
485
- */
486
- sharpen(sigma?: number, flat?: number, jagged?: number): Sharp;
487
-
488
472
  /**
489
473
  * Apply median filter. When used without parameters the default window is 3x3.
490
474
  * @param size square mask size: size x size (optional, default 3)
@@ -693,6 +677,13 @@ declare namespace sharp {
693
677
  */
694
678
  toBuffer(options: { resolveWithObject: true }): Promise<{ data: Buffer; info: OutputInfo }>;
695
679
 
680
+ /**
681
+ * Write output to a Uint8Array backed by a transferable ArrayBuffer. JPEG, PNG, WebP, AVIF, TIFF, GIF and RAW output are supported.
682
+ * By default, the format will match the input image, except SVG input which becomes PNG output.
683
+ * @returns A promise that resolves with an object containing the Uint8Array data and an info object containing the output image format, size (bytes), width, height and channels
684
+ */
685
+ toUint8Array(): Promise<{ data: Uint8Array; info: OutputInfo }>;
686
+
696
687
  /**
697
688
  * Keep all EXIF metadata from the input image in the output image.
698
689
  * EXIF metadata is unsupported for TIFF output.
@@ -849,7 +840,7 @@ declare namespace sharp {
849
840
  * @returns A sharp instance that can be used to chain operations
850
841
  */
851
842
  toFormat(
852
- format: keyof FormatEnum | AvailableFormatInfo,
843
+ format: keyof FormatEnum | AvailableFormatInfo | "avif",
853
844
  options?:
854
845
  | OutputOptions
855
846
  | JpegOptions
@@ -903,7 +894,7 @@ declare namespace sharp {
903
894
  * - sharp.gravity: north, northeast, east, southeast, south, southwest, west, northwest, center or centre.
904
895
  * - sharp.strategy: cover only, dynamically crop using either the entropy or attention strategy. Some of these values are based on the object-position CSS property.
905
896
  *
906
- * The experimental strategy-based approach resizes so one dimension is at its target length then repeatedly ranks edge regions,
897
+ * The strategy-based approach resizes so one dimension is at its target length then repeatedly ranks edge regions,
907
898
  * discarding the edge with the lowest score based on the selected strategy.
908
899
  * - entropy: focus on the region with the highest Shannon entropy.
909
900
  * - attention: focus on the region with the highest luminance frequency, colour saturation and presence of skin tones.
@@ -992,14 +983,6 @@ declare namespace sharp {
992
983
  * 'none' (least), 'truncated', 'error' or 'warning' (most), highers level imply lower levels, invalid metadata will always abort. (optional, default 'warning')
993
984
  */
994
985
  failOn?: FailOnOptions | undefined;
995
- /**
996
- * By default halt processing and raise an error when loading invalid images.
997
- * Set this flag to false if you'd rather apply a "best effort" to decode images,
998
- * even if the data is corrupt or invalid. (optional, default true)
999
- *
1000
- * @deprecated Use `failOn` instead
1001
- */
1002
- failOnError?: boolean | undefined;
1003
986
  /**
1004
987
  * Do not process input images where the number of pixels (width x height) exceeds this limit.
1005
988
  * Assumes image dimensions contained in the input metadata can be trusted.
@@ -1184,6 +1167,8 @@ declare namespace sharp {
1184
1167
 
1185
1168
  type HeifCompression = 'av1' | 'hevc';
1186
1169
 
1170
+ type HeifTune = 'iq' | 'ssim' | 'psnr';
1171
+
1187
1172
  type Unit = 'inch' | 'cm';
1188
1173
 
1189
1174
  interface WriteableMetadata {
@@ -1277,6 +1262,8 @@ declare namespace sharp {
1277
1262
  formatMagick?: string | undefined;
1278
1263
  /** Array of keyword/text pairs representing PNG text blocks, if present. */
1279
1264
  comments?: CommentsMetadata[] | undefined;
1265
+ /** HDR gain map, if present */
1266
+ gainMap?: GainMapMetadata | undefined;
1280
1267
  }
1281
1268
 
1282
1269
  interface LevelMetadata {
@@ -1289,16 +1276,21 @@ declare namespace sharp {
1289
1276
  text: string;
1290
1277
  }
1291
1278
 
1279
+ interface GainMapMetadata {
1280
+ /** JPEG image */
1281
+ image: Buffer;
1282
+ }
1283
+
1292
1284
  interface Stats {
1293
1285
  /** Array of channel statistics for each channel in the image. */
1294
1286
  channels: ChannelStats[];
1295
1287
  /** Value to identify if the image is opaque or transparent, based on the presence and use of alpha channel */
1296
1288
  isOpaque: boolean;
1297
- /** Histogram-based estimation of greyscale entropy, discarding alpha channel if any (experimental) */
1289
+ /** Histogram-based estimation of greyscale entropy, discarding alpha channel if any */
1298
1290
  entropy: number;
1299
- /** Estimation of greyscale sharpness based on the standard deviation of a Laplacian convolution, discarding alpha channel if any (experimental) */
1291
+ /** Estimation of greyscale sharpness based on the standard deviation of a Laplacian convolution, discarding alpha channel if any */
1300
1292
  sharpness: number;
1301
- /** Object containing most dominant sRGB colour based on a 4096-bin 3D histogram (experimental) */
1293
+ /** Object containing most dominant sRGB colour based on a 4096-bin 3D histogram */
1302
1294
  dominant: { r: number; g: number; b: number };
1303
1295
  }
1304
1296
 
@@ -1404,11 +1396,13 @@ declare namespace sharp {
1404
1396
  /** Level of CPU effort to reduce file size, integer 0-6 (optional, default 4) */
1405
1397
  effort?: number | undefined;
1406
1398
  /** Prevent use of animation key frames to minimise file size (slow) (optional, default false) */
1407
- minSize?: boolean;
1399
+ minSize?: boolean | undefined;
1408
1400
  /** Allow mixture of lossy and lossless animation frames (slow) (optional, default false) */
1409
- mixed?: boolean;
1401
+ mixed?: boolean | undefined;
1410
1402
  /** Preset options: one of default, photo, picture, drawing, icon, text (optional, default 'default') */
1411
1403
  preset?: keyof PresetEnum | undefined;
1404
+ /** Preserve the colour data in transparent pixels (optional, default false) */
1405
+ exact?: boolean | undefined;
1412
1406
  }
1413
1407
 
1414
1408
  interface AvifOptions extends OutputOptions {
@@ -1422,6 +1416,8 @@ declare namespace sharp {
1422
1416
  chromaSubsampling?: string | undefined;
1423
1417
  /** Set bitdepth to 8, 10 or 12 bit (optional, default 8) */
1424
1418
  bitdepth?: 8 | 10 | 12 | undefined;
1419
+ /** Tune output for a quality metric, one of 'iq', 'ssim' or 'psnr' (optional, default 'iq') */
1420
+ tune?: HeifTune | undefined;
1425
1421
  }
1426
1422
 
1427
1423
  interface HeifOptions extends OutputOptions {
@@ -1437,6 +1433,8 @@ declare namespace sharp {
1437
1433
  chromaSubsampling?: string | undefined;
1438
1434
  /** Set bitdepth to 8, 10 or 12 bit (optional, default 8) */
1439
1435
  bitdepth?: 8 | 10 | 12 | undefined;
1436
+ /** Tune output for a quality metric, one of 'ssim', 'psnr' or 'iq' (optional, default 'ssim') */
1437
+ tune?: HeifTune | undefined;
1440
1438
  }
1441
1439
 
1442
1440
  interface GifOptions extends OutputOptions, AnimationOptions {
@@ -1481,8 +1479,8 @@ declare namespace sharp {
1481
1479
  xres?: number | undefined;
1482
1480
  /** Vertical resolution in pixels/mm (optional, default 1.0) */
1483
1481
  yres?: number | undefined;
1484
- /** Reduce bitdepth to 1, 2 or 4 bit (optional, default 8) */
1485
- bitdepth?: 1 | 2 | 4 | 8 | undefined;
1482
+ /** Reduce bitdepth to 1, 2 or 4 bit (optional) */
1483
+ bitdepth?: 1 | 2 | 4 | undefined;
1486
1484
  /** Write 1-bit images as miniswhite (optional, default false) */
1487
1485
  miniswhite?: boolean | undefined;
1488
1486
  /** Resolution unit options: inch, cm (optional, default 'inch') */
@@ -1608,6 +1606,8 @@ declare namespace sharp {
1608
1606
  threshold?: number | undefined;
1609
1607
  /** Does the input more closely resemble line art (e.g. vector) rather than being photographic? (optional, default false) */
1610
1608
  lineArt?: boolean | undefined;
1609
+ /** Leave a margin around trimmed content, value is in pixels. (optional, default 0) */
1610
+ margin?: number | undefined;
1611
1611
  }
1612
1612
 
1613
1613
  interface RawOptions {
@@ -1913,16 +1913,13 @@ declare namespace sharp {
1913
1913
  }
1914
1914
 
1915
1915
  interface FormatEnum {
1916
- avif: AvailableFormatInfo;
1917
1916
  dcraw: AvailableFormatInfo;
1918
1917
  dz: AvailableFormatInfo;
1919
1918
  exr: AvailableFormatInfo;
1920
1919
  fits: AvailableFormatInfo;
1921
1920
  gif: AvailableFormatInfo;
1922
1921
  heif: AvailableFormatInfo;
1923
- input: AvailableFormatInfo;
1924
1922
  jpeg: AvailableFormatInfo;
1925
- jpg: AvailableFormatInfo;
1926
1923
  jp2: AvailableFormatInfo;
1927
1924
  jxl: AvailableFormatInfo;
1928
1925
  magick: AvailableFormatInfo;
@@ -1934,8 +1931,7 @@ declare namespace sharp {
1934
1931
  raw: AvailableFormatInfo;
1935
1932
  svg: AvailableFormatInfo;
1936
1933
  tiff: AvailableFormatInfo;
1937
- tif: AvailableFormatInfo;
1938
- v: AvailableFormatInfo;
1934
+ vips: AvailableFormatInfo;
1939
1935
  webp: AvailableFormatInfo;
1940
1936
  }
1941
1937
 
package/lib/input.js CHANGED
@@ -30,7 +30,7 @@ const inputStreamParameters = [
30
30
  // Format-specific
31
31
  'jp2', 'openSlide', 'pdf', 'raw', 'svg', 'tiff',
32
32
  // Deprecated
33
- 'failOnError', 'openSlideLevel', 'pdfBackground', 'tiffSubifd'
33
+ 'openSlideLevel', 'pdfBackground', 'tiffSubifd'
34
34
  ];
35
35
 
36
36
  /**
@@ -106,14 +106,6 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
106
106
  }`);
107
107
  }
108
108
  if (is.object(inputOptions)) {
109
- // Deprecated: failOnError
110
- if (is.defined(inputOptions.failOnError)) {
111
- if (is.bool(inputOptions.failOnError)) {
112
- inputDescriptor.failOn = inputOptions.failOnError ? 'warning' : 'none';
113
- } else {
114
- throw is.invalidParameterError('failOnError', 'boolean', inputOptions.failOnError);
115
- }
116
- }
117
109
  // failOn
118
110
  if (is.defined(inputOptions.failOn)) {
119
111
  if (is.string(inputOptions.failOn) && is.inArray(inputOptions.failOn, ['none', 'truncated', 'error', 'warning'])) {
@@ -575,6 +567,7 @@ function _isStreamInput () {
575
567
  * A `Promise` is returned when `callback` is not provided.
576
568
  *
577
569
  * - `format`: Name of decoder used to parse image e.g. `jpeg`, `png`, `webp`, `gif`, `svg`, `heif`, `tiff`
570
+ * - `mediaType`: Media Type (MIME Type) e.g. `image/jpeg`, `image/png`, `image/svg+xml`, `image/avif`
578
571
  * - `size`: Total size of image in bytes, for Stream and Buffer input only
579
572
  * - `width`: Number of pixels wide (EXIF orientation is not taken into consideration, see example below)
580
573
  * - `height`: Number of pixels high (EXIF orientation is not taken into consideration, see example below)
@@ -607,6 +600,7 @@ function _isStreamInput () {
607
600
  * - `tifftagPhotoshop`: Buffer containing raw TIFFTAG_PHOTOSHOP data, if present
608
601
  * - `formatMagick`: String containing format for images loaded via *magick
609
602
  * - `comments`: Array of keyword/text pairs representing PNG text blocks, if present.
603
+ * - `gainMap.image`: HDR gain map, if present, as compressed JPEG image.
610
604
  *
611
605
  * @example
612
606
  * const metadata = await sharp(input).metadata();
package/lib/operation.js CHANGED
@@ -259,45 +259,18 @@ function affine (matrix, options) {
259
259
  * })
260
260
  * .toBuffer();
261
261
  *
262
- * @param {Object|number} [options] - if present, is an Object with attributes
262
+ * @param {Object} [options] - if present, is an Object with attributes
263
263
  * @param {number} [options.sigma] - the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`, between 0.000001 and 10
264
264
  * @param {number} [options.m1=1.0] - the level of sharpening to apply to "flat" areas, between 0 and 1000000
265
265
  * @param {number} [options.m2=2.0] - the level of sharpening to apply to "jagged" areas, between 0 and 1000000
266
266
  * @param {number} [options.x1=2.0] - threshold between "flat" and "jagged", between 0 and 1000000
267
267
  * @param {number} [options.y2=10.0] - maximum amount of brightening, between 0 and 1000000
268
268
  * @param {number} [options.y3=20.0] - maximum amount of darkening, between 0 and 1000000
269
- * @param {number} [flat] - (deprecated) see `options.m1`.
270
- * @param {number} [jagged] - (deprecated) see `options.m2`.
271
269
  * @returns {Sharp}
272
270
  * @throws {Error} Invalid parameters
273
271
  */
274
- function sharpen (options, flat, jagged) {
275
- if (!is.defined(options)) {
276
- // No arguments: default to mild sharpen
277
- this.options.sharpenSigma = -1;
278
- } else if (is.bool(options)) {
279
- // Deprecated boolean argument: apply mild sharpen?
280
- this.options.sharpenSigma = options ? -1 : 0;
281
- } else if (is.number(options) && is.inRange(options, 0.01, 10000)) {
282
- // Deprecated numeric argument: specific sigma
283
- this.options.sharpenSigma = options;
284
- // Deprecated control over flat areas
285
- if (is.defined(flat)) {
286
- if (is.number(flat) && is.inRange(flat, 0, 10000)) {
287
- this.options.sharpenM1 = flat;
288
- } else {
289
- throw is.invalidParameterError('flat', 'number between 0 and 10000', flat);
290
- }
291
- }
292
- // Deprecated control over jagged areas
293
- if (is.defined(jagged)) {
294
- if (is.number(jagged) && is.inRange(jagged, 0, 10000)) {
295
- this.options.sharpenM2 = jagged;
296
- } else {
297
- throw is.invalidParameterError('jagged', 'number between 0 and 10000', jagged);
298
- }
299
- }
300
- } else if (is.plainObject(options)) {
272
+ function sharpen (options) {
273
+ if (is.plainObject(options)) {
301
274
  if (is.number(options.sigma) && is.inRange(options.sigma, 0.000001, 10)) {
302
275
  this.options.sharpenSigma = options.sigma;
303
276
  } else {
@@ -339,7 +312,7 @@ function sharpen (options, flat, jagged) {
339
312
  }
340
313
  }
341
314
  } else {
342
- throw is.invalidParameterError('sigma', 'number between 0.01 and 10000', options);
315
+ this.options.sharpenSigma = -1;
343
316
  }
344
317
  return this;
345
318
  }
@@ -510,8 +483,6 @@ function flatten (options) {
510
483
  *
511
484
  * Existing alpha channel values for non-white pixels remain unchanged.
512
485
  *
513
- * This feature is experimental and the API may change.
514
- *
515
486
  * @since 0.32.1
516
487
  *
517
488
  * @example
package/lib/output.js CHANGED
@@ -76,7 +76,7 @@ function toFile (fileOut, callback) {
76
76
  err = new Error('Missing output file path');
77
77
  } else if (is.string(this.options.input.file) && path.resolve(this.options.input.file) === path.resolve(fileOut)) {
78
78
  err = new Error('Cannot use same file for input and output');
79
- } else if (jp2Regex.test(path.extname(fileOut)) && !this.constructor.format.jp2k.output.file) {
79
+ } else if (jp2Regex.test(path.extname(fileOut)) && !this.constructor.format.jp2.output.file) {
80
80
  err = errJp2Save();
81
81
  }
82
82
  if (err) {
@@ -164,6 +164,41 @@ function toBuffer (options, callback) {
164
164
  return this._pipeline(is.fn(options) ? options : callback, stack);
165
165
  }
166
166
 
167
+ /**
168
+ * Write output to a `Uint8Array` backed by a transferable `ArrayBuffer`.
169
+ * JPEG, PNG, WebP, AVIF, TIFF, GIF and raw pixel data output are supported.
170
+ *
171
+ * Use {@link #toformat toFormat} or one of the format-specific functions such as {@link #jpeg jpeg}, {@link #png png} etc. to set the output format.
172
+ *
173
+ * If no explicit format is set, the output format will match the input image, except SVG input which becomes PNG output.
174
+ *
175
+ * By default all metadata will be removed, which includes EXIF-based orientation.
176
+ * See {@link #keepexif keepExif} and similar methods for control over this.
177
+ *
178
+ * Resolves with an `Object` containing:
179
+ * - `data` is the output image as a `Uint8Array` backed by a transferable `ArrayBuffer`.
180
+ * - `info` contains properties relating to the output image such as `width` and `height`.
181
+ *
182
+ * @since v0.35.0
183
+ *
184
+ * @example
185
+ * const { data, info } = await sharp(input).toUint8Array();
186
+ *
187
+ * @example
188
+ * const { data } = await sharp(input)
189
+ * .avif()
190
+ * .toUint8Array();
191
+ * const base64String = data.toBase64();
192
+ *
193
+ * @returns {Promise<{ data: Uint8Array, info: Object }>}
194
+ */
195
+ function toUint8Array () {
196
+ this.options.resolveWithObject = true;
197
+ this.options.typedArrayOut = true;
198
+ const stack = Error();
199
+ return this._pipeline(null, stack);
200
+ }
201
+
167
202
  /**
168
203
  * Keep all EXIF metadata from the input image in the output image.
169
204
  *
@@ -319,6 +354,30 @@ function withIccProfile (icc, options) {
319
354
  return this;
320
355
  }
321
356
 
357
+ /**
358
+ * If the input contains gain map metadata, use it to convert the main image to HDR (High Dynamic Range) before further processing.
359
+ * The input gain map is discarded.
360
+ *
361
+ * If the output is JPEG, generate and attach a new ISO 21496-1 gain map.
362
+ * JPEG output options other than `quality` are ignored.
363
+ *
364
+ * This feature is experimental and the API may change.
365
+ *
366
+ * @since 0.35.0
367
+ *
368
+ * @example
369
+ * const outputWithGainMap = await sharp(inputWithGainMap)
370
+ * .withGainMap()
371
+ * .toBuffer();
372
+ *
373
+ * @returns {Sharp}
374
+ */
375
+ function withGainMap() {
376
+ this.options.withGainMap = true;
377
+ this.options.colourspace = 'scrgb';
378
+ return this;
379
+ }
380
+
322
381
  /**
323
382
  * Keep XMP metadata from the input image in the output image.
324
383
  *
@@ -690,6 +749,7 @@ function png (options) {
690
749
  * @param {number|number[]} [options.delay] - delay(s) between animation frames (in milliseconds)
691
750
  * @param {boolean} [options.minSize=false] - prevent use of animation key frames to minimise file size (slow)
692
751
  * @param {boolean} [options.mixed=false] - allow mixture of lossy and lossless animation frames (slow)
752
+ * @param {boolean} [options.exact=false] - preserve the colour data in transparent pixels
693
753
  * @param {boolean} [options.force=true] - force WebP output, otherwise attempt to use input format
694
754
  * @returns {Sharp}
695
755
  * @throws {Error} Invalid options
@@ -742,6 +802,9 @@ function webp (options) {
742
802
  if (is.defined(options.mixed)) {
743
803
  this._setBooleanOption('webpMixed', options.mixed);
744
804
  }
805
+ if (is.defined(options.exact)) {
806
+ this._setBooleanOption('webpExact', options.exact);
807
+ }
745
808
  }
746
809
  trySetAnimationOptions(options, this.options);
747
810
  return this._updateFormatOut('webp', options);
@@ -887,7 +950,7 @@ function gif (options) {
887
950
  */
888
951
  function jp2 (options) {
889
952
  /* node:coverage ignore next 41 */
890
- if (!this.constructor.format.jp2k.output.buffer) {
953
+ if (!this.constructor.format.jp2.output.buffer) {
891
954
  throw errJp2Save();
892
955
  }
893
956
  if (is.object(options)) {
@@ -992,7 +1055,7 @@ function trySetAnimationOptions (source, target) {
992
1055
  * @param {number} [options.xres=1.0] - horizontal resolution in pixels/mm
993
1056
  * @param {number} [options.yres=1.0] - vertical resolution in pixels/mm
994
1057
  * @param {string} [options.resolutionUnit='inch'] - resolution unit options: inch, cm
995
- * @param {number} [options.bitdepth=8] - reduce bitdepth to 1, 2 or 4 bit
1058
+ * @param {number} [options.bitdepth=0] - reduce bitdepth to 1, 2 or 4 bit
996
1059
  * @param {boolean} [options.miniswhite=false] - write 1-bit images as miniswhite
997
1060
  * @returns {Sharp}
998
1061
  * @throws {Error} Invalid options
@@ -1007,10 +1070,10 @@ function tiff (options) {
1007
1070
  }
1008
1071
  }
1009
1072
  if (is.defined(options.bitdepth)) {
1010
- if (is.integer(options.bitdepth) && is.inArray(options.bitdepth, [1, 2, 4, 8])) {
1073
+ if (is.integer(options.bitdepth) && is.inArray(options.bitdepth, [1, 2, 4])) {
1011
1074
  this.options.tiffBitdepth = options.bitdepth;
1012
1075
  } else {
1013
- throw is.invalidParameterError('bitdepth', '1, 2, 4 or 8', options.bitdepth);
1076
+ throw is.invalidParameterError('bitdepth', '1, 2 or 4', options.bitdepth);
1014
1077
  }
1015
1078
  }
1016
1079
  // tiling
@@ -1092,8 +1155,7 @@ function tiff (options) {
1092
1155
  * AVIF image sequences are not supported.
1093
1156
  * Prebuilt binaries support a bitdepth of 8 only.
1094
1157
  *
1095
- * This feature is experimental on the Windows ARM64 platform
1096
- * and requires a CPU with ARM64v8.4 or later.
1158
+ * When using Windows ARM64, this feature requires a CPU with ARM64v8.4 or later.
1097
1159
  *
1098
1160
  * @example
1099
1161
  * const data = await sharp(input)
@@ -1113,11 +1175,13 @@ function tiff (options) {
1113
1175
  * @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 9 (slowest)
1114
1176
  * @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
1115
1177
  * @param {number} [options.bitdepth=8] - set bitdepth to 8, 10 or 12 bit
1178
+ * @param {string} [options.tune='iq'] - tune output for a quality metric, one of 'iq' (default), 'ssim' (default when lossless) or 'psnr'
1116
1179
  * @returns {Sharp}
1117
1180
  * @throws {Error} Invalid options
1118
1181
  */
1119
1182
  function avif (options) {
1120
- return this.heif({ ...options, compression: 'av1' });
1183
+ const tune = is.object(options) && is.defined(options.tune) ? options.tune : 'iq';
1184
+ return this.heif({ ...options, compression: 'av1', tune });
1121
1185
  }
1122
1186
 
1123
1187
  /**
@@ -1140,6 +1204,7 @@ function avif (options) {
1140
1204
  * @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 9 (slowest)
1141
1205
  * @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
1142
1206
  * @param {number} [options.bitdepth=8] - set bitdepth to 8, 10 or 12 bit
1207
+ * @param {string} [options.tune='ssim'] - tune output for a quality metric, one of 'ssim' (default), 'psnr' or 'iq'
1143
1208
  * @returns {Sharp}
1144
1209
  * @throws {Error} Invalid options
1145
1210
  */
@@ -1188,6 +1253,17 @@ function heif (options) {
1188
1253
  throw is.invalidParameterError('bitdepth', '8, 10 or 12', options.bitdepth);
1189
1254
  }
1190
1255
  }
1256
+ if (is.defined(options.tune)) {
1257
+ if (is.string(options.tune) && is.inArray(options.tune, ['iq', 'ssim', 'psnr'])) {
1258
+ if (this.options.heifLossless && options.tune === 'iq') {
1259
+ this.options.heifTune = 'ssim';
1260
+ } else {
1261
+ this.options.heifTune = options.tune;
1262
+ }
1263
+ } else {
1264
+ throw is.invalidParameterError('tune', 'one of: psnr, ssim, iq', options.tune);
1265
+ }
1266
+ }
1191
1267
  } else {
1192
1268
  throw is.invalidParameterError('options', 'Object', options);
1193
1269
  }
@@ -1635,11 +1711,13 @@ module.exports = (Sharp) => {
1635
1711
  // Public
1636
1712
  toFile,
1637
1713
  toBuffer,
1714
+ toUint8Array,
1638
1715
  keepExif,
1639
1716
  withExif,
1640
1717
  withExifMerge,
1641
1718
  keepIccProfile,
1642
1719
  withIccProfile,
1720
+ withGainMap,
1643
1721
  keepXmp,
1644
1722
  withXmp,
1645
1723
  keepMetadata,
package/lib/resize.js CHANGED
@@ -540,10 +540,19 @@ function extract (options) {
540
540
  * })
541
541
  * .toBuffer();
542
542
  *
543
+ * @example
544
+ * // Trim image leaving (up to) a 10 pixel margin around the trimmed content.
545
+ * const output = await sharp(input)
546
+ * .trim({
547
+ * margin: 10
548
+ * })
549
+ * .toBuffer();
550
+ *
543
551
  * @param {Object} [options]
544
552
  * @param {string|Object} [options.background='top-left pixel'] - Background colour, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to that of the top-left pixel.
545
553
  * @param {number} [options.threshold=10] - Allowed difference from the above colour, a positive number.
546
554
  * @param {boolean} [options.lineArt=false] - Does the input more closely resemble line art (e.g. vector) rather than being photographic?
555
+ * @param {number} [options.margin=0] - Leave a margin around trimmed content, value is in pixels.
547
556
  * @returns {Sharp}
548
557
  * @throws {Error} Invalid parameters
549
558
  */
@@ -564,6 +573,13 @@ function trim (options) {
564
573
  if (is.defined(options.lineArt)) {
565
574
  this._setBooleanOption('trimLineArt', options.lineArt);
566
575
  }
576
+ if (is.defined(options.margin)) {
577
+ if (is.integer(options.margin) && options.margin >= 0) {
578
+ this.options.trimMargin = options.margin;
579
+ } else {
580
+ throw is.invalidParameterError('margin', 'positive integer', options.margin);
581
+ }
582
+ }
567
583
  } else {
568
584
  throw is.invalidParameterError('trim', 'object', options);
569
585
  }
package/lib/sharp.js CHANGED
@@ -7,13 +7,14 @@
7
7
 
8
8
  const { familySync, versionSync } = require('detect-libc');
9
9
 
10
+ const { version } = require('../package.json');
10
11
  const { runtimePlatformArch, isUnsupportedNodeRuntime, prebuiltPlatforms, minimumLibvipsVersion } = require('./libvips');
11
12
  const runtimePlatform = runtimePlatformArch();
12
13
 
13
14
  const paths = [
14
- `../src/build/Release/sharp-${runtimePlatform}.node`,
15
- '../src/build/Release/sharp-wasm32.node',
16
- `@revizly/sharp-${runtimePlatform}/sharp.node`,
15
+ `../src/build/Release/sharp-${runtimePlatform}-${version}.node`,
16
+ `../src/build/Release/sharp-wasm32-${version}.node`,
17
+ `@revizly/harp-${runtimePlatform}/sharp.node`,
17
18
  '@revizly/sharp-wasm32/sharp.node'
18
19
  ];
19
20
 
@@ -72,6 +73,7 @@ if (sharp) {
72
73
  } else {
73
74
  help.push(
74
75
  `- Manually install libvips >= ${minimumLibvipsVersion}`,
76
+ ' See https://sharp.pixelplumbing.com/install#building-from-source',
75
77
  '- Add experimental WebAssembly-based dependencies:',
76
78
  ' npm install --cpu=wasm32 sharp',
77
79
  ' npm install @revizly/sharp-wasm32'
package/lib/utility.js CHANGED
@@ -24,7 +24,7 @@ const format = sharp.format();
24
24
  format.heif.output.alias = ['avif', 'heic'];
25
25
  format.jpeg.output.alias = ['jpe', 'jpg'];
26
26
  format.tiff.output.alias = ['tif'];
27
- format.jp2k.output.alias = ['j2c', 'j2k', 'jp2', 'jpx'];
27
+ format.jp2.output.alias = ['j2c', 'j2k', 'jp2', 'jpx'];
28
28
 
29
29
  /**
30
30
  * An Object containing the available interpolators and their proper values