sharp 0.28.2 → 0.29.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
@@ -16,7 +16,7 @@ Lanczos resampling ensures quality is not sacrificed for speed.
16
16
  As well as image resizing, operations such as
17
17
  rotation, extraction, compositing and gamma correction are available.
18
18
 
19
- Most modern macOS, Windows and Linux systems running Node.js v10+
19
+ Most modern macOS, Windows and Linux systems running Node.js >= 12.13.0
20
20
  do not require any additional install or runtime dependencies.
21
21
 
22
22
  ## Documentation
@@ -99,7 +99,7 @@ A [guide for contributors](https://github.com/lovell/sharp/blob/master/.github/C
99
99
  covers reporting bugs, requesting features and submitting code changes.
100
100
 
101
101
  [![Test Coverage](https://coveralls.io/repos/lovell/sharp/badge.svg?branch=master)](https://coveralls.io/r/lovell/sharp?branch=master)
102
- [![N-API v3](https://img.shields.io/badge/N--API-v3-green.svg)](https://nodejs.org/dist/latest/docs/api/n-api.html#n_api_n_api_version_matrix)
102
+ [![Node-API v5](https://img.shields.io/badge/Node--API-v5-green.svg)](https://nodejs.org/dist/latest/docs/api/n-api.html#n_api_n_api_version_matrix)
103
103
 
104
104
  ## Licensing
105
105
 
package/binding.gyp CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  'variables': {
3
3
  'vips_version': '<!(node -p "require(\'./lib/libvips\').minimumLibvipsVersion")',
4
- 'sharp_vendor_dir': '<(module_root_dir)/vendor/<(vips_version)'
4
+ 'platform_and_arch': '<!(node -p "require(\'./lib/platform\')()")',
5
+ 'sharp_vendor_dir': './vendor/<(vips_version)/<(platform_and_arch)'
5
6
  },
6
7
  'targets': [{
7
8
  'target_name': 'libvips-cpp',
@@ -37,6 +38,7 @@
37
38
  'msvs_settings': {
38
39
  'VCCLCompilerTool': {
39
40
  'ExceptionHandling': 1,
41
+ 'Optimization': 1,
40
42
  'WholeProgramOptimization': 'true'
41
43
  },
42
44
  'VCLibrarianTool': {
@@ -65,9 +67,9 @@
65
67
  }]
66
68
  ]
67
69
  }, {
68
- 'target_name': 'sharp',
70
+ 'target_name': 'sharp-<(platform_and_arch)',
69
71
  'defines': [
70
- 'NAPI_VERSION=3'
72
+ 'NAPI_VERSION=5'
71
73
  ],
72
74
  'dependencies': [
73
75
  '<!(node -p "require(\'node-addon-api\').gyp")',
@@ -138,7 +140,7 @@
138
140
  }],
139
141
  ['OS == "mac"', {
140
142
  'link_settings': {
141
- 'library_dirs': ['<(sharp_vendor_dir)/lib'],
143
+ 'library_dirs': ['../<(sharp_vendor_dir)/lib'],
142
144
  'libraries': [
143
145
  'libvips-cpp.42.dylib'
144
146
  ]
@@ -146,7 +148,7 @@
146
148
  'xcode_settings': {
147
149
  'OTHER_LDFLAGS': [
148
150
  # Ensure runtime linking is relative to sharp.node
149
- '-Wl,-rpath,\'@loader_path/../../vendor/<(vips_version)/lib\''
151
+ '-Wl,-rpath,\'@loader_path/../../<(sharp_vendor_dir)/lib\''
150
152
  ]
151
153
  }
152
154
  }],
@@ -155,13 +157,13 @@
155
157
  '_GLIBCXX_USE_CXX11_ABI=1'
156
158
  ],
157
159
  'link_settings': {
158
- 'library_dirs': ['<(sharp_vendor_dir)/lib'],
160
+ 'library_dirs': ['../<(sharp_vendor_dir)/lib'],
159
161
  'libraries': [
160
162
  '-l:libvips-cpp.so.42'
161
163
  ],
162
164
  'ldflags': [
163
165
  # Ensure runtime linking is relative to sharp.node
164
- '-Wl,-s -Wl,--disable-new-dtags -Wl,-rpath=\'$$ORIGIN/../../vendor/<(vips_version)/lib\''
166
+ '-Wl,-s -Wl,--disable-new-dtags -Wl,-rpath=\'$$ORIGIN/../../<(sharp_vendor_dir)/lib\''
165
167
  ]
166
168
  }
167
169
  }]
@@ -172,7 +174,7 @@
172
174
  '-std=c++0x',
173
175
  '-fexceptions',
174
176
  '-Wall',
175
- '-O3'
177
+ '-Os'
176
178
  ],
177
179
  'xcode_settings': {
178
180
  'CLANG_CXX_LANGUAGE_STANDARD': 'c++11',
@@ -182,7 +184,7 @@
182
184
  'OTHER_CPLUSPLUSFLAGS': [
183
185
  '-fexceptions',
184
186
  '-Wall',
185
- '-O3'
187
+ '-Oz'
186
188
  ]
187
189
  },
188
190
  'configurations': {
@@ -202,6 +204,7 @@
202
204
  'msvs_settings': {
203
205
  'VCCLCompilerTool': {
204
206
  'ExceptionHandling': 1,
207
+ 'Optimization': 1,
205
208
  'WholeProgramOptimization': 'true'
206
209
  },
207
210
  'VCLibrarianTool': {
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ const libvips = require('../lib/libvips');
4
+
5
+ try {
6
+ if (!(libvips.useGlobalLibvips() || libvips.hasVendoredLibvips())) {
7
+ process.exitCode = 1;
8
+ }
9
+ } catch (err) {
10
+ process.exitCode = 1;
11
+ }
@@ -4,19 +4,19 @@ const fs = require('fs');
4
4
  const path = require('path');
5
5
 
6
6
  const libvips = require('../lib/libvips');
7
+ const platform = require('../lib/platform');
7
8
 
8
9
  const minimumLibvipsVersion = libvips.minimumLibvipsVersion;
9
10
 
10
- const platform = process.env.npm_config_platform || process.platform;
11
- if (platform === 'win32') {
12
- const buildDir = path.join(__dirname, '..', 'build');
13
- const buildReleaseDir = path.join(buildDir, 'Release');
11
+ const platformAndArch = platform();
12
+
13
+ if (platformAndArch.startsWith('win32')) {
14
+ const buildReleaseDir = path.join(__dirname, '..', 'build', 'Release');
14
15
  libvips.log(`Creating ${buildReleaseDir}`);
15
16
  try {
16
- libvips.mkdirSync(buildDir);
17
17
  libvips.mkdirSync(buildReleaseDir);
18
18
  } catch (err) {}
19
- const vendorLibDir = path.join(__dirname, '..', 'vendor', minimumLibvipsVersion, 'lib');
19
+ const vendorLibDir = path.join(__dirname, '..', 'vendor', minimumLibvipsVersion, platformAndArch, 'lib');
20
20
  libvips.log(`Copying DLLs from ${vendorLibDir} to ${buildReleaseDir}`);
21
21
  try {
22
22
  fs
@@ -24,6 +24,7 @@ const minimumGlibcVersionByArch = {
24
24
 
25
25
  const hasSharpPrebuild = [
26
26
  'darwin-x64',
27
+ 'darwin-arm64',
27
28
  'linux-arm64',
28
29
  'linux-x64',
29
30
  'linuxmusl-x64',
@@ -35,7 +36,6 @@ const hasSharpPrebuild = [
35
36
  const { minimumLibvipsVersion, minimumLibvipsVersionLabelled } = libvips;
36
37
  const distHost = process.env.npm_config_sharp_libvips_binary_host || 'https://github.com/lovell/sharp-libvips/releases/download';
37
38
  const distBaseUrl = process.env.npm_config_sharp_dist_base_url || process.env.SHARP_DIST_BASE_URL || `${distHost}/v${minimumLibvipsVersionLabelled}/`;
38
- const supportsBrotli = ('BrotliDecompress' in zlib);
39
39
  const installationForced = !!(process.env.npm_config_sharp_install_force || process.env.SHARP_INSTALL_FORCE);
40
40
 
41
41
  const fail = function (err) {
@@ -43,7 +43,6 @@ const fail = function (err) {
43
43
  if (err.code === 'EACCES') {
44
44
  libvips.log('Are you trying to install as a root or sudo user? Try again with the --unsafe-perm flag');
45
45
  }
46
- libvips.log('Attempting to build from source via node-gyp but this may fail due to the above error');
47
46
  libvips.log('Please see https://sharp.pixelplumbing.com/install for required dependencies');
48
47
  process.exit(1);
49
48
  };
@@ -57,9 +56,7 @@ const handleError = function (err) {
57
56
  };
58
57
 
59
58
  const extractTarball = function (tarPath, platformAndArch) {
60
- const vendorPath = path.join(__dirname, '..', 'vendor');
61
- libvips.mkdirSync(vendorPath);
62
- const versionedVendorPath = path.join(vendorPath, minimumLibvipsVersion);
59
+ const versionedVendorPath = path.join(__dirname, '..', 'vendor', minimumLibvipsVersion, platformAndArch);
63
60
  libvips.mkdirSync(versionedVendorPath);
64
61
 
65
62
  const ignoreVendorInclude = hasSharpPrebuild.includes(platformAndArch) && !process.env.npm_config_build_from_source;
@@ -69,7 +66,7 @@ const extractTarball = function (tarPath, platformAndArch) {
69
66
 
70
67
  stream.pipeline(
71
68
  fs.createReadStream(tarPath),
72
- supportsBrotli ? new zlib.BrotliDecompress() : new zlib.Gunzip(),
69
+ new zlib.BrotliDecompress(),
73
70
  tarFs.extract(versionedVendorPath, { ignore }),
74
71
  function (err) {
75
72
  if (err) {
@@ -122,10 +119,8 @@ try {
122
119
  handleError(new Error(`Expected Node.js version ${supportedNodeVersion} but found ${process.versions.node}`));
123
120
  }
124
121
 
125
- const extension = supportsBrotli ? 'br' : 'gz';
126
-
127
122
  // Download to per-process temporary file
128
- const tarFilename = ['libvips', minimumLibvipsVersion, platformAndArch].join('-') + '.tar.' + extension;
123
+ const tarFilename = ['libvips', minimumLibvipsVersion, platformAndArch].join('-') + '.tar.br';
129
124
  const tarPathCache = path.join(libvips.cachePath(), tarFilename);
130
125
  if (fs.existsSync(tarPathCache)) {
131
126
  libvips.log(`Using cached ${tarPathCache}`);
package/lib/channel.js CHANGED
@@ -15,6 +15,8 @@ const bool = {
15
15
  /**
16
16
  * Remove alpha channel, if any. This is a no-op if the image does not have an alpha channel.
17
17
  *
18
+ * See also {@link /api-operation#flatten|flatten}.
19
+ *
18
20
  * @example
19
21
  * sharp('rgba.png')
20
22
  * .removeAlpha()
@@ -70,13 +72,17 @@ function ensureAlpha (alpha) {
70
72
  * Extract a single channel from a multi-channel image.
71
73
  *
72
74
  * @example
73
- * sharp(input)
75
+ * // green.jpg is a greyscale image containing the green channel of the input
76
+ * await sharp(input)
74
77
  * .extractChannel('green')
75
- * .toColourspace('b-w')
76
- * .toFile('green.jpg', function(err, info) {
77
- * // info.channels === 1
78
- * // green.jpg is a greyscale image containing the green channel of the input
79
- * });
78
+ * .toFile('green.jpg');
79
+ *
80
+ * @example
81
+ * // red1 is the red value of the first pixel, red2 the second pixel etc.
82
+ * const [red1, red2, ...] = await sharp(input)
83
+ * .extractChannel(0)
84
+ * .raw()
85
+ * .toBuffer();
80
86
  *
81
87
  * @param {number|string} channel - zero-indexed channel/band number to extract, or `red`, `green`, `blue` or `alpha`.
82
88
  * @returns {Sharp}
@@ -92,7 +98,7 @@ function extractChannel (channel) {
92
98
  } else {
93
99
  throw is.invalidParameterError('channel', 'integer or one of: red, green, blue, alpha', channel);
94
100
  }
95
- return this;
101
+ return this.toColourspace('b-w');
96
102
  }
97
103
 
98
104
  /**
package/lib/colour.js CHANGED
@@ -54,6 +54,45 @@ function grayscale (grayscale) {
54
54
  return this.greyscale(grayscale);
55
55
  }
56
56
 
57
+ /**
58
+ * Set the pipeline colourspace.
59
+ *
60
+ * The input image will be converted to the provided colourspace at the start of the pipeline.
61
+ * All operations will use this colourspace before converting to the output colourspace, as defined by {@link toColourspace}.
62
+ *
63
+ * This feature is experimental and has not yet been fully-tested with all operations.
64
+ *
65
+ * @since 0.29.0
66
+ *
67
+ * @example
68
+ * // Run pipeline in 16 bits per channel RGB while converting final result to 8 bits per channel sRGB.
69
+ * await sharp(input)
70
+ * .pipelineColourspace('rgb16')
71
+ * .toColourspace('srgb')
72
+ * .toFile('16bpc-pipeline-to-8bpc-output.png')
73
+ *
74
+ * @param {string} [colourspace] - pipeline colourspace e.g. `rgb16`, `scrgb`, `lab`, `grey16` [...](https://github.com/libvips/libvips/blob/41cff4e9d0838498487a00623462204eb10ee5b8/libvips/iofuncs/enumtypes.c#L774)
75
+ * @returns {Sharp}
76
+ * @throws {Error} Invalid parameters
77
+ */
78
+ function pipelineColourspace (colourspace) {
79
+ if (!is.string(colourspace)) {
80
+ throw is.invalidParameterError('colourspace', 'string', colourspace);
81
+ }
82
+ this.options.colourspaceInput = colourspace;
83
+ return this;
84
+ }
85
+
86
+ /**
87
+ * Alternative spelling of `pipelineColourspace`.
88
+ * @param {string} [colorspace] - pipeline colorspace.
89
+ * @returns {Sharp}
90
+ * @throws {Error} Invalid parameters
91
+ */
92
+ function pipelineColorspace (colorspace) {
93
+ return this.pipelineColourspace(colorspace);
94
+ }
95
+
57
96
  /**
58
97
  * Set the output colourspace.
59
98
  * By default output image will be web-friendly sRGB, with additional channels interpreted as alpha channels.
@@ -64,7 +103,7 @@ function grayscale (grayscale) {
64
103
  * .toColourspace('rgb16')
65
104
  * .toFile('16-bpp.png')
66
105
  *
67
- * @param {string} [colourspace] - output colourspace e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://github.com/libvips/libvips/blob/master/libvips/iofuncs/enumtypes.c#L568)
106
+ * @param {string} [colourspace] - output colourspace e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://github.com/libvips/libvips/blob/3c0bfdf74ce1dc37a6429bed47fa76f16e2cd70a/libvips/iofuncs/enumtypes.c#L777-L794)
68
107
  * @returns {Sharp}
69
108
  * @throws {Error} Invalid parameters
70
109
  */
@@ -119,6 +158,8 @@ module.exports = function (Sharp) {
119
158
  tint,
120
159
  greyscale,
121
160
  grayscale,
161
+ pipelineColourspace,
162
+ pipelineColorspace,
122
163
  toColourspace,
123
164
  toColorspace,
124
165
  // Private
package/lib/composite.js CHANGED
@@ -89,6 +89,8 @@ const blend = {
89
89
  * @param {Number} [images[].raw.width]
90
90
  * @param {Number} [images[].raw.height]
91
91
  * @param {Number} [images[].raw.channels]
92
+ * @param {boolean} [images[].failOnError=true] - @see {@link /api-constructor#parameters|constructor parameters}
93
+ * @param {number|boolean} [images[].limitInputPixels=268402689] - @see {@link /api-constructor#parameters|constructor parameters}
92
94
  * @returns {Sharp}
93
95
  * @throws {Error} Invalid parameters
94
96
  */
@@ -5,32 +5,7 @@ const stream = require('stream');
5
5
  const is = require('./is');
6
6
 
7
7
  require('./libvips').hasVendoredLibvips();
8
-
9
- /* istanbul ignore next */
10
- try {
11
- require('../build/Release/sharp.node');
12
- } catch (err) {
13
- // Bail early if bindings aren't available
14
- const help = ['', 'Something went wrong installing the "sharp" module', '', err.message, ''];
15
- if (/NODE_MODULE_VERSION/.test(err.message)) {
16
- help.push('- Ensure the version of Node.js used at install time matches that used at runtime');
17
- } else if (/invalid ELF header/.test(err.message)) {
18
- help.push(`- Ensure "${process.platform}" is used at install time as well as runtime`);
19
- } else if (/dylib/.test(err.message) && /Incompatible library version/.test(err.message)) {
20
- help.push('- Run "brew update && brew upgrade vips"');
21
- } else {
22
- help.push(
23
- '- Remove the "node_modules/sharp" directory then run',
24
- ' "npm install --ignore-scripts=false --verbose sharp" and look for errors'
25
- );
26
- }
27
- help.push(
28
- '- Consult the installation documentation at https://sharp.pixelplumbing.com/install',
29
- '- Search for this error at https://github.com/lovell/sharp/issues', ''
30
- );
31
- const error = help.join('\n');
32
- throw new Error(error);
33
- }
8
+ require('./sharp');
34
9
 
35
10
  // Use NODE_DEBUG=sharp to enable libvips warnings
36
11
  const debuglog = util.debuglog('sharp');
@@ -117,8 +92,9 @@ const debuglog = util.debuglog('sharp');
117
92
  * }
118
93
  * }).toFile('noise.png');
119
94
  *
120
- * @param {(Buffer|Uint8Array|Uint8ClampedArray|string)} [input] - if present, can be
121
- * a Buffer / Uint8Array / Uint8ClampedArray containing JPEG, PNG, WebP, AVIF, GIF, SVG, TIFF or raw pixel image data, or
95
+ * @param {(Buffer|Uint8Array|Uint8ClampedArray|Int8Array|Uint16Array|Int16Array|Uint32Array|Int32Array|Float32Array|Float64Array|string)} [input] - if present, can be
96
+ * a Buffer / Uint8Array / Uint8ClampedArray containing JPEG, PNG, WebP, AVIF, GIF, SVG or TIFF image data, or
97
+ * a TypedArray containing raw pixel image data, or
122
98
  * a String containing the filesystem path to an JPEG, PNG, WebP, AVIF, GIF, SVG or TIFF image file.
123
99
  * JPEG, PNG, WebP, AVIF, GIF, SVG, TIFF or raw pixel image data can be streamed into the object when not present.
124
100
  * @param {Object} [options] - if present, is an Object with optional attributes.
@@ -204,6 +180,7 @@ const Sharp = function (input, options) {
204
180
  flatten: false,
205
181
  flattenBackground: [0, 0, 0],
206
182
  negate: false,
183
+ negateAlpha: true,
207
184
  medianSize: 0,
208
185
  blurSigma: 0,
209
186
  sharpenSigma: 0,
@@ -216,9 +193,13 @@ const Sharp = function (input, options) {
216
193
  gammaOut: 0,
217
194
  greyscale: false,
218
195
  normalise: false,
196
+ claheWidth: 0,
197
+ claheHeight: 0,
198
+ claheMaxSlope: 3,
219
199
  brightness: 1,
220
200
  saturation: 1,
221
201
  hue: 0,
202
+ lightness: 0,
222
203
  booleanBufferIn: null,
223
204
  booleanFileIn: '',
224
205
  joinChannelIn: [],
@@ -226,6 +207,7 @@ const Sharp = function (input, options) {
226
207
  removeAlpha: false,
227
208
  ensureAlpha: -1,
228
209
  colourspace: 'srgb',
210
+ colourspaceInput: 'last',
229
211
  composite: [],
230
212
  // output
231
213
  fileOut: '',
@@ -251,8 +233,13 @@ const Sharp = function (input, options) {
251
233
  pngAdaptiveFiltering: false,
252
234
  pngPalette: false,
253
235
  pngQuality: 100,
254
- pngColours: 256,
236
+ pngBitdepth: 8,
255
237
  pngDither: 1,
238
+ jp2Quality: 80,
239
+ jp2TileHeight: 512,
240
+ jp2TileWidth: 512,
241
+ jp2Lossless: false,
242
+ jp2ChromaSubsampling: '4:4:4',
256
243
  webpQuality: 80,
257
244
  webpAlphaQuality: 100,
258
245
  webpLossless: false,
@@ -273,7 +260,8 @@ const Sharp = function (input, options) {
273
260
  heifLossless: false,
274
261
  heifCompression: 'av1',
275
262
  heifSpeed: 5,
276
- heifChromaSubsampling: '4:2:0',
263
+ heifChromaSubsampling: '4:4:4',
264
+ rawDepth: 'uchar',
277
265
  tileSize: 256,
278
266
  tileOverlap: 0,
279
267
  tileContainer: 'fs',
@@ -285,6 +273,7 @@ const Sharp = function (input, options) {
285
273
  tileBackground: [255, 255, 255, 255],
286
274
  tileCentre: false,
287
275
  tileId: 'https://example.com/iiif',
276
+ timeoutSeconds: 0,
288
277
  linearA: 1,
289
278
  linearB: 0,
290
279
  // Function to notify of libvips warnings
@@ -300,7 +289,8 @@ const Sharp = function (input, options) {
300
289
  this.options.input = this._createInputDescriptor(input, options, { allowStream: true });
301
290
  return this;
302
291
  };
303
- util.inherits(Sharp, stream.Duplex);
292
+ Object.setPrototypeOf(Sharp.prototype, stream.Duplex.prototype);
293
+ Object.setPrototypeOf(Sharp, stream.Duplex);
304
294
 
305
295
  /**
306
296
  * Take a "snapshot" of the Sharp instance, returning a new instance.
package/lib/input.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  const color = require('color');
4
4
  const is = require('./is');
5
- const sharp = require('../build/Release/sharp.node');
5
+ const sharp = require('./sharp');
6
6
 
7
7
  /**
8
8
  * Extract input options, if any, from an object.
@@ -34,8 +34,7 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
34
34
  throw Error('Input Buffer is empty');
35
35
  }
36
36
  inputDescriptor.buffer = input;
37
- } else if (is.uint8Array(input)) {
38
- // Uint8Array or Uint8ClampedArray
37
+ } else if (is.typedArray(input)) {
39
38
  if (input.length === 0) {
40
39
  throw Error('Input Bit Array is empty');
41
40
  }
@@ -104,6 +103,37 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
104
103
  inputDescriptor.rawHeight = inputOptions.raw.height;
105
104
  inputDescriptor.rawChannels = inputOptions.raw.channels;
106
105
  inputDescriptor.rawPremultiplied = !!inputOptions.raw.premultiplied;
106
+
107
+ switch (input.constructor) {
108
+ case Uint8Array:
109
+ case Uint8ClampedArray:
110
+ inputDescriptor.rawDepth = 'uchar';
111
+ break;
112
+ case Int8Array:
113
+ inputDescriptor.rawDepth = 'char';
114
+ break;
115
+ case Uint16Array:
116
+ inputDescriptor.rawDepth = 'ushort';
117
+ break;
118
+ case Int16Array:
119
+ inputDescriptor.rawDepth = 'short';
120
+ break;
121
+ case Uint32Array:
122
+ inputDescriptor.rawDepth = 'uint';
123
+ break;
124
+ case Int32Array:
125
+ inputDescriptor.rawDepth = 'int';
126
+ break;
127
+ case Float32Array:
128
+ inputDescriptor.rawDepth = 'float';
129
+ break;
130
+ case Float64Array:
131
+ inputDescriptor.rawDepth = 'double';
132
+ break;
133
+ default:
134
+ inputDescriptor.rawDepth = 'uchar';
135
+ break;
136
+ }
107
137
  } else {
108
138
  throw new Error('Expected width, height and channels for raw pixel input');
109
139
  }
@@ -271,6 +301,8 @@ function _isStreamInput () {
271
301
  * - `pagePrimary`: Number of the primary page in a HEIF image
272
302
  * - `levels`: Details of each level in a multi-level image provided as an array of objects, requires libvips compiled with support for OpenSlide
273
303
  * - `subifds`: Number of Sub Image File Directories in an OME-TIFF image
304
+ * - `background`: Default background colour, if present, for PNG (bKGD) and GIF images, either an RGB Object or a single greyscale value
305
+ * - `compression`: The encoder used to compress an HEIF file, `av1` (AVIF) or `hevc` (HEIC)
274
306
  * - `hasProfile`: Boolean indicating the presence of an embedded ICC profile
275
307
  * - `hasAlpha`: Boolean indicating the presence of an alpha transparency channel
276
308
  * - `orientation`: Number value of the EXIF Orientation header, if present
@@ -356,6 +388,9 @@ function metadata (callback) {
356
388
  * - `sharpness`: Estimation of greyscale sharpness based on the standard deviation of a Laplacian convolution, discarding alpha channel if any (experimental)
357
389
  * - `dominant`: Object containing most dominant sRGB colour based on a 4096-bin 3D histogram (experimental)
358
390
  *
391
+ * **Note**: Statistics are derived from the original input image. Any operations performed on the image must first be
392
+ * written to a buffer in order to run `stats` on the result (see third example).
393
+ *
359
394
  * @example
360
395
  * const image = sharp(inputJpg);
361
396
  * image
@@ -368,6 +403,13 @@ function metadata (callback) {
368
403
  * const { entropy, sharpness, dominant } = await sharp(input).stats();
369
404
  * const { r, g, b } = dominant;
370
405
  *
406
+ * @example
407
+ * const image = sharp(input);
408
+ * // store intermediate result
409
+ * const part = await image.extract(region).toBuffer();
410
+ * // create new instance to obtain statistics of extracted region
411
+ * const stats = await sharp(part).stats();
412
+ *
371
413
  * @param {Function} [callback] - called with the arguments `(err, stats)`
372
414
  * @returns {Promise<Object>}
373
415
  */
package/lib/is.js CHANGED
@@ -49,12 +49,26 @@ const buffer = function (val) {
49
49
  };
50
50
 
51
51
  /**
52
- * Is this value a Uint8Array or Uint8ClampedArray object?
52
+ * Is this value a typed array object?. E.g. Uint8Array or Uint8ClampedArray?
53
53
  * @private
54
54
  */
55
- const uint8Array = function (val) {
56
- // allow both since Uint8ClampedArray simply clamps the values between 0-255
57
- return val instanceof Uint8Array || val instanceof Uint8ClampedArray;
55
+ const typedArray = function (val) {
56
+ if (defined(val)) {
57
+ switch (val.constructor) {
58
+ case Uint8Array:
59
+ case Uint8ClampedArray:
60
+ case Int8Array:
61
+ case Uint16Array:
62
+ case Int16Array:
63
+ case Uint32Array:
64
+ case Int32Array:
65
+ case Float32Array:
66
+ case Float64Array:
67
+ return true;
68
+ }
69
+ }
70
+
71
+ return false;
58
72
  };
59
73
 
60
74
  /**
@@ -119,7 +133,7 @@ module.exports = {
119
133
  fn: fn,
120
134
  bool: bool,
121
135
  buffer: buffer,
122
- uint8Array: uint8Array,
136
+ typedArray: typedArray,
123
137
  string: string,
124
138
  number: number,
125
139
  integer: integer,
package/lib/libvips.js CHANGED
@@ -21,9 +21,9 @@ const spawnSyncOptions = {
21
21
 
22
22
  const mkdirSync = function (dirPath) {
23
23
  try {
24
- fs.mkdirSync(dirPath);
24
+ fs.mkdirSync(dirPath, { recursive: true });
25
25
  } catch (err) {
26
- /* istanbul ignore if */
26
+ /* istanbul ignore next */
27
27
  if (err.code !== 'EEXIST') {
28
28
  throw err;
29
29
  }
@@ -67,23 +67,8 @@ const globalLibvipsVersion = function () {
67
67
  };
68
68
 
69
69
  const hasVendoredLibvips = function () {
70
- const currentPlatformId = platform();
71
- const vendorPath = path.join(__dirname, '..', 'vendor', minimumLibvipsVersion);
72
- let vendorPlatformId;
73
- try {
74
- vendorPlatformId = require(path.join(vendorPath, 'platform.json'));
75
- } catch (err) {}
76
- /* istanbul ignore else */
77
- if (vendorPlatformId) {
78
- /* istanbul ignore else */
79
- if (currentPlatformId === vendorPlatformId) {
80
- return true;
81
- } else {
82
- throw new Error(`'${vendorPlatformId}' binaries cannot be used on the '${currentPlatformId}' platform. Please remove the 'node_modules/sharp' directory and run 'npm install' on the '${currentPlatformId}' platform.`);
83
- }
84
- } else {
85
- return false;
86
- }
70
+ const vendorPath = path.join(__dirname, '..', 'vendor', minimumLibvipsVersion, platform());
71
+ return fs.existsSync(vendorPath);
87
72
  };
88
73
 
89
74
  const pkgConfigPath = function () {