mirror of
https://github.com/lovell/sharp.git
synced 2026-02-06 06:36:17 +01:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
956f7e29db | ||
|
|
4264c0577e | ||
|
|
cc37b59309 | ||
|
|
9f2f92095d | ||
|
|
0c1075c089 | ||
|
|
9c64710c8b | ||
|
|
f6f16b91db | ||
|
|
1986b5cfe6 | ||
|
|
6445b72d41 | ||
|
|
df7b8ba738 | ||
|
|
202083999e | ||
|
|
315f519e1d | ||
|
|
d7d580ae6f | ||
|
|
7017af303d | ||
|
|
0dc325daa4 | ||
|
|
6dffb47973 |
2
.github/CONTRIBUTING.md
vendored
2
.github/CONTRIBUTING.md
vendored
@@ -27,7 +27,7 @@ Please select the `master` branch as the destination for your Pull Request so yo
|
|||||||
|
|
||||||
Please squash your changes into a single commit using a command like `git rebase -i upstream/master`.
|
Please squash your changes into a single commit using a command like `git rebase -i upstream/master`.
|
||||||
|
|
||||||
To test C++ changes, you can compile the module using `npm install` and then run the tests using `npm test`.
|
To test C++ changes, you can compile the module using `npm install --build-from-source` and then run the tests using `npm test`.
|
||||||
|
|
||||||
## Submit a Pull Request with a new feature
|
## Submit a Pull Request with a new feature
|
||||||
|
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ await sharp({
|
|||||||
sigma: 30
|
sigma: 30
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.toFile('noise.png');
|
}).toFile('noise.png');
|
||||||
```
|
```
|
||||||
|
|
||||||
- Throws **[Error][10]** Invalid parameters
|
- Throws **[Error][10]** Invalid parameters
|
||||||
|
|||||||
@@ -326,7 +326,7 @@ most web browsers do not display these properly.
|
|||||||
- `options` **[Object][6]?** output options
|
- `options` **[Object][6]?** output options
|
||||||
- `options.quality` **[number][9]** quality, integer 1-100 (optional, default `50`)
|
- `options.quality` **[number][9]** quality, integer 1-100 (optional, default `50`)
|
||||||
- `options.lossless` **[boolean][7]** use lossless compression (optional, default `false`)
|
- `options.lossless` **[boolean][7]** use lossless compression (optional, default `false`)
|
||||||
- `options.speed` **[boolean][7]** CPU effort vs file size, 0 (slowest/smallest) to 8 (fastest/largest) (optional, default `5`)
|
- `options.speed` **[number][9]** CPU effort vs file size, 0 (slowest/smallest) to 8 (fastest/largest) (optional, default `5`)
|
||||||
- `options.chromaSubsampling` **[string][2]** set to '4:4:4' to prevent chroma subsampling otherwise defaults to '4:2:0' chroma subsampling, requires libvips v8.11.0 (optional, default `'4:2:0'`)
|
- `options.chromaSubsampling` **[string][2]** set to '4:4:4' to prevent chroma subsampling otherwise defaults to '4:2:0' chroma subsampling, requires libvips v8.11.0 (optional, default `'4:2:0'`)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,24 @@
|
|||||||
|
|
||||||
Requires libvips v8.10.5
|
Requires libvips v8.10.5
|
||||||
|
|
||||||
|
### v0.27.2 - 22nd February 2021
|
||||||
|
|
||||||
|
* macOS: Prevent use of globally-installed ARM64 libvips with Rosetta x64 emulation.
|
||||||
|
[#2460](https://github.com/lovell/sharp/issues/2460)
|
||||||
|
|
||||||
|
* Linux (musl): Prevent use of prebuilt linuxmusl-x64 binaries with musl >= 1.2.0.
|
||||||
|
[#2570](https://github.com/lovell/sharp/issues/2570)
|
||||||
|
|
||||||
|
* Improve 16-bit grey+alpha support by using libvips' `has_alpha` detection.
|
||||||
|
[#2569](https://github.com/lovell/sharp/issues/2569)
|
||||||
|
|
||||||
|
* Allow the use of non lower case extensions with `toFormat`.
|
||||||
|
[#2581](https://github.com/lovell/sharp/pull/2581)
|
||||||
|
[@florian-busch](https://github.com/florian-busch)
|
||||||
|
|
||||||
|
* Allow use of `recomb` operation with single channel input.
|
||||||
|
[#2584](https://github.com/lovell/sharp/issues/2584)
|
||||||
|
|
||||||
### v0.27.1 - 27th January 2021
|
### v0.27.1 - 27th January 2021
|
||||||
|
|
||||||
* Ensure TIFF is cast when using float predictor.
|
* Ensure TIFF is cast when using float predictor.
|
||||||
|
|||||||
@@ -206,3 +206,6 @@ GitHub: https://github.com/stefanprobst
|
|||||||
|
|
||||||
Name: Thomas Beiganz
|
Name: Thomas Beiganz
|
||||||
GitHub: https://github.com/beig
|
GitHub: https://github.com/beig
|
||||||
|
|
||||||
|
Name: Florian Busch
|
||||||
|
GitHub: https://github.com/florian-busch
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="https://pixel.plumbing/px/72x72/sharp-logo.svg">
|
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="https://pixel.plumbing/px/72x72/sharp-logo.svg">
|
||||||
<link rel="apple-touch-icon-precomposed" href="https://pixel.plumbing/px/57x57/sharp-logo.svg">
|
<link rel="apple-touch-icon-precomposed" href="https://pixel.plumbing/px/57x57/sharp-logo.svg">
|
||||||
<link rel="author" href="/humans.txt" type="text/plain">
|
<link rel="author" href="/humans.txt" type="text/plain">
|
||||||
<link rel="preload" href="https://cdn.jsdelivr.net/gh/lovell/sharp@v0.27.1/docs/README.md" as="fetch" type="text/markdown" crossorigin>
|
<link rel="preload" href="https://cdn.jsdelivr.net/gh/lovell/sharp@v0.27.2/docs/README.md" as="fetch" type="text/markdown" crossorigin>
|
||||||
<link rel="preload" href="https://cdn.jsdelivr.net/gh/lovell/sharp@master/docs/image/sharp-logo.svg" as="image" type="image/svg+xml" crossorigin>
|
<link rel="preload" href="https://cdn.jsdelivr.net/gh/lovell/sharp@master/docs/image/sharp-logo.svg" as="image" type="image/svg+xml" crossorigin>
|
||||||
<link rel="dns-prefetch" href="https://pixel.plumbing">
|
<link rel="dns-prefetch" href="https://pixel.plumbing">
|
||||||
<link rel="dns-prefetch" href="https://www.google-analytics.com">
|
<link rel="dns-prefetch" href="https://www.google-analytics.com">
|
||||||
@@ -139,7 +139,7 @@
|
|||||||
docuteApiTitlePlugin,
|
docuteApiTitlePlugin,
|
||||||
docuteApiSearchPlugin
|
docuteApiSearchPlugin
|
||||||
],
|
],
|
||||||
sourcePath: 'https://cdn.jsdelivr.net/gh/lovell/sharp@v0.27.1/docs',
|
sourcePath: 'https://cdn.jsdelivr.net/gh/lovell/sharp@v0.27.2/docs',
|
||||||
nav: [
|
nav: [
|
||||||
{
|
{
|
||||||
title: 'Funding',
|
title: 'Funding',
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Ready-compiled sharp and libvips binaries are provided for use with
|
|||||||
Node.js v10+ on the most common platforms:
|
Node.js v10+ on the most common platforms:
|
||||||
|
|
||||||
* macOS x64 (>= 10.13)
|
* macOS x64 (>= 10.13)
|
||||||
* Linux x64 (glibc >= 2.17, musl >= 1.1.24)
|
* Linux x64 (glibc >= 2.17, musl >=1.1.24 <1.2.0)
|
||||||
* Linux ARM64 (glibc >= 2.29)
|
* Linux ARM64 (glibc >= 2.29)
|
||||||
* Windows x64
|
* Windows x64
|
||||||
* Windows x86
|
* Windows x86
|
||||||
@@ -60,7 +60,13 @@ Check the output of running `npm install --verbose sharp` for useful error messa
|
|||||||
|
|
||||||
## Apple M1
|
## Apple M1
|
||||||
|
|
||||||
libvips must currently be installed via Homebrew before installing sharp.
|
If you are using ARM64 Node.js, which can be checked using:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
node -p "process.arch === 'arm64'"
|
||||||
|
```
|
||||||
|
|
||||||
|
then libvips must currently be installed via Homebrew before installing sharp.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
brew install vips
|
brew install vips
|
||||||
@@ -192,6 +198,18 @@ docker run -v "$PWD":/var/task lambci/lambda:build-nodejs12.x npm install sharp
|
|||||||
To get the best performance select the largest memory available.
|
To get the best performance select the largest memory available.
|
||||||
A 1536 MB function provides ~12x more CPU time than a 128 MB function.
|
A 1536 MB function provides ~12x more CPU time than a 128 MB function.
|
||||||
|
|
||||||
|
## Webpack
|
||||||
|
|
||||||
|
Ensure sharp is added to the
|
||||||
|
[externals](https://webpack.js.org/configuration/externals/)
|
||||||
|
configuration.
|
||||||
|
|
||||||
|
```js
|
||||||
|
externals: {
|
||||||
|
'sharp': 'commonjs sharp'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Worker threads
|
## Worker threads
|
||||||
|
|
||||||
The main thread must call `require('sharp')`
|
The main thread must call `require('sharp')`
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -17,7 +17,7 @@ const extractKeywords = (str) =>
|
|||||||
str
|
str
|
||||||
.split(/[ -/]/)
|
.split(/[ -/]/)
|
||||||
.map((word) => word.toLowerCase().replace(/[^a-z]/g, ''))
|
.map((word) => word.toLowerCase().replace(/[^a-z]/g, ''))
|
||||||
.filter((word) => word.length > 2 && !stopWords.includes(word))
|
.filter((word) => word.length > 2 && word.length < 15 && !stopWords.includes(word))
|
||||||
)
|
)
|
||||||
].join(' ');
|
].join(' ');
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ module.exports = [
|
|||||||
'does',
|
'does',
|
||||||
'each',
|
'each',
|
||||||
'either',
|
'either',
|
||||||
|
'ensure',
|
||||||
'etc',
|
'etc',
|
||||||
|
'every',
|
||||||
'for',
|
'for',
|
||||||
'from',
|
'from',
|
||||||
'get',
|
'get',
|
||||||
|
|||||||
@@ -74,6 +74,9 @@ try {
|
|||||||
if (arch === 'ia32' && !platformAndArch.startsWith('win32')) {
|
if (arch === 'ia32' && !platformAndArch.startsWith('win32')) {
|
||||||
throw new Error(`Intel Architecture 32-bit systems require manual installation of libvips >= ${minimumLibvipsVersion}`);
|
throw new Error(`Intel Architecture 32-bit systems require manual installation of libvips >= ${minimumLibvipsVersion}`);
|
||||||
}
|
}
|
||||||
|
if (platformAndArch === 'darwin-arm64') {
|
||||||
|
throw new Error("Please run 'brew install vips' to install libvips on Apple M1 (ARM64) systems");
|
||||||
|
}
|
||||||
if (platformAndArch === 'freebsd-x64' || platformAndArch === 'openbsd-x64' || platformAndArch === 'sunos-x64') {
|
if (platformAndArch === 'freebsd-x64' || platformAndArch === 'openbsd-x64' || platformAndArch === 'sunos-x64') {
|
||||||
throw new Error(`BSD/SunOS systems require manual installation of libvips >= ${minimumLibvipsVersion}`);
|
throw new Error(`BSD/SunOS systems require manual installation of libvips >= ${minimumLibvipsVersion}`);
|
||||||
}
|
}
|
||||||
@@ -82,6 +85,11 @@ try {
|
|||||||
throw new Error(`Use with glibc ${detectLibc.version} requires manual installation of libvips >= ${minimumLibvipsVersion}`);
|
throw new Error(`Use with glibc ${detectLibc.version} requires manual installation of libvips >= ${minimumLibvipsVersion}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (detectLibc.family === detectLibc.MUSL && detectLibc.version) {
|
||||||
|
if (!semver.satisfies(detectLibc.version, '>=1.1.24 <1.2.0')) {
|
||||||
|
throw new Error(`Use with musl ${detectLibc.version} requires manual installation of libvips >= ${minimumLibvipsVersion}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const supportedNodeVersion = process.env.npm_package_engines_node || require('../package.json').engines.node;
|
const supportedNodeVersion = process.env.npm_package_engines_node || require('../package.json').engines.node;
|
||||||
if (!semver.satisfies(process.versions.node, supportedNodeVersion)) {
|
if (!semver.satisfies(process.versions.node, supportedNodeVersion)) {
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ const debuglog = util.debuglog('sharp');
|
|||||||
* sigma: 30
|
* sigma: 30
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* }.toFile('noise.png');
|
* }).toFile('noise.png');
|
||||||
*
|
*
|
||||||
* @param {(Buffer|Uint8Array|Uint8ClampedArray|string)} [input] - if present, can be
|
* @param {(Buffer|Uint8Array|Uint8ClampedArray|string)} [input] - if present, can be
|
||||||
* a Buffer / Uint8Array / Uint8ClampedArray containing JPEG, PNG, WebP, AVIF, GIF, SVG, TIFF or raw pixel image data, or
|
* a Buffer / Uint8Array / Uint8ClampedArray containing JPEG, PNG, WebP, AVIF, GIF, SVG, TIFF or raw pixel image data, or
|
||||||
|
|||||||
@@ -37,6 +37,15 @@ const cachePath = function () {
|
|||||||
return libvipsCachePath;
|
return libvipsCachePath;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isRosetta = function () {
|
||||||
|
/* istanbul ignore next */
|
||||||
|
if (process.platform === 'darwin' && process.arch === 'x64') {
|
||||||
|
const translated = spawnSync('sysctl sysctl.proc_translated', spawnSyncOptions).stdout;
|
||||||
|
return (translated || '').trim() === 'sysctl.proc_translated: 1';
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
const globalLibvipsVersion = function () {
|
const globalLibvipsVersion = function () {
|
||||||
if (process.platform !== 'win32') {
|
if (process.platform !== 'win32') {
|
||||||
const globalLibvipsVersion = spawnSync(`PKG_CONFIG_PATH="${pkgConfigPath()}" pkg-config --modversion vips-cpp`, spawnSyncOptions).stdout;
|
const globalLibvipsVersion = spawnSync(`PKG_CONFIG_PATH="${pkgConfigPath()}" pkg-config --modversion vips-cpp`, spawnSyncOptions).stdout;
|
||||||
@@ -82,7 +91,10 @@ const useGlobalLibvips = function () {
|
|||||||
if (Boolean(env.SHARP_IGNORE_GLOBAL_LIBVIPS) === true) {
|
if (Boolean(env.SHARP_IGNORE_GLOBAL_LIBVIPS) === true) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
/* istanbul ignore next */
|
||||||
|
if (isRosetta()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
const globalVipsVersion = globalLibvipsVersion();
|
const globalVipsVersion = globalLibvipsVersion();
|
||||||
return !!globalVipsVersion && /* istanbul ignore next */
|
return !!globalVipsVersion && /* istanbul ignore next */
|
||||||
semver.gte(globalVipsVersion, minimumLibvipsVersion);
|
semver.gte(globalVipsVersion, minimumLibvipsVersion);
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ const formats = new Map([
|
|||||||
['gif', 'gif']
|
['gif', 'gif']
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const errMagickSave = new Error('GIF output requires libvips with support for ImageMagick');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write output image data to a file.
|
* Write output image data to a file.
|
||||||
*
|
*
|
||||||
@@ -47,25 +49,23 @@ const formats = new Map([
|
|||||||
* @throws {Error} Invalid parameters
|
* @throws {Error} Invalid parameters
|
||||||
*/
|
*/
|
||||||
function toFile (fileOut, callback) {
|
function toFile (fileOut, callback) {
|
||||||
if (!fileOut || fileOut.length === 0) {
|
let err;
|
||||||
const errOutputInvalid = new Error('Missing output file path');
|
if (!is.string(fileOut)) {
|
||||||
|
err = new Error('Missing output file path');
|
||||||
|
} else if (this.options.input.file === fileOut) {
|
||||||
|
err = new Error('Cannot use same file for input and output');
|
||||||
|
} else if (this.options.formatOut === 'input' && fileOut.toLowerCase().endsWith('.gif') && !this.constructor.format.magick.output.file) {
|
||||||
|
err = errMagickSave;
|
||||||
|
}
|
||||||
|
if (err) {
|
||||||
if (is.fn(callback)) {
|
if (is.fn(callback)) {
|
||||||
callback(errOutputInvalid);
|
callback(err);
|
||||||
} else {
|
} else {
|
||||||
return Promise.reject(errOutputInvalid);
|
return Promise.reject(err);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this.options.input.file === fileOut) {
|
this.options.fileOut = fileOut;
|
||||||
const errOutputIsInput = new Error('Cannot use same file for input and output');
|
return this._pipeline(callback);
|
||||||
if (is.fn(callback)) {
|
|
||||||
callback(errOutputIsInput);
|
|
||||||
} else {
|
|
||||||
return Promise.reject(errOutputIsInput);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.options.fileOut = fileOut;
|
|
||||||
return this._pipeline(callback);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -188,7 +188,7 @@ function withMetadata (options) {
|
|||||||
* @throws {Error} unsupported format or options
|
* @throws {Error} unsupported format or options
|
||||||
*/
|
*/
|
||||||
function toFormat (format, options) {
|
function toFormat (format, options) {
|
||||||
const actualFormat = formats.get(is.object(format) && is.string(format.id) ? format.id : format);
|
const actualFormat = formats.get((is.object(format) && is.string(format.id) ? format.id : format).toLowerCase());
|
||||||
if (!actualFormat) {
|
if (!actualFormat) {
|
||||||
throw is.invalidParameterError('format', `one of: ${[...formats.keys()].join(', ')}`, format);
|
throw is.invalidParameterError('format', `one of: ${[...formats.keys()].join(', ')}`, format);
|
||||||
}
|
}
|
||||||
@@ -426,7 +426,7 @@ function webp (options) {
|
|||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
function gif (options) {
|
function gif (options) {
|
||||||
if (!this.constructor.format.magick.output.buffer) {
|
if (!this.constructor.format.magick.output.buffer) {
|
||||||
throw new Error('The gif operation requires libvips to have been installed with support for ImageMagick');
|
throw errMagickSave;
|
||||||
}
|
}
|
||||||
trySetAnimationOptions(options, this.options);
|
trySetAnimationOptions(options, this.options);
|
||||||
return this._updateFormatOut('gif', options);
|
return this._updateFormatOut('gif', options);
|
||||||
@@ -582,7 +582,7 @@ function tiff (options) {
|
|||||||
* @param {Object} [options] - output options
|
* @param {Object} [options] - output options
|
||||||
* @param {number} [options.quality=50] - quality, integer 1-100
|
* @param {number} [options.quality=50] - quality, integer 1-100
|
||||||
* @param {boolean} [options.lossless=false] - use lossless compression
|
* @param {boolean} [options.lossless=false] - use lossless compression
|
||||||
* @param {boolean} [options.speed=5] - CPU effort vs file size, 0 (slowest/smallest) to 8 (fastest/largest)
|
* @param {number} [options.speed=5] - CPU effort vs file size, 0 (slowest/smallest) to 8 (fastest/largest)
|
||||||
* @param {string} [options.chromaSubsampling='4:2:0'] - set to '4:4:4' to prevent chroma subsampling otherwise defaults to '4:2:0' chroma subsampling, requires libvips v8.11.0
|
* @param {string} [options.chromaSubsampling='4:2:0'] - set to '4:4:4' to prevent chroma subsampling otherwise defaults to '4:2:0' chroma subsampling, requires libvips v8.11.0
|
||||||
* @returns {Sharp}
|
* @returns {Sharp}
|
||||||
* @throws {Error} Invalid options
|
* @throws {Error} Invalid options
|
||||||
|
|||||||
@@ -157,14 +157,10 @@ simd(true);
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
module.exports = function (Sharp) {
|
module.exports = function (Sharp) {
|
||||||
[
|
Sharp.cache = cache;
|
||||||
cache,
|
Sharp.concurrency = concurrency;
|
||||||
concurrency,
|
Sharp.counters = counters;
|
||||||
counters,
|
Sharp.simd = simd;
|
||||||
simd
|
|
||||||
].forEach(function (f) {
|
|
||||||
Sharp[f.name] = f;
|
|
||||||
});
|
|
||||||
Sharp.format = format;
|
Sharp.format = format;
|
||||||
Sharp.interpolators = interpolators;
|
Sharp.interpolators = interpolators;
|
||||||
Sharp.versions = versions;
|
Sharp.versions = versions;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "sharp",
|
"name": "sharp",
|
||||||
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, AVIF and TIFF images",
|
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, AVIF and TIFF images",
|
||||||
"version": "0.27.1",
|
"version": "0.27.2",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://github.com/lovell/sharp",
|
"homepage": "https://github.com/lovell/sharp",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
"install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node-gyp rebuild && node install/dll-copy)",
|
"install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node-gyp rebuild && node install/dll-copy)",
|
||||||
"clean": "rm -rf node_modules/ build/ vendor/ .nyc_output/ coverage/ test/fixtures/output.*",
|
"clean": "rm -rf node_modules/ build/ vendor/ .nyc_output/ coverage/ test/fixtures/output.*",
|
||||||
"test": "semistandard && cpplint && npm run test-unit && npm run test-licensing",
|
"test": "semistandard && cpplint && npm run test-unit && npm run test-licensing",
|
||||||
"test-unit": "nyc --reporter=lcov --branches=99 mocha --parallel --slow=5000 --timeout=60000 ./test/unit/*.js",
|
"test-unit": "nyc --reporter=lcov --branches=99 mocha --slow=5000 --timeout=60000 ./test/unit/*.js",
|
||||||
"test-licensing": "license-checker --production --summary --onlyAllow=\"Apache-2.0;BSD;ISC;MIT\"",
|
"test-licensing": "license-checker --production --summary --onlyAllow=\"Apache-2.0;BSD;ISC;MIT\"",
|
||||||
"test-coverage": "./test/coverage/report.sh",
|
"test-coverage": "./test/coverage/report.sh",
|
||||||
"test-leak": "./test/leak/leak.sh",
|
"test-leak": "./test/leak/leak.sh",
|
||||||
@@ -122,7 +122,7 @@
|
|||||||
"detect-libc": "^1.0.3",
|
"detect-libc": "^1.0.3",
|
||||||
"node-addon-api": "^3.1.0",
|
"node-addon-api": "^3.1.0",
|
||||||
"npmlog": "^4.1.2",
|
"npmlog": "^4.1.2",
|
||||||
"prebuild-install": "^6.0.0",
|
"prebuild-install": "^6.0.1",
|
||||||
"semver": "^7.3.4",
|
"semver": "^7.3.4",
|
||||||
"simple-get": "^4.0.0",
|
"simple-get": "^4.0.0",
|
||||||
"tar-fs": "^2.1.1",
|
"tar-fs": "^2.1.1",
|
||||||
@@ -136,7 +136,7 @@
|
|||||||
"exif-reader": "^1.0.3",
|
"exif-reader": "^1.0.3",
|
||||||
"icc": "^2.0.0",
|
"icc": "^2.0.0",
|
||||||
"license-checker": "^25.0.1",
|
"license-checker": "^25.0.1",
|
||||||
"mocha": "^8.2.1",
|
"mocha": "^8.3.0",
|
||||||
"mock-fs": "^4.13.0",
|
"mock-fs": "^4.13.0",
|
||||||
"nyc": "^15.1.0",
|
"nyc": "^15.1.0",
|
||||||
"prebuild": "^10.0.1",
|
"prebuild": "^10.0.1",
|
||||||
|
|||||||
@@ -421,12 +421,7 @@ namespace sharp {
|
|||||||
Uses colour space interpretation with number of channels to guess this.
|
Uses colour space interpretation with number of channels to guess this.
|
||||||
*/
|
*/
|
||||||
bool HasAlpha(VImage image) {
|
bool HasAlpha(VImage image) {
|
||||||
int const bands = image.bands();
|
return image.has_alpha();
|
||||||
VipsInterpretation const interpretation = image.interpretation();
|
|
||||||
return (
|
|
||||||
(bands == 2 && interpretation == VIPS_INTERPRETATION_B_W) ||
|
|
||||||
(bands == 4 && interpretation != VIPS_INTERPRETATION_CMYK) ||
|
|
||||||
(bands == 5 && interpretation == VIPS_INTERPRETATION_CMYK));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -149,8 +149,8 @@ namespace sharp {
|
|||||||
*/
|
*/
|
||||||
VImage Recomb(VImage image, std::unique_ptr<double[]> const &matrix) {
|
VImage Recomb(VImage image, std::unique_ptr<double[]> const &matrix) {
|
||||||
double *m = matrix.get();
|
double *m = matrix.get();
|
||||||
|
image = image.colourspace(VIPS_INTERPRETATION_sRGB);
|
||||||
return image
|
return image
|
||||||
.colourspace(VIPS_INTERPRETATION_sRGB)
|
|
||||||
.recomb(image.bands() == 3
|
.recomb(image.bands() == 3
|
||||||
? VImage::new_from_memory(
|
? VImage::new_from_memory(
|
||||||
m, 9 * sizeof(double), 3, 3, 1, VIPS_FORMAT_DOUBLE
|
m, 9 * sizeof(double), 3, 3, 1, VIPS_FORMAT_DOUBLE
|
||||||
|
|||||||
@@ -63,12 +63,17 @@ describe('GIF input', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!sharp.format.magick.output.buffer) {
|
if (!sharp.format.magick.output.buffer) {
|
||||||
it('GIF output should fail due to missing ImageMagick', () => {
|
it('GIF buffer output should fail due to missing ImageMagick', () => {
|
||||||
assert.throws(
|
assert.throws(
|
||||||
() => {
|
() => sharp().gif(),
|
||||||
sharp().gif();
|
/GIF output requires libvips with support for ImageMagick/
|
||||||
},
|
);
|
||||||
/The gif operation requires libvips to have been installed with support for ImageMagick/
|
});
|
||||||
|
|
||||||
|
it('GIF file output should fail due to missing ImageMagick', () => {
|
||||||
|
assert.rejects(
|
||||||
|
async () => await sharp().toFile('test.gif'),
|
||||||
|
/GIF output requires libvips with support for ImageMagick/
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,15 +5,17 @@ const assert = require('assert');
|
|||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
|
|
||||||
|
const sepia = [
|
||||||
|
[0.3588, 0.7044, 0.1368],
|
||||||
|
[0.299, 0.587, 0.114],
|
||||||
|
[0.2392, 0.4696, 0.0912]
|
||||||
|
];
|
||||||
|
|
||||||
describe('Recomb', function () {
|
describe('Recomb', function () {
|
||||||
it('applies a sepia filter using recomb', function (done) {
|
it('applies a sepia filter using recomb', function (done) {
|
||||||
const output = fixtures.path('output.recomb-sepia.jpg');
|
const output = fixtures.path('output.recomb-sepia.jpg');
|
||||||
sharp(fixtures.inputJpgWithLandscapeExif1)
|
sharp(fixtures.inputJpgWithLandscapeExif1)
|
||||||
.recomb([
|
.recomb(sepia)
|
||||||
[0.3588, 0.7044, 0.1368],
|
|
||||||
[0.299, 0.587, 0.114],
|
|
||||||
[0.2392, 0.4696, 0.0912]
|
|
||||||
])
|
|
||||||
.toFile(output, function (err, info) {
|
.toFile(output, function (err, info) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
@@ -31,11 +33,7 @@ describe('Recomb', function () {
|
|||||||
it('applies a sepia filter using recomb to an PNG with Alpha', function (done) {
|
it('applies a sepia filter using recomb to an PNG with Alpha', function (done) {
|
||||||
const output = fixtures.path('output.recomb-sepia.png');
|
const output = fixtures.path('output.recomb-sepia.png');
|
||||||
sharp(fixtures.inputPngAlphaPremultiplicationSmall)
|
sharp(fixtures.inputPngAlphaPremultiplicationSmall)
|
||||||
.recomb([
|
.recomb(sepia)
|
||||||
[0.3588, 0.7044, 0.1368],
|
|
||||||
[0.299, 0.587, 0.114],
|
|
||||||
[0.2392, 0.4696, 0.0912]
|
|
||||||
])
|
|
||||||
.toFile(output, function (err, info) {
|
.toFile(output, function (err, info) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('png', info.format);
|
assert.strictEqual('png', info.format);
|
||||||
@@ -50,6 +48,20 @@ describe('Recomb', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('recomb with a single channel input', async () => {
|
||||||
|
const { info } = await sharp(Buffer.alloc(64), {
|
||||||
|
raw: {
|
||||||
|
width: 8,
|
||||||
|
height: 8,
|
||||||
|
channels: 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.recomb(sepia)
|
||||||
|
.toBuffer({ resolveWithObject: true });
|
||||||
|
|
||||||
|
assert.strictEqual(3, info.channels);
|
||||||
|
});
|
||||||
|
|
||||||
it('applies a different sepia filter using recomb', function (done) {
|
it('applies a different sepia filter using recomb', function (done) {
|
||||||
const output = fixtures.path('output.recomb-sepia2.jpg');
|
const output = fixtures.path('output.recomb-sepia2.jpg');
|
||||||
sharp(fixtures.inputJpgWithLandscapeExif1)
|
sharp(fixtures.inputJpgWithLandscapeExif1)
|
||||||
|
|||||||
26
test/unit/toFormat.js
Normal file
26
test/unit/toFormat.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const assert = require('assert');
|
||||||
|
const sharp = require('../../');
|
||||||
|
const fixtures = require('../fixtures');
|
||||||
|
|
||||||
|
describe('toFormat', () => {
|
||||||
|
it('accepts upper case characters as format parameter (string)', function (done) {
|
||||||
|
sharp(fixtures.inputJpg)
|
||||||
|
.toFormat('PNG')
|
||||||
|
.toBuffer(function (err, data, info) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual('png', info.format);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('accepts upper case characters as format parameter (object)', function (done) {
|
||||||
|
sharp(fixtures.inputJpg)
|
||||||
|
.toFormat({ id: 'PNG' })
|
||||||
|
.toBuffer(function (err, data, info) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual('png', info.format);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user