sharp 0.20.5 → 0.21.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 +3 -3
- package/binding.gyp +5 -0
- package/docs/api-channel.md +16 -0
- package/docs/api-colour.md +1 -19
- package/docs/api-composite.md +2 -3
- package/docs/api-constructor.md +2 -2
- package/docs/api-input.md +6 -2
- package/docs/api-operation.md +40 -115
- package/docs/api-output.md +3 -0
- package/docs/api-resize.md +159 -109
- package/docs/api-utility.md +4 -7
- package/docs/changelog.md +87 -0
- package/docs/index.md +10 -4
- package/docs/install.md +18 -38
- package/docs/performance.md +14 -21
- package/install/dll-copy.js +3 -2
- package/install/libvips.js +55 -36
- package/lib/channel.js +18 -0
- package/lib/colour.js +34 -15
- package/lib/composite.js +2 -3
- package/lib/constructor.js +19 -41
- package/lib/input.js +7 -3
- package/lib/libvips.js +38 -6
- package/lib/operation.js +27 -118
- package/lib/output.js +22 -2
- package/lib/platform.js +4 -1
- package/lib/resize.js +308 -104
- package/lib/utility.js +5 -8
- package/package.json +20 -13
- package/src/common.cc +50 -13
- package/src/common.h +12 -10
- package/src/libvips/cplusplus/VImage.cpp +95 -95
- package/src/libvips/cplusplus/vips-operators.cpp +268 -185
- package/src/metadata.cc +15 -0
- package/src/metadata.h +3 -0
- package/src/operations.cc +27 -54
- package/src/operations.h +6 -1
- package/src/pipeline.cc +81 -89
- package/src/pipeline.h +25 -13
- package/src/stats.cc +11 -8
- package/src/stats.h +3 -1
- package/src/utilities.cc +1 -1
package/docs/performance.md
CHANGED
|
@@ -3,19 +3,17 @@
|
|
|
3
3
|
### Test environment
|
|
4
4
|
|
|
5
5
|
* AWS EC2 eu-west-1 [c5.large](https://aws.amazon.com/ec2/instance-types/c5/) (2x Xeon Platinum 8124M CPU @ 3.00GHz)
|
|
6
|
-
* Ubuntu
|
|
7
|
-
* Node.js
|
|
6
|
+
* Ubuntu 18.04 (hvm-ssd/ubuntu-bionic-18.04-amd64-server-20180912 ami-00035f41c82244dab)
|
|
7
|
+
* Node.js v10.11.0
|
|
8
8
|
|
|
9
9
|
### The contenders
|
|
10
10
|
|
|
11
|
-
* [jimp](https://www.npmjs.com/package/jimp) v0.
|
|
12
|
-
* [
|
|
13
|
-
* [mapnik](https://www.npmjs.org/package/mapnik) v3.6.2 - Whilst primarily a map renderer, Mapnik contains bitmap image utilities.
|
|
11
|
+
* [jimp](https://www.npmjs.com/package/jimp) v0.5.3 - Image processing in pure JavaScript. Provides bicubic interpolation.
|
|
12
|
+
* [mapnik](https://www.npmjs.org/package/mapnik) v4.0.1 - Whilst primarily a map renderer, Mapnik contains bitmap image utilities.
|
|
14
13
|
* [imagemagick-native](https://www.npmjs.com/package/imagemagick-native) v1.9.3 - Wrapper around libmagick++, supports Buffers only.
|
|
15
14
|
* [imagemagick](https://www.npmjs.com/package/imagemagick) v0.1.3 - Supports filesystem only and "*has been unmaintained for a long time*".
|
|
16
15
|
* [gm](https://www.npmjs.com/package/gm) v1.23.1 - Fully featured wrapper around GraphicsMagick's `gm` command line utility.
|
|
17
|
-
*
|
|
18
|
-
* sharp v0.19.0 / libvips v8.6.1 - Caching within libvips disabled to ensure a fair comparison.
|
|
16
|
+
* sharp v0.21.0 / libvips v8.7.0 - Caching within libvips disabled to ensure a fair comparison.
|
|
19
17
|
|
|
20
18
|
### The task
|
|
21
19
|
|
|
@@ -27,19 +25,14 @@ then compress to JPEG at a "quality" setting of 80.
|
|
|
27
25
|
|
|
28
26
|
| Module | Input | Output | Ops/sec | Speed-up |
|
|
29
27
|
| :----------------- | :----- | :----- | ------: | -------: |
|
|
30
|
-
| jimp
|
|
31
|
-
|
|
|
32
|
-
|
|
|
33
|
-
| imagemagick-native | buffer | buffer | 4.
|
|
34
|
-
|
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
| sharp | stream | stream | 24.43 | 21.4 |
|
|
39
|
-
| sharp | file | file | 25.97 | 22.7 |
|
|
40
|
-
| sharp | file | buffer | 26.00 | 22.8 |
|
|
41
|
-
| sharp | buffer | file | 26.33 | 23.0 |
|
|
42
|
-
| sharp | buffer | buffer | 26.43 | 23.1 |
|
|
28
|
+
| jimp | buffer | buffer | 0.71 | 1.0 |
|
|
29
|
+
| mapnik | buffer | buffer | 3.32 | 4.7 |
|
|
30
|
+
| gm | buffer | buffer | 3.97 | 5.6 |
|
|
31
|
+
| imagemagick-native | buffer | buffer | 4.06 | 5.7 |
|
|
32
|
+
| imagemagick | file | file | 4.24 | 6.0 |
|
|
33
|
+
| sharp | stream | stream | 25.30 | 35.6 |
|
|
34
|
+
| sharp | file | file | 26.17 | 36.9 |
|
|
35
|
+
| sharp | buffer | buffer | 26.45 | 37.3 |
|
|
43
36
|
|
|
44
37
|
Greater libvips performance can be expected with caching enabled (default)
|
|
45
38
|
and using 8+ core machines, especially those with larger L1/L2 CPU caches.
|
|
@@ -57,7 +50,7 @@ brew install mapnik
|
|
|
57
50
|
```
|
|
58
51
|
|
|
59
52
|
```sh
|
|
60
|
-
sudo apt-get install imagemagick libmagick++-dev graphicsmagick
|
|
53
|
+
sudo apt-get install imagemagick libmagick++-dev graphicsmagick libmapnik-dev
|
|
61
54
|
```
|
|
62
55
|
|
|
63
56
|
```sh
|
package/install/dll-copy.js
CHANGED
|
@@ -4,6 +4,7 @@ const fs = require('fs');
|
|
|
4
4
|
const path = require('path');
|
|
5
5
|
|
|
6
6
|
const copyFileSync = require('fs-copy-file-sync');
|
|
7
|
+
const libvips = require('../lib/libvips');
|
|
7
8
|
const npmLog = require('npmlog');
|
|
8
9
|
|
|
9
10
|
if (process.platform === 'win32') {
|
|
@@ -11,8 +12,8 @@ if (process.platform === 'win32') {
|
|
|
11
12
|
const buildReleaseDir = path.join(buildDir, 'Release');
|
|
12
13
|
npmLog.info('sharp', `Creating ${buildReleaseDir}`);
|
|
13
14
|
try {
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
libvips.mkdirSync(buildDir);
|
|
16
|
+
libvips.mkdirSync(buildReleaseDir);
|
|
16
17
|
} catch (err) {}
|
|
17
18
|
const vendorLibDir = path.join(__dirname, '..', 'vendor', 'lib');
|
|
18
19
|
npmLog.info('sharp', `Copying DLLs from ${vendorLibDir} to ${buildReleaseDir}`);
|
package/install/libvips.js
CHANGED
|
@@ -9,6 +9,7 @@ const npmLog = require('npmlog');
|
|
|
9
9
|
const semver = require('semver');
|
|
10
10
|
const simpleGet = require('simple-get');
|
|
11
11
|
const tar = require('tar');
|
|
12
|
+
const copyFileSync = require('fs-copy-file-sync');
|
|
12
13
|
|
|
13
14
|
const agent = require('../lib/agent');
|
|
14
15
|
const libvips = require('../lib/libvips');
|
|
@@ -17,6 +18,24 @@ const platform = require('../lib/platform');
|
|
|
17
18
|
const minimumLibvipsVersion = libvips.minimumLibvipsVersion;
|
|
18
19
|
const distBaseUrl = process.env.SHARP_DIST_BASE_URL || `https://github.com/lovell/sharp-libvips/releases/download/v${minimumLibvipsVersion}/`;
|
|
19
20
|
|
|
21
|
+
const fail = function (err) {
|
|
22
|
+
npmLog.error('sharp', err.message);
|
|
23
|
+
npmLog.error('sharp', 'Please see http://sharp.pixelplumbing.com/page/install');
|
|
24
|
+
process.exit(1);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const extractTarball = function (tarPath) {
|
|
28
|
+
const vendorPath = path.join(__dirname, '..', 'vendor');
|
|
29
|
+
libvips.mkdirSync(vendorPath);
|
|
30
|
+
tar
|
|
31
|
+
.extract({
|
|
32
|
+
file: tarPath,
|
|
33
|
+
cwd: vendorPath,
|
|
34
|
+
strict: true
|
|
35
|
+
})
|
|
36
|
+
.catch(fail);
|
|
37
|
+
};
|
|
38
|
+
|
|
20
39
|
try {
|
|
21
40
|
const useGlobalLibvips = libvips.useGlobalLibvips();
|
|
22
41
|
if (useGlobalLibvips) {
|
|
@@ -29,54 +48,54 @@ try {
|
|
|
29
48
|
} else {
|
|
30
49
|
// Is this arch/platform supported?
|
|
31
50
|
const arch = process.env.npm_config_arch || process.arch;
|
|
32
|
-
|
|
51
|
+
const platformAndArch = platform();
|
|
52
|
+
if (platformAndArch === 'win32-ia32') {
|
|
33
53
|
throw new Error('Windows x86 (32-bit) node.exe is not supported');
|
|
34
54
|
}
|
|
35
55
|
if (arch === 'ia32') {
|
|
36
|
-
throw new Error(`Intel Architecture 32-bit systems require manual installation of libvips >= ${minimumLibvipsVersion}
|
|
56
|
+
throw new Error(`Intel Architecture 32-bit systems require manual installation of libvips >= ${minimumLibvipsVersion}`);
|
|
37
57
|
}
|
|
38
|
-
if (
|
|
39
|
-
throw new Error(`
|
|
58
|
+
if (platformAndArch === 'freebsd-x64') {
|
|
59
|
+
throw new Error(`FreeBSD systems require manual installation of libvips >= ${minimumLibvipsVersion}`);
|
|
40
60
|
}
|
|
41
61
|
if (detectLibc.family === detectLibc.GLIBC && detectLibc.version && semver.lt(`${detectLibc.version}.0`, '2.13.0')) {
|
|
42
62
|
throw new Error(`Use with glibc version ${detectLibc.version} requires manual installation of libvips >= ${minimumLibvipsVersion}`);
|
|
43
63
|
}
|
|
44
64
|
// Download to per-process temporary file
|
|
45
|
-
const tarFilename = ['libvips', minimumLibvipsVersion,
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
})
|
|
68
|
-
.then(function () {
|
|
65
|
+
const tarFilename = ['libvips', minimumLibvipsVersion, platformAndArch].join('-') + '.tar.gz';
|
|
66
|
+
const tarPathCache = path.join(libvips.cachePath(), tarFilename);
|
|
67
|
+
if (fs.existsSync(tarPathCache)) {
|
|
68
|
+
npmLog.info('sharp', `Using cached ${tarPathCache}`);
|
|
69
|
+
extractTarball(tarPathCache);
|
|
70
|
+
} else {
|
|
71
|
+
const tarPathTemp = path.join(os.tmpdir(), `${process.pid}-${tarFilename}`);
|
|
72
|
+
const tmpFile = fs.createWriteStream(tarPathTemp);
|
|
73
|
+
const url = distBaseUrl + tarFilename;
|
|
74
|
+
npmLog.info('sharp', `Downloading ${url}`);
|
|
75
|
+
simpleGet({ url: url, agent: agent() }, function (err, response) {
|
|
76
|
+
if (err) {
|
|
77
|
+
throw err;
|
|
78
|
+
}
|
|
79
|
+
if (response.statusCode !== 200) {
|
|
80
|
+
throw new Error(`Status ${response.statusCode}`);
|
|
81
|
+
}
|
|
82
|
+
response.pipe(tmpFile);
|
|
83
|
+
});
|
|
84
|
+
tmpFile
|
|
85
|
+
.on('error', fail)
|
|
86
|
+
.on('close', function () {
|
|
69
87
|
try {
|
|
88
|
+
// Attempt to rename
|
|
89
|
+
fs.renameSync(tarPathTemp, tarPathCache);
|
|
90
|
+
} catch (err) {
|
|
91
|
+
// Fall back to copy and unlink
|
|
92
|
+
copyFileSync(tarPathTemp, tarPathCache);
|
|
70
93
|
fs.unlinkSync(tarPathTemp);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
.catch(function (err) {
|
|
74
|
-
throw err;
|
|
94
|
+
}
|
|
95
|
+
extractTarball(tarPathCache);
|
|
75
96
|
});
|
|
76
|
-
}
|
|
97
|
+
}
|
|
77
98
|
}
|
|
78
99
|
} catch (err) {
|
|
79
|
-
|
|
80
|
-
npmLog.error('sharp', 'Please see http://sharp.pixelplumbing.com/page/install');
|
|
81
|
-
process.exit(1);
|
|
100
|
+
fail(err);
|
|
82
101
|
}
|
package/lib/channel.js
CHANGED
|
@@ -12,6 +12,23 @@ const bool = {
|
|
|
12
12
|
eor: 'eor'
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Remove alpha channel, if any. This is a no-op if the image does not have an alpha channel.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* sharp('rgba.png')
|
|
20
|
+
* .removeAlpha()
|
|
21
|
+
* .toFile('rgb.png', function(err, info) {
|
|
22
|
+
* // rgb.png is a 3 channel image without an alpha channel
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* @returns {Sharp}
|
|
26
|
+
*/
|
|
27
|
+
function removeAlpha () {
|
|
28
|
+
this.options.removeAlpha = true;
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
|
|
15
32
|
/**
|
|
16
33
|
* Extract a single channel from a multi-channel image.
|
|
17
34
|
*
|
|
@@ -102,6 +119,7 @@ function bandbool (boolOp) {
|
|
|
102
119
|
module.exports = function (Sharp) {
|
|
103
120
|
// Public instance functions
|
|
104
121
|
[
|
|
122
|
+
removeAlpha,
|
|
105
123
|
extractChannel,
|
|
106
124
|
joinChannel,
|
|
107
125
|
bandbool
|
package/lib/colour.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const deprecate = require('util').deprecate;
|
|
4
|
+
|
|
3
5
|
const color = require('color');
|
|
4
6
|
const is = require('./is');
|
|
5
7
|
|
|
@@ -16,25 +18,20 @@ const colourspace = {
|
|
|
16
18
|
};
|
|
17
19
|
|
|
18
20
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* Delegates to the _color_ module, which can throw an Error
|
|
23
|
-
* but is liberal in what it accepts, clipping values to sensible min/max.
|
|
24
|
-
* The alpha value is a float between `0` (transparent) and `1` (opaque).
|
|
25
|
-
*
|
|
26
|
-
* @param {String|Object} rgba - parsed by the [color](https://www.npmjs.org/package/color) module to extract values for red, green, blue and alpha.
|
|
27
|
-
* @returns {Sharp}
|
|
28
|
-
* @throws {Error} Invalid parameter
|
|
21
|
+
* @deprecated
|
|
22
|
+
* @private
|
|
29
23
|
*/
|
|
30
24
|
function background (rgba) {
|
|
31
25
|
const colour = color(rgba);
|
|
32
|
-
|
|
26
|
+
const background = [
|
|
33
27
|
colour.red(),
|
|
34
28
|
colour.green(),
|
|
35
29
|
colour.blue(),
|
|
36
30
|
Math.round(colour.alpha() * 255)
|
|
37
31
|
];
|
|
32
|
+
this.options.resizeBackground = background;
|
|
33
|
+
this.options.extendBackground = background;
|
|
34
|
+
this.options.flattenBackground = background.slice(0, 3);
|
|
38
35
|
return this;
|
|
39
36
|
}
|
|
40
37
|
|
|
@@ -80,7 +77,7 @@ function grayscale (grayscale) {
|
|
|
80
77
|
/**
|
|
81
78
|
* Set the output colourspace.
|
|
82
79
|
* By default output image will be web-friendly sRGB, with additional channels interpreted as alpha channels.
|
|
83
|
-
* @param {String} [colourspace] - output colourspace e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://github.com/
|
|
80
|
+
* @param {String} [colourspace] - output colourspace e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://github.com/libvips/libvips/blob/master/libvips/iofuncs/enumtypes.c#L568)
|
|
84
81
|
* @returns {Sharp}
|
|
85
82
|
* @throws {Error} Invalid parameters
|
|
86
83
|
*/
|
|
@@ -102,23 +99,45 @@ function toColorspace (colorspace) {
|
|
|
102
99
|
return this.toColourspace(colorspace);
|
|
103
100
|
}
|
|
104
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Update a colour attribute of the this.options Object.
|
|
104
|
+
* @private
|
|
105
|
+
* @param {String} key
|
|
106
|
+
* @param {String|Object} val
|
|
107
|
+
* @throws {Error} Invalid key
|
|
108
|
+
*/
|
|
109
|
+
function _setColourOption (key, val) {
|
|
110
|
+
if (is.object(val) || is.string(val)) {
|
|
111
|
+
const colour = color(val);
|
|
112
|
+
this.options[key] = [
|
|
113
|
+
colour.red(),
|
|
114
|
+
colour.green(),
|
|
115
|
+
colour.blue(),
|
|
116
|
+
Math.round(colour.alpha() * 255)
|
|
117
|
+
];
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
105
121
|
/**
|
|
106
122
|
* Decorate the Sharp prototype with colour-related functions.
|
|
107
123
|
* @private
|
|
108
124
|
*/
|
|
109
125
|
module.exports = function (Sharp) {
|
|
110
|
-
// Public instance functions
|
|
111
126
|
[
|
|
112
|
-
|
|
127
|
+
// Public
|
|
113
128
|
tint,
|
|
114
129
|
greyscale,
|
|
115
130
|
grayscale,
|
|
116
131
|
toColourspace,
|
|
117
|
-
toColorspace
|
|
132
|
+
toColorspace,
|
|
133
|
+
// Private
|
|
134
|
+
_setColourOption
|
|
118
135
|
].forEach(function (f) {
|
|
119
136
|
Sharp.prototype[f.name] = f;
|
|
120
137
|
});
|
|
121
138
|
// Class attributes
|
|
122
139
|
Sharp.colourspace = colourspace;
|
|
123
140
|
Sharp.colorspace = colourspace;
|
|
141
|
+
// Deprecated
|
|
142
|
+
Sharp.prototype.background = deprecate(background, 'background(background) is deprecated, use resize({ background }), extend({ background }) or flatten({ background }) instead');
|
|
124
143
|
};
|
package/lib/composite.js
CHANGED
|
@@ -19,8 +19,7 @@ const is = require('./is');
|
|
|
19
19
|
* .overlayWith('overlay.png', { gravity: sharp.gravity.southeast } )
|
|
20
20
|
* .sharpen()
|
|
21
21
|
* .withMetadata()
|
|
22
|
-
* .quality
|
|
23
|
-
* .webp()
|
|
22
|
+
* .webp( { quality: 90 } )
|
|
24
23
|
* .toBuffer()
|
|
25
24
|
* .then(function(outputBuffer) {
|
|
26
25
|
* // outputBuffer contains upside down, 300px wide, alpha channel flattened
|
|
@@ -35,7 +34,7 @@ const is = require('./is');
|
|
|
35
34
|
* @param {Number} [options.left] - the pixel offset from the left edge.
|
|
36
35
|
* @param {Boolean} [options.tile=false] - set to true to repeat the overlay image across the entire image with the given `gravity`.
|
|
37
36
|
* @param {Boolean} [options.cutout=false] - set to true to apply only the alpha channel of the overlay image to the input image, giving the appearance of one image being cut out of another.
|
|
38
|
-
* @param {Number} [options.density=72] -
|
|
37
|
+
* @param {Number} [options.density=72] - number representing the DPI for vector overlay image.
|
|
39
38
|
* @param {Object} [options.raw] - describes overlay when using raw pixel data.
|
|
40
39
|
* @param {Number} [options.raw.width]
|
|
41
40
|
* @param {Number} [options.raw.height]
|
package/lib/constructor.js
CHANGED
|
@@ -4,42 +4,10 @@ const path = require('path');
|
|
|
4
4
|
const util = require('util');
|
|
5
5
|
const stream = require('stream');
|
|
6
6
|
const events = require('events');
|
|
7
|
-
const semver = require('semver');
|
|
8
7
|
const is = require('./is');
|
|
9
|
-
const platform = require('./platform');
|
|
10
|
-
const sharp = require('../build/Release/sharp.node');
|
|
11
8
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
let vendorPlatformId;
|
|
15
|
-
try {
|
|
16
|
-
vendorPlatformId = require('../vendor/platform.json');
|
|
17
|
-
} catch (err) {
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
const currentPlatformId = platform();
|
|
21
|
-
/* istanbul ignore if */
|
|
22
|
-
if (currentPlatformId !== vendorPlatformId) {
|
|
23
|
-
throw new Error(`'${vendorPlatformId}' binaries cannot be used on the '${currentPlatformId}' platform. Please remove the 'node_modules/sharp/vendor' directory and run 'npm rebuild'.`);
|
|
24
|
-
}
|
|
25
|
-
})();
|
|
26
|
-
|
|
27
|
-
// Versioning
|
|
28
|
-
let versions = {
|
|
29
|
-
vips: sharp.libvipsVersion()
|
|
30
|
-
};
|
|
31
|
-
(function () {
|
|
32
|
-
// Does libvips meet minimum requirement?
|
|
33
|
-
const libvipsVersionMin = require('../package.json').config.libvips;
|
|
34
|
-
/* istanbul ignore if */
|
|
35
|
-
if (semver.lt(versions.vips, libvipsVersionMin)) {
|
|
36
|
-
throw new Error('Found libvips ' + versions.vips + ' but require at least ' + libvipsVersionMin);
|
|
37
|
-
}
|
|
38
|
-
// Include versions of dependencies, if present
|
|
39
|
-
try {
|
|
40
|
-
versions = require('../vendor/versions.json');
|
|
41
|
-
} catch (err) {}
|
|
42
|
-
})();
|
|
9
|
+
require('./libvips').hasVendoredLibvips();
|
|
10
|
+
const sharp = require('../build/Release/sharp.node');
|
|
43
11
|
|
|
44
12
|
// Use NODE_DEBUG=sharp to enable libvips warnings
|
|
45
13
|
const debuglog = util.debuglog('sharp');
|
|
@@ -81,7 +49,7 @@ const debuglog = util.debuglog('sharp');
|
|
|
81
49
|
* width: 300,
|
|
82
50
|
* height: 200,
|
|
83
51
|
* channels: 4,
|
|
84
|
-
* background: { r: 255, g: 0, b: 0, alpha:
|
|
52
|
+
* background: { r: 255, g: 0, b: 0, alpha: 0.5 }
|
|
85
53
|
* }
|
|
86
54
|
* })
|
|
87
55
|
* .png()
|
|
@@ -96,7 +64,7 @@ const debuglog = util.debuglog('sharp');
|
|
|
96
64
|
* @param {Boolean} [options.failOnError=false] - by default apply a "best effort"
|
|
97
65
|
* to decode images, even if the data is corrupt or invalid. Set this flag to true
|
|
98
66
|
* if you'd rather halt processing and raise an error when loading invalid images.
|
|
99
|
-
* @param {Number} [options.density=72] -
|
|
67
|
+
* @param {Number} [options.density=72] - number representing the DPI for vector images.
|
|
100
68
|
* @param {Number} [options.page=0] - page number to extract for multi-page input (GIF, TIFF)
|
|
101
69
|
* @param {Object} [options.raw] - describes raw pixel input image data. See `raw()` for pixel ordering.
|
|
102
70
|
* @param {Number} [options.raw.width]
|
|
@@ -136,10 +104,12 @@ const Sharp = function (input, options) {
|
|
|
136
104
|
width: -1,
|
|
137
105
|
height: -1,
|
|
138
106
|
canvas: 'crop',
|
|
139
|
-
|
|
140
|
-
|
|
107
|
+
position: 0,
|
|
108
|
+
resizeBackground: [0, 0, 0, 255],
|
|
141
109
|
useExifOrientation: false,
|
|
142
110
|
angle: 0,
|
|
111
|
+
rotationAngle: 0,
|
|
112
|
+
rotationBackground: [0, 0, 0, 255],
|
|
143
113
|
rotateBeforePreExtract: false,
|
|
144
114
|
flip: false,
|
|
145
115
|
flop: false,
|
|
@@ -147,14 +117,15 @@ const Sharp = function (input, options) {
|
|
|
147
117
|
extendBottom: 0,
|
|
148
118
|
extendLeft: 0,
|
|
149
119
|
extendRight: 0,
|
|
120
|
+
extendBackground: [0, 0, 0, 255],
|
|
150
121
|
withoutEnlargement: false,
|
|
151
122
|
kernel: 'lanczos3',
|
|
152
123
|
fastShrinkOnLoad: true,
|
|
153
124
|
// operations
|
|
154
|
-
background: [0, 0, 0, 255],
|
|
155
125
|
tintA: 128,
|
|
156
126
|
tintB: 128,
|
|
157
127
|
flatten: false,
|
|
128
|
+
flattenBackground: [0, 0, 0],
|
|
158
129
|
negate: false,
|
|
159
130
|
medianSize: 0,
|
|
160
131
|
blurSigma: 0,
|
|
@@ -163,7 +134,7 @@ const Sharp = function (input, options) {
|
|
|
163
134
|
sharpenJagged: 2,
|
|
164
135
|
threshold: 0,
|
|
165
136
|
thresholdGrayscale: true,
|
|
166
|
-
|
|
137
|
+
trimThreshold: 0,
|
|
167
138
|
gamma: 0,
|
|
168
139
|
greyscale: false,
|
|
169
140
|
normalise: 0,
|
|
@@ -171,6 +142,7 @@ const Sharp = function (input, options) {
|
|
|
171
142
|
booleanFileIn: '',
|
|
172
143
|
joinChannelIn: [],
|
|
173
144
|
extractChannel: -1,
|
|
145
|
+
removeAlpha: false,
|
|
174
146
|
colourspace: 'srgb',
|
|
175
147
|
// overlay
|
|
176
148
|
overlayGravity: 0,
|
|
@@ -193,6 +165,7 @@ const Sharp = function (input, options) {
|
|
|
193
165
|
jpegOvershootDeringing: false,
|
|
194
166
|
jpegOptimiseScans: false,
|
|
195
167
|
jpegOptimiseCoding: true,
|
|
168
|
+
jpegQuantisationTable: 0,
|
|
196
169
|
pngProgressive: false,
|
|
197
170
|
pngCompressionLevel: 9,
|
|
198
171
|
pngAdaptiveFiltering: false,
|
|
@@ -249,7 +222,12 @@ Sharp.format = sharp.format();
|
|
|
249
222
|
* @example
|
|
250
223
|
* console.log(sharp.versions);
|
|
251
224
|
*/
|
|
252
|
-
Sharp.versions =
|
|
225
|
+
Sharp.versions = {
|
|
226
|
+
vips: sharp.libvipsVersion()
|
|
227
|
+
};
|
|
228
|
+
try {
|
|
229
|
+
Sharp.versions = require('../vendor/versions.json');
|
|
230
|
+
} catch (err) {}
|
|
253
231
|
|
|
254
232
|
/**
|
|
255
233
|
* Export constructor.
|
package/lib/input.js
CHANGED
|
@@ -36,7 +36,7 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
36
36
|
}
|
|
37
37
|
// Density
|
|
38
38
|
if (is.defined(inputOptions.density)) {
|
|
39
|
-
if (is.
|
|
39
|
+
if (is.inRange(inputOptions.density, 1, 2400)) {
|
|
40
40
|
inputDescriptor.density = inputOptions.density;
|
|
41
41
|
} else {
|
|
42
42
|
throw new Error('Invalid density (1 to 2400) ' + inputOptions.density);
|
|
@@ -177,12 +177,15 @@ function clone () {
|
|
|
177
177
|
* A Promises/A+ promise is returned when `callback` is not provided.
|
|
178
178
|
*
|
|
179
179
|
* - `format`: Name of decoder used to decompress image data e.g. `jpeg`, `png`, `webp`, `gif`, `svg`
|
|
180
|
+
* - `size`: Total size of image in bytes, for Stream and Buffer input only
|
|
180
181
|
* - `width`: Number of pixels wide (EXIF orientation is not taken into consideration)
|
|
181
182
|
* - `height`: Number of pixels high (EXIF orientation is not taken into consideration)
|
|
182
|
-
* - `space`: Name of colour space interpretation e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://github.com/
|
|
183
|
+
* - `space`: Name of colour space interpretation e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://github.com/libvips/libvips/blob/master/libvips/iofuncs/enumtypes.c#L636)
|
|
183
184
|
* - `channels`: Number of bands e.g. `3` for sRGB, `4` for CMYK
|
|
184
|
-
* - `depth`: Name of pixel depth format e.g. `uchar`, `char`, `ushort`, `float` [...](https://github.com/
|
|
185
|
+
* - `depth`: Name of pixel depth format e.g. `uchar`, `char`, `ushort`, `float` [...](https://github.com/libvips/libvips/blob/master/libvips/iofuncs/enumtypes.c#L672)
|
|
185
186
|
* - `density`: Number of pixels per inch (DPI), if present
|
|
187
|
+
* - `chromaSubsampling`: String containing JPEG chroma subsampling, `4:2:0` or `4:4:4` for RGB, `4:2:0:4` or `4:4:4:4` for CMYK
|
|
188
|
+
* - `isProgressive`: Boolean indicating whether the image is interlaced using a progressive scan
|
|
186
189
|
* - `hasProfile`: Boolean indicating the presence of an embedded ICC profile
|
|
187
190
|
* - `hasAlpha`: Boolean indicating the presence of an alpha transparency channel
|
|
188
191
|
* - `orientation`: Number value of the EXIF Orientation header, if present
|
|
@@ -264,6 +267,7 @@ function metadata (callback) {
|
|
|
264
267
|
* - `maxX` (x-coordinate of one of the pixel where the maximum lies)
|
|
265
268
|
* - `maxY` (y-coordinate of one of the pixel where the maximum lies)
|
|
266
269
|
* - `isOpaque`: Value to identify if the image is opaque or transparent, based on the presence and use of alpha channel
|
|
270
|
+
* - `entropy`: Histogram-based estimation of greyscale entropy, discarding alpha channel if any (experimental)
|
|
267
271
|
*
|
|
268
272
|
* @example
|
|
269
273
|
* const image = sharp(inputJpg);
|
package/lib/libvips.js
CHANGED
|
@@ -1,17 +1,38 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const os = require('os');
|
|
3
5
|
const path = require('path');
|
|
4
6
|
const spawnSync = require('child_process').spawnSync;
|
|
5
7
|
const semver = require('semver');
|
|
6
8
|
const platform = require('./platform');
|
|
7
9
|
|
|
8
|
-
const
|
|
10
|
+
const env = process.env;
|
|
11
|
+
const minimumLibvipsVersion = env.npm_package_config_libvips || require('../package.json').config.libvips;
|
|
9
12
|
|
|
10
13
|
const spawnSyncOptions = {
|
|
11
14
|
encoding: 'utf8',
|
|
12
15
|
shell: true
|
|
13
16
|
};
|
|
14
17
|
|
|
18
|
+
const mkdirSync = function (dirPath) {
|
|
19
|
+
try {
|
|
20
|
+
fs.mkdirSync(dirPath);
|
|
21
|
+
} catch (err) {
|
|
22
|
+
if (err.code !== 'EEXIST') {
|
|
23
|
+
throw err;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const cachePath = function () {
|
|
29
|
+
const npmCachePath = env.npm_config_cache || (env.APPDATA ? path.join(env.APPDATA, 'npm-cache') : path.join(os.homedir(), '.npm'));
|
|
30
|
+
mkdirSync(npmCachePath);
|
|
31
|
+
const libvipsCachePath = path.join(npmCachePath, '_libvips');
|
|
32
|
+
mkdirSync(libvipsCachePath);
|
|
33
|
+
return libvipsCachePath;
|
|
34
|
+
};
|
|
35
|
+
|
|
15
36
|
const globalLibvipsVersion = function () {
|
|
16
37
|
if (process.platform !== 'win32') {
|
|
17
38
|
const globalLibvipsVersion = spawnSync(`PKG_CONFIG_PATH="${pkgConfigPath()}" pkg-config --modversion vips-cpp`, spawnSyncOptions).stdout || '';
|
|
@@ -23,21 +44,30 @@ const globalLibvipsVersion = function () {
|
|
|
23
44
|
|
|
24
45
|
const hasVendoredLibvips = function () {
|
|
25
46
|
const currentPlatformId = platform();
|
|
47
|
+
const vendorPath = path.join(__dirname, '..', 'vendor');
|
|
48
|
+
let vendorVersionId;
|
|
49
|
+
let vendorPlatformId;
|
|
26
50
|
try {
|
|
27
|
-
|
|
51
|
+
vendorVersionId = require(path.join(vendorPath, 'versions.json')).vips;
|
|
52
|
+
vendorPlatformId = require(path.join(vendorPath, 'platform.json'));
|
|
53
|
+
} catch (err) {}
|
|
54
|
+
if (vendorVersionId && vendorVersionId !== minimumLibvipsVersion) {
|
|
55
|
+
throw new Error(`Found vendored libvips v${vendorVersionId} but require v${minimumLibvipsVersion}. Please remove the 'node_modules/sharp/vendor' directory and run 'npm install'.`);
|
|
56
|
+
}
|
|
57
|
+
if (vendorPlatformId) {
|
|
28
58
|
if (currentPlatformId === vendorPlatformId) {
|
|
29
59
|
return true;
|
|
30
60
|
} else {
|
|
31
61
|
throw new Error(`'${vendorPlatformId}' binaries cannot be used on the '${currentPlatformId}' platform. Please remove the 'node_modules/sharp/vendor' directory and run 'npm install'.`);
|
|
32
62
|
}
|
|
33
|
-
}
|
|
63
|
+
}
|
|
34
64
|
return false;
|
|
35
65
|
};
|
|
36
66
|
|
|
37
67
|
const pkgConfigPath = function () {
|
|
38
68
|
if (process.platform !== 'win32') {
|
|
39
69
|
const brewPkgConfigPath = spawnSync('which brew >/dev/null 2>&1 && eval $(brew --env) && echo $PKG_CONFIG_LIBDIR', spawnSyncOptions).stdout || '';
|
|
40
|
-
return [brewPkgConfigPath.trim(),
|
|
70
|
+
return [brewPkgConfigPath.trim(), env.PKG_CONFIG_PATH, '/usr/local/lib/pkgconfig', '/usr/lib/pkgconfig']
|
|
41
71
|
.filter(function (p) { return !!p; })
|
|
42
72
|
.join(':');
|
|
43
73
|
} else {
|
|
@@ -46,7 +76,7 @@ const pkgConfigPath = function () {
|
|
|
46
76
|
};
|
|
47
77
|
|
|
48
78
|
const useGlobalLibvips = function () {
|
|
49
|
-
if (Boolean(
|
|
79
|
+
if (Boolean(env.SHARP_IGNORE_GLOBAL_LIBVIPS) === true) {
|
|
50
80
|
return false;
|
|
51
81
|
}
|
|
52
82
|
|
|
@@ -56,8 +86,10 @@ const useGlobalLibvips = function () {
|
|
|
56
86
|
|
|
57
87
|
module.exports = {
|
|
58
88
|
minimumLibvipsVersion: minimumLibvipsVersion,
|
|
89
|
+
cachePath: cachePath,
|
|
59
90
|
globalLibvipsVersion: globalLibvipsVersion,
|
|
60
91
|
hasVendoredLibvips: hasVendoredLibvips,
|
|
61
92
|
pkgConfigPath: pkgConfigPath,
|
|
62
|
-
useGlobalLibvips: useGlobalLibvips
|
|
93
|
+
useGlobalLibvips: useGlobalLibvips,
|
|
94
|
+
mkdirSync: mkdirSync
|
|
63
95
|
};
|