@revizly/sharp 0.35.0-revizly4 → 0.35.0-revizly40

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.
Files changed (46) hide show
  1. package/README.md +12 -18
  2. package/{lib/channel.js → dist/channel.cjs} +1 -1
  3. package/dist/channel.mjs +177 -0
  4. package/{lib/colour.js → dist/colour.cjs} +1 -1
  5. package/dist/colour.mjs +195 -0
  6. package/{lib/composite.js → dist/composite.cjs} +2 -1
  7. package/dist/composite.mjs +213 -0
  8. package/{lib/constructor.js → dist/constructor.cjs} +42 -29
  9. package/dist/constructor.mjs +512 -0
  10. package/dist/index.cjs +25 -0
  11. package/dist/index.d.cts +1999 -0
  12. package/dist/index.d.mts +2046 -0
  13. package/dist/index.mjs +25 -0
  14. package/{lib/input.js → dist/input.cjs} +22 -17
  15. package/dist/input.mjs +814 -0
  16. package/{lib/is.js → dist/is.cjs} +1 -1
  17. package/dist/is.mjs +143 -0
  18. package/{lib/libvips.js → dist/libvips.cjs} +35 -30
  19. package/dist/libvips.mjs +212 -0
  20. package/{lib/operation.js → dist/operation.cjs} +22 -47
  21. package/dist/operation.mjs +991 -0
  22. package/{lib/output.js → dist/output.cjs} +161 -28
  23. package/dist/output.mjs +1799 -0
  24. package/{lib/resize.js → dist/resize.cjs} +40 -18
  25. package/dist/resize.mjs +617 -0
  26. package/dist/sharp.cjs +119 -0
  27. package/dist/sharp.mjs +119 -0
  28. package/{lib/utility.js → dist/utility.cjs} +11 -7
  29. package/dist/utility.mjs +295 -0
  30. package/install/build.js +3 -3
  31. package/lib/index.d.ts +99 -71
  32. package/package.json +46 -27
  33. package/src/binding.gyp +18 -13
  34. package/src/common.cc +70 -17
  35. package/src/common.h +22 -3
  36. package/src/metadata.cc +66 -8
  37. package/src/metadata.h +6 -1
  38. package/src/operations.cc +25 -8
  39. package/src/operations.h +1 -1
  40. package/src/pipeline.cc +194 -69
  41. package/src/pipeline.h +14 -1
  42. package/src/stats.cc +6 -6
  43. package/src/utilities.cc +4 -3
  44. package/install/check.js +0 -14
  45. package/lib/index.js +0 -16
  46. package/lib/sharp.js +0 -121
@@ -78,7 +78,7 @@ const string = (val) => typeof val === 'string' && val.length > 0;
78
78
  * Is this value a real number?
79
79
  * @private
80
80
  */
81
- const number = (val) => typeof val === 'number' && !Number.isNaN(val);
81
+ const number = (val) => typeof val === 'number' && Number.isFinite(val);
82
82
 
