sharp 0.28.1 → 0.29.1
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 +2 -2
- package/binding.gyp +12 -9
- package/install/can-compile.js +11 -0
- package/install/dll-copy.js +6 -6
- package/install/libvips.js +24 -18
- package/lib/agent.js +1 -1
- package/lib/channel.js +13 -7
- package/lib/colour.js +42 -1
- package/lib/composite.js +2 -0
- package/lib/constructor.js +21 -30
- package/lib/input.js +52 -3
- package/lib/is.js +19 -5
- package/lib/libvips.js +9 -22
- package/lib/operation.js +74 -7
- package/lib/output.js +133 -17
- package/lib/sharp.js +24 -0
- package/lib/utility.js +1 -1
- package/package.json +23 -16
- package/src/common.cc +47 -14
- package/src/common.h +17 -5
- package/src/libvips/cplusplus/VConnection.cpp +0 -26
- package/src/libvips/cplusplus/VImage.cpp +54 -16
- package/src/libvips/cplusplus/VInterpolate.cpp +0 -13
- package/src/libvips/cplusplus/vips-operators.cpp +185 -1
- package/src/metadata.cc +14 -0
- package/src/metadata.h +1 -0
- package/src/operations.cc +36 -3
- package/src/operations.h +18 -2
- package/src/pipeline.cc +104 -34
- package/src/pipeline.h +29 -3
- package/src/utilities.cc +1 -1
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
|
|
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
|
[](https://coveralls.io/r/lovell/sharp?branch=master)
|
|
102
|
-
[](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
|
-
'
|
|
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=
|
|
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': ['
|
|
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
|
|
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': ['
|
|
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
|
|
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
|
-
'-
|
|
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
|
-
'-
|
|
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': {
|
package/install/dll-copy.js
CHANGED
|
@@ -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
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const buildReleaseDir = path.join(
|
|
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
|
package/install/libvips.js
CHANGED
|
@@ -7,7 +7,8 @@ const stream = require('stream');
|
|
|
7
7
|
const zlib = require('zlib');
|
|
8
8
|
|
|
9
9
|
const detectLibc = require('detect-libc');
|
|
10
|
-
const
|
|
10
|
+
const semverLessThan = require('semver/functions/lt');
|
|
11
|
+
const semverSatisfies = require('semver/functions/satisfies');
|
|
11
12
|
const simpleGet = require('simple-get');
|
|
12
13
|
const tarFs = require('tar-fs');
|
|
13
14
|
|
|
@@ -23,6 +24,7 @@ const minimumGlibcVersionByArch = {
|
|
|
23
24
|
|
|
24
25
|
const hasSharpPrebuild = [
|
|
25
26
|
'darwin-x64',
|
|
27
|
+
'darwin-arm64',
|
|
26
28
|
'linux-arm64',
|
|
27
29
|
'linux-x64',
|
|
28
30
|
'linuxmusl-x64',
|
|
@@ -34,22 +36,27 @@ const hasSharpPrebuild = [
|
|
|
34
36
|
const { minimumLibvipsVersion, minimumLibvipsVersionLabelled } = libvips;
|
|
35
37
|
const distHost = process.env.npm_config_sharp_libvips_binary_host || 'https://github.com/lovell/sharp-libvips/releases/download';
|
|
36
38
|
const distBaseUrl = process.env.npm_config_sharp_dist_base_url || process.env.SHARP_DIST_BASE_URL || `${distHost}/v${minimumLibvipsVersionLabelled}/`;
|
|
37
|
-
const
|
|
39
|
+
const installationForced = !!(process.env.npm_config_sharp_install_force || process.env.SHARP_INSTALL_FORCE);
|
|
38
40
|
|
|
39
41
|
const fail = function (err) {
|
|
40
42
|
libvips.log(err);
|
|
41
43
|
if (err.code === 'EACCES') {
|
|
42
44
|
libvips.log('Are you trying to install as a root or sudo user? Try again with the --unsafe-perm flag');
|
|
43
45
|
}
|
|
44
|
-
libvips.log('Attempting to build from source via node-gyp but this may fail due to the above error');
|
|
45
46
|
libvips.log('Please see https://sharp.pixelplumbing.com/install for required dependencies');
|
|
46
47
|
process.exit(1);
|
|
47
48
|
};
|
|
48
49
|
|
|
50
|
+
const handleError = function (err) {
|
|
51
|
+
if (installationForced) {
|
|
52
|
+
libvips.log(`Installation warning: ${err.message}`);
|
|
53
|
+
} else {
|
|
54
|
+
throw err;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
49
58
|
const extractTarball = function (tarPath, platformAndArch) {
|
|
50
|
-
const
|
|
51
|
-
libvips.mkdirSync(vendorPath);
|
|
52
|
-
const versionedVendorPath = path.join(vendorPath, minimumLibvipsVersion);
|
|
59
|
+
const versionedVendorPath = path.join(__dirname, '..', 'vendor', minimumLibvipsVersion, platformAndArch);
|
|
53
60
|
libvips.mkdirSync(versionedVendorPath);
|
|
54
61
|
|
|
55
62
|
const ignoreVendorInclude = hasSharpPrebuild.includes(platformAndArch) && !process.env.npm_config_build_from_source;
|
|
@@ -59,7 +66,7 @@ const extractTarball = function (tarPath, platformAndArch) {
|
|
|
59
66
|
|
|
60
67
|
stream.pipeline(
|
|
61
68
|
fs.createReadStream(tarPath),
|
|
62
|
-
|
|
69
|
+
new zlib.BrotliDecompress(),
|
|
63
70
|
tarFs.extract(versionedVendorPath, { ignore }),
|
|
64
71
|
function (err) {
|
|
65
72
|
if (err) {
|
|
@@ -95,26 +102,25 @@ try {
|
|
|
95
102
|
if (platformAndArch === 'freebsd-x64' || platformAndArch === 'openbsd-x64' || platformAndArch === 'sunos-x64') {
|
|
96
103
|
throw new Error(`BSD/SunOS systems require manual installation of libvips >= ${minimumLibvipsVersion}`);
|
|
97
104
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
105
|
+
// Linux libc version check
|
|
106
|
+
if (detectLibc.family === detectLibc.GLIBC && detectLibc.version && minimumGlibcVersionByArch[arch]) {
|
|
107
|
+
if (semverLessThan(`${detectLibc.version}.0`, `${minimumGlibcVersionByArch[arch]}.0`)) {
|
|
108
|
+
handleError(new Error(`Use with glibc ${detectLibc.version} requires manual installation of libvips >= ${minimumLibvipsVersion}`));
|
|
101
109
|
}
|
|
102
110
|
}
|
|
103
111
|
if (detectLibc.family === detectLibc.MUSL && detectLibc.version) {
|
|
104
|
-
if (
|
|
105
|
-
|
|
112
|
+
if (semverLessThan(detectLibc.version, '1.1.24')) {
|
|
113
|
+
handleError(new Error(`Use with musl ${detectLibc.version} requires manual installation of libvips >= ${minimumLibvipsVersion}`));
|
|
106
114
|
}
|
|
107
115
|
}
|
|
108
|
-
|
|
116
|
+
// Node.js minimum version check
|
|
109
117
|
const supportedNodeVersion = process.env.npm_package_engines_node || require('../package.json').engines.node;
|
|
110
|
-
if (!
|
|
111
|
-
|
|
118
|
+
if (!semverSatisfies(process.versions.node, supportedNodeVersion)) {
|
|
119
|
+
handleError(new Error(`Expected Node.js version ${supportedNodeVersion} but found ${process.versions.node}`));
|
|
112
120
|
}
|
|
113
121
|
|
|
114
|
-
const extension = supportsBrotli ? 'br' : 'gz';
|
|
115
|
-
|
|
116
122
|
// Download to per-process temporary file
|
|
117
|
-
const tarFilename = ['libvips', minimumLibvipsVersion, platformAndArch].join('-') + '.tar.'
|
|
123
|
+
const tarFilename = ['libvips', minimumLibvipsVersion, platformAndArch].join('-') + '.tar.br';
|
|
118
124
|
const tarPathCache = path.join(libvips.cachePath(), tarFilename);
|
|
119
125
|
if (fs.existsSync(tarPathCache)) {
|
|
120
126
|
libvips.log(`Using cached ${tarPathCache}`);
|
package/lib/agent.js
CHANGED
|
@@ -25,7 +25,7 @@ module.exports = function () {
|
|
|
25
25
|
? tunnelAgent.httpsOverHttps
|
|
26
26
|
: tunnelAgent.httpsOverHttp;
|
|
27
27
|
const proxyAuth = proxy.username && proxy.password
|
|
28
|
-
? `${proxy.username}:${proxy.password}`
|
|
28
|
+
? `${decodeURIComponent(proxy.username)}:${decodeURIComponent(proxy.password)}`
|
|
29
29
|
: null;
|
|
30
30
|
return tunnel({
|
|
31
31
|
proxy: {
|
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
|
-
*
|
|
75
|
+
* // green.jpg is a greyscale image containing the green channel of the input
|
|
76
|
+
* await sharp(input)
|
|
74
77
|
* .extractChannel('green')
|
|
75
|
-
* .
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
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/
|
|
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
|
*/
|
package/lib/constructor.js
CHANGED
|
@@ -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
|
|
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.
|
|
@@ -139,6 +115,8 @@ const debuglog = util.debuglog('sharp');
|
|
|
139
115
|
* @param {number} [options.raw.width] - integral number of pixels wide.
|
|
140
116
|
* @param {number} [options.raw.height] - integral number of pixels high.
|
|
141
117
|
* @param {number} [options.raw.channels] - integral number of channels, between 1 and 4.
|
|
118
|
+
* @param {boolean} [options.raw.premultiplied] - specifies that the raw input has already been premultiplied, set to `true`
|
|
119
|
+
* to avoid sharp premultiplying the image. (optional, default `false`)
|
|
142
120
|
* @param {Object} [options.create] - describes a new image to be created.
|
|
143
121
|
* @param {number} [options.create.width] - integral number of pixels wide.
|
|
144
122
|
* @param {number} [options.create.height] - integral number of pixels high.
|
|
@@ -202,6 +180,7 @@ const Sharp = function (input, options) {
|
|
|
202
180
|
flatten: false,
|
|
203
181
|
flattenBackground: [0, 0, 0],
|
|
204
182
|
negate: false,
|
|
183
|
+
negateAlpha: true,
|
|
205
184
|
medianSize: 0,
|
|
206
185
|
blurSigma: 0,
|
|
207
186
|
sharpenSigma: 0,
|
|
@@ -214,9 +193,13 @@ const Sharp = function (input, options) {
|
|
|
214
193
|
gammaOut: 0,
|
|
215
194
|
greyscale: false,
|
|
216
195
|
normalise: false,
|
|
196
|
+
claheWidth: 0,
|
|
197
|
+
claheHeight: 0,
|
|
198
|
+
claheMaxSlope: 3,
|
|
217
199
|
brightness: 1,
|
|
218
200
|
saturation: 1,
|
|
219
201
|
hue: 0,
|
|
202
|
+
lightness: 0,
|
|
220
203
|
booleanBufferIn: null,
|
|
221
204
|
booleanFileIn: '',
|
|
222
205
|
joinChannelIn: [],
|
|
@@ -224,6 +207,7 @@ const Sharp = function (input, options) {
|
|
|
224
207
|
removeAlpha: false,
|
|
225
208
|
ensureAlpha: -1,
|
|
226
209
|
colourspace: 'srgb',
|
|
210
|
+
colourspaceInput: 'last',
|
|
227
211
|
composite: [],
|
|
228
212
|
// output
|
|
229
213
|
fileOut: '',
|
|
@@ -231,6 +215,7 @@ const Sharp = function (input, options) {
|
|
|
231
215
|
streamOut: false,
|
|
232
216
|
withMetadata: false,
|
|
233
217
|
withMetadataOrientation: -1,
|
|
218
|
+
withMetadataDensity: 0,
|
|
234
219
|
withMetadataIcc: '',
|
|
235
220
|
withMetadataStrs: {},
|
|
236
221
|
resolveWithObject: false,
|
|
@@ -248,8 +233,13 @@ const Sharp = function (input, options) {
|
|
|
248
233
|
pngAdaptiveFiltering: false,
|
|
249
234
|
pngPalette: false,
|
|
250
235
|
pngQuality: 100,
|
|
251
|
-
|
|
236
|
+
pngBitdepth: 8,
|
|
252
237
|
pngDither: 1,
|
|
238
|
+
jp2Quality: 80,
|
|
239
|
+
jp2TileHeight: 512,
|
|
240
|
+
jp2TileWidth: 512,
|
|
241
|
+
jp2Lossless: false,
|
|
242
|
+
jp2ChromaSubsampling: '4:4:4',
|
|
253
243
|
webpQuality: 80,
|
|
254
244
|
webpAlphaQuality: 100,
|
|
255
245
|
webpLossless: false,
|
|
@@ -270,7 +260,8 @@ const Sharp = function (input, options) {
|
|
|
270
260
|
heifLossless: false,
|
|
271
261
|
heifCompression: 'av1',
|
|
272
262
|
heifSpeed: 5,
|
|
273
|
-
heifChromaSubsampling: '4:
|
|
263
|
+
heifChromaSubsampling: '4:4:4',
|
|
264
|
+
rawDepth: 'uchar',
|
|
274
265
|
tileSize: 256,
|
|
275
266
|
tileOverlap: 0,
|
|
276
267
|
tileContainer: 'fs',
|
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('
|
|
5
|
+
const sharp = require('./sharp');
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Extract input options, if any, from an object.
|
|
@@ -30,9 +30,14 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
30
30
|
inputDescriptor.file = input;
|
|
31
31
|
} else if (is.buffer(input)) {
|
|
32
32
|
// Buffer
|
|
33
|
+
if (input.length === 0) {
|
|
34
|
+
throw Error('Input Buffer is empty');
|
|
35
|
+
}
|
|
33
36
|
inputDescriptor.buffer = input;
|
|
34
|
-
} else if (is.
|
|
35
|
-
|
|
37
|
+
} else if (is.typedArray(input)) {
|
|
38
|
+
if (input.length === 0) {
|
|
39
|
+
throw Error('Input Bit Array is empty');
|
|
40
|
+
}
|
|
36
41
|
inputDescriptor.buffer = Buffer.from(input.buffer);
|
|
37
42
|
} else if (is.plainObject(input) && !is.defined(inputOptions)) {
|
|
38
43
|
// Plain Object descriptor, e.g. create
|
|
@@ -97,6 +102,38 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
97
102
|
inputDescriptor.rawWidth = inputOptions.raw.width;
|
|
98
103
|
inputDescriptor.rawHeight = inputOptions.raw.height;
|
|
99
104
|
inputDescriptor.rawChannels = inputOptions.raw.channels;
|
|
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
|
+
}
|
|
100
137
|
} else {
|
|
101
138
|
throw new Error('Expected width, height and channels for raw pixel input');
|
|
102
139
|
}
|
|
@@ -264,6 +301,8 @@ function _isStreamInput () {
|
|
|
264
301
|
* - `pagePrimary`: Number of the primary page in a HEIF image
|
|
265
302
|
* - `levels`: Details of each level in a multi-level image provided as an array of objects, requires libvips compiled with support for OpenSlide
|
|
266
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)
|
|
267
306
|
* - `hasProfile`: Boolean indicating the presence of an embedded ICC profile
|
|
268
307
|
* - `hasAlpha`: Boolean indicating the presence of an alpha transparency channel
|
|
269
308
|
* - `orientation`: Number value of the EXIF Orientation header, if present
|
|
@@ -349,6 +388,9 @@ function metadata (callback) {
|
|
|
349
388
|
* - `sharpness`: Estimation of greyscale sharpness based on the standard deviation of a Laplacian convolution, discarding alpha channel if any (experimental)
|
|
350
389
|
* - `dominant`: Object containing most dominant sRGB colour based on a 4096-bin 3D histogram (experimental)
|
|
351
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
|
+
*
|
|
352
394
|
* @example
|
|
353
395
|
* const image = sharp(inputJpg);
|
|
354
396
|
* image
|
|
@@ -361,6 +403,13 @@ function metadata (callback) {
|
|
|
361
403
|
* const { entropy, sharpness, dominant } = await sharp(input).stats();
|
|
362
404
|
* const { r, g, b } = dominant;
|
|
363
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
|
+
*
|
|
364
413
|
* @param {Function} [callback] - called with the arguments `(err, stats)`
|
|
365
414
|
* @returns {Promise<Object>}
|
|
366
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
|
|
52
|
+
* Is this value a typed array object?. E.g. Uint8Array or Uint8ClampedArray?
|
|
53
53
|
* @private
|
|
54
54
|
*/
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
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
|
-
|
|
136
|
+
typedArray: typedArray,
|
|
123
137
|
string: string,
|
|
124
138
|
number: number,
|
|
125
139
|
integer: integer,
|