sharp 0.25.3 → 0.26.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 +1 -1
- package/binding.gyp +82 -71
- package/install/dll-copy.js +3 -1
- package/install/libvips.js +26 -14
- package/lib/channel.js +5 -8
- package/lib/constructor.js +34 -18
- package/lib/input.js +27 -5
- package/lib/is.js +4 -4
- package/lib/libvips.js +2 -8
- package/lib/output.js +130 -35
- package/lib/platform.js +2 -1
- package/lib/resize.js +2 -1
- package/lib/utility.js +1 -1
- package/package.json +22 -17
- package/src/common.cc +125 -50
- package/src/common.h +24 -2
- package/src/libvips/cplusplus/VImage.cpp +451 -450
- package/src/libvips/cplusplus/vips-operators.cpp +117 -1
- package/src/metadata.cc +20 -0
- package/src/metadata.h +1 -0
- package/src/operations.cc +0 -23
- package/src/operations.h +0 -10
- package/src/pipeline.cc +82 -13
- package/src/pipeline.h +10 -2
- package/src/stats.cc +30 -1
- package/src/stats.h +9 -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 v10+
|
|
19
|
+
Most modern macOS, Windows and Linux systems running Node.js v10.16.0+
|
|
20
20
|
do not require any additional install or runtime dependencies.
|
|
21
21
|
|
|
22
22
|
## Examples
|
package/binding.gyp
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
+
'variables': {
|
|
3
|
+
'vips_version': '<!(node -p "require(\'./lib/libvips\').minimumLibvipsVersion")',
|
|
4
|
+
'sharp_vendor_dir': '<(module_root_dir)/vendor/<(vips_version)'
|
|
5
|
+
},
|
|
2
6
|
'targets': [{
|
|
3
7
|
'target_name': 'libvips-cpp',
|
|
4
8
|
'conditions': [
|
|
@@ -16,23 +20,38 @@
|
|
|
16
20
|
'src/libvips/cplusplus/VImage.cpp'
|
|
17
21
|
],
|
|
18
22
|
'include_dirs': [
|
|
19
|
-
'
|
|
20
|
-
'
|
|
21
|
-
'
|
|
22
|
-
],
|
|
23
|
-
'libraries': [
|
|
24
|
-
'../vendor/lib/libvips.lib',
|
|
25
|
-
'../vendor/lib/libglib-2.0.lib',
|
|
26
|
-
'../vendor/lib/libgobject-2.0.lib'
|
|
23
|
+
'<(sharp_vendor_dir)/include',
|
|
24
|
+
'<(sharp_vendor_dir)/include/glib-2.0',
|
|
25
|
+
'<(sharp_vendor_dir)/lib/glib-2.0/include'
|
|
27
26
|
],
|
|
27
|
+
'link_settings': {
|
|
28
|
+
'library_dirs': ['<(sharp_vendor_dir)/lib'],
|
|
29
|
+
'libraries': [
|
|
30
|
+
'libvips.lib',
|
|
31
|
+
'libglib-2.0.lib',
|
|
32
|
+
'libgobject-2.0.lib'
|
|
33
|
+
],
|
|
34
|
+
},
|
|
28
35
|
'configurations': {
|
|
29
36
|
'Release': {
|
|
30
37
|
'msvs_settings': {
|
|
31
38
|
'VCCLCompilerTool': {
|
|
32
|
-
'ExceptionHandling': 1
|
|
39
|
+
'ExceptionHandling': 1,
|
|
40
|
+
'WholeProgramOptimization': 'true'
|
|
41
|
+
},
|
|
42
|
+
'VCLibrarianTool': {
|
|
43
|
+
'AdditionalOptions': [
|
|
44
|
+
'/LTCG:INCREMENTAL'
|
|
45
|
+
]
|
|
33
46
|
},
|
|
34
47
|
'VCLinkerTool': {
|
|
35
|
-
'ImageHasSafeExceptionHandlers': 'false'
|
|
48
|
+
'ImageHasSafeExceptionHandlers': 'false',
|
|
49
|
+
'OptimizeReferences': 2,
|
|
50
|
+
'EnableCOMDATFolding': 2,
|
|
51
|
+
'LinkIncremental': 1,
|
|
52
|
+
'AdditionalOptions': [
|
|
53
|
+
'/LTCG:INCREMENTAL'
|
|
54
|
+
]
|
|
36
55
|
}
|
|
37
56
|
},
|
|
38
57
|
'msvs_disabled_warnings': [
|
|
@@ -58,8 +77,8 @@
|
|
|
58
77
|
'runtime_link%': 'shared',
|
|
59
78
|
'conditions': [
|
|
60
79
|
['OS != "win"', {
|
|
61
|
-
'pkg_config_path': '<!(node -
|
|
62
|
-
'use_global_libvips': '<!(node -
|
|
80
|
+
'pkg_config_path': '<!(node -p "require(\'./lib/libvips\').pkgConfigPath()")',
|
|
81
|
+
'use_global_libvips': '<!(node -p "Boolean(require(\'./lib/libvips\').useGlobalLibvips()).toString()")'
|
|
63
82
|
}, {
|
|
64
83
|
'pkg_config_path': '',
|
|
65
84
|
'use_global_libvips': ''
|
|
@@ -76,7 +95,7 @@
|
|
|
76
95
|
'src/sharp.cc'
|
|
77
96
|
],
|
|
78
97
|
'include_dirs': [
|
|
79
|
-
'
|
|
98
|
+
'<!(node -p "require(\'node-addon-api\').include_dir")',
|
|
80
99
|
],
|
|
81
100
|
'conditions': [
|
|
82
101
|
['use_global_libvips == "true"', {
|
|
@@ -98,9 +117,9 @@
|
|
|
98
117
|
}, {
|
|
99
118
|
# Use pre-built libvips stored locally within node_modules
|
|
100
119
|
'include_dirs': [
|
|
101
|
-
'
|
|
102
|
-
'
|
|
103
|
-
'
|
|
120
|
+
'<(sharp_vendor_dir)/include',
|
|
121
|
+
'<(sharp_vendor_dir)/include/glib-2.0',
|
|
122
|
+
'<(sharp_vendor_dir)/lib/glib-2.0/include'
|
|
104
123
|
],
|
|
105
124
|
'conditions': [
|
|
106
125
|
['OS == "win"', {
|
|
@@ -108,64 +127,45 @@
|
|
|
108
127
|
'_ALLOW_KEYWORD_MACROS',
|
|
109
128
|
'_FILE_OFFSET_BITS=64'
|
|
110
129
|
],
|
|
111
|
-
'
|
|
112
|
-
'
|
|
113
|
-
'
|
|
114
|
-
|
|
115
|
-
|
|
130
|
+
'link_settings': {
|
|
131
|
+
'library_dirs': ['<(sharp_vendor_dir)/lib'],
|
|
132
|
+
'libraries': [
|
|
133
|
+
'libvips.lib',
|
|
134
|
+
'libglib-2.0.lib',
|
|
135
|
+
'libgobject-2.0.lib'
|
|
136
|
+
]
|
|
137
|
+
}
|
|
116
138
|
}],
|
|
117
139
|
['OS == "mac"', {
|
|
118
|
-
'
|
|
119
|
-
'
|
|
120
|
-
'
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
140
|
+
'link_settings': {
|
|
141
|
+
'library_dirs': ['<(sharp_vendor_dir)/lib'],
|
|
142
|
+
'libraries': [
|
|
143
|
+
'libvips-cpp.42.dylib',
|
|
144
|
+
'libvips.42.dylib'
|
|
145
|
+
]
|
|
146
|
+
},
|
|
147
|
+
'xcode_settings': {
|
|
148
|
+
'OTHER_LDFLAGS': [
|
|
149
|
+
# Ensure runtime linking is relative to sharp.node
|
|
150
|
+
'-Wl,-rpath,\'@loader_path/../../vendor/<(vips_version)/lib\''
|
|
151
|
+
]
|
|
152
|
+
}
|
|
126
153
|
}],
|
|
127
154
|
['OS == "linux"', {
|
|
128
155
|
'defines': [
|
|
129
156
|
'_GLIBCXX_USE_CXX11_ABI=0'
|
|
130
157
|
],
|
|
131
|
-
'
|
|
132
|
-
'
|
|
133
|
-
'
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
'
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
'../vendor/lib/libfreetype.so',
|
|
143
|
-
'../vendor/lib/libfribidi.so',
|
|
144
|
-
'../vendor/lib/libgdk_pixbuf-2.0.so',
|
|
145
|
-
'../vendor/lib/libgif.so',
|
|
146
|
-
'../vendor/lib/libgio-2.0.so',
|
|
147
|
-
'../vendor/lib/libgmodule-2.0.so',
|
|
148
|
-
'../vendor/lib/libgsf-1.so',
|
|
149
|
-
'../vendor/lib/libgthread-2.0.so',
|
|
150
|
-
'../vendor/lib/libharfbuzz.so',
|
|
151
|
-
'../vendor/lib/libjpeg.so',
|
|
152
|
-
'../vendor/lib/liblcms2.so',
|
|
153
|
-
'../vendor/lib/liborc-0.4.so',
|
|
154
|
-
'../vendor/lib/libpango-1.0.so',
|
|
155
|
-
'../vendor/lib/libpangocairo-1.0.so',
|
|
156
|
-
'../vendor/lib/libpangoft2-1.0.so',
|
|
157
|
-
'../vendor/lib/libpixman-1.so',
|
|
158
|
-
'../vendor/lib/libpng.so',
|
|
159
|
-
'../vendor/lib/librsvg-2.so',
|
|
160
|
-
'../vendor/lib/libtiff.so',
|
|
161
|
-
'../vendor/lib/libwebp.so',
|
|
162
|
-
'../vendor/lib/libwebpdemux.so',
|
|
163
|
-
'../vendor/lib/libwebpmux.so',
|
|
164
|
-
'../vendor/lib/libxml2.so',
|
|
165
|
-
'../vendor/lib/libz.so',
|
|
166
|
-
# Ensure runtime linking is relative to sharp.node
|
|
167
|
-
'-Wl,--disable-new-dtags -Wl,-rpath=\'$${ORIGIN}/../../vendor/lib\''
|
|
168
|
-
]
|
|
158
|
+
'link_settings': {
|
|
159
|
+
'library_dirs': ['<(sharp_vendor_dir)/lib'],
|
|
160
|
+
'libraries': [
|
|
161
|
+
'-l:libvips-cpp.so.42',
|
|
162
|
+
'-l:libvips.so.42'
|
|
163
|
+
],
|
|
164
|
+
'ldflags': [
|
|
165
|
+
# Ensure runtime linking is relative to sharp.node
|
|
166
|
+
'-Wl,-s -Wl,--disable-new-dtags -Wl,-rpath=\'$$ORIGIN/../../vendor/<(vips_version)/lib\''
|
|
167
|
+
]
|
|
168
|
+
}
|
|
169
169
|
}]
|
|
170
170
|
]
|
|
171
171
|
}]
|
|
@@ -178,8 +178,7 @@
|
|
|
178
178
|
],
|
|
179
179
|
'xcode_settings': {
|
|
180
180
|
'CLANG_CXX_LANGUAGE_STANDARD': 'c++11',
|
|
181
|
-
'
|
|
182
|
-
'MACOSX_DEPLOYMENT_TARGET': '10.7',
|
|
181
|
+
'MACOSX_DEPLOYMENT_TARGET': '10.9',
|
|
183
182
|
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
|
|
184
183
|
'GCC_ENABLE_CPP_RTTI': 'YES',
|
|
185
184
|
'OTHER_CPLUSPLUSFLAGS': [
|
|
@@ -204,10 +203,22 @@
|
|
|
204
203
|
['OS == "win"', {
|
|
205
204
|
'msvs_settings': {
|
|
206
205
|
'VCCLCompilerTool': {
|
|
207
|
-
'ExceptionHandling': 1
|
|
206
|
+
'ExceptionHandling': 1,
|
|
207
|
+
'WholeProgramOptimization': 'true'
|
|
208
|
+
},
|
|
209
|
+
'VCLibrarianTool': {
|
|
210
|
+
'AdditionalOptions': [
|
|
211
|
+
'/LTCG:INCREMENTAL'
|
|
212
|
+
]
|
|
208
213
|
},
|
|
209
214
|
'VCLinkerTool': {
|
|
210
|
-
'ImageHasSafeExceptionHandlers': 'false'
|
|
215
|
+
'ImageHasSafeExceptionHandlers': 'false',
|
|
216
|
+
'OptimizeReferences': 2,
|
|
217
|
+
'EnableCOMDATFolding': 2,
|
|
218
|
+
'LinkIncremental': 1,
|
|
219
|
+
'AdditionalOptions': [
|
|
220
|
+
'/LTCG:INCREMENTAL'
|
|
221
|
+
]
|
|
211
222
|
}
|
|
212
223
|
},
|
|
213
224
|
'msvs_disabled_warnings': [
|
package/install/dll-copy.js
CHANGED
|
@@ -6,6 +6,8 @@ const path = require('path');
|
|
|
6
6
|
const libvips = require('../lib/libvips');
|
|
7
7
|
const npmLog = require('npmlog');
|
|
8
8
|
|
|
9
|
+
const minimumLibvipsVersion = libvips.minimumLibvipsVersion;
|
|
10
|
+
|
|
9
11
|
const platform = process.env.npm_config_platform || process.platform;
|
|
10
12
|
if (platform === 'win32') {
|
|
11
13
|
const buildDir = path.join(__dirname, '..', 'build');
|
|
@@ -15,7 +17,7 @@ if (platform === 'win32') {
|
|
|
15
17
|
libvips.mkdirSync(buildDir);
|
|
16
18
|
libvips.mkdirSync(buildReleaseDir);
|
|
17
19
|
} catch (err) {}
|
|
18
|
-
const vendorLibDir = path.join(__dirname, '..', 'vendor', 'lib');
|
|
20
|
+
const vendorLibDir = path.join(__dirname, '..', 'vendor', minimumLibvipsVersion, 'lib');
|
|
19
21
|
npmLog.info('sharp', `Copying DLLs from ${vendorLibDir} to ${buildReleaseDir}`);
|
|
20
22
|
try {
|
|
21
23
|
fs
|
package/install/libvips.js
CHANGED
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const os = require('os');
|
|
5
5
|
const path = require('path');
|
|
6
|
+
const stream = require('stream');
|
|
7
|
+
const zlib = require('zlib');
|
|
6
8
|
|
|
7
9
|
const detectLibc = require('detect-libc');
|
|
8
10
|
const npmLog = require('npmlog');
|
|
9
11
|
const semver = require('semver');
|
|
10
12
|
const simpleGet = require('simple-get');
|
|
11
|
-
const
|
|
13
|
+
const tarFs = require('tar-fs');
|
|
12
14
|
|
|
13
15
|
const agent = require('../lib/agent');
|
|
14
16
|
const libvips = require('../lib/libvips');
|
|
@@ -21,7 +23,8 @@ const minimumGlibcVersionByArch = {
|
|
|
21
23
|
};
|
|
22
24
|
|
|
23
25
|
const { minimumLibvipsVersion, minimumLibvipsVersionLabelled } = libvips;
|
|
24
|
-
const
|
|
26
|
+
const distHost = process.env.npm_config_sharp_libvips_binary_host || 'https://github.com/lovell/sharp-libvips/releases/download';
|
|
27
|
+
const distBaseUrl = process.env.npm_config_sharp_dist_base_url || process.env.SHARP_DIST_BASE_URL || `${distHost}/v${minimumLibvipsVersionLabelled}/`;
|
|
25
28
|
|
|
26
29
|
const fail = function (err) {
|
|
27
30
|
npmLog.error('sharp', err.message);
|
|
@@ -36,18 +39,21 @@ const fail = function (err) {
|
|
|
36
39
|
const extractTarball = function (tarPath) {
|
|
37
40
|
const vendorPath = path.join(__dirname, '..', 'vendor');
|
|
38
41
|
libvips.mkdirSync(vendorPath);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (
|
|
47
|
-
|
|
42
|
+
const versionedVendorPath = path.join(vendorPath, minimumLibvipsVersion);
|
|
43
|
+
libvips.mkdirSync(versionedVendorPath);
|
|
44
|
+
stream.pipeline(
|
|
45
|
+
fs.createReadStream(tarPath),
|
|
46
|
+
new zlib.BrotliDecompress(),
|
|
47
|
+
tarFs.extract(versionedVendorPath),
|
|
48
|
+
function (err) {
|
|
49
|
+
if (err) {
|
|
50
|
+
if (/unexpected end of file/.test(err.message)) {
|
|
51
|
+
npmLog.error('sharp', `Please delete ${tarPath} as it is not a valid tarball`);
|
|
52
|
+
}
|
|
53
|
+
fail(err);
|
|
48
54
|
}
|
|
49
|
-
|
|
50
|
-
|
|
55
|
+
}
|
|
56
|
+
);
|
|
51
57
|
};
|
|
52
58
|
|
|
53
59
|
try {
|
|
@@ -74,8 +80,14 @@ try {
|
|
|
74
80
|
throw new Error(`Use with glibc ${detectLibc.version} requires manual installation of libvips >= ${minimumLibvipsVersion}`);
|
|
75
81
|
}
|
|
76
82
|
}
|
|
83
|
+
|
|
84
|
+
const supportedNodeVersion = process.env.npm_package_engines_node || require('../package.json').engines.node;
|
|
85
|
+
if (!semver.satisfies(process.versions.node, supportedNodeVersion)) {
|
|
86
|
+
throw new Error(`Expected Node.js version ${supportedNodeVersion} but found ${process.versions.node}`);
|
|
87
|
+
}
|
|
88
|
+
|
|
77
89
|
// Download to per-process temporary file
|
|
78
|
-
const tarFilename = ['libvips', minimumLibvipsVersion, platformAndArch].join('-') + '.tar.
|
|
90
|
+
const tarFilename = ['libvips', minimumLibvipsVersion, platformAndArch].join('-') + '.tar.br';
|
|
79
91
|
const tarPathCache = path.join(libvips.cachePath(), tarFilename);
|
|
80
92
|
if (fs.existsSync(tarPathCache)) {
|
|
81
93
|
npmLog.info('sharp', `Using cached ${tarPathCache}`);
|
package/lib/channel.js
CHANGED
|
@@ -60,22 +60,19 @@ function ensureAlpha () {
|
|
|
60
60
|
* // green.jpg is a greyscale image containing the green channel of the input
|
|
61
61
|
* });
|
|
62
62
|
*
|
|
63
|
-
* @param {number|string} channel - zero-indexed band number to extract, or `red`, `green
|
|
63
|
+
* @param {number|string} channel - zero-indexed channel/band number to extract, or `red`, `green`, `blue` or `alpha`.
|
|
64
64
|
* @returns {Sharp}
|
|
65
65
|
* @throws {Error} Invalid channel
|
|
66
66
|
*/
|
|
67
67
|
function extractChannel (channel) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
channel = 1;
|
|
72
|
-
} else if (channel === 'blue') {
|
|
73
|
-
channel = 2;
|
|
68
|
+
const channelMap = { red: 0, green: 1, blue: 2, alpha: 3 };
|
|
69
|
+
if (Object.keys(channelMap).includes(channel)) {
|
|
70
|
+
channel = channelMap[channel];
|
|
74
71
|
}
|
|
75
72
|
if (is.integer(channel) && is.inRange(channel, 0, 4)) {
|
|
76
73
|
this.options.extractChannel = channel;
|
|
77
74
|
} else {
|
|
78
|
-
throw is.invalidParameterError('channel', 'integer or one of: red, green, blue', channel);
|
|
75
|
+
throw is.invalidParameterError('channel', 'integer or one of: red, green, blue, alpha', channel);
|
|
79
76
|
}
|
|
80
77
|
return this;
|
|
81
78
|
}
|
package/lib/constructor.js
CHANGED
|
@@ -38,15 +38,20 @@ try {
|
|
|
38
38
|
const debuglog = util.debuglog('sharp');
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
|
-
* @constructs sharp
|
|
42
|
-
*
|
|
43
41
|
* Constructor factory to create an instance of `sharp`, to which further methods are chained.
|
|
44
42
|
*
|
|
45
43
|
* JPEG, PNG, WebP or TIFF format image data can be streamed out from this object.
|
|
46
44
|
* When using Stream based output, derived attributes are available from the `info` event.
|
|
47
45
|
*
|
|
46
|
+
* Non-critical problems encountered during processing are emitted as `warning` events.
|
|
47
|
+
*
|
|
48
48
|
* Implements the [stream.Duplex](http://nodejs.org/api/stream.html#stream_class_stream_duplex) class.
|
|
49
49
|
*
|
|
50
|
+
* @constructs Sharp
|
|
51
|
+
*
|
|
52
|
+
* @emits Sharp#info
|
|
53
|
+
* @emits Sharp#warning
|
|
54
|
+
*
|
|
50
55
|
* @example
|
|
51
56
|
* sharp('input.jpg')
|
|
52
57
|
* .resize(300, 200)
|
|
@@ -81,30 +86,36 @@ const debuglog = util.debuglog('sharp');
|
|
|
81
86
|
* .toBuffer()
|
|
82
87
|
* .then( ... );
|
|
83
88
|
*
|
|
84
|
-
* @
|
|
89
|
+
* @example
|
|
90
|
+
* // Convert an animated GIF to an animated WebP
|
|
91
|
+
* await sharp('in.gif', { animated: true }).toFile('out.webp');
|
|
92
|
+
*
|
|
93
|
+
* @param {(Buffer|string)} [input] - if present, can be
|
|
85
94
|
* a Buffer containing JPEG, PNG, WebP, GIF, SVG, TIFF or raw pixel image data, or
|
|
86
95
|
* a String containing the filesystem path to an JPEG, PNG, WebP, GIF, SVG or TIFF image file.
|
|
87
96
|
* JPEG, PNG, WebP, GIF, SVG, TIFF or raw pixel image data can be streamed into the object when not present.
|
|
88
97
|
* @param {Object} [options] - if present, is an Object with optional attributes.
|
|
89
|
-
* @param {
|
|
98
|
+
* @param {boolean} [options.failOnError=true] - by default halt processing and raise an error when loading invalid images.
|
|
90
99
|
* Set this flag to `false` if you'd rather apply a "best effort" to decode images, even if the data is corrupt or invalid.
|
|
91
|
-
* @param {
|
|
100
|
+
* @param {number|boolean} [options.limitInputPixels=268402689] - Do not process input images where the number of pixels
|
|
92
101
|
* (width x height) exceeds this limit. Assumes image dimensions contained in the input metadata can be trusted.
|
|
93
102
|
* An integral Number of pixels, zero or false to remove limit, true to use default limit of 268402689 (0x3FFF x 0x3FFF).
|
|
94
|
-
* @param {
|
|
103
|
+
* @param {boolean} [options.sequentialRead=false] - Set this to `true` to use sequential rather than random access where possible.
|
|
95
104
|
* This can reduce memory usage and might improve performance on some systems.
|
|
96
|
-
* @param {
|
|
97
|
-
* @param {
|
|
98
|
-
* @param {
|
|
105
|
+
* @param {number} [options.density=72] - number representing the DPI for vector images in the range 1 to 100000.
|
|
106
|
+
* @param {number} [options.pages=1] - number of pages to extract for multi-page input (GIF, TIFF, PDF), use -1 for all pages.
|
|
107
|
+
* @param {number} [options.page=0] - page number to start extracting from for multi-page input (GIF, TIFF, PDF), zero based.
|
|
108
|
+
* @param {number} [options.level=0] - level to extract from a multi-level input (OpenSlide), zero based.
|
|
109
|
+
* @param {boolean} [options.animated=false] - Set to `true` to read all frames/pages of an animated image (equivalent of setting `pages` to `-1`).
|
|
99
110
|
* @param {Object} [options.raw] - describes raw pixel input image data. See `raw()` for pixel ordering.
|
|
100
|
-
* @param {
|
|
101
|
-
* @param {
|
|
102
|
-
* @param {
|
|
111
|
+
* @param {number} [options.raw.width]
|
|
112
|
+
* @param {number} [options.raw.height]
|
|
113
|
+
* @param {number} [options.raw.channels] - 1-4
|
|
103
114
|
* @param {Object} [options.create] - describes a new image to be created.
|
|
104
|
-
* @param {
|
|
105
|
-
* @param {
|
|
106
|
-
* @param {
|
|
107
|
-
* @param {
|
|
115
|
+
* @param {number} [options.create.width]
|
|
116
|
+
* @param {number} [options.create.height]
|
|
117
|
+
* @param {number} [options.create.channels] - 3-4
|
|
118
|
+
* @param {string|Object} [options.create.background] - parsed by the [color](https://www.npmjs.org/package/color) module to extract values for red, green, blue and alpha.
|
|
108
119
|
* @returns {Sharp}
|
|
109
120
|
* @throws {Error} Invalid parameters
|
|
110
121
|
*/
|
|
@@ -181,6 +192,7 @@ const Sharp = function (input, options) {
|
|
|
181
192
|
streamOut: false,
|
|
182
193
|
withMetadata: false,
|
|
183
194
|
withMetadataOrientation: -1,
|
|
195
|
+
withMetadataIcc: '',
|
|
184
196
|
resolveWithObject: false,
|
|
185
197
|
// output format
|
|
186
198
|
jpegQuality: 80,
|
|
@@ -208,7 +220,7 @@ const Sharp = function (input, options) {
|
|
|
208
220
|
tiffCompression: 'jpeg',
|
|
209
221
|
tiffPredictor: 'horizontal',
|
|
210
222
|
tiffPyramid: false,
|
|
211
|
-
|
|
223
|
+
tiffBitdepth: 8,
|
|
212
224
|
tiffTile: false,
|
|
213
225
|
tiffTileHeight: 256,
|
|
214
226
|
tiffTileWidth: 256,
|
|
@@ -226,10 +238,14 @@ const Sharp = function (input, options) {
|
|
|
226
238
|
tileAngle: 0,
|
|
227
239
|
tileSkipBlanks: -1,
|
|
228
240
|
tileBackground: [255, 255, 255, 255],
|
|
241
|
+
tileCentre: false,
|
|
229
242
|
linearA: 1,
|
|
230
243
|
linearB: 0,
|
|
231
244
|
// Function to notify of libvips warnings
|
|
232
|
-
debuglog:
|
|
245
|
+
debuglog: warning => {
|
|
246
|
+
this.emit('warning', warning);
|
|
247
|
+
debuglog(warning);
|
|
248
|
+
},
|
|
233
249
|
// Function to notify of queue length changes
|
|
234
250
|
queueListener: function (queueLength) {
|
|
235
251
|
Sharp.queue.emit('change', queueLength);
|
package/lib/input.js
CHANGED
|
@@ -9,9 +9,9 @@ const sharp = require('../build/Release/sharp.node');
|
|
|
9
9
|
* @private
|
|
10
10
|
*/
|
|
11
11
|
function _inputOptionsFromObject (obj) {
|
|
12
|
-
const { raw, density, limitInputPixels, sequentialRead, failOnError } = obj;
|
|
13
|
-
return [raw, density, limitInputPixels, sequentialRead, failOnError].some(is.defined)
|
|
14
|
-
? { raw, density, limitInputPixels, sequentialRead, failOnError }
|
|
12
|
+
const { raw, density, limitInputPixels, sequentialRead, failOnError, animated, page, pages } = obj;
|
|
13
|
+
return [raw, density, limitInputPixels, sequentialRead, failOnError, animated, page, pages].some(is.defined)
|
|
14
|
+
? { raw, density, limitInputPixels, sequentialRead, failOnError, animated, page, pages }
|
|
15
15
|
: undefined;
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -57,10 +57,10 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
57
57
|
}
|
|
58
58
|
// Density
|
|
59
59
|
if (is.defined(inputOptions.density)) {
|
|
60
|
-
if (is.inRange(inputOptions.density, 1,
|
|
60
|
+
if (is.inRange(inputOptions.density, 1, 100000)) {
|
|
61
61
|
inputDescriptor.density = inputOptions.density;
|
|
62
62
|
} else {
|
|
63
|
-
throw is.invalidParameterError('density', 'number between 1 and
|
|
63
|
+
throw is.invalidParameterError('density', 'number between 1 and 100000', inputOptions.density);
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
// limitInputPixels
|
|
@@ -99,6 +99,13 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
// Multi-page input (GIF, TIFF, PDF)
|
|
102
|
+
if (is.defined(inputOptions.animated)) {
|
|
103
|
+
if (is.bool(inputOptions.animated)) {
|
|
104
|
+
inputDescriptor.pages = inputOptions.animated ? -1 : 1;
|
|
105
|
+
} else {
|
|
106
|
+
throw is.invalidParameterError('animated', 'boolean', inputOptions.animated);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
102
109
|
if (is.defined(inputOptions.pages)) {
|
|
103
110
|
if (is.integer(inputOptions.pages) && is.inRange(inputOptions.pages, -1, 100000)) {
|
|
104
111
|
inputDescriptor.pages = inputOptions.pages;
|
|
@@ -113,6 +120,14 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
113
120
|
throw is.invalidParameterError('page', 'integer between 0 and 100000', inputOptions.page);
|
|
114
121
|
}
|
|
115
122
|
}
|
|
123
|
+
// Multi-level input (OpenSlide)
|
|
124
|
+
if (is.defined(inputOptions.level)) {
|
|
125
|
+
if (is.integer(inputOptions.level) && is.inRange(inputOptions.level, 0, 256)) {
|
|
126
|
+
inputDescriptor.level = inputOptions.level;
|
|
127
|
+
} else {
|
|
128
|
+
throw is.invalidParameterError('level', 'integer between 0 and 256', inputOptions.level);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
116
131
|
// Create new image
|
|
117
132
|
if (is.defined(inputOptions.create)) {
|
|
118
133
|
if (
|
|
@@ -208,6 +223,7 @@ function _isStreamInput () {
|
|
|
208
223
|
* - `loop`: Number of times to loop an animated image, zero refers to a continuous loop.
|
|
209
224
|
* - `delay`: Delay in ms between each page in an animated image, provided as an array of integers.
|
|
210
225
|
* - `pagePrimary`: Number of the primary page in a HEIF image
|
|
226
|
+
* - `levels`: Details of each level in a multi-level image provided as an array of objects, requires libvips compiled with support for OpenSlide
|
|
211
227
|
* - `hasProfile`: Boolean indicating the presence of an embedded ICC profile
|
|
212
228
|
* - `hasAlpha`: Boolean indicating the presence of an alpha transparency channel
|
|
213
229
|
* - `orientation`: Number value of the EXIF Orientation header, if present
|
|
@@ -290,6 +306,8 @@ function metadata (callback) {
|
|
|
290
306
|
* - `maxY` (y-coordinate of one of the pixel where the maximum lies)
|
|
291
307
|
* - `isOpaque`: Is the image fully opaque? Will be `true` if the image has no alpha channel or if every pixel is fully opaque.
|
|
292
308
|
* - `entropy`: Histogram-based estimation of greyscale entropy, discarding alpha channel if any (experimental)
|
|
309
|
+
* - `sharpness`: Estimation of greyscale sharpness based on the standard deviation of a Laplacian convolution, discarding alpha channel if any (experimental)
|
|
310
|
+
* - `dominant`: Object containing most dominant sRGB colour based on a 4096-bin 3D histogram (experimental)
|
|
293
311
|
*
|
|
294
312
|
* @example
|
|
295
313
|
* const image = sharp(inputJpg);
|
|
@@ -299,6 +317,10 @@ function metadata (callback) {
|
|
|
299
317
|
* // stats contains the channel-wise statistics array and the isOpaque value
|
|
300
318
|
* });
|
|
301
319
|
*
|
|
320
|
+
* @example
|
|
321
|
+
* const { entropy, sharpness, dominant } = await sharp(input).stats();
|
|
322
|
+
* const { r, g, b } = dominant;
|
|
323
|
+
*
|
|
302
324
|
* @param {Function} [callback] - called with the arguments `(err, stats)`
|
|
303
325
|
* @returns {Promise<Object>}
|
|
304
326
|
*/
|
package/lib/is.js
CHANGED
|
@@ -21,7 +21,7 @@ const object = function (val) {
|
|
|
21
21
|
* @private
|
|
22
22
|
*/
|
|
23
23
|
const plainObject = function (val) {
|
|
24
|
-
return
|
|
24
|
+
return Object.prototype.toString.call(val) === '[object Object]';
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
/**
|
|
@@ -45,7 +45,7 @@ const bool = function (val) {
|
|
|
45
45
|
* @private
|
|
46
46
|
*/
|
|
47
47
|
const buffer = function (val) {
|
|
48
|
-
return
|
|
48
|
+
return val instanceof Buffer;
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
/**
|
|
@@ -69,7 +69,7 @@ const number = function (val) {
|
|
|
69
69
|
* @private
|
|
70
70
|
*/
|
|
71
71
|
const integer = function (val) {
|
|
72
|
-
return
|
|
72
|
+
return Number.isInteger(val);
|
|
73
73
|
};
|
|
74
74
|
|
|
75
75
|
/**
|
|
@@ -85,7 +85,7 @@ const inRange = function (val, min, max) {
|
|
|
85
85
|
* @private
|
|
86
86
|
*/
|
|
87
87
|
const inArray = function (val, list) {
|
|
88
|
-
return list.
|
|
88
|
+
return list.includes(val);
|
|
89
89
|
};
|
|
90
90
|
|
|
91
91
|
/**
|
package/lib/libvips.js
CHANGED
|
@@ -48,24 +48,18 @@ const globalLibvipsVersion = function () {
|
|
|
48
48
|
|
|
49
49
|
const hasVendoredLibvips = function () {
|
|
50
50
|
const currentPlatformId = platform();
|
|
51
|
-
const vendorPath = path.join(__dirname, '..', 'vendor');
|
|
52
|
-
let vendorVersionId;
|
|
51
|
+
const vendorPath = path.join(__dirname, '..', 'vendor', minimumLibvipsVersion);
|
|
53
52
|
let vendorPlatformId;
|
|
54
53
|
try {
|
|
55
|
-
vendorVersionId = require(path.join(vendorPath, 'versions.json')).vips;
|
|
56
54
|
vendorPlatformId = require(path.join(vendorPath, 'platform.json'));
|
|
57
55
|
} catch (err) {}
|
|
58
|
-
/* istanbul ignore if */
|
|
59
|
-
if (vendorVersionId && vendorVersionId !== minimumLibvipsVersion) {
|
|
60
|
-
throw new Error(`Found vendored libvips v${vendorVersionId} but require v${minimumLibvipsVersion}. Please remove the 'node_modules/sharp/vendor' directory and run 'npm install'.`);
|
|
61
|
-
}
|
|
62
56
|
/* istanbul ignore else */
|
|
63
57
|
if (vendorPlatformId) {
|
|
64
58
|
/* istanbul ignore else */
|
|
65
59
|
if (currentPlatformId === vendorPlatformId) {
|
|
66
60
|
return true;
|
|
67
61
|
} else {
|
|
68
|
-
throw new Error(`'${vendorPlatformId}' binaries cannot be used on the '${currentPlatformId}' platform. Please remove the 'node_modules/sharp
|
|
62
|
+
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.`);
|
|
69
63
|
}
|
|
70
64
|
} else {
|
|
71
65
|
return false;
|