@revizly/sharp 0.35.0-revizly4 → 0.35.0-revizly41
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 +12 -18
- package/{lib/channel.js → dist/channel.cjs} +1 -1
- package/dist/channel.mjs +177 -0
- package/{lib/colour.js → dist/colour.cjs} +11 -7
- package/dist/colour.mjs +199 -0
- package/{lib/composite.js → dist/composite.cjs} +2 -1
- package/dist/composite.mjs +213 -0
- package/{lib/constructor.js → dist/constructor.cjs} +42 -29
- package/dist/constructor.mjs +512 -0
- package/dist/index.cjs +25 -0
- package/dist/index.d.cts +2001 -0
- package/dist/index.d.mts +2048 -0
- package/dist/index.mjs +25 -0
- package/{lib/input.js → dist/input.cjs} +26 -21
- package/dist/input.mjs +814 -0
- package/{lib/is.js → dist/is.cjs} +1 -1
- package/dist/is.mjs +143 -0
- package/{lib/libvips.js → dist/libvips.cjs} +35 -30
- package/dist/libvips.mjs +212 -0
- package/{lib/operation.js → dist/operation.cjs} +33 -51
- package/dist/operation.mjs +998 -0
- package/{lib/output.js → dist/output.cjs} +161 -28
- package/dist/output.mjs +1799 -0
- package/{lib/resize.js → dist/resize.cjs} +46 -24
- package/dist/resize.mjs +617 -0
- package/dist/sharp.cjs +125 -0
- package/dist/sharp.mjs +125 -0
- package/{lib/utility.js → dist/utility.cjs} +18 -8
- package/dist/utility.mjs +301 -0
- package/install/build.js +3 -3
- package/lib/index.d.ts +105 -75
- package/package.json +46 -27
- package/src/binding.gyp +18 -13
- package/src/common.cc +70 -17
- package/src/common.h +22 -3
- package/src/metadata.cc +66 -8
- package/src/metadata.h +6 -1
- package/src/operations.cc +25 -8
- package/src/operations.h +1 -1
- package/src/pipeline.cc +206 -69
- package/src/pipeline.h +16 -1
- package/src/stats.cc +6 -6
- package/src/utilities.cc +7 -6
- package/install/check.js +0 -14
- package/lib/index.js +0 -16
- 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' &&
|
|
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
|
|
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 =
|
|
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
|
-
'
|
|
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
|
|
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 (!
|
|
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 =
|
|
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
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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 &&
|
|
194
|
+
return !!globalVipsVersion && semver.gte(globalVipsVersion, minimumLibvipsVersion);
|
|
190
195
|
};
|
|
191
196
|
|
|
192
197
|
module.exports = {
|
package/dist/libvips.mjs
ADDED
|
@@ -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,13 @@ function flop (flop) {
|
|
|
178
178
|
* @throws {Error} Invalid parameters
|
|
179
179
|
*/
|
|
180
180
|
function affine (matrix, options) {
|
|
181
|
-
const
|
|
181
|
+
const isValidShape = Array.isArray(matrix) && (
|
|
182
|
+
// 1x4 array of numbers
|
|
183
|
+
(matrix.length === 4 && matrix.every(is.number)) ||
|
|
184
|
+
// 2x2 array of arrays of numbers
|
|
185
|
+
(matrix.length === 2 && matrix.every((row) => Array.isArray(row) && row.length === 2))
|
|
186
|
+
);
|
|
187
|
+
const flatMatrix = isValidShape ? matrix.flat() : [];
|
|
182
188
|
if (flatMatrix.length === 4 && flatMatrix.every(is.number)) {
|
|
183
189
|
this.options.affineMatrix = flatMatrix;
|
|
184
190
|
} else {
|
|
@@ -259,45 +265,18 @@ function affine (matrix, options) {
|
|
|
259
265
|
* })
|
|
260
266
|
* .toBuffer();
|
|
261
267
|
*
|
|
262
|
-
* @param {Object
|
|
268
|
+
* @param {Object} [options] - if present, is an Object with attributes
|
|
263
269
|
* @param {number} [options.sigma] - the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`, between 0.000001 and 10
|
|
264
270
|
* @param {number} [options.m1=1.0] - the level of sharpening to apply to "flat" areas, between 0 and 1000000
|
|
265
271
|
* @param {number} [options.m2=2.0] - the level of sharpening to apply to "jagged" areas, between 0 and 1000000
|
|
266
272
|
* @param {number} [options.x1=2.0] - threshold between "flat" and "jagged", between 0 and 1000000
|
|
267
273
|
* @param {number} [options.y2=10.0] - maximum amount of brightening, between 0 and 1000000
|
|
268
274
|
* @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
275
|
* @returns {Sharp}
|
|
272
276
|
* @throws {Error} Invalid parameters
|
|
273
277
|
*/
|
|
274
|
-
function sharpen (options
|
|
275
|
-
if (
|
|
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)) {
|
|
278
|
+
function sharpen (options) {
|
|
279
|
+
if (is.plainObject(options)) {
|
|
301
280
|
if (is.number(options.sigma) && is.inRange(options.sigma, 0.000001, 10)) {
|
|
302
281
|
this.options.sharpenSigma = options.sigma;
|
|
303
282
|
} else {
|
|
@@ -339,7 +318,7 @@ function sharpen (options, flat, jagged) {
|
|
|
339
318
|
}
|
|
340
319
|
}
|
|
341
320
|
} else {
|
|
342
|
-
|
|
321
|
+
this.options.sharpenSigma = -1;
|
|
343
322
|
}
|
|
344
323
|
return this;
|
|
345
324
|
}
|
|
@@ -451,10 +430,10 @@ function blur (options) {
|
|
|
451
430
|
function dilate (width) {
|
|
452
431
|
if (!is.defined(width)) {
|
|
453
432
|
this.options.dilateWidth = 1;
|
|
454
|
-
} else if (is.integer(width) && width
|
|
433
|
+
} else if (is.integer(width) && is.inRange(width, 1, 65536)) {
|
|
455
434
|
this.options.dilateWidth = width;
|
|
456
435
|
} else {
|
|
457
|
-
throw is.invalidParameterError('
|
|
436
|
+
throw is.invalidParameterError('width', 'integer between 1 and 65536', width);
|
|
458
437
|
}
|
|
459
438
|
return this;
|
|
460
439
|
}
|
|
@@ -474,10 +453,10 @@ function dilate (width) {
|
|
|
474
453
|
function erode (width) {
|
|
475
454
|
if (!is.defined(width)) {
|
|
476
455
|
this.options.erodeWidth = 1;
|
|
477
|
-
} else if (is.integer(width) && width
|
|
456
|
+
} else if (is.integer(width) && is.inRange(width, 1, 65536)) {
|
|
478
457
|
this.options.erodeWidth = width;
|
|
479
458
|
} else {
|
|
480
|
-
throw is.invalidParameterError('
|
|
459
|
+
throw is.invalidParameterError('width', 'integer between 1 and 65536', width);
|
|
481
460
|
}
|
|
482
461
|
return this;
|
|
483
462
|
}
|
|
@@ -510,8 +489,6 @@ function flatten (options) {
|
|
|
510
489
|
*
|
|
511
490
|
* Existing alpha channel values for non-white pixels remain unchanged.
|
|
512
491
|
*
|
|
513
|
-
* This feature is experimental and the API may change.
|
|
514
|
-
*
|
|
515
492
|
* @since 0.32.1
|
|
516
493
|
*
|
|
517
494
|
* @example
|
|
@@ -675,23 +652,23 @@ function normalize (options) {
|
|
|
675
652
|
* .toBuffer();
|
|
676
653
|
*
|
|
677
654
|
* @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.
|
|
655
|
+
* @param {number} options.width - Integral width of the search window, in pixels, between 1 and 65536.
|
|
656
|
+
* @param {number} options.height - Integral height of the search window, in pixels, between 1 and 65536.
|
|
680
657
|
* @param {number} [options.maxSlope=3] - Integral level of brightening, between 0 and 100, where 0 disables contrast limiting.
|
|
681
658
|
* @returns {Sharp}
|
|
682
659
|
* @throws {Error} Invalid parameters
|
|
683
660
|
*/
|
|
684
661
|
function clahe (options) {
|
|
685
662
|
if (is.plainObject(options)) {
|
|
686
|
-
if (is.integer(options.width) && options.width
|
|
663
|
+
if (is.integer(options.width) && is.inRange(options.width, 1, 65536)) {
|
|
687
664
|
this.options.claheWidth = options.width;
|
|
688
665
|
} else {
|
|
689
|
-
throw is.invalidParameterError('width', 'integer
|
|
666
|
+
throw is.invalidParameterError('width', 'integer between 1 and 65536', options.width);
|
|
690
667
|
}
|
|
691
|
-
if (is.integer(options.height) && options.height
|
|
668
|
+
if (is.integer(options.height) && is.inRange(options.height, 1, 65536)) {
|
|
692
669
|
this.options.claheHeight = options.height;
|
|
693
670
|
} else {
|
|
694
|
-
throw is.invalidParameterError('height', 'integer
|
|
671
|
+
throw is.invalidParameterError('height', 'integer between 1 and 65536', options.height);
|
|
695
672
|
}
|
|
696
673
|
if (is.defined(options.maxSlope)) {
|
|
697
674
|
if (is.integer(options.maxSlope) && is.inRange(options.maxSlope, 0, 100)) {
|
|
@@ -735,7 +712,8 @@ function convolve (kernel) {
|
|
|
735
712
|
if (!is.object(kernel) || !Array.isArray(kernel.kernel) ||
|
|
736
713
|
!is.integer(kernel.width) || !is.integer(kernel.height) ||
|
|
737
714
|
!is.inRange(kernel.width, 3, 1001) || !is.inRange(kernel.height, 3, 1001) ||
|
|
738
|
-
kernel.height * kernel.width !== kernel.kernel.length
|
|
715
|
+
kernel.height * kernel.width !== kernel.kernel.length ||
|
|
716
|
+
!kernel.kernel.every(is.number)
|
|
739
717
|
) {
|
|
740
718
|
// must pass in a kernel
|
|
741
719
|
throw new Error('Invalid convolution kernel');
|
|
@@ -888,12 +866,16 @@ function recomb (inputMatrix) {
|
|
|
888
866
|
if (!Array.isArray(inputMatrix)) {
|
|
889
867
|
throw is.invalidParameterError('inputMatrix', 'array', inputMatrix);
|
|
890
868
|
}
|
|
891
|
-
|
|
892
|
-
|
|
869
|
+
const dimensions = inputMatrix.length;
|
|
870
|
+
if (dimensions !== 3 && dimensions !== 4) {
|
|
871
|
+
throw is.invalidParameterError('inputMatrix', '3x3 or 4x4 array', dimensions);
|
|
872
|
+
}
|
|
873
|
+
if (!inputMatrix.every((row) => Array.isArray(row) && row.length === dimensions)) {
|
|
874
|
+
throw is.invalidParameterError('inputMatrix', `array of ${dimensions} arrays of length ${dimensions}`, inputMatrix);
|
|
893
875
|
}
|
|
894
|
-
const recombMatrix = inputMatrix.flat()
|
|
895
|
-
if (recombMatrix.
|
|
896
|
-
throw is.invalidParameterError('inputMatrix', '
|
|
876
|
+
const recombMatrix = inputMatrix.flat();
|
|
877
|
+
if (!recombMatrix.every(is.number)) {
|
|
878
|
+
throw is.invalidParameterError('inputMatrix', 'array of numbers', recombMatrix);
|
|
897
879
|
}
|
|
898
880
|
this.options.recombMatrix = recombMatrix;
|
|
899
881
|
return this;
|