sharp 0.27.2 → 0.28.0
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 +14 -13
- package/binding.gyp +3 -5
- package/install/dll-copy.js +4 -4
- package/install/libvips.js +58 -32
- package/lib/constructor.js +3 -4
- package/lib/libvips.js +9 -0
- package/lib/operation.js +9 -4
- package/lib/output.js +59 -25
- package/lib/resize.js +42 -15
- package/lib/utility.js +13 -2
- package/package.json +7 -9
- package/src/common.cc +2 -0
- package/src/common.h +2 -2
- package/src/pipeline.cc +17 -2
- package/src/pipeline.h +2 -1
- package/src/sharp.cc +1 -0
- package/src/utilities.cc +16 -0
- package/src/utilities.h +1 -0
package/README.md
CHANGED
|
@@ -19,6 +19,14 @@ rotation, extraction, compositing and gamma correction are available.
|
|
|
19
19
|
Most modern macOS, Windows and Linux systems running Node.js v10+
|
|
20
20
|
do not require any additional install or runtime dependencies.
|
|
21
21
|
|
|
22
|
+
## Documentation
|
|
23
|
+
|
|
24
|
+
Visit [sharp.pixelplumbing.com](https://sharp.pixelplumbing.com/) for complete
|
|
25
|
+
[installation instructions](https://sharp.pixelplumbing.com/install),
|
|
26
|
+
[API documentation](https://sharp.pixelplumbing.com/api-constructor),
|
|
27
|
+
[benchmark tests](https://sharp.pixelplumbing.com/performance) and
|
|
28
|
+
[changelog](https://sharp.pixelplumbing.com/changelog).
|
|
29
|
+
|
|
22
30
|
## Examples
|
|
23
31
|
|
|
24
32
|
```sh
|
|
@@ -43,6 +51,7 @@ sharp(inputBuffer)
|
|
|
43
51
|
sharp('input.jpg')
|
|
44
52
|
.rotate()
|
|
45
53
|
.resize(200)
|
|
54
|
+
.jpeg({ mozjpeg: true })
|
|
46
55
|
.toBuffer()
|
|
47
56
|
.then( data => { ... })
|
|
48
57
|
.catch( err => { ... });
|
|
@@ -84,23 +93,15 @@ readableStream
|
|
|
84
93
|
.pipe(writableStream);
|
|
85
94
|
```
|
|
86
95
|
|
|
87
|
-
|
|
88
|
-
[](https://nodejs.org/dist/latest/docs/api/n-api.html#n_api_n_api_version_matrix)
|
|
89
|
-
|
|
90
|
-
### Documentation
|
|
91
|
-
|
|
92
|
-
Visit [sharp.pixelplumbing.com](https://sharp.pixelplumbing.com/) for complete
|
|
93
|
-
[installation instructions](https://sharp.pixelplumbing.com/install),
|
|
94
|
-
[API documentation](https://sharp.pixelplumbing.com/api-constructor),
|
|
95
|
-
[benchmark tests](https://sharp.pixelplumbing.com/performance) and
|
|
96
|
-
[changelog](https://sharp.pixelplumbing.com/changelog).
|
|
97
|
-
|
|
98
|
-
### Contributing
|
|
96
|
+
## Contributing
|
|
99
97
|
|
|
100
98
|
A [guide for contributors](https://github.com/lovell/sharp/blob/master/.github/CONTRIBUTING.md)
|
|
101
99
|
covers reporting bugs, requesting features and submitting code changes.
|
|
102
100
|
|
|
103
|
-
|
|
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
|
+
|
|
104
|
+
## Licensing
|
|
104
105
|
|
|
105
106
|
Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Lovell Fuller and contributors.
|
|
106
107
|
|
package/binding.gyp
CHANGED
|
@@ -140,8 +140,7 @@
|
|
|
140
140
|
'link_settings': {
|
|
141
141
|
'library_dirs': ['<(sharp_vendor_dir)/lib'],
|
|
142
142
|
'libraries': [
|
|
143
|
-
'libvips-cpp.42.dylib'
|
|
144
|
-
'libvips.42.dylib'
|
|
143
|
+
'libvips-cpp.42.dylib'
|
|
145
144
|
]
|
|
146
145
|
},
|
|
147
146
|
'xcode_settings': {
|
|
@@ -153,13 +152,12 @@
|
|
|
153
152
|
}],
|
|
154
153
|
['OS == "linux"', {
|
|
155
154
|
'defines': [
|
|
156
|
-
'_GLIBCXX_USE_CXX11_ABI=
|
|
155
|
+
'_GLIBCXX_USE_CXX11_ABI=1'
|
|
157
156
|
],
|
|
158
157
|
'link_settings': {
|
|
159
158
|
'library_dirs': ['<(sharp_vendor_dir)/lib'],
|
|
160
159
|
'libraries': [
|
|
161
|
-
'-l:libvips-cpp.so.42'
|
|
162
|
-
'-l:libvips.so.42'
|
|
160
|
+
'-l:libvips-cpp.so.42'
|
|
163
161
|
],
|
|
164
162
|
'ldflags': [
|
|
165
163
|
# Ensure runtime linking is relative to sharp.node
|
package/install/dll-copy.js
CHANGED
|
@@ -4,7 +4,6 @@ const fs = require('fs');
|
|
|
4
4
|
const path = require('path');
|
|
5
5
|
|
|
6
6
|
const libvips = require('../lib/libvips');
|
|
7
|
-
const npmLog = require('npmlog');
|
|
8
7
|
|
|
9
8
|
const minimumLibvipsVersion = libvips.minimumLibvipsVersion;
|
|
10
9
|
|
|
@@ -12,13 +11,13 @@ const platform = process.env.npm_config_platform || process.platform;
|
|
|
12
11
|
if (platform === 'win32') {
|
|
13
12
|
const buildDir = path.join(__dirname, '..', 'build');
|
|
14
13
|
const buildReleaseDir = path.join(buildDir, 'Release');
|
|
15
|
-
|
|
14
|
+
libvips.log(`Creating ${buildReleaseDir}`);
|
|
16
15
|
try {
|
|
17
16
|
libvips.mkdirSync(buildDir);
|
|
18
17
|
libvips.mkdirSync(buildReleaseDir);
|
|
19
18
|
} catch (err) {}
|
|
20
19
|
const vendorLibDir = path.join(__dirname, '..', 'vendor', minimumLibvipsVersion, 'lib');
|
|
21
|
-
|
|
20
|
+
libvips.log(`Copying DLLs from ${vendorLibDir} to ${buildReleaseDir}`);
|
|
22
21
|
try {
|
|
23
22
|
fs
|
|
24
23
|
.readdirSync(vendorLibDir)
|
|
@@ -32,6 +31,7 @@ if (platform === 'win32') {
|
|
|
32
31
|
);
|
|
33
32
|
});
|
|
34
33
|
} catch (err) {
|
|
35
|
-
|
|
34
|
+
libvips.log(err);
|
|
35
|
+
process.exit(1);
|
|
36
36
|
}
|
|
37
37
|
}
|
package/install/libvips.js
CHANGED
|
@@ -7,7 +7,6 @@ const stream = require('stream');
|
|
|
7
7
|
const zlib = require('zlib');
|
|
8
8
|
|
|
9
9
|
const detectLibc = require('detect-libc');
|
|
10
|
-
const npmLog = require('npmlog');
|
|
11
10
|
const semver = require('semver');
|
|
12
11
|
const simpleGet = require('simple-get');
|
|
13
12
|
const tarFs = require('tar-fs');
|
|
@@ -22,34 +21,50 @@ const minimumGlibcVersionByArch = {
|
|
|
22
21
|
x64: '2.17'
|
|
23
22
|
};
|
|
24
23
|
|
|
24
|
+
const hasSharpPrebuild = [
|
|
25
|
+
'darwin-x64',
|
|
26
|
+
'linux-arm64',
|
|
27
|
+
'linux-x64',
|
|
28
|
+
'linuxmusl-x64',
|
|
29
|
+
'linuxmusl-arm64',
|
|
30
|
+
'win32-ia32',
|
|
31
|
+
'win32-x64'
|
|
32
|
+
];
|
|
33
|
+
|
|
25
34
|
const { minimumLibvipsVersion, minimumLibvipsVersionLabelled } = libvips;
|
|
26
35
|
const distHost = process.env.npm_config_sharp_libvips_binary_host || 'https://github.com/lovell/sharp-libvips/releases/download';
|
|
27
36
|
const distBaseUrl = process.env.npm_config_sharp_dist_base_url || process.env.SHARP_DIST_BASE_URL || `${distHost}/v${minimumLibvipsVersionLabelled}/`;
|
|
28
37
|
const supportsBrotli = ('BrotliDecompress' in zlib);
|
|
29
38
|
|
|
30
39
|
const fail = function (err) {
|
|
31
|
-
|
|
40
|
+
libvips.log(err);
|
|
32
41
|
if (err.code === 'EACCES') {
|
|
33
|
-
|
|
42
|
+
libvips.log('Are you trying to install as a root or sudo user? Try again with the --unsafe-perm flag');
|
|
34
43
|
}
|
|
35
|
-
|
|
36
|
-
|
|
44
|
+
libvips.log('Attempting to build from source via node-gyp but this may fail due to the above error');
|
|
45
|
+
libvips.log('Please see https://sharp.pixelplumbing.com/install for required dependencies');
|
|
37
46
|
process.exit(1);
|
|
38
47
|
};
|
|
39
48
|
|
|
40
|
-
const extractTarball = function (tarPath) {
|
|
49
|
+
const extractTarball = function (tarPath, platformAndArch) {
|
|
41
50
|
const vendorPath = path.join(__dirname, '..', 'vendor');
|
|
42
51
|
libvips.mkdirSync(vendorPath);
|
|
43
52
|
const versionedVendorPath = path.join(vendorPath, minimumLibvipsVersion);
|
|
44
53
|
libvips.mkdirSync(versionedVendorPath);
|
|
54
|
+
|
|
55
|
+
const ignoreVendorInclude = hasSharpPrebuild.includes(platformAndArch) && !process.env.npm_config_build_from_source;
|
|
56
|
+
const ignore = function (name) {
|
|
57
|
+
return ignoreVendorInclude && name.includes('include/');
|
|
58
|
+
};
|
|
59
|
+
|
|
45
60
|
stream.pipeline(
|
|
46
61
|
fs.createReadStream(tarPath),
|
|
47
62
|
supportsBrotli ? new zlib.BrotliDecompress() : new zlib.Gunzip(),
|
|
48
|
-
tarFs.extract(versionedVendorPath),
|
|
63
|
+
tarFs.extract(versionedVendorPath, { ignore }),
|
|
49
64
|
function (err) {
|
|
50
65
|
if (err) {
|
|
51
66
|
if (/unexpected end of file/.test(err.message)) {
|
|
52
|
-
|
|
67
|
+
fail(new Error(`Please delete ${tarPath} as it is not a valid tarball`));
|
|
53
68
|
}
|
|
54
69
|
fail(err);
|
|
55
70
|
}
|
|
@@ -62,11 +77,11 @@ try {
|
|
|
62
77
|
|
|
63
78
|
if (useGlobalLibvips) {
|
|
64
79
|
const globalLibvipsVersion = libvips.globalLibvipsVersion();
|
|
65
|
-
|
|
66
|
-
|
|
80
|
+
libvips.log(`Detected globally-installed libvips v${globalLibvipsVersion}`);
|
|
81
|
+
libvips.log('Building from source via node-gyp');
|
|
67
82
|
process.exit(1);
|
|
68
83
|
} else if (libvips.hasVendoredLibvips()) {
|
|
69
|
-
|
|
84
|
+
libvips.log(`Using existing vendored libvips v${minimumLibvipsVersion}`);
|
|
70
85
|
} else {
|
|
71
86
|
// Is this arch/platform supported?
|
|
72
87
|
const arch = process.env.npm_config_arch || process.arch;
|
|
@@ -86,7 +101,7 @@ try {
|
|
|
86
101
|
}
|
|
87
102
|
}
|
|
88
103
|
if (detectLibc.family === detectLibc.MUSL && detectLibc.version) {
|
|
89
|
-
if (
|
|
104
|
+
if (semver.lt(detectLibc.version, '1.1.24')) {
|
|
90
105
|
throw new Error(`Use with musl ${detectLibc.version} requires manual installation of libvips >= ${minimumLibvipsVersion}`);
|
|
91
106
|
}
|
|
92
107
|
}
|
|
@@ -102,13 +117,11 @@ try {
|
|
|
102
117
|
const tarFilename = ['libvips', minimumLibvipsVersion, platformAndArch].join('-') + '.tar.' + extension;
|
|
103
118
|
const tarPathCache = path.join(libvips.cachePath(), tarFilename);
|
|
104
119
|
if (fs.existsSync(tarPathCache)) {
|
|
105
|
-
|
|
106
|
-
extractTarball(tarPathCache);
|
|
120
|
+
libvips.log(`Using cached ${tarPathCache}`);
|
|
121
|
+
extractTarball(tarPathCache, platformAndArch);
|
|
107
122
|
} else {
|
|
108
|
-
const tarPathTemp = path.join(os.tmpdir(), `${process.pid}-${tarFilename}`);
|
|
109
|
-
const tmpFile = fs.createWriteStream(tarPathTemp);
|
|
110
123
|
const url = distBaseUrl + tarFilename;
|
|
111
|
-
|
|
124
|
+
libvips.log(`Downloading ${url}`);
|
|
112
125
|
simpleGet({ url: url, agent: agent() }, function (err, response) {
|
|
113
126
|
if (err) {
|
|
114
127
|
fail(err);
|
|
@@ -117,24 +130,37 @@ try {
|
|
|
117
130
|
} else if (response.statusCode !== 200) {
|
|
118
131
|
fail(new Error(`Status ${response.statusCode} ${response.statusMessage}`));
|
|
119
132
|
} else {
|
|
133
|
+
const tarPathTemp = path.join(os.tmpdir(), `${process.pid}-${tarFilename}`);
|
|
134
|
+
const tmpFileStream = fs.createWriteStream(tarPathTemp);
|
|
120
135
|
response
|
|
121
|
-
.on('error',
|
|
122
|
-
|
|
136
|
+
.on('error', function (err) {
|
|
137
|
+
tmpFileStream.destroy(err);
|
|
138
|
+
})
|
|
139
|
+
.on('close', function () {
|
|
140
|
+
if (!response.complete) {
|
|
141
|
+
tmpFileStream.destroy(new Error('Download incomplete (connection was terminated)'));
|
|
142
|
+
}
|
|
143
|
+
})
|
|
144
|
+
.pipe(tmpFileStream);
|
|
145
|
+
tmpFileStream
|
|
146
|
+
.on('error', function (err) {
|
|
147
|
+
// Clean up temporary file
|
|
148
|
+
fs.unlinkSync(tarPathTemp);
|
|
149
|
+
fail(err);
|
|
150
|
+
})
|
|
151
|
+
.on('close', function () {
|
|
152
|
+
try {
|
|
153
|
+
// Attempt to rename
|
|
154
|
+
fs.renameSync(tarPathTemp, tarPathCache);
|
|
155
|
+
} catch (err) {
|
|
156
|
+
// Fall back to copy and unlink
|
|
157
|
+
fs.copyFileSync(tarPathTemp, tarPathCache);
|
|
158
|
+
fs.unlinkSync(tarPathTemp);
|
|
159
|
+
}
|
|
160
|
+
extractTarball(tarPathCache);
|
|
161
|
+
});
|
|
123
162
|
}
|
|
124
163
|
});
|
|
125
|
-
tmpFile
|
|
126
|
-
.on('error', fail)
|
|
127
|
-
.on('close', function () {
|
|
128
|
-
try {
|
|
129
|
-
// Attempt to rename
|
|
130
|
-
fs.renameSync(tarPathTemp, tarPathCache);
|
|
131
|
-
} catch (err) {
|
|
132
|
-
// Fall back to copy and unlink
|
|
133
|
-
fs.copyFileSync(tarPathTemp, tarPathCache);
|
|
134
|
-
fs.unlinkSync(tarPathTemp);
|
|
135
|
-
}
|
|
136
|
-
extractTarball(tarPathCache);
|
|
137
|
-
});
|
|
138
164
|
}
|
|
139
165
|
}
|
|
140
166
|
} catch (err) {
|
package/lib/constructor.js
CHANGED
|
@@ -18,12 +18,10 @@ try {
|
|
|
18
18
|
help.push(`- Ensure "${process.platform}" is used at install time as well as runtime`);
|
|
19
19
|
} else if (/dylib/.test(err.message) && /Incompatible library version/.test(err.message)) {
|
|
20
20
|
help.push('- Run "brew update && brew upgrade vips"');
|
|
21
|
-
} else if (/Cannot find module/.test(err.message)) {
|
|
22
|
-
help.push('- Run "npm rebuild --verbose sharp" and look for errors');
|
|
23
21
|
} else {
|
|
24
22
|
help.push(
|
|
25
23
|
'- Remove the "node_modules/sharp" directory then run',
|
|
26
|
-
' "npm install --ignore-scripts=false --verbose" and look for errors'
|
|
24
|
+
' "npm install --ignore-scripts=false --verbose sharp" and look for errors'
|
|
27
25
|
);
|
|
28
26
|
}
|
|
29
27
|
help.push(
|
|
@@ -244,7 +242,7 @@ const Sharp = function (input, options) {
|
|
|
244
242
|
jpegOptimiseCoding: true,
|
|
245
243
|
jpegQuantisationTable: 0,
|
|
246
244
|
pngProgressive: false,
|
|
247
|
-
pngCompressionLevel:
|
|
245
|
+
pngCompressionLevel: 6,
|
|
248
246
|
pngAdaptiveFiltering: false,
|
|
249
247
|
pngPalette: false,
|
|
250
248
|
pngQuality: 100,
|
|
@@ -281,6 +279,7 @@ const Sharp = function (input, options) {
|
|
|
281
279
|
tileSkipBlanks: -1,
|
|
282
280
|
tileBackground: [255, 255, 255, 255],
|
|
283
281
|
tileCentre: false,
|
|
282
|
+
tileId: 'https://example.com/iiif',
|
|
284
283
|
linearA: 1,
|
|
285
284
|
linearB: 0,
|
|
286
285
|
// Function to notify of libvips warnings
|
package/lib/libvips.js
CHANGED
|
@@ -37,6 +37,14 @@ const cachePath = function () {
|
|
|
37
37
|
return libvipsCachePath;
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
+
const log = function (item) {
|
|
41
|
+
if (item instanceof Error) {
|
|
42
|
+
console.error(`sharp: ${item.message}`);
|
|
43
|
+
} else {
|
|
44
|
+
console.log(`sharp: ${item}`);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
40
48
|
const isRosetta = function () {
|
|
41
49
|
/* istanbul ignore next */
|
|
42
50
|
if (process.platform === 'darwin' && process.arch === 'x64') {
|
|
@@ -104,6 +112,7 @@ module.exports = {
|
|
|
104
112
|
minimumLibvipsVersion,
|
|
105
113
|
minimumLibvipsVersionLabelled,
|
|
106
114
|
cachePath,
|
|
115
|
+
log,
|
|
107
116
|
globalLibvipsVersion,
|
|
108
117
|
hasVendoredLibvips,
|
|
109
118
|
pkgConfigPath,
|
package/lib/operation.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const { flatten: flattenArray } = require('array-flatten');
|
|
4
3
|
const color = require('color');
|
|
5
4
|
const is = require('./is');
|
|
6
5
|
|
|
@@ -127,7 +126,7 @@ function flop (flop) {
|
|
|
127
126
|
* @throws {Error} Invalid parameters
|
|
128
127
|
*/
|
|
129
128
|
function affine (matrix, options) {
|
|
130
|
-
const flatMatrix =
|
|
129
|
+
const flatMatrix = [].concat(...matrix);
|
|
131
130
|
if (flatMatrix.length === 4 && flatMatrix.every(is.number)) {
|
|
132
131
|
this.options.affineMatrix = flatMatrix;
|
|
133
132
|
} else {
|
|
@@ -269,7 +268,13 @@ function blur (sigma) {
|
|
|
269
268
|
}
|
|
270
269
|
|
|
271
270
|
/**
|
|
272
|
-
* Merge alpha transparency channel, if any, with a background.
|
|
271
|
+
* Merge alpha transparency channel, if any, with a background, then remove the alpha channel.
|
|
272
|
+
*
|
|
273
|
+
* @example
|
|
274
|
+
* await sharp(rgbaInput)
|
|
275
|
+
* .flatten('#F0A703')
|
|
276
|
+
* .toBuffer();
|
|
277
|
+
*
|
|
273
278
|
* @param {Object} [options]
|
|
274
279
|
* @param {string|Object} [options.background={r: 0, g: 0, b: 0}] - background colour, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to black.
|
|
275
280
|
* @returns {Sharp}
|
|
@@ -397,7 +402,7 @@ function convolve (kernel) {
|
|
|
397
402
|
}
|
|
398
403
|
|
|
399
404
|
/**
|
|
400
|
-
* Any pixel value
|
|
405
|
+
* Any pixel value greater than or equal to the threshold value will be set to 255, otherwise it will be set to 0.
|
|
401
406
|
* @param {number} [threshold=128] - a value in the range 0-255 representing the level at which the threshold will be applied.
|
|
402
407
|
* @param {Object} [options]
|
|
403
408
|
* @param {Boolean} [options.greyscale=true] - convert to single channel greyscale.
|
package/lib/output.js
CHANGED
|
@@ -105,10 +105,10 @@ function toFile (fileOut, callback) {
|
|
|
105
105
|
* .catch(err => { ... });
|
|
106
106
|
*
|
|
107
107
|
* @example
|
|
108
|
-
* const data = await sharp('my-image.jpg')
|
|
108
|
+
* const { data, info } = await sharp('my-image.jpg')
|
|
109
109
|
* // output the raw pixels
|
|
110
110
|
* .raw()
|
|
111
|
-
* .toBuffer();
|
|
111
|
+
* .toBuffer({ resolveWithObject: true });
|
|
112
112
|
*
|
|
113
113
|
* // create a more type safe way to work with the raw pixel data
|
|
114
114
|
* // this will not copy the data, instead it will change `data`s underlying ArrayBuffer
|
|
@@ -116,7 +116,9 @@ function toFile (fileOut, callback) {
|
|
|
116
116
|
* const pixelArray = new Uint8ClampedArray(data.buffer);
|
|
117
117
|
*
|
|
118
118
|
* // When you are done changing the pixelArray, sharp takes the `pixelArray` as an input
|
|
119
|
-
*
|
|
119
|
+
* const { width, height, channels } = info;
|
|
120
|
+
* await sharp(pixelArray, { raw: { width, height, channels } })
|
|
121
|
+
* .toFile('my-changed-image.jpg');
|
|
120
122
|
*
|
|
121
123
|
* @param {Object} [options]
|
|
122
124
|
* @param {boolean} [options.resolveWithObject] Resolve the Promise with an Object containing `data` and `info` properties instead of resolving only with `data`.
|
|
@@ -198,8 +200,6 @@ function toFormat (format, options) {
|
|
|
198
200
|
/**
|
|
199
201
|
* Use these JPEG options for output image.
|
|
200
202
|
*
|
|
201
|
-
* Some of these options require the use of a globally-installed libvips compiled with support for mozjpeg.
|
|
202
|
-
*
|
|
203
203
|
* @example
|
|
204
204
|
* // Convert any input to very high quality JPEG output
|
|
205
205
|
* const data = await sharp(input)
|
|
@@ -209,18 +209,25 @@ function toFormat (format, options) {
|
|
|
209
209
|
* })
|
|
210
210
|
* .toBuffer();
|
|
211
211
|
*
|
|
212
|
+
* @example
|
|
213
|
+
* // Use mozjpeg to reduce output JPEG file size (slower)
|
|
214
|
+
* const data = await sharp(input)
|
|
215
|
+
* .jpeg({ mozjpeg: true })
|
|
216
|
+
* .toBuffer();
|
|
217
|
+
*
|
|
212
218
|
* @param {Object} [options] - output options
|
|
213
219
|
* @param {number} [options.quality=80] - quality, integer 1-100
|
|
214
220
|
* @param {boolean} [options.progressive=false] - use progressive (interlace) scan
|
|
215
221
|
* @param {string} [options.chromaSubsampling='4:2:0'] - set to '4:4:4' to prevent chroma subsampling otherwise defaults to '4:2:0' chroma subsampling
|
|
216
222
|
* @param {boolean} [options.optimiseCoding=true] - optimise Huffman coding tables
|
|
217
223
|
* @param {boolean} [options.optimizeCoding=true] - alternative spelling of optimiseCoding
|
|
218
|
-
* @param {boolean} [options.
|
|
219
|
-
* @param {boolean} [options.
|
|
220
|
-
* @param {boolean} [options.
|
|
221
|
-
* @param {boolean} [options.
|
|
222
|
-
* @param {
|
|
223
|
-
* @param {number} [options.
|
|
224
|
+
* @param {boolean} [options.mozjpeg=false] - use mozjpeg defaults, equivalent to `{ trellisQuantisation: true, overshootDeringing: true, optimiseScans: true, quantisationTable: 3 }`
|
|
225
|
+
* @param {boolean} [options.trellisQuantisation=false] - apply trellis quantisation
|
|
226
|
+
* @param {boolean} [options.overshootDeringing=false] - apply overshoot deringing
|
|
227
|
+
* @param {boolean} [options.optimiseScans=false] - optimise progressive scans, forces progressive
|
|
228
|
+
* @param {boolean} [options.optimizeScans=false] - alternative spelling of optimiseScans
|
|
229
|
+
* @param {number} [options.quantisationTable=0] - quantization table to use, integer 0-8
|
|
230
|
+
* @param {number} [options.quantizationTable=0] - alternative spelling of quantisationTable
|
|
224
231
|
* @param {boolean} [options.force=true] - force JPEG output, otherwise attempt to use input format
|
|
225
232
|
* @returns {Sharp}
|
|
226
233
|
* @throws {Error} Invalid options
|
|
@@ -244,6 +251,23 @@ function jpeg (options) {
|
|
|
244
251
|
throw is.invalidParameterError('chromaSubsampling', 'one of: 4:2:0, 4:4:4', options.chromaSubsampling);
|
|
245
252
|
}
|
|
246
253
|
}
|
|
254
|
+
const optimiseCoding = is.bool(options.optimizeCoding) ? options.optimizeCoding : options.optimiseCoding;
|
|
255
|
+
if (is.defined(optimiseCoding)) {
|
|
256
|
+
this._setBooleanOption('jpegOptimiseCoding', optimiseCoding);
|
|
257
|
+
}
|
|
258
|
+
if (is.defined(options.mozjpeg)) {
|
|
259
|
+
if (is.bool(options.mozjpeg)) {
|
|
260
|
+
if (options.mozjpeg) {
|
|
261
|
+
this.options.jpegTrellisQuantisation = true;
|
|
262
|
+
this.options.jpegOvershootDeringing = true;
|
|
263
|
+
this.options.jpegOptimiseScans = true;
|
|
264
|
+
this.options.jpegProgressive = true;
|
|
265
|
+
this.options.jpegQuantisationTable = 3;
|
|
266
|
+
}
|
|
267
|
+
} else {
|
|
268
|
+
throw is.invalidParameterError('mozjpeg', 'boolean', options.mozjpeg);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
247
271
|
const trellisQuantisation = is.bool(options.trellisQuantization) ? options.trellisQuantization : options.trellisQuantisation;
|
|
248
272
|
if (is.defined(trellisQuantisation)) {
|
|
249
273
|
this._setBooleanOption('jpegTrellisQuantisation', trellisQuantisation);
|
|
@@ -258,10 +282,6 @@ function jpeg (options) {
|
|
|
258
282
|
this.options.jpegProgressive = true;
|
|
259
283
|
}
|
|
260
284
|
}
|
|
261
|
-
const optimiseCoding = is.bool(options.optimizeCoding) ? options.optimizeCoding : options.optimiseCoding;
|
|
262
|
-
if (is.defined(optimiseCoding)) {
|
|
263
|
-
this._setBooleanOption('jpegOptimiseCoding', optimiseCoding);
|
|
264
|
-
}
|
|
265
285
|
const quantisationTable = is.number(options.quantizationTable) ? options.quantizationTable : options.quantisationTable;
|
|
266
286
|
if (is.defined(quantisationTable)) {
|
|
267
287
|
if (is.integer(quantisationTable) && is.inRange(quantisationTable, 0, 8)) {
|
|
@@ -277,26 +297,31 @@ function jpeg (options) {
|
|
|
277
297
|
/**
|
|
278
298
|
* Use these PNG options for output image.
|
|
279
299
|
*
|
|
280
|
-
* PNG output is
|
|
300
|
+
* By default, PNG output is full colour at 8 or 16 bits per pixel.
|
|
281
301
|
* Indexed PNG input at 1, 2 or 4 bits per pixel is converted to 8 bits per pixel.
|
|
282
|
-
*
|
|
283
|
-
* Some of these options require the use of a globally-installed libvips compiled with support for libimagequant (GPL).
|
|
302
|
+
* Set `palette` to `true` for slower, indexed PNG output.
|
|
284
303
|
*
|
|
285
304
|
* @example
|
|
286
|
-
* // Convert any input to PNG output
|
|
305
|
+
* // Convert any input to full colour PNG output
|
|
287
306
|
* const data = await sharp(input)
|
|
288
307
|
* .png()
|
|
289
308
|
* .toBuffer();
|
|
290
309
|
*
|
|
310
|
+
* @example
|
|
311
|
+
* // Convert any input to indexed PNG output (slower)
|
|
312
|
+
* const data = await sharp(input)
|
|
313
|
+
* .png({ palette: true })
|
|
314
|
+
* .toBuffer();
|
|
315
|
+
*
|
|
291
316
|
* @param {Object} [options]
|
|
292
317
|
* @param {boolean} [options.progressive=false] - use progressive (interlace) scan
|
|
293
|
-
* @param {number} [options.compressionLevel=
|
|
318
|
+
* @param {number} [options.compressionLevel=6] - zlib compression level, 0 (fastest, largest) to 9 (slowest, smallest)
|
|
294
319
|
* @param {boolean} [options.adaptiveFiltering=false] - use adaptive row filtering
|
|
295
|
-
* @param {boolean} [options.palette=false] - quantise to a palette-based image with alpha transparency support
|
|
296
|
-
* @param {number} [options.quality=100] - use the lowest number of colours needed to achieve given quality, sets `palette` to `true
|
|
297
|
-
* @param {number} [options.colours=256] - maximum number of palette entries, sets `palette` to `true
|
|
298
|
-
* @param {number} [options.colors=256] - alternative spelling of `options.colours`, sets `palette` to `true
|
|
299
|
-
* @param {number} [options.dither=1.0] - level of Floyd-Steinberg error diffusion, sets `palette` to `true
|
|
320
|
+
* @param {boolean} [options.palette=false] - quantise to a palette-based image with alpha transparency support
|
|
321
|
+
* @param {number} [options.quality=100] - use the lowest number of colours needed to achieve given quality, sets `palette` to `true`
|
|
322
|
+
* @param {number} [options.colours=256] - maximum number of palette entries, sets `palette` to `true`
|
|
323
|
+
* @param {number} [options.colors=256] - alternative spelling of `options.colours`, sets `palette` to `true`
|
|
324
|
+
* @param {number} [options.dither=1.0] - level of Floyd-Steinberg error diffusion, sets `palette` to `true`
|
|
300
325
|
* @param {boolean} [options.force=true] - force PNG output, otherwise attempt to use input format
|
|
301
326
|
* @returns {Sharp}
|
|
302
327
|
* @throws {Error} Invalid options
|
|
@@ -704,6 +729,7 @@ function raw () {
|
|
|
704
729
|
* @param {string} [options.layout='dz'] filesystem layout, possible values are `dz`, `iiif`, `zoomify` or `google`.
|
|
705
730
|
* @param {boolean} [options.centre=false] centre image in tile.
|
|
706
731
|
* @param {boolean} [options.center=false] alternative spelling of centre.
|
|
732
|
+
* @param {string} [options.id='https://example.com/iiif'] when `layout` is `iiif`, sets the `@id` attribute of `info.json`
|
|
707
733
|
* @returns {Sharp}
|
|
708
734
|
* @throws {Error} Invalid parameters
|
|
709
735
|
*/
|
|
@@ -777,6 +803,14 @@ function tile (options) {
|
|
|
777
803
|
if (is.defined(centre)) {
|
|
778
804
|
this._setBooleanOption('tileCentre', centre);
|
|
779
805
|
}
|
|
806
|
+
// @id attribute for IIIF layout
|
|
807
|
+
if (is.defined(options.id)) {
|
|
808
|
+
if (is.string(options.id)) {
|
|
809
|
+
this.options.tileId = options.id;
|
|
810
|
+
} else {
|
|
811
|
+
throw is.invalidParameterError('id', 'string', options.id);
|
|
812
|
+
}
|
|
813
|
+
}
|
|
780
814
|
}
|
|
781
815
|
// Format
|
|
782
816
|
if (is.inArray(this.options.formatOut, ['jpeg', 'png', 'webp'])) {
|
package/lib/resize.js
CHANGED
|
@@ -302,11 +302,20 @@ function resize (width, height, options) {
|
|
|
302
302
|
* })
|
|
303
303
|
* ...
|
|
304
304
|
*
|
|
305
|
+
* @example
|
|
306
|
+
* // Add a row of 10 red pixels to the bottom
|
|
307
|
+
* sharp(input)
|
|
308
|
+
* .extend({
|
|
309
|
+
* bottom: 10,
|
|
310
|
+
* background: 'red'
|
|
311
|
+
* })
|
|
312
|
+
* ...
|
|
313
|
+
*
|
|
305
314
|
* @param {(number|Object)} extend - single pixel count to add to all edges or an Object with per-edge counts
|
|
306
|
-
* @param {number} [extend.top]
|
|
307
|
-
* @param {number} [extend.left]
|
|
308
|
-
* @param {number} [extend.bottom]
|
|
309
|
-
* @param {number} [extend.right]
|
|
315
|
+
* @param {number} [extend.top=0]
|
|
316
|
+
* @param {number} [extend.left=0]
|
|
317
|
+
* @param {number} [extend.bottom=0]
|
|
318
|
+
* @param {number} [extend.right=0]
|
|
310
319
|
* @param {String|Object} [extend.background={r: 0, g: 0, b: 0, alpha: 1}] - background colour, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to black without transparency.
|
|
311
320
|
* @returns {Sharp}
|
|
312
321
|
* @throws {Error} Invalid parameters
|
|
@@ -317,17 +326,35 @@ function extend (extend) {
|
|
|
317
326
|
this.options.extendBottom = extend;
|
|
318
327
|
this.options.extendLeft = extend;
|
|
319
328
|
this.options.extendRight = extend;
|
|
320
|
-
} else if (
|
|
321
|
-
is.
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
329
|
+
} else if (is.object(extend)) {
|
|
330
|
+
if (is.defined(extend.top)) {
|
|
331
|
+
if (is.integer(extend.top) && extend.top >= 0) {
|
|
332
|
+
this.options.extendTop = extend.top;
|
|
333
|
+
} else {
|
|
334
|
+
throw is.invalidParameterError('top', 'positive integer', extend.top);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
if (is.defined(extend.bottom)) {
|
|
338
|
+
if (is.integer(extend.bottom) && extend.bottom >= 0) {
|
|
339
|
+
this.options.extendBottom = extend.bottom;
|
|
340
|
+
} else {
|
|
341
|
+
throw is.invalidParameterError('bottom', 'positive integer', extend.bottom);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
if (is.defined(extend.left)) {
|
|
345
|
+
if (is.integer(extend.left) && extend.left >= 0) {
|
|
346
|
+
this.options.extendLeft = extend.left;
|
|
347
|
+
} else {
|
|
348
|
+
throw is.invalidParameterError('left', 'positive integer', extend.left);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
if (is.defined(extend.right)) {
|
|
352
|
+
if (is.integer(extend.right) && extend.right >= 0) {
|
|
353
|
+
this.options.extendRight = extend.right;
|
|
354
|
+
} else {
|
|
355
|
+
throw is.invalidParameterError('right', 'positive integer', extend.right);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
331
358
|
this._setBackgroundColourOption('extendBackground', extend.background);
|
|
332
359
|
} else {
|
|
333
360
|
throw is.invalidParameterError('extend', 'integer or object', extend);
|
package/lib/utility.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const events = require('events');
|
|
4
|
+
const detectLibc = require('detect-libc');
|
|
5
|
+
|
|
4
6
|
const is = require('./is');
|
|
5
7
|
const sharp = require('../build/Release/sharp.node');
|
|
6
8
|
|
|
@@ -84,8 +86,12 @@ cache(true);
|
|
|
84
86
|
/**
|
|
85
87
|
* Gets or, when a concurrency is provided, sets
|
|
86
88
|
* the number of threads _libvips'_ should create to process each image.
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
+
*
|
|
90
|
+
* The default value is the number of CPU cores,
|
|
91
|
+
* except when using glibc-based Linux without jemalloc,
|
|
92
|
+
* where the default is `1` to help reduce memory fragmentation.
|
|
93
|
+
*
|
|
94
|
+
* A value of `0` will reset this to the number of CPU cores.
|
|
89
95
|
*
|
|
90
96
|
* The maximum number of images that can be processed in parallel
|
|
91
97
|
* is limited by libuv's `UV_THREADPOOL_SIZE` environment variable.
|
|
@@ -103,6 +109,11 @@ cache(true);
|
|
|
103
109
|
function concurrency (concurrency) {
|
|
104
110
|
return sharp.concurrency(is.integer(concurrency) ? concurrency : null);
|
|
105
111
|
}
|
|
112
|
+
/* istanbul ignore next */
|
|
113
|
+
if (detectLibc.family === detectLibc.GLIBC && !sharp._isUsingJemalloc()) {
|
|
114
|
+
// Reduce default concurrency to 1 when using glibc memory allocator
|
|
115
|
+
sharp.concurrency(1);
|
|
116
|
+
}
|
|
106
117
|
|
|
107
118
|
/**
|
|
108
119
|
* An EventEmitter that emits a `change` event when a task is either:
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sharp",
|
|
3
3
|
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, AVIF and TIFF images",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.28.0",
|
|
5
5
|
"author": "Lovell Fuller <npm@lovell.info>",
|
|
6
6
|
"homepage": "https://github.com/lovell/sharp",
|
|
7
7
|
"contributors": [
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node-gyp rebuild && node install/dll-copy)",
|
|
81
81
|
"clean": "rm -rf node_modules/ build/ vendor/ .nyc_output/ coverage/ test/fixtures/output.*",
|
|
82
82
|
"test": "semistandard && cpplint && npm run test-unit && npm run test-licensing",
|
|
83
|
-
"test-unit": "nyc --reporter=lcov --branches=99 mocha --slow=
|
|
83
|
+
"test-unit": "nyc --reporter=lcov --branches=99 mocha --slow=1000 --timeout=60000 ./test/unit/*.js",
|
|
84
84
|
"test-licensing": "license-checker --production --summary --onlyAllow=\"Apache-2.0;BSD;ISC;MIT\"",
|
|
85
85
|
"test-coverage": "./test/coverage/report.sh",
|
|
86
86
|
"test-leak": "./test/leak/leak.sh",
|
|
@@ -117,14 +117,12 @@
|
|
|
117
117
|
"vips"
|
|
118
118
|
],
|
|
119
119
|
"dependencies": {
|
|
120
|
-
"array-flatten": "^3.0.0",
|
|
121
120
|
"color": "^3.1.3",
|
|
122
121
|
"detect-libc": "^1.0.3",
|
|
123
122
|
"node-addon-api": "^3.1.0",
|
|
124
|
-
"npmlog": "^4.1.2",
|
|
125
123
|
"prebuild-install": "^6.0.1",
|
|
126
|
-
"semver": "^7.3.
|
|
127
|
-
"simple-get": "^
|
|
124
|
+
"semver": "^7.3.5",
|
|
125
|
+
"simple-get": "^3.1.0",
|
|
128
126
|
"tar-fs": "^2.1.1",
|
|
129
127
|
"tunnel-agent": "^0.6.0"
|
|
130
128
|
},
|
|
@@ -132,11 +130,11 @@
|
|
|
132
130
|
"async": "^3.2.0",
|
|
133
131
|
"cc": "^3.0.1",
|
|
134
132
|
"decompress-zip": "^0.3.3",
|
|
135
|
-
"documentation": "^13.
|
|
133
|
+
"documentation": "^13.2.0",
|
|
136
134
|
"exif-reader": "^1.0.3",
|
|
137
135
|
"icc": "^2.0.0",
|
|
138
136
|
"license-checker": "^25.0.1",
|
|
139
|
-
"mocha": "^8.3.
|
|
137
|
+
"mocha": "^8.3.2",
|
|
140
138
|
"mock-fs": "^4.13.0",
|
|
141
139
|
"nyc": "^15.1.0",
|
|
142
140
|
"prebuild": "^10.0.1",
|
|
@@ -145,7 +143,7 @@
|
|
|
145
143
|
},
|
|
146
144
|
"license": "Apache-2.0",
|
|
147
145
|
"config": {
|
|
148
|
-
"libvips": "8.10.
|
|
146
|
+
"libvips": "8.10.6",
|
|
149
147
|
"runtime": "napi",
|
|
150
148
|
"target": 3
|
|
151
149
|
},
|
package/src/common.cc
CHANGED
|
@@ -213,6 +213,8 @@ namespace sharp {
|
|
|
213
213
|
{ "VipsForeignLoadTiffBuffer", ImageType::TIFF },
|
|
214
214
|
{ "VipsForeignLoadGifFile", ImageType::GIF },
|
|
215
215
|
{ "VipsForeignLoadGifBuffer", ImageType::GIF },
|
|
216
|
+
{ "VipsForeignLoadNsgifFile", ImageType::GIF },
|
|
217
|
+
{ "VipsForeignLoadNsgifBuffer", ImageType::GIF },
|
|
216
218
|
{ "VipsForeignLoadSvgFile", ImageType::SVG },
|
|
217
219
|
{ "VipsForeignLoadSvgBuffer", ImageType::SVG },
|
|
218
220
|
{ "VipsForeignLoadHeifFile", ImageType::HEIF },
|
package/src/common.h
CHANGED
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
|
|
27
27
|
#if (VIPS_MAJOR_VERSION < 8) || \
|
|
28
28
|
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 10) || \
|
|
29
|
-
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 10 && VIPS_MICRO_VERSION <
|
|
30
|
-
#error "libvips version 8.10.
|
|
29
|
+
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 10 && VIPS_MICRO_VERSION < 6)
|
|
30
|
+
#error "libvips version 8.10.6+ is required - please see https://sharp.pixelplumbing.com/install"
|
|
31
31
|
#endif
|
|
32
32
|
|
|
33
33
|
#if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)))
|
package/src/pipeline.cc
CHANGED
|
@@ -562,9 +562,17 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
562
562
|
// Use gravity in overlay
|
|
563
563
|
if (compositeImage.width() <= baton->width) {
|
|
564
564
|
across = static_cast<int>(ceil(static_cast<double>(image.width()) / compositeImage.width()));
|
|
565
|
+
// Ensure odd number of tiles across when gravity is centre, north or south
|
|
566
|
+
if (composite->gravity == 0 || composite->gravity == 1 || composite->gravity == 3) {
|
|
567
|
+
across |= 1;
|
|
568
|
+
}
|
|
565
569
|
}
|
|
566
570
|
if (compositeImage.height() <= baton->height) {
|
|
567
571
|
down = static_cast<int>(ceil(static_cast<double>(image.height()) / compositeImage.height()));
|
|
572
|
+
// Ensure odd number of tiles down when gravity is centre, east or west
|
|
573
|
+
if (composite->gravity == 0 || composite->gravity == 2 || composite->gravity == 4) {
|
|
574
|
+
down |= 1;
|
|
575
|
+
}
|
|
568
576
|
}
|
|
569
577
|
if (across != 0 || down != 0) {
|
|
570
578
|
int left;
|
|
@@ -594,8 +602,13 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
594
602
|
int top;
|
|
595
603
|
if (composite->hasOffset) {
|
|
596
604
|
// Composite image at given offsets
|
|
597
|
-
|
|
598
|
-
|
|
605
|
+
if (composite->tile) {
|
|
606
|
+
std::tie(left, top) = sharp::CalculateCrop(image.width(), image.height(),
|
|
607
|
+
compositeImage.width(), compositeImage.height(), composite->left, composite->top);
|
|
608
|
+
} else {
|
|
609
|
+
left = composite->left;
|
|
610
|
+
top = composite->top;
|
|
611
|
+
}
|
|
599
612
|
} else {
|
|
600
613
|
// Composite image with given gravity
|
|
601
614
|
std::tie(left, top) = sharp::CalculateCrop(image.width(), image.height(),
|
|
@@ -1038,6 +1051,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1038
1051
|
->set("angle", CalculateAngleRotation(baton->tileAngle))
|
|
1039
1052
|
->set("background", baton->tileBackground)
|
|
1040
1053
|
->set("centre", baton->tileCentre)
|
|
1054
|
+
->set("id", const_cast<char*>(baton->tileId.data()))
|
|
1041
1055
|
->set("skip_blanks", baton->tileSkipBlanks);
|
|
1042
1056
|
// libvips chooses a default depth based on layout. Instead of replicating that logic here by
|
|
1043
1057
|
// not passing anything - libvips will handle choice
|
|
@@ -1438,6 +1452,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1438
1452
|
vips_enum_from_nick(nullptr, VIPS_TYPE_FOREIGN_DZ_DEPTH,
|
|
1439
1453
|
sharp::AttrAsStr(options, "tileDepth").data()));
|
|
1440
1454
|
baton->tileCentre = sharp::AttrAsBool(options, "tileCentre");
|
|
1455
|
+
baton->tileId = sharp::AttrAsStr(options, "tileId");
|
|
1441
1456
|
|
|
1442
1457
|
// Force random access for certain operations
|
|
1443
1458
|
if (baton->input->access == VIPS_ACCESS_SEQUENTIAL) {
|
package/src/pipeline.h
CHANGED
|
@@ -192,6 +192,7 @@ struct PipelineBaton {
|
|
|
192
192
|
std::vector<double> tileBackground;
|
|
193
193
|
int tileSkipBlanks;
|
|
194
194
|
VipsForeignDzDepth tileDepth;
|
|
195
|
+
std::string tileId;
|
|
195
196
|
std::unique_ptr<double[]> recombMatrix;
|
|
196
197
|
|
|
197
198
|
PipelineBaton():
|
|
@@ -258,7 +259,7 @@ struct PipelineBaton {
|
|
|
258
259
|
jpegOptimiseScans(false),
|
|
259
260
|
jpegOptimiseCoding(true),
|
|
260
261
|
pngProgressive(false),
|
|
261
|
-
pngCompressionLevel(
|
|
262
|
+
pngCompressionLevel(6),
|
|
262
263
|
pngAdaptiveFiltering(false),
|
|
263
264
|
pngPalette(false),
|
|
264
265
|
pngQuality(100),
|
package/src/sharp.cc
CHANGED
|
@@ -44,6 +44,7 @@ Napi::Object init(Napi::Env env, Napi::Object exports) {
|
|
|
44
44
|
exports.Set("libvipsVersion", Napi::Function::New(env, libvipsVersion));
|
|
45
45
|
exports.Set("format", Napi::Function::New(env, format));
|
|
46
46
|
exports.Set("_maxColourDistance", Napi::Function::New(env, _maxColourDistance));
|
|
47
|
+
exports.Set("_isUsingJemalloc", Napi::Function::New(env, _isUsingJemalloc));
|
|
47
48
|
exports.Set("stats", Napi::Function::New(env, stats));
|
|
48
49
|
return exports;
|
|
49
50
|
}
|
package/src/utilities.cc
CHANGED
|
@@ -225,3 +225,19 @@ Napi::Value _maxColourDistance(const Napi::CallbackInfo& info) {
|
|
|
225
225
|
|
|
226
226
|
return Napi::Number::New(env, maxColourDistance);
|
|
227
227
|
}
|
|
228
|
+
|
|
229
|
+
#if defined(__GNUC__)
|
|
230
|
+
// mallctl will be resolved by the runtime linker when jemalloc is being used
|
|
231
|
+
extern "C" {
|
|
232
|
+
int mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen) __attribute__((weak));
|
|
233
|
+
}
|
|
234
|
+
Napi::Value _isUsingJemalloc(const Napi::CallbackInfo& info) {
|
|
235
|
+
Napi::Env env = info.Env();
|
|
236
|
+
return Napi::Boolean::New(env, mallctl != nullptr);
|
|
237
|
+
}
|
|
238
|
+
#else
|
|
239
|
+
Napi::Value _isUsingJemalloc(const Napi::CallbackInfo& info) {
|
|
240
|
+
Napi::Env env = info.Env();
|
|
241
|
+
return Napi::Boolean::New(env, false);
|
|
242
|
+
}
|
|
243
|
+
#endif
|
package/src/utilities.h
CHANGED
|
@@ -24,5 +24,6 @@ Napi::Value simd(const Napi::CallbackInfo& info);
|
|
|
24
24
|
Napi::Value libvipsVersion(const Napi::CallbackInfo& info);
|
|
25
25
|
Napi::Value format(const Napi::CallbackInfo& info);
|
|
26
26
|
Napi::Value _maxColourDistance(const Napi::CallbackInfo& info);
|
|
27
|
+
Napi::Value _isUsingJemalloc(const Napi::CallbackInfo& info);
|
|
27
28
|
|
|
28
29
|
#endif // SRC_UTILITIES_H_
|