Upgrade to libvips v8.8.0, remove deprecated overlayWith
1
.gitignore
vendored
@ -12,4 +12,5 @@ vendor
|
|||||||
.gitattributes
|
.gitattributes
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.nyc_output
|
.nyc_output
|
||||||
|
.vscode/
|
||||||
package-lock.json
|
package-lock.json
|
||||||
|
@ -13,3 +13,4 @@ vendor
|
|||||||
.prebuildrc
|
.prebuildrc
|
||||||
.nyc_output
|
.nyc_output
|
||||||
.github/
|
.github/
|
||||||
|
.vscode/
|
||||||
|
32
.travis.yml
@ -1,11 +1,5 @@
|
|||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- name: "Linux (glibc) - Node 6"
|
|
||||||
os: linux
|
|
||||||
dist: trusty
|
|
||||||
sudo: false
|
|
||||||
language: node_js
|
|
||||||
node_js: "6"
|
|
||||||
- name: "Linux (glibc) - Node 8"
|
- name: "Linux (glibc) - Node 8"
|
||||||
os: linux
|
os: linux
|
||||||
dist: trusty
|
dist: trusty
|
||||||
@ -27,12 +21,6 @@ matrix:
|
|||||||
after_success:
|
after_success:
|
||||||
- npm install coveralls
|
- npm install coveralls
|
||||||
- cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
|
- cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
|
||||||
- name: "Linux (glibc) - Node 11"
|
|
||||||
os: linux
|
|
||||||
dist: trusty
|
|
||||||
sudo: false
|
|
||||||
language: node_js
|
|
||||||
node_js: "11"
|
|
||||||
- name: "Linux (musl) - Node 8"
|
- name: "Linux (musl) - Node 8"
|
||||||
os: linux
|
os: linux
|
||||||
dist: trusty
|
dist: trusty
|
||||||
@ -53,16 +41,6 @@ matrix:
|
|||||||
- sudo docker exec sharp apk add build-base git python2 --update-cache
|
- sudo docker exec sharp apk add build-base git python2 --update-cache
|
||||||
install: sudo docker exec sharp sh -c "npm install --unsafe-perm"
|
install: sudo docker exec sharp sh -c "npm install --unsafe-perm"
|
||||||
script: sudo docker exec sharp sh -c "npm test"
|
script: sudo docker exec sharp sh -c "npm test"
|
||||||
- name: "Linux (musl) - Node 11"
|
|
||||||
os: linux
|
|
||||||
dist: trusty
|
|
||||||
sudo: true
|
|
||||||
language: minimal
|
|
||||||
before_install:
|
|
||||||
- sudo docker run -dit --name sharp --env CI --env PREBUILD_TOKEN --volume "${PWD}:/mnt/sharp" --workdir /mnt/sharp node:11-alpine
|
|
||||||
- sudo docker exec sharp apk add build-base git python2 --update-cache
|
|
||||||
install: sudo docker exec sharp sh -c "npm install --unsafe-perm"
|
|
||||||
script: sudo docker exec sharp sh -c "npm test"
|
|
||||||
- name: "Linux (musl) - Node 12"
|
- name: "Linux (musl) - Node 12"
|
||||||
os: linux
|
os: linux
|
||||||
dist: trusty
|
dist: trusty
|
||||||
@ -73,11 +51,6 @@ matrix:
|
|||||||
- sudo docker exec sharp apk add build-base git python2 --update-cache
|
- sudo docker exec sharp apk add build-base git python2 --update-cache
|
||||||
install: sudo docker exec sharp sh -c "npm install --unsafe-perm"
|
install: sudo docker exec sharp sh -c "npm install --unsafe-perm"
|
||||||
script: sudo docker exec sharp sh -c "npm test"
|
script: sudo docker exec sharp sh -c "npm test"
|
||||||
- name: "OS X - Node 6"
|
|
||||||
os: osx
|
|
||||||
osx_image: xcode9.2
|
|
||||||
language: node_js
|
|
||||||
node_js: "6"
|
|
||||||
- name: "OS X - Node 8"
|
- name: "OS X - Node 8"
|
||||||
os: osx
|
os: osx
|
||||||
osx_image: xcode9.2
|
osx_image: xcode9.2
|
||||||
@ -88,11 +61,6 @@ matrix:
|
|||||||
osx_image: xcode9.2
|
osx_image: xcode9.2
|
||||||
language: node_js
|
language: node_js
|
||||||
node_js: "10"
|
node_js: "10"
|
||||||
- name: "OS X - Node 11"
|
|
||||||
os: osx
|
|
||||||
osx_image: xcode9.2
|
|
||||||
language: node_js
|
|
||||||
node_js: "11"
|
|
||||||
- name: "OS X - Node 12"
|
- name: "OS X - Node 12"
|
||||||
os: osx
|
os: osx
|
||||||
osx_image: xcode9.2
|
osx_image: xcode9.2
|
||||||
|
@ -20,7 +20,7 @@ As well as image resizing, operations such as
|
|||||||
rotation, extraction, compositing and gamma correction are available.
|
rotation, extraction, compositing and gamma correction are available.
|
||||||
|
|
||||||
Most modern 64-bit OS X, Windows and Linux systems running
|
Most modern 64-bit OS X, Windows and Linux systems running
|
||||||
Node versions 6, 8, 10, 11 and 12
|
Node versions 8, 10 and 12
|
||||||
do not require any additional install or runtime dependencies.
|
do not require any additional install or runtime dependencies.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
@ -4,10 +4,8 @@ build: off
|
|||||||
platform: x64
|
platform: x64
|
||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- nodejs_version: "6"
|
|
||||||
- nodejs_version: "8"
|
- nodejs_version: "8"
|
||||||
- nodejs_version: "10"
|
- nodejs_version: "10"
|
||||||
- nodejs_version: "11"
|
|
||||||
- nodejs_version: "12"
|
- nodejs_version: "12"
|
||||||
install:
|
install:
|
||||||
- ps: Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) x64
|
- ps: Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) x64
|
||||||
|
14
binding.gyp
@ -97,7 +97,8 @@
|
|||||||
'conditions': [
|
'conditions': [
|
||||||
['OS == "win"', {
|
['OS == "win"', {
|
||||||
'defines': [
|
'defines': [
|
||||||
'_ALLOW_KEYWORD_MACROS'
|
'_ALLOW_KEYWORD_MACROS',
|
||||||
|
'_FILE_OFFSET_BITS=64'
|
||||||
],
|
],
|
||||||
'libraries': [
|
'libraries': [
|
||||||
'../vendor/lib/libvips.lib',
|
'../vendor/lib/libvips.lib',
|
||||||
@ -183,22 +184,15 @@
|
|||||||
'configurations': {
|
'configurations': {
|
||||||
'Release': {
|
'Release': {
|
||||||
'cflags_cc': [
|
'cflags_cc': [
|
||||||
'-Wno-cast-function-type',
|
'-Wno-cast-function-type'
|
||||||
'-Wno-deprecated-declarations'
|
|
||||||
],
|
],
|
||||||
'xcode_settings': {
|
|
||||||
'OTHER_CPLUSPLUSFLAGS': [
|
|
||||||
'-Wno-deprecated-declarations'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
'msvs_settings': {
|
'msvs_settings': {
|
||||||
'VCCLCompilerTool': {
|
'VCCLCompilerTool': {
|
||||||
'ExceptionHandling': 1
|
'ExceptionHandling': 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'msvs_disabled_warnings': [
|
'msvs_disabled_warnings': [
|
||||||
4275,
|
4275
|
||||||
4996
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,5 +1,16 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
### v0.23 - "*vision*"
|
||||||
|
|
||||||
|
Requires libvips v8.8.0.
|
||||||
|
|
||||||
|
#### v0.23.0 - TBD
|
||||||
|
|
||||||
|
* Remove `overlayWith` previously deprecated in v0.22.0.
|
||||||
|
|
||||||
|
* Drop support for Node.js versions 6 and 11.
|
||||||
|
[#1212](https://github.com/lovell/sharp/issues/1674)
|
||||||
|
|
||||||
### v0.22 - "*uptake*"
|
### v0.22 - "*uptake*"
|
||||||
|
|
||||||
Requires libvips v8.7.4.
|
Requires libvips v8.7.4.
|
||||||
|
@ -16,7 +16,7 @@ As well as image resizing, operations such as
|
|||||||
rotation, extraction, compositing and gamma correction are available.
|
rotation, extraction, compositing and gamma correction are available.
|
||||||
|
|
||||||
Most modern 64-bit OS X, Windows and Linux systems running
|
Most modern 64-bit OS X, Windows and Linux systems running
|
||||||
Node versions 6, 8, 10, 11 and 12
|
Node versions 8, 10 and 12
|
||||||
do not require any additional install or runtime dependencies.
|
do not require any additional install or runtime dependencies.
|
||||||
|
|
||||||
[](https://coveralls.io/r/lovell/sharp?branch=master)
|
[](https://coveralls.io/r/lovell/sharp?branch=master)
|
||||||
|
@ -10,12 +10,12 @@ yarn add sharp
|
|||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
* Node.js v6+
|
* Node.js v8.5.0+
|
||||||
|
|
||||||
### Building from source
|
### Building from source
|
||||||
|
|
||||||
Pre-compiled binaries for sharp are provided for use with
|
Pre-compiled binaries for sharp are provided for use with
|
||||||
Node versions 6, 8, 10, 11 and 12 on
|
Node versions 8, 10 and 12 on
|
||||||
64-bit Windows, OS X and Linux platforms.
|
64-bit Windows, OS X and Linux platforms.
|
||||||
|
|
||||||
Sharp will be built from source at install time when:
|
Sharp will be built from source at install time when:
|
||||||
@ -36,19 +36,20 @@ Building from source requires:
|
|||||||
[](https://travis-ci.org/lovell/sharp)
|
[](https://travis-ci.org/lovell/sharp)
|
||||||
|
|
||||||
libvips and its dependencies are fetched and stored within `node_modules/sharp/vendor` during `npm install`.
|
libvips and its dependencies are fetched and stored within `node_modules/sharp/vendor` during `npm install`.
|
||||||
This involves an automated HTTPS download of approximately 9MB.
|
This involves an automated HTTPS download of approximately 10MB.
|
||||||
|
|
||||||
Most Linux-based (glibc, musl) operating systems running on x64 and ARMv6+ CPUs should "just work", e.g.:
|
Most Linux-based (glibc, musl) operating systems running on x64 and ARMv6+ CPUs should "just work", e.g.:
|
||||||
|
|
||||||
* Debian 7+
|
* Debian 8+
|
||||||
* Ubuntu 14.04+
|
* Ubuntu 14.04+
|
||||||
* Centos 7+
|
* Red Hat Enterprise 8
|
||||||
* Alpine 3.8+ (Node 8+)
|
* CentOS 8
|
||||||
|
* Alpine 3.8+
|
||||||
* Fedora
|
* Fedora
|
||||||
* openSUSE 13.2+
|
* openSUSE 13.2+
|
||||||
* Archlinux
|
* Archlinux
|
||||||
* Raspbian Jessie
|
* Raspbian Jessie
|
||||||
* Amazon Linux
|
* Amazon Linux 2
|
||||||
* Solus
|
* Solus
|
||||||
|
|
||||||
To use a globally-installed version of libvips instead of the provided binaries,
|
To use a globally-installed version of libvips instead of the provided binaries,
|
||||||
@ -61,7 +62,8 @@ and `LD_LIBRARY_PATH` at runtime.
|
|||||||
|
|
||||||
This allows the use of newer versions of libvips with older versions of sharp.
|
This allows the use of newer versions of libvips with older versions of sharp.
|
||||||
|
|
||||||
For 32-bit Intel CPUs and older Linux-based operating systems such as Centos 6,
|
For 32-bit Intel CPUs and older Linux-based operating systems such as
|
||||||
|
those based on Red Hat Enterprise Linux 7 (e.g. CentOS 7, Amazon Linux 1)
|
||||||
compiling libvips from source is recommended.
|
compiling libvips from source is recommended.
|
||||||
|
|
||||||
[https://libvips.github.io/libvips/install.html#building-libvips-from-a-source-tarball](https://libvips.github.io/libvips/install.html#building-libvips-from-a-source-tarball)
|
[https://libvips.github.io/libvips/install.html#building-libvips-from-a-source-tarball](https://libvips.github.io/libvips/install.html#building-libvips-from-a-source-tarball)
|
||||||
@ -97,7 +99,7 @@ that it can be located using `pkg-config --modversion vips-cpp`.
|
|||||||
[](https://ci.appveyor.com/project/lovell/sharp)
|
[](https://ci.appveyor.com/project/lovell/sharp)
|
||||||
|
|
||||||
libvips and its dependencies are fetched and stored within `node_modules\sharp\vendor` during `npm install`.
|
libvips and its dependencies are fetched and stored within `node_modules\sharp\vendor` during `npm install`.
|
||||||
This involves an automated HTTPS download of approximately 14MB.
|
This involves an automated HTTPS download of approximately 10MB.
|
||||||
If you are having issues during installation consider removing the directory
|
If you are having issues during installation consider removing the directory
|
||||||
`C:\Users\[user]\AppData\Roaming\npm-cache\_libvips`.
|
`C:\Users\[user]\AppData\Roaming\npm-cache\_libvips`.
|
||||||
|
|
||||||
@ -150,7 +152,7 @@ docker pull tailor/docker-libvips
|
|||||||
|
|
||||||
### AWS Lambda
|
### AWS Lambda
|
||||||
|
|
||||||
Set the Lambda runtime to Node.js 8.10.
|
Set the Lambda runtime to `nodejs10.x`.
|
||||||
|
|
||||||
The binaries in the `node_modules` directory of the
|
The binaries in the `node_modules` directory of the
|
||||||
[deployment package](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-create-deployment-pkg.html)
|
[deployment package](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-create-deployment-pkg.html)
|
||||||
@ -160,14 +162,14 @@ On non-Linux machines such as OS X and Windows run the following:
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
rm -rf node_modules/sharp
|
rm -rf node_modules/sharp
|
||||||
npm install --arch=x64 --platform=linux --target=8.10.0 sharp
|
npm install --arch=x64 --platform=linux --target=10.15.0 sharp
|
||||||
```
|
```
|
||||||
|
|
||||||
Alternatively a Docker container closely matching the Lambda runtime can be used:
|
Alternatively a Docker container closely matching the Lambda runtime can be used:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
rm -rf node_modules/sharp
|
rm -rf node_modules/sharp
|
||||||
docker run -v "$PWD":/var/task lambci/lambda:build-nodejs8.10 npm install sharp
|
docker run -v "$PWD":/var/task lambci/lambda:build-nodejs10.x npm install sharp
|
||||||
```
|
```
|
||||||
|
|
||||||
To get the best performance select the largest memory available.
|
To get the best performance select the largest memory available.
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
const copyFileSync = require('fs-copy-file-sync');
|
|
||||||
const libvips = require('../lib/libvips');
|
const libvips = require('../lib/libvips');
|
||||||
const npmLog = require('npmlog');
|
const npmLog = require('npmlog');
|
||||||
|
|
||||||
@ -24,7 +23,7 @@ if (process.platform === 'win32') {
|
|||||||
return /\.dll$/.test(filename);
|
return /\.dll$/.test(filename);
|
||||||
})
|
})
|
||||||
.forEach(function (filename) {
|
.forEach(function (filename) {
|
||||||
copyFileSync(
|
fs.copyFileSync(
|
||||||
path.join(vendorLibDir, filename),
|
path.join(vendorLibDir, filename),
|
||||||
path.join(buildReleaseDir, filename)
|
path.join(buildReleaseDir, filename)
|
||||||
);
|
);
|
||||||
|
@ -9,7 +9,6 @@ const npmLog = require('npmlog');
|
|||||||
const semver = require('semver');
|
const semver = require('semver');
|
||||||
const simpleGet = require('simple-get');
|
const simpleGet = require('simple-get');
|
||||||
const tar = require('tar');
|
const tar = require('tar');
|
||||||
const copyFileSync = require('fs-copy-file-sync');
|
|
||||||
|
|
||||||
const agent = require('../lib/agent');
|
const agent = require('../lib/agent');
|
||||||
const libvips = require('../lib/libvips');
|
const libvips = require('../lib/libvips');
|
||||||
@ -64,7 +63,7 @@ try {
|
|||||||
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}`);
|
||||||
}
|
}
|
||||||
if (detectLibc.family === detectLibc.GLIBC && detectLibc.version && semver.lt(`${detectLibc.version}.0`, '2.13.0')) {
|
if (detectLibc.family === detectLibc.GLIBC && detectLibc.version && semver.lt(`${detectLibc.version}.0`, '2.19.0')) {
|
||||||
throw new Error(`Use with glibc version ${detectLibc.version} requires manual installation of libvips >= ${minimumLibvipsVersion}`);
|
throw new Error(`Use with glibc version ${detectLibc.version} requires manual installation of libvips >= ${minimumLibvipsVersion}`);
|
||||||
}
|
}
|
||||||
// Download to per-process temporary file
|
// Download to per-process temporary file
|
||||||
@ -97,7 +96,7 @@ try {
|
|||||||
fs.renameSync(tarPathTemp, tarPathCache);
|
fs.renameSync(tarPathTemp, tarPathCache);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Fall back to copy and unlink
|
// Fall back to copy and unlink
|
||||||
copyFileSync(tarPathTemp, tarPathCache);
|
fs.copyFileSync(tarPathTemp, tarPathCache);
|
||||||
fs.unlinkSync(tarPathTemp);
|
fs.unlinkSync(tarPathTemp);
|
||||||
}
|
}
|
||||||
extractTarball(tarPathCache);
|
extractTarball(tarPathCache);
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const deprecate = require('util').deprecate;
|
|
||||||
|
|
||||||
const is = require('./is');
|
const is = require('./is');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -154,21 +152,11 @@ function composite (images) {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
function overlayWith (input, options) {
|
|
||||||
const blend = (is.object(options) && options.cutout) ? 'dest-in' : 'over';
|
|
||||||
return this.composite([Object.assign({ input, blend }, options)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decorate the Sharp prototype with composite-related functions.
|
* Decorate the Sharp prototype with composite-related functions.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
module.exports = function (Sharp) {
|
module.exports = function (Sharp) {
|
||||||
Sharp.prototype.composite = composite;
|
Sharp.prototype.composite = composite;
|
||||||
Sharp.prototype.overlayWith = deprecate(overlayWith, 'overlayWith(input, options) is deprecated, use composite([{ input, ...options }]) instead');
|
|
||||||
Sharp.blend = blend;
|
Sharp.blend = blend;
|
||||||
};
|
};
|
||||||
|
23
package.json
@ -93,39 +93,38 @@
|
|||||||
"vips"
|
"vips"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"color": "^3.1.1",
|
"color": "^3.1.2",
|
||||||
"detect-libc": "^1.0.3",
|
"detect-libc": "^1.0.3",
|
||||||
"fs-copy-file-sync": "^1.1.1",
|
"nan": "^2.14.0",
|
||||||
"nan": "^2.13.2",
|
|
||||||
"npmlog": "^4.1.2",
|
"npmlog": "^4.1.2",
|
||||||
"prebuild-install": "^5.3.0",
|
"prebuild-install": "^5.3.0",
|
||||||
"semver": "^6.0.0",
|
"semver": "^6.1.2",
|
||||||
"simple-get": "^3.0.3",
|
"simple-get": "^3.0.3",
|
||||||
"tar": "^4.4.8",
|
"tar": "^4.4.10",
|
||||||
"tunnel-agent": "^0.6.0"
|
"tunnel-agent": "^0.6.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"async": "^2.6.2",
|
"async": "^3.1.0",
|
||||||
"cc": "^1.0.2",
|
"cc": "^1.0.2",
|
||||||
"decompress-zip": "^0.3.2",
|
"decompress-zip": "^0.3.2",
|
||||||
"documentation": "^10.0.0",
|
"documentation": "^11.0.1",
|
||||||
"exif-reader": "^1.0.2",
|
"exif-reader": "^1.0.2",
|
||||||
"icc": "^1.0.0",
|
"icc": "^1.0.0",
|
||||||
"license-checker": "^25.0.1",
|
"license-checker": "^25.0.1",
|
||||||
"mocha": "^6.1.4",
|
"mocha": "^6.1.4",
|
||||||
"mock-fs": "^4.9.0",
|
"mock-fs": "^4.10.1",
|
||||||
"nyc": "^14.0.0",
|
"nyc": "^14.1.1",
|
||||||
"prebuild": "^8.2.1",
|
"prebuild": "^9.0.0",
|
||||||
"prebuild-ci": "^3.0.0",
|
"prebuild-ci": "^3.0.0",
|
||||||
"rimraf": "^2.6.3",
|
"rimraf": "^2.6.3",
|
||||||
"semistandard": "^13.0.1"
|
"semistandard": "^13.0.1"
|
||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"config": {
|
"config": {
|
||||||
"libvips": "8.7.4"
|
"libvips": "8.8.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=8.5.0"
|
||||||
},
|
},
|
||||||
"semistandard": {
|
"semistandard": {
|
||||||
"env": [
|
"env": [
|
||||||
|
@ -25,8 +25,8 @@
|
|||||||
|
|
||||||
// Verify platform and compiler compatibility
|
// Verify platform and compiler compatibility
|
||||||
|
|
||||||
#if (VIPS_MAJOR_VERSION < 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 7))
|
#if (VIPS_MAJOR_VERSION < 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 8))
|
||||||
#error libvips version 8.7.0+ is required - see sharp.pixelplumbing.com/page/install
|
#error libvips version 8.8.0+ is required - see sharp.pixelplumbing.com/page/install
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)))
|
#if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)))
|
||||||
|
@ -32,8 +32,6 @@
|
|||||||
#endif /*HAVE_CONFIG_H*/
|
#endif /*HAVE_CONFIG_H*/
|
||||||
#include <vips/intl.h>
|
#include <vips/intl.h>
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <vips/vips8>
|
#include <vips/vips8>
|
||||||
|
|
||||||
VIPS_NAMESPACE_START
|
VIPS_NAMESPACE_START
|
||||||
|
@ -563,7 +563,7 @@ VImage::new_from_file( const char *name, VOption *options )
|
|||||||
}
|
}
|
||||||
|
|
||||||
VImage
|
VImage
|
||||||
VImage::new_from_buffer( void *buf, size_t len, const char *option_string,
|
VImage::new_from_buffer( const void *buf, size_t len, const char *option_string,
|
||||||
VOption *options )
|
VOption *options )
|
||||||
{
|
{
|
||||||
const char *operation_name;
|
const char *operation_name;
|
||||||
@ -588,6 +588,13 @@ VImage::new_from_buffer( void *buf, size_t len, const char *option_string,
|
|||||||
return( out );
|
return( out );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VImage
|
||||||
|
VImage::new_from_buffer( const std::string &buf, const char *option_string,
|
||||||
|
VOption *options )
|
||||||
|
{
|
||||||
|
return( new_from_buffer( buf.c_str(), buf.size(), option_string, options ) );
|
||||||
|
}
|
||||||
|
|
||||||
VImage
|
VImage
|
||||||
VImage::new_matrix( int width, int height )
|
VImage::new_matrix( int width, int height )
|
||||||
{
|
{
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include <vips/vips8>
|
#include <vips/vips8>
|
||||||
#include <node.h>
|
#include <node.h>
|
||||||
@ -30,6 +32,17 @@
|
|||||||
#include "operations.h"
|
#include "operations.h"
|
||||||
#include "pipeline.h"
|
#include "pipeline.h"
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
#define STAT64_STRUCT __stat64
|
||||||
|
#define STAT64_FUNCTION _stat64
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
#define STAT64_STRUCT stat
|
||||||
|
#define STAT64_FUNCTION stat
|
||||||
|
#else
|
||||||
|
#define STAT64_STRUCT stat64
|
||||||
|
#define STAT64_FUNCTION stat64
|
||||||
|
#endif
|
||||||
|
|
||||||
class PipelineWorker : public Nan::AsyncWorker {
|
class PipelineWorker : public Nan::AsyncWorker {
|
||||||
public:
|
public:
|
||||||
PipelineWorker(
|
PipelineWorker(
|
||||||
@ -1005,8 +1018,8 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|||||||
argv[2] = info;
|
argv[2] = info;
|
||||||
} else {
|
} else {
|
||||||
// Add file size to info
|
// Add file size to info
|
||||||
GStatBuf st;
|
struct STAT64_STRUCT st;
|
||||||
if (g_stat(baton->fileOut.data(), &st) == 0) {
|
if (STAT64_FUNCTION(baton->fileOut.data(), &st) == 0) {
|
||||||
Set(info, New("size").ToLocalChecked(), New<v8::Uint32>(static_cast<uint32_t>(st.st_size)));
|
Set(info, New("size").ToLocalChecked(), New<v8::Uint32>(static_cast<uint32_t>(st.st_size)));
|
||||||
}
|
}
|
||||||
argv[1] = info;
|
argv[1] = info;
|
||||||
|
@ -194,7 +194,7 @@ struct PipelineBaton {
|
|||||||
blurSigma(0.0),
|
blurSigma(0.0),
|
||||||
brightness(1.0),
|
brightness(1.0),
|
||||||
saturation(1.0),
|
saturation(1.0),
|
||||||
hue(0.0),
|
hue(0),
|
||||||
medianSize(0),
|
medianSize(0),
|
||||||
sharpenSigma(0.0),
|
sharpenSigma(0.0),
|
||||||
sharpenFlat(1.0),
|
sharpenFlat(1.0),
|
||||||
|
@ -115,7 +115,7 @@ class StatsWorker : public Nan::AsyncWorker {
|
|||||||
|
|
||||||
std::vector<ChannelStats>::iterator it;
|
std::vector<ChannelStats>::iterator it;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (it=baton->channelStats.begin() ; it < baton->channelStats.end(); it++, i++) {
|
for (it = baton->channelStats.begin(); it < baton->channelStats.end(); it++, i++) {
|
||||||
v8::Local<v8::Object> channelStat = New<v8::Object>();
|
v8::Local<v8::Object> channelStat = New<v8::Object>();
|
||||||
Set(channelStat, New("min").ToLocalChecked(), New<v8::Number>(it->min));
|
Set(channelStat, New("min").ToLocalChecked(), New<v8::Number>(it->min));
|
||||||
Set(channelStat, New("max").ToLocalChecked(), New<v8::Number>(it->max));
|
Set(channelStat, New("max").ToLocalChecked(), New<v8::Number>(it->max));
|
||||||
@ -127,7 +127,7 @@ class StatsWorker : public Nan::AsyncWorker {
|
|||||||
Set(channelStat, New("minY").ToLocalChecked(), New<v8::Number>(it->minY));
|
Set(channelStat, New("minY").ToLocalChecked(), New<v8::Number>(it->minY));
|
||||||
Set(channelStat, New("maxX").ToLocalChecked(), New<v8::Number>(it->maxX));
|
Set(channelStat, New("maxX").ToLocalChecked(), New<v8::Number>(it->maxX));
|
||||||
Set(channelStat, New("maxY").ToLocalChecked(), New<v8::Number>(it->maxY));
|
Set(channelStat, New("maxY").ToLocalChecked(), New<v8::Number>(it->maxY));
|
||||||
channels->Set(i, channelStat);
|
Set(channels, i, channelStat);
|
||||||
}
|
}
|
||||||
|
|
||||||
Set(info, New("channels").ToLocalChecked(), channels);
|
Set(info, New("channels").ToLocalChecked(), channels);
|
||||||
|
@ -8,17 +8,17 @@
|
|||||||
"test": "node perf && node random && node parallel"
|
"test": "node perf && node random && node parallel"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"async": "^2.6.1",
|
"async": "^3.1.0",
|
||||||
"benchmark": "^2.1.4",
|
"benchmark": "^2.1.4",
|
||||||
"gm": "^1.23.1",
|
"gm": "^1.23.1",
|
||||||
"imagemagick": "^0.1.3",
|
"imagemagick": "^0.1.3",
|
||||||
"imagemagick-native": "^1.9.3",
|
"imagemagick-native": "^1.9.3",
|
||||||
"jimp": "^0.5.3",
|
"jimp": "^0.6.4",
|
||||||
"mapnik": "^4.0.1",
|
"mapnik": "^4.2.1",
|
||||||
"semver": "^5.5.1"
|
"semver": "^6.1.2"
|
||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=8.5.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
test/fixtures/alpha-layer-1-fill-low-alpha.png
vendored
Before Width: | Height: | Size: 222 KiB |
BIN
test/fixtures/alpha-layer-2-ink-low-alpha.png
vendored
Before Width: | Height: | Size: 89 KiB |
BIN
test/fixtures/alpha-layer-2-ink.png
vendored
Before Width: | Height: | Size: 80 KiB |
Before Width: | Height: | Size: 234 KiB |
Before Width: | Height: | Size: 186 KiB |
BIN
test/fixtures/expected/alpha-layer-01-low-alpha.png
vendored
Before Width: | Height: | Size: 188 KiB |
BIN
test/fixtures/expected/alpha-layer-01.png
vendored
Before Width: | Height: | Size: 234 KiB |
Before Width: | Height: | Size: 259 KiB |
Before Width: | Height: | Size: 208 KiB |
BIN
test/fixtures/expected/alpha-layer-012-low-alpha.png
vendored
Before Width: | Height: | Size: 209 KiB |
BIN
test/fixtures/expected/alpha-layer-012.png
vendored
Before Width: | Height: | Size: 260 KiB |
Before Width: | Height: | Size: 221 KiB |
Before Width: | Height: | Size: 179 KiB |
BIN
test/fixtures/expected/alpha-layer-12-low-alpha.png
vendored
Before Width: | Height: | Size: 179 KiB |
BIN
test/fixtures/expected/alpha-layer-12.png
vendored
Before Width: | Height: | Size: 200 KiB |
BIN
test/fixtures/expected/crop-strategy-attention.jpg
vendored
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.9 KiB |
BIN
test/fixtures/expected/svg-embedded.png
vendored
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 84 KiB |
3
test/fixtures/index.js
vendored
@ -80,9 +80,6 @@ module.exports = {
|
|||||||
inputPngWithTransparency16bit: getPath('tbgn2c16.png'), // http://www.schaik.com/pngsuite/tbgn2c16.png
|
inputPngWithTransparency16bit: getPath('tbgn2c16.png'), // http://www.schaik.com/pngsuite/tbgn2c16.png
|
||||||
inputPngOverlayLayer0: getPath('alpha-layer-0-background.png'),
|
inputPngOverlayLayer0: getPath('alpha-layer-0-background.png'),
|
||||||
inputPngOverlayLayer1: getPath('alpha-layer-1-fill.png'),
|
inputPngOverlayLayer1: getPath('alpha-layer-1-fill.png'),
|
||||||
inputPngOverlayLayer2: getPath('alpha-layer-2-ink.png'),
|
|
||||||
inputPngOverlayLayer1LowAlpha: getPath('alpha-layer-1-fill-low-alpha.png'),
|
|
||||||
inputPngOverlayLayer2LowAlpha: getPath('alpha-layer-2-ink-low-alpha.png'),
|
|
||||||
inputPngAlphaPremultiplicationSmall: getPath('alpha-premultiply-1024x768-paper.png'),
|
inputPngAlphaPremultiplicationSmall: getPath('alpha-premultiply-1024x768-paper.png'),
|
||||||
inputPngAlphaPremultiplicationLarge: getPath('alpha-premultiply-2048x1536-paper.png'),
|
inputPngAlphaPremultiplicationLarge: getPath('alpha-premultiply-2048x1536-paper.png'),
|
||||||
inputPngBooleanNoAlpha: getPath('bandbool.png'),
|
inputPngBooleanNoAlpha: getPath('bandbool.png'),
|
||||||
|
@ -75,8 +75,8 @@ describe('Image metadata', function () {
|
|||||||
// XMP
|
// XMP
|
||||||
assert.strictEqual('object', typeof metadata.xmp);
|
assert.strictEqual('object', typeof metadata.xmp);
|
||||||
assert.strictEqual(true, metadata.xmp instanceof Buffer);
|
assert.strictEqual(true, metadata.xmp instanceof Buffer);
|
||||||
assert.strictEqual(12495, metadata.xmp.byteLength);
|
assert.strictEqual(12466, metadata.xmp.byteLength);
|
||||||
assert.strictEqual(metadata.xmp.indexOf(Buffer.from('http://ns.adobe.com/xap/1.0')), 0);
|
assert.strictEqual(metadata.xmp.indexOf(Buffer.from('<?xpacket begin="')), 0);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,589 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const fs = require('fs');
|
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
const fixtures = require('../fixtures');
|
|
||||||
const sharp = require('../../');
|
|
||||||
|
|
||||||
// Helpers
|
|
||||||
const getPaths = function (baseName, extension) {
|
|
||||||
if (typeof extension === 'undefined') {
|
|
||||||
extension = 'png';
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
actual: fixtures.path('output.' + baseName + '.' + extension),
|
|
||||||
expected: fixtures.expected(baseName + '.' + extension)
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Test
|
|
||||||
describe('Overlays', function () {
|
|
||||||
it('Overlay transparent PNG file on solid background', function (done) {
|
|
||||||
const paths = getPaths('alpha-layer-01');
|
|
||||||
|
|
||||||
sharp(fixtures.inputPngOverlayLayer0)
|
|
||||||
.overlayWith(fixtures.inputPngOverlayLayer1)
|
|
||||||
.toFile(paths.actual, function (error) {
|
|
||||||
if (error) return done(error);
|
|
||||||
fixtures.assertMaxColourDistance(paths.actual, paths.expected);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Overlay transparent PNG Buffer on solid background', function (done) {
|
|
||||||
const paths = getPaths('alpha-layer-01');
|
|
||||||
|
|
||||||
sharp(fixtures.inputPngOverlayLayer0)
|
|
||||||
.overlayWith(fs.readFileSync(fixtures.inputPngOverlayLayer1))
|
|
||||||
.toFile(paths.actual, function (error) {
|
|
||||||
if (error) return done(error);
|
|
||||||
fixtures.assertMaxColourDistance(paths.actual, paths.expected);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Overlay low-alpha transparent PNG on solid background', function (done) {
|
|
||||||
const paths = getPaths('alpha-layer-01-low-alpha');
|
|
||||||
|
|
||||||
sharp(fixtures.inputPngOverlayLayer0)
|
|
||||||
.overlayWith(fixtures.inputPngOverlayLayer1LowAlpha)
|
|
||||||
.toFile(paths.actual, function (error) {
|
|
||||||
if (error) return done(error);
|
|
||||||
fixtures.assertMaxColourDistance(paths.actual, paths.expected);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Composite three transparent PNGs into one', function (done) {
|
|
||||||
const paths = getPaths('alpha-layer-012');
|
|
||||||
|
|
||||||
sharp(fixtures.inputPngOverlayLayer0)
|
|
||||||
.overlayWith(fixtures.inputPngOverlayLayer1)
|
|
||||||
.toBuffer(function (error, data) {
|
|
||||||
if (error) return done(error);
|
|
||||||
sharp(data)
|
|
||||||
.overlayWith(fixtures.inputPngOverlayLayer2)
|
|
||||||
.toFile(paths.actual, function (error) {
|
|
||||||
if (error) return done(error);
|
|
||||||
fixtures.assertMaxColourDistance(paths.actual, paths.expected);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Composite two transparent PNGs into one', function (done) {
|
|
||||||
const paths = getPaths('alpha-layer-12');
|
|
||||||
|
|
||||||
sharp(fixtures.inputPngOverlayLayer1)
|
|
||||||
.overlayWith(fixtures.inputPngOverlayLayer2)
|
|
||||||
.toFile(paths.actual, function (error) {
|
|
||||||
if (error) return done(error);
|
|
||||||
fixtures.assertMaxColourDistance(paths.actual, paths.expected);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Composite two low-alpha transparent PNGs into one', function (done) {
|
|
||||||
const paths = getPaths('alpha-layer-12-low-alpha');
|
|
||||||
|
|
||||||
sharp(fixtures.inputPngOverlayLayer1LowAlpha)
|
|
||||||
.overlayWith(fixtures.inputPngOverlayLayer2LowAlpha)
|
|
||||||
.toFile(paths.actual, function (error) {
|
|
||||||
if (error) return done(error);
|
|
||||||
fixtures.assertMaxColourDistance(paths.actual, paths.expected, 2);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Composite three low-alpha transparent PNGs into one', function (done) {
|
|
||||||
const paths = getPaths('alpha-layer-012-low-alpha');
|
|
||||||
|
|
||||||
sharp(fixtures.inputPngOverlayLayer0)
|
|
||||||
.overlayWith(fixtures.inputPngOverlayLayer1LowAlpha)
|
|
||||||
.toBuffer(function (error, data) {
|
|
||||||
if (error) return done(error);
|
|
||||||
|
|
||||||
sharp(data)
|
|
||||||
.overlayWith(fixtures.inputPngOverlayLayer2LowAlpha)
|
|
||||||
.toFile(paths.actual, function (error) {
|
|
||||||
if (error) return done(error);
|
|
||||||
fixtures.assertMaxColourDistance(paths.actual, paths.expected);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Composite rgb+alpha PNG onto JPEG', function (done) {
|
|
||||||
const paths = getPaths('overlay-jpeg-with-rgb', 'jpg');
|
|
||||||
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.resize(2048, 1536)
|
|
||||||
.overlayWith(fixtures.inputPngOverlayLayer1)
|
|
||||||
.toFile(paths.actual, function (error, info) {
|
|
||||||
if (error) return done(error);
|
|
||||||
fixtures.assertMaxColourDistance(paths.actual, paths.expected, 102);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Composite greyscale+alpha PNG onto JPEG', function (done) {
|
|
||||||
const paths = getPaths('overlay-jpeg-with-greyscale', 'jpg');
|
|
||||||
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.resize(400, 300)
|
|
||||||
.overlayWith(fixtures.inputPngWithGreyAlpha)
|
|
||||||
.toFile(paths.actual, function (error, info) {
|
|
||||||
if (error) return done(error);
|
|
||||||
fixtures.assertMaxColourDistance(paths.actual, paths.expected, 102);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Composite WebP onto JPEG', function (done) {
|
|
||||||
const paths = getPaths('overlay-jpeg-with-webp', 'jpg');
|
|
||||||
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.resize(300, 300)
|
|
||||||
.overlayWith(fixtures.inputWebPWithTransparency)
|
|
||||||
.toFile(paths.actual, function (error, info) {
|
|
||||||
if (error) return done(error);
|
|
||||||
fixtures.assertMaxColourDistance(paths.actual, paths.expected, 102);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Composite JPEG onto PNG, ensure premultiply', function (done) {
|
|
||||||
sharp(fixtures.inputPngOverlayLayer1)
|
|
||||||
.overlayWith(fixtures.inputJpgWithLandscapeExif1)
|
|
||||||
.toBuffer(function (err, data, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
assert.strictEqual(true, info.premultiplied);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Composite opaque JPEG onto JPEG, ensure premultiply', function (done) {
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.overlayWith(fixtures.inputJpgWithLandscapeExif1)
|
|
||||||
.toBuffer(function (err, data, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
assert.strictEqual(true, info.premultiplied);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Fail when overlay is larger', function (done) {
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.resize(320)
|
|
||||||
.overlayWith(fixtures.inputPngOverlayLayer1)
|
|
||||||
.toBuffer(function (error) {
|
|
||||||
assert.strictEqual(true, error instanceof Error);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Fail with empty String parameter', function () {
|
|
||||||
assert.throws(function () {
|
|
||||||
sharp().overlayWith('');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Fail with non-String parameter', function () {
|
|
||||||
assert.throws(function () {
|
|
||||||
sharp().overlayWith(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Fail with unsupported gravity', function () {
|
|
||||||
assert.throws(function () {
|
|
||||||
sharp()
|
|
||||||
.overlayWith(fixtures.inputPngOverlayLayer1, {
|
|
||||||
gravity: 9
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Empty options', function () {
|
|
||||||
assert.doesNotThrow(function () {
|
|
||||||
sharp().overlayWith(fixtures.inputPngOverlayLayer1, {});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Overlay with numeric gravity', function () {
|
|
||||||
Object.keys(sharp.gravity).forEach(function (gravity) {
|
|
||||||
it(gravity, function (done) {
|
|
||||||
const expected = fixtures.expected('overlay-gravity-' + gravity + '.jpg');
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.resize(80)
|
|
||||||
.overlayWith(fixtures.inputPngWithTransparency16bit, {
|
|
||||||
gravity: gravity
|
|
||||||
})
|
|
||||||
.toBuffer(function (err, data, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
assert.strictEqual('jpeg', info.format);
|
|
||||||
assert.strictEqual(80, info.width);
|
|
||||||
assert.strictEqual(65, info.height);
|
|
||||||
assert.strictEqual(3, info.channels);
|
|
||||||
fixtures.assertSimilar(expected, data, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Overlay with string-based gravity', function () {
|
|
||||||
Object.keys(sharp.gravity).forEach(function (gravity) {
|
|
||||||
it(gravity, function (done) {
|
|
||||||
const expected = fixtures.expected('overlay-gravity-' + gravity + '.jpg');
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.resize(80)
|
|
||||||
.overlayWith(fixtures.inputPngWithTransparency16bit, {
|
|
||||||
gravity: sharp.gravity[gravity]
|
|
||||||
})
|
|
||||||
.toBuffer(function (err, data, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
assert.strictEqual('jpeg', info.format);
|
|
||||||
assert.strictEqual(80, info.width);
|
|
||||||
assert.strictEqual(65, info.height);
|
|
||||||
assert.strictEqual(3, info.channels);
|
|
||||||
fixtures.assertSimilar(expected, data, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Overlay with tile enabled and gravity', function () {
|
|
||||||
Object.keys(sharp.gravity).forEach(function (gravity) {
|
|
||||||
it(gravity, function (done) {
|
|
||||||
const expected = fixtures.expected('overlay-tile-gravity-' + gravity + '.jpg');
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.resize(80)
|
|
||||||
.overlayWith(fixtures.inputPngWithTransparency16bit, {
|
|
||||||
tile: true,
|
|
||||||
gravity: gravity
|
|
||||||
})
|
|
||||||
.toBuffer(function (err, data, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
assert.strictEqual('jpeg', info.format);
|
|
||||||
assert.strictEqual(80, info.width);
|
|
||||||
assert.strictEqual(65, info.height);
|
|
||||||
assert.strictEqual(3, info.channels);
|
|
||||||
fixtures.assertSimilar(expected, data, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Overlay with top-left offsets', function () {
|
|
||||||
it('Overlay with 10px top & 10px left offsets', function (done) {
|
|
||||||
const expected = fixtures.expected('overlay-valid-offsets-10-10.jpg');
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.resize(400)
|
|
||||||
.overlayWith(fixtures.inputPngWithTransparency16bit, {
|
|
||||||
top: 10,
|
|
||||||
left: 10
|
|
||||||
})
|
|
||||||
.toBuffer(function (err, data, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
assert.strictEqual('jpeg', info.format);
|
|
||||||
assert.strictEqual(3, info.channels);
|
|
||||||
fixtures.assertSimilar(expected, data, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Overlay with 100px top & 300px left offsets', function (done) {
|
|
||||||
const expected = fixtures.expected('overlay-valid-offsets-100-300.jpg');
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.resize(400)
|
|
||||||
.overlayWith(fixtures.inputPngWithTransparency16bit, {
|
|
||||||
top: 100,
|
|
||||||
left: 300
|
|
||||||
})
|
|
||||||
.toBuffer(function (err, data, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
assert.strictEqual('jpeg', info.format);
|
|
||||||
assert.strictEqual(3, info.channels);
|
|
||||||
fixtures.assertSimilar(expected, data, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Overlay with only top offset', function () {
|
|
||||||
assert.throws(function () {
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.resize(400)
|
|
||||||
.overlayWith(fixtures.inputPngWithTransparency16bit, {
|
|
||||||
top: 1000
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Overlay with only left offset', function () {
|
|
||||||
assert.throws(function () {
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.resize(400)
|
|
||||||
.overlayWith(fixtures.inputPngWithTransparency16bit, {
|
|
||||||
left: 1000
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Overlay with negative offsets', function () {
|
|
||||||
assert.throws(function () {
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.resize(400)
|
|
||||||
.overlayWith(fixtures.inputPngWithTransparency16bit, {
|
|
||||||
top: -1000,
|
|
||||||
left: -1000
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Overlay with 0 offset', function (done) {
|
|
||||||
const expected = fixtures.expected('overlay-offset-0.jpg');
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.resize(400)
|
|
||||||
.overlayWith(fixtures.inputPngWithTransparency16bit, {
|
|
||||||
top: 0,
|
|
||||||
left: 0
|
|
||||||
})
|
|
||||||
.toBuffer(function (err, data, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
assert.strictEqual('jpeg', info.format);
|
|
||||||
assert.strictEqual(3, info.channels);
|
|
||||||
fixtures.assertSimilar(expected, data, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Overlay with offset and gravity', function (done) {
|
|
||||||
const expected = fixtures.expected('overlay-offset-with-gravity.jpg');
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.resize(400)
|
|
||||||
.overlayWith(fixtures.inputPngWithTransparency16bit, {
|
|
||||||
left: 10,
|
|
||||||
top: 10,
|
|
||||||
gravity: 4
|
|
||||||
|
|
||||||
})
|
|
||||||
.toBuffer(function (err, data, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
assert.strictEqual('jpeg', info.format);
|
|
||||||
assert.strictEqual(3, info.channels);
|
|
||||||
fixtures.assertSimilar(expected, data, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Overlay with offset and gravity and tile', function (done) {
|
|
||||||
const expected = fixtures.expected('overlay-offset-with-gravity-tile.jpg');
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.resize(400)
|
|
||||||
.overlayWith(fixtures.inputPngWithTransparency16bit, {
|
|
||||||
left: 10,
|
|
||||||
top: 10,
|
|
||||||
gravity: 4,
|
|
||||||
tile: true
|
|
||||||
})
|
|
||||||
.toBuffer(function (err, data, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
assert.strictEqual('jpeg', info.format);
|
|
||||||
assert.strictEqual(3, info.channels);
|
|
||||||
fixtures.assertSimilar(expected, data, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Overlay with offset and tile', function (done) {
|
|
||||||
const expected = fixtures.expected('overlay-offset-with-tile.jpg');
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.resize(400)
|
|
||||||
.overlayWith(fixtures.inputPngWithTransparency16bit, {
|
|
||||||
left: 10,
|
|
||||||
top: 10,
|
|
||||||
tile: true
|
|
||||||
})
|
|
||||||
.toBuffer(function (err, data, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
assert.strictEqual('jpeg', info.format);
|
|
||||||
assert.strictEqual(3, info.channels);
|
|
||||||
fixtures.assertSimilar(expected, data, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Overlay with invalid tile option', function () {
|
|
||||||
assert.throws(function () {
|
|
||||||
sharp().overlayWith('ignore', { tile: 1 });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Overlay with very large offset', function (done) {
|
|
||||||
const expected = fixtures.expected('overlay-very-large-offset.jpg');
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.resize(400)
|
|
||||||
.overlayWith(fixtures.inputPngWithTransparency16bit, {
|
|
||||||
left: 10000,
|
|
||||||
top: 10000
|
|
||||||
})
|
|
||||||
.toBuffer(function (err, data, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
assert.strictEqual('jpeg', info.format);
|
|
||||||
assert.strictEqual(3, info.channels);
|
|
||||||
fixtures.assertSimilar(expected, data, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Overlay 100x100 with 50x50 so bottom edges meet', function (done) {
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.resize(50, 50)
|
|
||||||
.toBuffer(function (err, overlay) {
|
|
||||||
if (err) throw err;
|
|
||||||
sharp(fixtures.inputJpgWithLandscapeExif1)
|
|
||||||
.resize(100, 100)
|
|
||||||
.overlayWith(overlay, {
|
|
||||||
top: 50,
|
|
||||||
left: 40
|
|
||||||
})
|
|
||||||
.toBuffer(function (err, data, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
assert.strictEqual('jpeg', info.format);
|
|
||||||
assert.strictEqual(100, info.width);
|
|
||||||
assert.strictEqual(100, info.height);
|
|
||||||
fixtures.assertSimilar(fixtures.expected('overlay-bottom-edges-meet.jpg'), data, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('With tile enabled and image rotated 90 degrees', function (done) {
|
|
||||||
const expected = fixtures.expected('overlay-tile-rotated90.jpg');
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.rotate(90)
|
|
||||||
.resize(80)
|
|
||||||
.overlayWith(fixtures.inputPngWithTransparency16bit, {
|
|
||||||
tile: true
|
|
||||||
})
|
|
||||||
.toBuffer(function (err, data, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
assert.strictEqual('jpeg', info.format);
|
|
||||||
assert.strictEqual(80, info.width);
|
|
||||||
assert.strictEqual(98, info.height);
|
|
||||||
assert.strictEqual(3, info.channels);
|
|
||||||
fixtures.assertSimilar(expected, data, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('With tile enabled and image rotated 90 degrees and gravity northwest', function (done) {
|
|
||||||
const expected = fixtures.expected('overlay-tile-rotated90-gravity-northwest.jpg');
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.rotate(90)
|
|
||||||
.resize(80)
|
|
||||||
.overlayWith(fixtures.inputPngWithTransparency16bit, {
|
|
||||||
tile: true,
|
|
||||||
gravity: 'northwest'
|
|
||||||
})
|
|
||||||
.toBuffer(function (err, data, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
assert.strictEqual('jpeg', info.format);
|
|
||||||
assert.strictEqual(80, info.width);
|
|
||||||
assert.strictEqual(98, info.height);
|
|
||||||
assert.strictEqual(3, info.channels);
|
|
||||||
fixtures.assertSimilar(expected, data, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Overlay with cutout enabled and gravity', function () {
|
|
||||||
Object.keys(sharp.gravity).forEach(function (gravity) {
|
|
||||||
it(gravity, function (done) {
|
|
||||||
const expected = fixtures.expected('overlay-cutout-gravity-' + gravity + '.jpg');
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.resize(80)
|
|
||||||
.overlayWith(fixtures.inputPngWithTransparency16bit, {
|
|
||||||
cutout: true,
|
|
||||||
gravity: gravity
|
|
||||||
})
|
|
||||||
.toBuffer(function (err, data, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
assert.strictEqual('jpeg', info.format);
|
|
||||||
assert.strictEqual(80, info.width);
|
|
||||||
assert.strictEqual(65, info.height);
|
|
||||||
assert.strictEqual(3, info.channels);
|
|
||||||
fixtures.assertSimilar(expected, data, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('With cutout enabled and image rotated 90 degrees', function (done) {
|
|
||||||
const expected = fixtures.expected('overlay-cutout-rotated90.jpg');
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.rotate(90)
|
|
||||||
.resize(80)
|
|
||||||
.overlayWith(fixtures.inputPngWithTransparency16bit, {
|
|
||||||
cutout: true
|
|
||||||
})
|
|
||||||
.toBuffer(function (err, data, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
assert.strictEqual('jpeg', info.format);
|
|
||||||
assert.strictEqual(80, info.width);
|
|
||||||
assert.strictEqual(98, info.height);
|
|
||||||
assert.strictEqual(3, info.channels);
|
|
||||||
fixtures.assertSimilar(expected, data, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('With cutout enabled and image rotated 90 degrees and gravity northwest', function (done) {
|
|
||||||
const expected = fixtures.expected('overlay-cutout-rotated90-gravity-northwest.jpg');
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.rotate(90)
|
|
||||||
.resize(80)
|
|
||||||
.overlayWith(fixtures.inputPngWithTransparency16bit, {
|
|
||||||
cutout: true,
|
|
||||||
gravity: 'northwest'
|
|
||||||
})
|
|
||||||
.toBuffer(function (err, data, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
assert.strictEqual('jpeg', info.format);
|
|
||||||
assert.strictEqual(80, info.width);
|
|
||||||
assert.strictEqual(98, info.height);
|
|
||||||
assert.strictEqual(3, info.channels);
|
|
||||||
fixtures.assertSimilar(expected, data, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Composite RGBA raw buffer onto JPEG', function (done) {
|
|
||||||
sharp(fixtures.inputPngOverlayLayer1)
|
|
||||||
.raw()
|
|
||||||
.toBuffer(function (err, data, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.resize(2048, 1536)
|
|
||||||
.overlayWith(data, { raw: info })
|
|
||||||
.toBuffer(function (err, data, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
assert.strictEqual(true, info.premultiplied);
|
|
||||||
fixtures.assertSimilar(fixtures.expected('overlay-jpeg-with-rgb.jpg'), data, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Returns an error when called with an invalid file', function (done) {
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.overlayWith('notfound.png')
|
|
||||||
.toBuffer(function (err) {
|
|
||||||
assert(err instanceof Error);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Composite JPEG onto JPEG', function (done) {
|
|
||||||
sharp(fixtures.inputJpg)
|
|
||||||
.resize(480, 320)
|
|
||||||
.overlayWith(fixtures.inputJpgBooleanTest)
|
|
||||||
.toBuffer(function (err, data, info) {
|
|
||||||
if (err) throw err;
|
|
||||||
assert.strictEqual('jpeg', info.format);
|
|
||||||
assert.strictEqual(480, info.width);
|
|
||||||
assert.strictEqual(320, info.height);
|
|
||||||
assert.strictEqual(3, info.channels);
|
|
||||||
assert.strictEqual(true, info.premultiplied);
|
|
||||||
fixtures.assertSimilar(fixtures.expected('overlay-jpeg-with-jpeg.jpg'), data, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -338,7 +338,7 @@ describe('Resize fit=cover', function () {
|
|||||||
assert.strictEqual(3, info.channels);
|
assert.strictEqual(3, info.channels);
|
||||||
assert.strictEqual(80, info.width);
|
assert.strictEqual(80, info.width);
|
||||||
assert.strictEqual(320, info.height);
|
assert.strictEqual(320, info.height);
|
||||||
assert.strictEqual(-143, info.cropOffsetLeft);
|
assert.strictEqual(-107, info.cropOffsetLeft);
|
||||||
assert.strictEqual(0, info.cropOffsetTop);
|
assert.strictEqual(0, info.cropOffsetTop);
|
||||||
fixtures.assertSimilar(fixtures.expected('crop-strategy-attention.jpg'), data, done);
|
fixtures.assertSimilar(fixtures.expected('crop-strategy-attention.jpg'), data, done);
|
||||||
});
|
});
|
||||||
|
@ -109,7 +109,7 @@ describe('TIFF', function () {
|
|||||||
.toFile(fixtures.outputTiff, (err, info) => {
|
.toFile(fixtures.outputTiff, (err, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('tiff', info.format);
|
assert.strictEqual('tiff', info.format);
|
||||||
assert(info.size === startSize);
|
assert.strictEqual(startSize, info.size);
|
||||||
rimraf(fixtures.outputTiff, done);
|
rimraf(fixtures.outputTiff, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|