83
83
  /**
84
84
  * Is this value an integer?
package/dist/is.mjs ADDED
@@ -0,0 +1,143 @@
1
+ /*!
2
+ Copyright 2013 Lovell Fuller and others.
3
+ SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ /**
7
+ * Is this value defined and not null?
8
+ * @private
9
+ */
10
+ const defined = (val) => typeof val !== 'undefined' && val !== null;
11
+
12
+ /**
13
+ * Is this value an object?
14
+ * @private
15
+ */
16
+ const object = (val) => typeof val === 'object';
17
+
18
+ /**
19
+ * Is this value a plain object?
20
+ * @private
21
+ */
22
+ const plainObject = (val) => Object.prototype.toString.call(val) === '[object Object]';
23
+
24
+ /**
25
+ * Is this value a function?
26
+ * @private
27
+ */
28
+ const fn = (val) => typeof val === 'function';
29
+
30
+ /**
31
+ * Is this value a boolean?
32
+ * @private
33
+ */
34
+ const bool = (val) => typeof val === 'boolean';
35
+
36
+ /**
37
+ * Is this value a Buffer object?
38
+ * @private
39
+ */
40
+ const buffer = (val) => val instanceof Buffer;
41
+
42
+ /**
43
+ * Is this value a typed array object?. E.g. Uint8Array or Uint8ClampedArray?
44
+ * @private
45
+ */
46
+ const typedArray = (val) => {
47
+ if (defined(val)) {
48
+ switch (val.constructor) {
49
+ case Uint8Array:
50
+ case Uint8ClampedArray:
51
+ case Int8Array:
52
+ case Uint16Array:
53
+ case Int16Array:
54
+ case Uint32Array:
55
+ case Int32Array:
56
+ case Float32Array:
57
+ case Float64Array:
58
+ return true;
59
+ }
60
+ }
61
+
62
+ return false;
63
+ };
64
+
65
+ /**
66
+ * Is this value an ArrayBuffer object?
67
+ * @private
68
+ */
69
+ const arrayBuffer = (val) => val instanceof ArrayBuffer;
70
+
71
+ /**
72
+ * Is this value a non-empty string?
73
+ * @private
74
+ */
75
+ const string = (val) => typeof val === 'string' && val.length > 0;
76
+
77
+ /**
78
+ * Is this value a real number?
79
+ * @private
80
+ */
81
+ const number = (val) => typeof val === 'number' && Number.isFinite(val);
82
+
83
+ /**
84
+ * Is this value an integer?
85
+ * @private
86
+ */
87
+ const integer = (val) => Number.isInteger(val);
88
+
89
+ /**
90
+ * Is this value within an inclusive given range?
91
+ * @private
92
+ */
93
+ const inRange = (val, min, max) => val >= min && val <= max;
94
+
95
+ /**
96
+ * Is this value within the elements of an array?
97
+ * @private
98
+ */
99
+ const inArray = (val, list) => list.includes(val);
100
+
101
+ /**
102
+ * Create an Error with a message relating to an invalid parameter.
103
+ *
104
+ * @param {string} name - parameter name.
105
+ * @param {string} expected - description of the type/value/range expected.
106
+ * @param {*} actual - the value received.
107
+ * @returns {Error} Containing the formatted message.
108
+ * @private
109
+ */
110
+ const invalidParameterError = (name, expected, actual) => new Error(
111
+ `Expected ${expected} for ${name} but received ${actual} of type ${typeof actual}`
112
+ );
113
+
114
+ /**
115
+ * Ensures an Error from C++ contains a JS stack.
116
+ *
117
+ * @param {Error} native - Error with message from C++.
118
+ * @param {Error} context - Error with stack from JS.
119
+ * @returns {Error} Error with message and stack.
120
+ * @private
121
+ */
122
+ const nativeError = (native, context) => {
123
+ context.message = native.message;
124
+ return context;
125
+ };
126
+
127
+ export default {
128
+ defined,
129
+ object,
130
+ plainObject,
131
+ fn,
132
+ bool,
133
+ buffer,
134
+ typedArray,
135
+ arrayBuffer,
136
+ string,
137
+ number,
138
+ integer,
139
+ inRange,
140
+ inArray,
141
+ invalidParameterError,
142
+ nativeError
143
+ };
@@ -5,20 +5,18 @@
5
5
 
6
6
  const { spawnSync } = require('node:child_process');
7
7
  const { createHash } = require('node:crypto');
8
- const semverCoerce = require('semver/functions/coerce');
9
- const semverGreaterThanOrEqualTo = require('semver/functions/gte');
10
- const semverSatisfies = require('semver/functions/satisfies');
8
+ const semver = require('semver');
11
9
  const detectLibc = require('detect-libc');
12
-
13
- const { config, engines, optionalDependencies } = require('../package.json');
10
+ const pkg = require('../package.json');
14
11
 
15
12
  /* node:coverage ignore next */
16
- const minimumLibvipsVersionLabelled = process.env.npm_package_config_libvips || config.libvips;
17
- const minimumLibvipsVersion = semverCoerce(minimumLibvipsVersionLabelled).version;
13
+ const minimumLibvipsVersionLabelled = process.env.npm_package_config_libvips || pkg.config.libvips;
14
+ const minimumLibvipsVersion = semver.coerce(minimumLibvipsVersionLabelled).version;
18
15
 
19
16
  const prebuiltPlatforms = [
20
17
  'darwin-arm64', 'darwin-x64',
21
- 'linux-arm', 'linux-arm64', 'linux-ppc64', 'linux-riscv64', 'linux-s390x', 'linux-x64',
18
+ 'freebsd-arm64', 'freebsd-x64',
19
+ 'linux-arm', 'linux-arm64', 'linux-ppc64', 'linux-riscv64', 'linux-s390x', 'linux-wasm32', 'linux-x64',
22
20
  'linuxmusl-arm64', 'linuxmusl-x64',
23
21
  'win32-arm64', 'win32-ia32', 'win32-x64'
24
22
  ];
@@ -36,13 +34,13 @@ const log = (item) => {
36
34
  }
37
35
  };
38
36
 
39
- /* node:coverage ignore next */
37
+ /* node:coverage disable */
38
+
40
39
  const runtimeLibc = () => detectLibc.isNonGlibcLinuxSync() ? detectLibc.familySync() : '';
41
40
 
42
41
  const runtimePlatformArch = () => `${process.platform}${runtimeLibc()}-${process.arch}`;
43
42
 
44
43
  const buildPlatformArch = () => {
45
- /* node:coverage ignore next 3 */
46
44
  if (isEmscripten()) {
47
45
  return 'wasm32';
48
46
  }
@@ -55,7 +53,6 @@ const buildSharpLibvipsIncludeDir = () => {
55
53
  try {
56
54
  return require(`@revizly/sharp-libvips-dev-${buildPlatformArch()}/include`);
57
55
  } catch {
58
- /* node:coverage ignore next 5 */
59
56
  try {
60
57
  return require('@revizly/sharp-libvips-dev/include');
61
58
  } catch {}
@@ -64,7 +61,6 @@ const buildSharpLibvipsIncludeDir = () => {
64
61
  };
65
62
 
66
63
  const buildSharpLibvipsCPlusPlusDir = () => {
67
- /* node:coverage ignore next 4 */
68
64
  try {
69
65
  return require('@revizly/sharp-libvips-dev/cplusplus');
70
66
  } catch {}
@@ -75,7 +71,6 @@ const buildSharpLibvipsLibDir = () => {
75
71
  try {
76
72
  return require(`@revizly/sharp-libvips-dev-${buildPlatformArch()}/lib`);
77
73
  } catch {
78
- /* node:coverage ignore next 5 */
79
74
  try {
80
75
  return require(`@revizly/sharp-libvips-${buildPlatformArch()}/lib`);
81
76
  } catch {}
@@ -83,12 +78,10 @@ const buildSharpLibvipsLibDir = () => {
83
78
  return '';
84
79
  };
85
80
 
86
- /* node:coverage disable */
87
-
88
81
  const isUnsupportedNodeRuntime = () => {
89
82
  if (process.release?.name === 'node' && process.versions) {
90
- if (!semverSatisfies(process.versions.node, engines.node)) {
91
- return { found: process.versions.node, expected: engines.node };
83
+ if (!semver.satisfies(process.versions.node, pkg.engines.node)) {
84
+ return { found: process.versions.node, expected: pkg.engines.node };
92
85
  }
93
86
  }
94
87
  };
@@ -113,7 +106,7 @@ const sha512 = (s) => createHash('sha512').update(s).digest('hex');
113
106
  const yarnLocator = () => {
114
107
  try {
115
108
  const identHash = sha512(`imgsharp-libvips-${buildPlatformArch()}`);
116
- const npmVersion = semverCoerce(optionalDependencies[`@revizly/sharp-libvips-${buildPlatformArch()}`], {
109
+ const npmVersion = semver.coerce(pkg.optionalDependencies[`@revizly/sharp-libvips-${buildPlatformArch()}`], {
117
110
  includePrerelease: true
118
111
  }).version;
119
112
  return sha512(`${identHash}npm:${npmVersion}`).slice(0, 10);
@@ -144,22 +137,34 @@ const globalLibvipsVersion = () => {
144
137
  }
145
138
  };
146
139
 
140
+ const getBrewPkgConfigPath = () => {
141
+ try {
142
+ const brewPrefix = (spawnSync('brew', ['--prefix'], { encoding: 'utf8' }).stdout || '').trim();
143
+ if (brewPrefix) {
144
+ return `${brewPrefix}/lib/pkgconfig`;
145
+ }
146
+ } catch (_err) {}
147
+ return undefined;
148
+ };
149
+
150
+ const getPkgConfigPath = () => {
151
+ try {
152
+ const pkgConfigPath = (spawnSync('pkg-config', ['--variable', 'pc_path', 'pkg-config'], { encoding: 'utf8' }).stdout || '').trim();
153
+ if (pkgConfigPath) {
154
+ return pkgConfigPath;
155
+ }
156
+ } catch (_err) {}
157
+ return undefined;
158
+ };
159
+
147
160
  /* node:coverage enable */
148
161
 
149
162
  const pkgConfigPath = () => {
150
163
  if (process.platform !== 'win32') {
151
- /* node:coverage ignore next 4 */
152
- const brewPkgConfigPath = spawnSync(
153
- 'which brew >/dev/null 2>&1 && brew environment --plain | grep PKG_CONFIG_LIBDIR | cut -d" " -f2',
154
- spawnSyncOptions
155
- ).stdout || '';
156
164
  return [
157
- brewPkgConfigPath.trim(),
158
- process.env.PKG_CONFIG_PATH,
159
- '/usr/local/lib/pkgconfig',
160
- '/usr/lib/pkgconfig',
161
- '/usr/local/libdata/pkgconfig',
162
- '/usr/libdata/pkgconfig'
165
+ getBrewPkgConfigPath(),
166
+ getPkgConfigPath(),
167
+ process.env.PKG_CONFIG_PATH
163
168
  ].filter(Boolean).join(':');
164
169
  } else {
165
170
  return '';
@@ -186,7 +191,7 @@ const useGlobalLibvips = (logger) => {
186
191
  }
187
192
  const globalVipsVersion = globalLibvipsVersion();
188
193
  /* node:coverage ignore next */
189
- return !!globalVipsVersion && semverGreaterThanOrEqualTo(globalVipsVersion, minimumLibvipsVersion);
194
+ return !!globalVipsVersion && semver.gte(globalVipsVersion, minimumLibvipsVersion);
190
195
  };
191
196
 
192
197
  module.exports = {
@@ -0,0 +1,212 @@
1
+ /*!
2
+ Copyright 2013 Lovell Fuller and others.
3
+ SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ import { spawnSync } from 'node:child_process';
7
+ import { createHash } from 'node:crypto';
8
+ import semver from 'semver';
9
+ import detectLibc from 'detect-libc';
10
+ import pkg from '../package.json' with { type: 'json' };
11
+
12
+ /* node:coverage ignore next */
13
+ const minimumLibvipsVersionLabelled = process.env.npm_package_config_libvips || pkg.config.libvips;
14
+ const minimumLibvipsVersion = semver.coerce(minimumLibvipsVersionLabelled).version;
15
+
16
+ const prebuiltPlatforms = [
17
+ 'darwin-arm64', 'darwin-x64',
18
+ 'freebsd-arm64', 'freebsd-x64',
19
+ 'linux-arm', 'linux-arm64', 'linux-ppc64', 'linux-riscv64', 'linux-s390x', 'linux-wasm32', 'linux-x64',
20
+ 'linuxmusl-arm64', 'linuxmusl-x64',
21
+ 'win32-arm64', 'win32-ia32', 'win32-x64'
22
+ ];
23
+
24
+ const spawnSyncOptions = {
25
+ encoding: 'utf8',
26
+ shell: true
27
+ };
28
+
29
+ const log = (item) => {
30
+ if (item instanceof Error) {
31
+ console.error(`sharp: Installation error: ${item.message}`);
32
+ } else {
33
+ console.log(`sharp: ${item}`);
34
+ }
35
+ };
36
+
37
+ /* node:coverage disable */
38
+
39
+ const runtimeLibc = () => detectLibc.isNonGlibcLinuxSync() ? detectLibc.familySync() : '';
40
+
41
+ const runtimePlatformArch = () => `${process.platform}${runtimeLibc()}-${process.arch}`;
42
+
43
+ const buildPlatformArch = () => {
44
+ if (isEmscripten()) {
45
+ return 'wasm32';
46
+ }
47
+ const { npm_config_arch, npm_config_platform, npm_config_libc } = process.env;
48
+ const libc = typeof npm_config_libc === 'string' ? npm_config_libc : runtimeLibc();
49
+ return `${npm_config_platform || process.platform}${libc}-${npm_config_arch || process.arch}`;
50
+ };
51
+
52
+ const buildSharpLibvipsIncludeDir = () => {
53
+ try {
54
+ return require(`@revizly/sharp-libvips-dev-${buildPlatformArch()}/include`);
55
+ } catch {
56
+ try {
57
+ return require('@revizly/sharp-libvips-dev/include');
58
+ } catch {}
59
+ }
60
+ return '';
61
+ };
62
+
63
+ const buildSharpLibvipsCPlusPlusDir = () => {
64
+ try {
65
+ return require('@revizly/sharp-libvips-dev/cplusplus');
66
+ } catch {}
67
+ return '';
68
+ };
69
+
70
+ const buildSharpLibvipsLibDir = () => {
71
+ try {
72
+ return require(`@revizly/sharp-libvips-dev-${buildPlatformArch()}/lib`);
73
+ } catch {
74
+ try {
75
+ return require(`@revizly/sharp-libvips-${buildPlatformArch()}/lib`);
76
+ } catch {}
77
+ }
78
+ return '';
79
+ };
80
+
81
+ const isUnsupportedNodeRuntime = () => {
82
+ if (process.release?.name === 'node' && process.versions) {
83
+ if (!semver.satisfies(process.versions.node, pkg.engines.node)) {
84
+ return { found: process.versions.node, expected: pkg.engines.node };
85
+ }
86
+ }
87
+ };
88
+
89
+ const isEmscripten = () => {
90
+ const { CC } = process.env;
91
+ return Boolean(CC?.endsWith('/emcc'));
92
+ };
93
+
94
+ const isRosetta = () => {
95
+ if (process.platform === 'darwin' && process.arch === 'x64') {
96
+ const translated = spawnSync('sysctl sysctl.proc_translated', spawnSyncOptions).stdout;
97
+ return (translated || '').trim() === 'sysctl.proc_translated: 1';
98
+ }
99
+ return false;
100
+ };
101
+
102
+ /* node:coverage enable */
103
+
104
+ const sha512 = (s) => createHash('sha512').update(s).digest('hex');
105
+
106
+ const yarnLocator = () => {
107
+ try {
108
+ const identHash = sha512(`imgsharp-libvips-${buildPlatformArch()}`);
109
+ const npmVersion = semver.coerce(pkg.optionalDependencies[`@revizly/sharp-libvips-${buildPlatformArch()}`], {
110
+ includePrerelease: true
111
+ }).version;
112
+ return sha512(`${identHash}npm:${npmVersion}`).slice(0, 10);
113
+ } catch {}
114
+ return '';
115
+ };
116
+
117
+ /* node:coverage disable */
118
+
119
+ const spawnRebuild = () =>
120
+ spawnSync(`node-gyp rebuild --directory=src ${isEmscripten() ? '--nodedir=emscripten' : ''}`, {
121
+ ...spawnSyncOptions,
122
+ stdio: 'inherit'
123
+ }).status;
124
+
125
+ const globalLibvipsVersion = () => {
126
+ if (process.platform !== 'win32') {
127
+ const globalLibvipsVersion = spawnSync('pkg-config --modversion vips-cpp', {
128
+ ...spawnSyncOptions,
129
+ env: {
130
+ ...process.env,
131
+ PKG_CONFIG_PATH: pkgConfigPath()
132
+ }
133
+ }).stdout;
134
+ return (globalLibvipsVersion || '').trim();
135
+ } else {
136
+ return '';
137
+ }
138
+ };
139
+
140
+ const getBrewPkgConfigPath = () => {
141
+ try {
142
+ const brewPrefix = (spawnSync('brew', ['--prefix'], { encoding: 'utf8' }).stdout || '').trim();
143
+ if (brewPrefix) {
144
+ return `${brewPrefix}/lib/pkgconfig`;
145
+ }
146
+ } catch (_err) {}
147
+ return undefined;
148
+ };
149
+
150
+ const getPkgConfigPath = () => {
151
+ try {
152
+ const pkgConfigPath = (spawnSync('pkg-config', ['--variable', 'pc_path', 'pkg-config'], { encoding: 'utf8' }).stdout || '').trim();
153
+ if (pkgConfigPath) {
154
+ return pkgConfigPath;
155
+ }
156
+ } catch (_err) {}
157
+ return undefined;
158
+ };
159
+
160
+ /* node:coverage enable */
161
+
162
+ const pkgConfigPath = () => {
163
+ if (process.platform !== 'win32') {
164
+ return [
165
+ getBrewPkgConfigPath(),
166
+ getPkgConfigPath(),
167
+ process.env.PKG_CONFIG_PATH
168
+ ].filter(Boolean).join(':');
169
+ } else {
170
+ return '';
171
+ }
172
+ };
173
+
174
+ const skipSearch = (status, reason, logger) => {
175
+ if (logger) {
176
+ logger(`Detected ${reason}, skipping search for globally-installed libvips`);
177
+ }
178
+ return status;
179
+ };
180
+
181
+ const useGlobalLibvips = (logger) => {
182
+ if (Boolean(process.env.SHARP_IGNORE_GLOBAL_LIBVIPS) === true) {
183
+ return skipSearch(false, 'SHARP_IGNORE_GLOBAL_LIBVIPS', logger);
184
+ }
185
+ if (Boolean(process.env.SHARP_FORCE_GLOBAL_LIBVIPS) === true) {
186
+ return skipSearch(true, 'SHARP_FORCE_GLOBAL_LIBVIPS', logger);
187
+ }
188
+ /* node:coverage ignore next 3 */
189
+ if (isRosetta()) {
190
+ return skipSearch(false, 'Rosetta', logger);
191
+ }
192
+ const globalVipsVersion = globalLibvipsVersion();
193
+ /* node:coverage ignore next */
194
+ return !!globalVipsVersion && semver.gte(globalVipsVersion, minimumLibvipsVersion);
195
+ };
196
+
197
+ export default {
198
+ minimumLibvipsVersion,
199
+ prebuiltPlatforms,
200
+ buildPlatformArch,
201
+ buildSharpLibvipsIncludeDir,
202
+ buildSharpLibvipsCPlusPlusDir,
203
+ buildSharpLibvipsLibDir,
204
+ isUnsupportedNodeRuntime,
205
+ runtimePlatformArch,
206
+ log,
207
+ yarnLocator,
208
+ spawnRebuild,
209
+ globalLibvipsVersion,
210
+ pkgConfigPath,
211
+ useGlobalLibvips
212
+ };
@@ -3,7 +3,7 @@
3
3
  SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
 
6
- const is = require('./is');
6
+ const is = require('./is.cjs');
7
7
 
8
8
  /**
9
9
  * How accurate an operation should be.
@@ -178,7 +178,7 @@ function flop (flop) {
178
178
  * @throws {Error} Invalid parameters
179
179
  */
180
180
  function affine (matrix, options) {
181
- const flatMatrix = [].concat(...matrix);
181
+ const flatMatrix = Array.isArray(matrix) ? [].concat(...matrix) : [];
182
182
  if (flatMatrix.length === 4 && flatMatrix.every(is.number)) {
183
183
  this.options.affineMatrix = flatMatrix;
184
184
  } else {
@@ -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
  }
@@ -451,10 +424,10 @@ function blur (options) {
451
424
  function dilate (width) {
452
425
  if (!is.defined(width)) {
453
426
  this.options.dilateWidth = 1;
454
- } else if (is.integer(width) && width > 0) {
427
+ } else if (is.integer(width) && is.inRange(width, 1, 65536)) {
455
428
  this.options.dilateWidth = width;
456
429
  } else {
457
- throw is.invalidParameterError('dilate', 'positive integer', dilate);
430
+ throw is.invalidParameterError('width', 'integer between 1 and 65536', width);
458
431
  }
459
432
  return this;
460
433
  }
@@ -474,10 +447,10 @@ function dilate (width) {
474
447
  function erode (width) {
475
448
  if (!is.defined(width)) {
476
449
  this.options.erodeWidth = 1;
477
- } else if (is.integer(width) && width > 0) {
450
+ } else if (is.integer(width) && is.inRange(width, 1, 65536)) {
478
451
  this.options.erodeWidth = width;
479
452
  } else {
480
- throw is.invalidParameterError('erode', 'positive integer', erode);
453
+ throw is.invalidParameterError('width', 'integer between 1 and 65536', width);
481
454
  }
482
455
  return this;
483
456
  }
@@ -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
@@ -675,23 +646,23 @@ function normalize (options) {
675
646
  * .toBuffer();
676
647
  *
677
648
  * @param {Object} options
678
- * @param {number} options.width - Integral width of the search window, in pixels.
679
- * @param {number} options.height - Integral height of the search window, in pixels.
649
+ * @param {number} options.width - Integral width of the search window, in pixels, between 1 and 65536.
650
+ * @param {number} options.height - Integral height of the search window, in pixels, between 1 and 65536.
680
651
  * @param {number} [options.maxSlope=3] - Integral level of brightening, between 0 and 100, where 0 disables contrast limiting.
681
652
  * @returns {Sharp}
682
653
  * @throws {Error} Invalid parameters
683
654
  */
684
655
  function clahe (options) {
685
656
  if (is.plainObject(options)) {
686
- if (is.integer(options.width) && options.width > 0) {
657
+ if (is.integer(options.width) && is.inRange(options.width, 1, 65536)) {
687
658
  this.options.claheWidth = options.width;
688
659
  } else {
689
- throw is.invalidParameterError('width', 'integer greater than zero', options.width);
660
+ throw is.invalidParameterError('width', 'integer between 1 and 65536', options.width);
690
661
  }
691
- if (is.integer(options.height) && options.height > 0) {
662
+ if (is.integer(options.height) && is.inRange(options.height, 1, 65536)) {
692
663
  this.options.claheHeight = options.height;
693
664
  } else {
694
- throw is.invalidParameterError('height', 'integer greater than zero', options.height);
665
+ throw is.invalidParameterError('height', 'integer between 1 and 65536', options.height);
695
666
  }
696
667
  if (is.defined(options.maxSlope)) {
697
668
  if (is.integer(options.maxSlope) && is.inRange(options.maxSlope, 0, 100)) {
@@ -735,7 +706,8 @@ function convolve (kernel) {
735
706
  if (!is.object(kernel) || !Array.isArray(kernel.kernel) ||
736
707
  !is.integer(kernel.width) || !is.integer(kernel.height) ||
737
708
  !is.inRange(kernel.width, 3, 1001) || !is.inRange(kernel.height, 3, 1001) ||
738
- kernel.height * kernel.width !== kernel.kernel.length
709
+ kernel.height * kernel.width !== kernel.kernel.length ||
710
+ !kernel.kernel.every(is.number)
739
711
  ) {
740
712
  // must pass in a kernel
741
713
  throw new Error('Invalid convolution kernel');
@@ -891,10 +863,13 @@ function recomb (inputMatrix) {
891
863
  if (inputMatrix.length !== 3 && inputMatrix.length !== 4) {
892
864
  throw is.invalidParameterError('inputMatrix', '3x3 or 4x4 array', inputMatrix.length);
893
865
  }
894
- const recombMatrix = inputMatrix.flat().map(Number);
866
+ const recombMatrix = inputMatrix.flat();
895
867
  if (recombMatrix.length !== 9 && recombMatrix.length !== 16) {
896
868
  throw is.invalidParameterError('inputMatrix', 'cardinality of 9 or 16', recombMatrix.length);
897
869
  }
870
+ if (!recombMatrix.every(is.number)) {
871
+ throw is.invalidParameterError('inputMatrix', 'array of numbers', recombMatrix);
872
+ }
898
873
  this.options.recombMatrix = recombMatrix;
899
874
  return this;
900
875
  }