Compare commits

...

127 Commits

Author SHA1 Message Date
Lovell Fuller
5bed3a7d52 Release v0.20.7 2018-08-21 11:50:14 +01:00
Lovell Fuller
ece111280b Use copy+unlink if rename fails during install #1345 2018-08-20 15:14:31 +01:00
Lovell Fuller
a15a9b956b Release v0.20.6 2018-08-20 11:40:10 +01:00
Lovell Fuller
42860c2f83 Changelog, credit and doc refresh for #1342 2018-08-19 10:43:25 +01:00
Alun Davies
b5b95e5ae1 Expose depth option for tile-based output (#1342) 2018-08-18 15:09:53 +01:00
Lovell Fuller
d705cffdd6 Ensure extractChannel works with 16-bit images #1330 2018-08-12 20:22:39 +01:00
Rodrigo Alviani
23a4bc103e Docs: correct quality option in overlayWith example (#1325) 2018-08-08 08:42:18 +01:00
Lovell Fuller
c14434f9e7 Add removeAlpha op, removes alpha channel if any #1248 2018-08-07 20:32:11 +01:00
Lovell Fuller
25bd2cea3e Add experimental entropy field to stats response 2018-08-06 15:41:27 +01:00
Lovell Fuller
532de4ecab Cache libvips binaries to reduce re-install time #1301 2018-08-05 10:31:41 +01:00
Lovell Fuller
bfdd27eeef Doc refresh and dependency bumps 2018-08-05 09:42:09 +01:00
Lovell Fuller
bd9f238ab4 Improve install time error messages for FreeBSD #1310 2018-08-04 22:27:32 +01:00
Lovell Fuller
75556bb57c Ensure vendor platform mismatch throws error #1303 2018-08-04 21:34:11 +01:00
thegareth
2de062a34a Docs: update the "make a transparent image" example (#1316)
Alpha for colour is between 0-1, not 0-255.
2018-08-02 09:42:25 +01:00
Lovell Fuller
4589b15dea Changelog and credit for #1285 #1290 2018-07-10 16:12:16 +01:00
Sylvain Dumont
8b75ce6786 Allow full WebP alphaQuality range of 0-100 (#1290) 2018-07-10 15:58:17 +01:00
Espen Hovlandsdal
7bbc5176a1 Expose mozjpeg quant_table flag (#1285) 2018-07-10 15:56:05 +01:00
Lovell Fuller
5cb35485f1 Release v0.20.5 2018-06-27 08:44:31 +01:00
Lovell Fuller
80189ed689 Add changelog and credit for #1265 2018-06-27 07:54:41 +01:00
Muhammad Faheem Akhtar
3d7e8ef432 Docs: update new Buffer() to Buffer.from() (#1273) 2018-06-26 08:19:27 +01:00
Lovell Fuller
1999c7103c Docs: add CSS to improve left-hand nav nesting 2018-06-25 19:58:50 +01:00
Thomas Vantuycom
9c20ae383e Remove top of file table of contents in documentation (#1270) 2018-06-24 21:45:51 +01:00
Tom Lokhorst
76c41eaf05 Expose libjpeg optimize_coding flag (#1265) 2018-06-21 18:12:10 +01:00
Lovell Fuller
873aa6700f Release v0.20.4 2018-06-20 08:26:28 +01:00
Lovell Fuller
0d9590a9a0 Documentation refresh 2018-06-20 08:14:03 +01:00
Lovell Fuller
94607b585a Ensure extractChannel sets bw colourspace interp #1257 2018-06-19 22:47:52 +01:00
Lovell Fuller
da0b0348a2 Prevent rounding err with shrink-on-load and 90/270 rot #1241 2018-06-19 21:19:34 +01:00
Lovell Fuller
09263455b5 Release v0.20.3 2018-05-29 08:38:42 +01:00
Lovell Fuller
ddc23493d4 Add warning about possible concurrent tile race #1151 2018-05-25 19:53:23 +01:00
Lovell Fuller
54a71fc142 Fix tint op by ensuring LAB and allowing negative values #1235
Add test cases for more tint colours and input interpretations
2018-05-23 20:51:47 +01:00
Lovell Fuller
b1a9bf10a2 Pre-built binaries provided for even-numbered major versions 2018-05-21 11:44:34 +01:00
Lovell Fuller
97cfbe1b63 Bump dependency versions 2018-05-19 15:19:23 +01:00
Lovell Fuller
0ee8c63551 Replace use of libvips API deprecated since v8.6.1
See jcupitt/libvips@b085908
2018-05-19 15:03:50 +01:00
Lovell Fuller
0ac5a9ad82 Promote nw.js details to main installation docs - see 6e51f2d 2018-05-19 14:53:22 +01:00
Michael
6e51f2d608 rebuild doc for NW.js (#1229)
refers to https://github.com/lovell/sharp/issues/1223
2018-05-15 07:28:09 +01:00
Lovell Fuller
f23a8dc9dc Release v0.20.2 2018-04-28 18:29:32 +01:00
Lovell Fuller
d09fe6178c Add support for Node 10, drop support for Node 9 2018-04-28 18:12:10 +01:00
Lovell Fuller
ae2cfcc4f3 Version bumps, hold simple-get at v2 for Node 4 support 2018-04-28 18:11:20 +01:00
Lovell Fuller
853cc65e32 Changelog entry for #1208 2018-04-28 14:06:45 +01:00
Nathan Graves
5d140d949f Add support for Group4 (CCITTFAX4) compression to TIFF output (#1208) 2018-04-26 19:49:08 +01:00
Lovell Fuller
6d2da2b3ba Switch unzip test dependency for Node 10 support 2018-04-25 20:37:10 +01:00
Lovell Fuller
165e337e44 Changelog entry and doc refresh for #1204 2018-04-25 10:19:33 +01:00
Nathan Graves
b154cd0418 Add support for page selection with multi-page TIFF input (#1204) 2018-04-24 22:57:27 +01:00
Lovell Fuller
8ef1532691 Dependency version bumps 2018-04-17 20:46:22 +01:00
Lovell Fuller
771e44f2a7 Add error highlighting lack of Windows x86 node.exe support 2018-04-17 20:37:19 +01:00
Lovell Fuller
8933f1128d Changelog entry and credit for #1165 2018-04-11 20:30:16 +01:00
Rik Heywood
dbac4b9a63 Add tint operation to set image chroma 2018-04-11 20:05:48 +01:00
Lovell Fuller
bdac5b5807 Add code usage examples for output-related functions 2018-04-06 19:52:00 +01:00
Lovell Fuller
b0961b5213 Bump dependencies 2018-04-06 19:49:17 +01:00
Thomas Parisot
0d7c3fc4d8 Ignore global libvips during install via SHARP_IGNORE_GLOBAL_LIBVIPS (#1165) 2018-03-22 18:48:30 +00:00
Lovell Fuller
8dac256096 Release v0.20.1 2018-03-17 14:04:35 +00:00
Lovell Fuller
8320da39c3 Changelog entry and doc refresh for #1161 2018-03-17 11:12:43 +00:00
Andrea Bianco
875937e3d8 Expose libvips' median filter operation (#1161) 2018-03-17 10:52:44 +00:00
Lovell Fuller
f880adbaac Bump dependencies ahead of v0.20.1 2018-03-16 20:46:08 +00:00
Lovell Fuller
48c5f86adb Improve install when global libvips below min version #1148 2018-03-13 20:37:42 +00:00
Lovell Fuller
f60f7dab12 Prevent error when cumulative rounding below target #1154 2018-03-13 19:42:10 +00:00
Lovell Fuller
8f690236ed Release v0.20.0 2018-03-04 21:54:28 +00:00
Lovell Fuller
430a4297aa Add support for prebuilt sharp binaries on common platforms 2018-03-04 14:33:44 +00:00
Oskar Thornblad
69e3ab02c4 Mention EXIF orientation in metadata's jsdocs (#1142) 2018-03-04 14:19:53 +00:00
Lovell Fuller
b87a20b881 Release v0.19.1 2018-02-24 10:02:12 +00:00
Lovell Fuller
0e6f2d16ab Bump dependencies 2018-02-23 19:27:34 +00:00
Lovell Fuller
498b061819 Upgrade nan dependency, enables async hooks 2018-02-23 19:18:31 +00:00
Lovell Fuller
5ab6f599fb Prevent crop when at or below target dimensions #1134 2018-02-23 10:31:11 +00:00
Lovell Fuller
8b80626035 Changelog, credit and doc refresh for #1121 2018-02-18 19:14:37 +00:00
Andrea Bianco
f86ae79fdb Expose angle option in tile feature (#1121) 2018-02-18 20:00:08 +01:00
Lovell Fuller
1a4e68096f Changelog and credit for #1024, bump dependencies 2018-02-04 13:30:47 +00:00
Marcel
d599d1f29e Expose linear transform feature of libvips (#1024) 2018-02-04 10:36:04 +00:00
Lovell Fuller
73edfb3d2c Update list of files that npm can ignore 2018-01-13 10:28:31 +00:00
Lovell Fuller
ebae68d579 Doc refresh for #1077 2018-01-13 10:27:43 +00:00
Tony Mobily
573836e2b8 Add mention of max() to preserve ratio in withoutEnlargement (#1077) 2018-01-13 09:59:59 +00:00
Lovell Fuller
da5deb8177 Release v0.19.0 2018-01-11 22:31:51 +00:00
Lovell Fuller
8fca89e876 Update documentation hostname 2018-01-10 23:35:50 +00:00
Lovell Fuller
d5295a2d0c Doc refresh for #1079 2018-01-10 22:24:46 +00:00
Oleg Aleynik
c4df115948 Expose IPTC and XMP metadata when available (#1079) 2018-01-10 22:12:11 +00:00
Lovell Fuller
8afcb16d8e Update performance benchmark results for v0.19.0 2018-01-07 14:30:25 +00:00
Lovell Fuller
3764d63244 Add valgrind suppressions for Node 8 2018-01-06 13:39:26 +00:00
Lovell Fuller
c82914df30 Doc refresh and devDependencies version bumps 2018-01-06 00:07:35 +00:00
Lovell Fuller
84ba921f5b Unpin tar dep as race condition is fixed - see 053e727 2018-01-05 10:51:24 +00:00
Lovell Fuller
8e74668e3c Update linter plus related spacing fixes 2018-01-05 10:18:08 +00:00
Lovell Fuller
707c05b5f5 Update libvips dependency minimum to v8.6.1 2018-01-05 09:57:33 +00:00
Lovell Fuller
9bd2cec199 Update benchmark test dependencies 2018-01-02 20:19:11 +00:00
Lovell Fuller
358b8fe8b6 Refresh Lambda install docs to recommend use of Docker 2017-12-22 19:31:03 +00:00
Lovell Fuller
7115ae5375 Prevent toFile ext taking precedence over toFormat #1037 2017-12-20 20:33:08 +00:00
Lovell Fuller
13997ca653 Run unit test files sequentially through valgrind 2017-12-18 19:57:26 +00:00
Lovell Fuller
9fa04a0b93 Attach event listener to clone only for Stream #995 2017-12-12 21:53:27 +00:00
Lovell Fuller
0894145284 Changelog and doc refresh for #1038 2017-12-12 19:42:07 +00:00
Kenric D'Souza
927b77700d Add gravity support to embed feature (#1038) 2017-12-12 19:29:16 +00:00
Lovell Fuller
1d7a0ea99e Changelog and doc refresh for #915 2017-12-09 13:14:23 +00:00
Rahul Nanwani
d6aee8e5ba Add pixel-derived image statistics via vips_stats (#915) 2017-12-09 11:17:48 +00:00
Lovell Fuller
dfaa39fa5d Enable OS X CI 2017-12-09 10:47:02 +00:00
Lovell Fuller
8fe3b59efe Update test fixtures for e9b7231ac0 2017-12-08 17:54:39 +00:00
Lovell Fuller
47237b1f15 Add expected min libvips version to error messages 2017-12-07 23:16:33 +00:00
Lovell Fuller
053e727bd5 Pin tar dependency as latest version has a race condition with Node 4 2017-12-01 19:00:28 +00:00
Lovell Fuller
2ce9e81d80 Wait for close event before decompressing tarball
Should reduce the chance of a race condition
2017-11-30 20:29:18 +00:00
Lovell Fuller
50848ee462 Add unit test coverage report for C++ 2017-11-30 20:16:30 +00:00
Lovell Fuller
ef06d560cd Windows CI: retry npm install to workaround race condition 2017-11-30 20:12:14 +00:00
Lovell Fuller
2abf9f96c7 Force TIFF predictor=none to match fixture in squash tests 2017-11-27 19:55:20 +00:00
Lovell Fuller
a91686b4cd Temporarily revert to previous npm for Node 9 support 2017-11-27 19:38:44 +00:00
Lovell Fuller
1be424cd47 Add missing file from commit fc233ed 2017-11-27 19:35:08 +00:00
Lovell Fuller
929ea10f76 Re-enable test for 1200 DPI SVG rasterisation to PNG 2017-11-27 19:31:31 +00:00
Lovell Fuller
11d1f39e3d Add Node 9 to CI test environments 2017-11-27 19:15:09 +00:00
Lovell Fuller
fc233ed4ff Update upstream libvips source to v8.6.0-beta1 2017-11-27 19:14:30 +00:00
Lovell Fuller
efd2e893cf Ensure expected fixtures match libvips v8.6.0 behaviour 2017-11-27 19:13:39 +00:00
Lovell Fuller
2a18b9a8f7 Remove centreSampling option, update some expected test fixtures
See https://github.com/jcupitt/libvips/issues/705
2017-11-26 13:49:56 +00:00
Lovell Fuller
6aa214181b Version bump dependencies 2017-11-25 11:25:27 +00:00
Lovell Fuller
7067beda99 Docs refresh for cropOffsetLeft/cropOffsetTop 2017-11-25 11:24:53 +00:00
Lovell Fuller
e0f0baf164 Silence a couple of MSVC type conversion warnings 2017-11-17 20:10:10 +00:00
Lovell Fuller
1fec132dee Add tilecache before smartcrop to avoid over-computation 2017-11-17 19:53:50 +00:00
Lovell Fuller
ba521fccb4 Replace caw with its tunnel-agent dependency 2017-11-07 19:38:10 +00:00
Lovell Fuller
965a97105e Default TIFF predictor to horizontal to match libvips' behaviour 2017-10-19 19:40:07 +01:00
Lovell Fuller
3c88c84998 Doc refresh, changelog and dead code removal for #977 2017-10-19 11:05:43 +01:00
Jarda Kotěšovec
d0f66c3734 Switch to libvips' resize, make fastShrinkOnLoad optional (#977) 2017-10-19 11:05:43 +01:00
Lovell Fuller
ebc2a741f6 Ensure accessMethod is applied during shrink-on-load 2017-10-19 11:05:43 +01:00
Lovell Fuller
d46512af1c Doc refresh and changelog entry for #976 2017-10-19 11:05:43 +01:00
Matthew McEachen
b4d72bd544 Add failOnError option to fail-fast on bad input image data (#976) 2017-10-19 11:05:43 +01:00
Lovell Fuller
382d476271 Temporarily allow CI failures on OS X 2017-10-19 11:05:43 +01:00
Lovell Fuller
80c240b54a Add compile time check for libvips 8.6.0+ 2017-10-19 11:05:43 +01:00
Lovell Fuller
21f99d88ab Docs: possible to install libvips via pkg on FreeBSD 2017-10-19 11:05:43 +01:00
Lovell Fuller
d5873a00d5 Docs refresh 2017-10-19 11:05:43 +01:00
Lovell Fuller
99076edc89 Default PNG output to adaptiveFiltering=false, compressionLevel=9
PNG is mostly used for logos and line art, so these defaults will
produce the smallest files for most output most of the time.
2017-10-19 11:05:43 +01:00
Lovell Fuller
7b6c80327e Verify platform of vendor binaries at install and run time 2017-10-19 11:05:43 +01:00
Lovell Fuller
57946ed672 Upgrade to libvips v8.6.0
Expose offset coordinates of strategy-based crop
Switch to Github releases for prebuilt libvips
Move packaging scripts to lovell/sharp-libvips repo
2017-10-19 11:05:43 +01:00
Aditya Bharti
aad16ac50d Improved jsdocs for withoutEnlargement and sequentialRead #972 (#992) 2017-10-15 09:28:08 +01:00
Brooks Becton
bbe897e607 Added Coding tools section and added types link (#975) 2017-10-04 13:02:11 +01:00
Mika Fischer
eca0e66e23 Remove use of dynamic require to facilitate bundling (#960) 2017-09-25 21:00:40 +01:00
Lovell Fuller
3511723914 Release v0.18.4 2017-09-18 18:26:12 +01:00
Lovell Fuller
6a1c7b7588 Ensure input Buffer really is marked as Persistent #950 2017-09-16 20:17:32 +01:00
160 changed files with 4730 additions and 1778 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
src/libvips/* linguist-vendored

7
.gitignore vendored
View File

@@ -1,6 +1,6 @@
build
node_modules
coverage
/coverage
test/bench/node_modules
test/fixtures/output*
test/leak/libvips.supp
@@ -9,8 +9,7 @@ test/saliency/Image*
test/saliency/[Uu]serData*
!test/saliency/userData.js
vendor
packaging/libvips*
packaging/*.log
!packaging/build
.gitattributes
.DS_Store
.nyc_output
package-lock.json

View File

@@ -2,13 +2,14 @@ build
node_modules
coverage
.editorconfig
.gitattributes
.gitignore
test
.travis.yml
appveyor.yml
circle.yml
mkdocs.yml
docs/css/
vendor
packaging
preinstall.sh
.prebuildrc
.nyc_output
CONTRIBUTING.md

4
.prebuildrc Normal file
View File

@@ -0,0 +1,4 @@
{
"include-regex": "(sharp\\.node|libvips-cpp\\.dll)",
"strip": true
}

View File

@@ -13,15 +13,22 @@ matrix:
dist: trusty
sudo: false
node_js: "8"
- os: linux
dist: trusty
sudo: false
node_js: "10"
- os: osx
osx_image: xcode8
osx_image: xcode8.3
node_js: "4"
- os: osx
osx_image: xcode8
osx_image: xcode8.3
node_js: "6"
- os: osx
osx_image: xcode8
osx_image: xcode8.3
node_js: "8"
- os: osx
osx_image: xcode8.3
node_js: "10"
after_success:
- npm install coveralls
- cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js

View File

@@ -14,7 +14,7 @@ New bugs are assigned a `triage` label whilst under investigation.
If a [similar request](https://github.com/lovell/sharp/labels/enhancement) exists, it's probably fastest to add a comment to it about your requirement.
Implementation is usually straightforward if _libvips_ [already supports](http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/ch03.html) the feature you need.
Implementation is usually straightforward if _libvips_ [already supports](https://jcupitt.github.io/libvips/API/current/) the feature you need.
## Submit a Pull Request to fix a bug
@@ -41,8 +41,8 @@ Any change that modifies the existing public API should be added to the relevant
| Release | WIP branch |
| ------: | :--------- |
| v0.18.0 | ridge |
| v0.19.0 | suit |
| v0.21.0 | teeth |
| v0.22.0 | uptake |
Please squash your changes into a single commit using a command like `git rebase -i upstream/<wip-branch>`.
@@ -89,15 +89,6 @@ Requires [Valgrind](http://valgrind.org/).
npm run test-leak
```
### Packaging tests
Tests the installation on a number of Linux-based operating systems.
Requires docker.
```sh
npm run test-packaging
```
## Finally
Please feel free to ask any questions via a

View File

@@ -4,6 +4,10 @@
npm install sharp
```
```sh
yarn add sharp
```
The typical use case for this high speed Node.js module
is to convert large images in common formats to
smaller, web-friendly JPEG, PNG and WebP images of varying dimensions.
@@ -17,13 +21,14 @@ Lanczos resampling ensures quality is not sacrificed for speed.
As well as image resizing, operations such as
rotation, extraction, compositing and gamma correction are available.
OS X, Windows (x64), Linux (x64, ARM) systems do not require
the installation of any external runtime dependencies.
Most modern 64-bit OS X, Windows and Linux (glibc) systems running
Node versions 4, 6, 8 and 10
do not require any additional install or runtime dependencies.
## Examples
```javascript
import sharp from 'sharp';
const sharp = require('sharp');
```
```javascript
@@ -33,8 +38,6 @@ sharp(inputBuffer)
// A Promises/A+ promise is returned when callback is not provided.
```
```javascript
sharp('input.jpg')
.rotate()
@@ -45,7 +48,7 @@ sharp('input.jpg')
```
```javascript
const roundedCorners = new Buffer(
const roundedCorners = Buffer.from(
'<svg><rect x="0" y="0" width="200" height="200" rx="50" ry="50"/></svg>'
);
@@ -64,11 +67,11 @@ readableStream
### Documentation
Visit [sharp.dimens.io](http://sharp.dimens.io/) for complete
[installation instructions](http://sharp.dimens.io/page/install),
[API documentation](http://sharp.dimens.io/page/api),
[benchmark tests](http://sharp.dimens.io/page/performance) and
[changelog](http://sharp.dimens.io/page/changelog).
Visit [sharp.pixelplumbing.com](http://sharp.pixelplumbing.com/) for complete
[installation instructions](http://sharp.pixelplumbing.com/page/install),
[API documentation](http://sharp.pixelplumbing.com/page/api),
[benchmark tests](http://sharp.pixelplumbing.com/page/performance) and
[changelog](http://sharp.pixelplumbing.com/page/changelog).
### Contributing
@@ -77,7 +80,7 @@ covers reporting bugs, requesting features and submitting code changes.
### Licence
Copyright 2013, 2014, 2015, 2016, 2017 Lovell Fuller and contributors.
Copyright 2013, 2014, 2015, 2016, 2017, 2018 Lovell Fuller and contributors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -6,10 +6,11 @@ environment:
matrix:
- nodejs_version: "4"
- nodejs_version: "6"
- nodejs_version: "7"
- nodejs_version: "8"
- nodejs_version: "10"
install:
- ps: Install-Product node $env:nodejs_version x64
- npm install -g npm@latest
- npm install -g npm@5
- npm install
test_script:
- npm test

View File

@@ -5,9 +5,6 @@
['OS == "win"', {
# Build libvips C++ binding for Windows due to MSVC std library ABI changes
'type': 'shared_library',
'variables': {
'download_vips': '<!(node -e "require(\'./binding\').download_vips()")'
},
'defines': [
'VIPS_CPLUSPLUS_EXPORTS',
'_ALLOW_KEYWORD_MACROS'
@@ -49,43 +46,22 @@
'dependencies': [
'libvips-cpp'
],
# Nested variables "pattern" borrowed from http://src.chromium.org/viewvc/chrome/trunk/src/build/common.gypi
'variables': {
'variables': {
'variables': {
'conditions': [
['OS != "win"', {
# Build the PKG_CONFIG_PATH environment variable with all possible combinations
'pkg_config_path': '<!(which brew >/dev/null 2>&1 && eval $(brew --env) && echo $PKG_CONFIG_LIBDIR || true):$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig:/usr/lib/pkgconfig'
}, {
'pkg_config_path': ''
}]
],
},
'conditions': [
['OS != "win"', {
# Which version, if any, of libvips is available globally via pkg-config?
'global_vips_version': '<!(PKG_CONFIG_PATH="<(pkg_config_path)" pkg-config --modversion vips-cpp 2>/dev/null || true)'
}, {
'global_vips_version': ''
}]
],
'pkg_config_path%': '<(pkg_config_path)'
},
'pkg_config_path%': '<(pkg_config_path)',
'runtime_link%': 'shared',
'conditions': [
['OS != "win"', {
# Does the globally available version of libvips, if any, meet the minimum version requirement?
'use_global_vips': '<!(GLOBAL_VIPS_VERSION="<(global_vips_version)" node -e "require(\'./binding\').use_global_vips()")'
'pkg_config_path': '<!(node -e "console.log(require(\'./lib/libvips\').pkgConfigPath())")',
'use_global_libvips': '<!(node -e "console.log(Boolean(require(\'./lib/libvips\').useGlobalLibvips()).toString())")'
}, {
'use_global_vips': ''
'pkg_config_path': '',
'use_global_libvips': ''
}]
]
},
'sources': [
'src/common.cc',
'src/metadata.cc',
'src/stats.cc',
'src/operations.cc',
'src/pipeline.cc',
'src/sharp.cc',
@@ -95,7 +71,7 @@
'<!(node -e "require(\'nan\')")'
],
'conditions': [
['use_global_vips == "true"', {
['use_global_libvips == "true"', {
# Use pkg-config for include and lib
'include_dirs': ['<!@(PKG_CONFIG_PATH="<(pkg_config_path)" pkg-config --cflags-only-I vips-cpp vips glib-2.0 | sed s\/-I//g)'],
'conditions': [
@@ -112,7 +88,7 @@
}]
]
}, {
# Attempt to download pre-built libvips and install locally within node_modules
# Use pre-built libvips stored locally within node_modules
'include_dirs': [
'vendor/include',
'vendor/include/glib-2.0',
@@ -130,9 +106,6 @@
]
}],
['OS == "mac"', {
'variables': {
'download_vips': '<!(node -e "require(\'./binding\').download_vips()")'
},
'libraries': [
'../vendor/lib/libvips-cpp.42.dylib',
'../vendor/lib/libvips.42.dylib',
@@ -143,9 +116,6 @@
]
}],
['OS == "linux"', {
'variables': {
'download_vips': '<!(node -e "require(\'./binding\').download_vips()")'
},
'defines': [
'_GLIBCXX_USE_CXX11_ABI=0'
],
@@ -218,61 +188,5 @@
]
}
},
}, {
'target_name': 'win_copy_dlls',
'type': 'none',
'dependencies': [
'sharp'
],
'conditions': [
['OS == "win"', {
# Windows lacks support for rpath
'copies': [{
'destination': 'build/Release',
'files': [
'vendor/lib/GNU.Gettext.dll',
'vendor/lib/libasprintf-0.dll',
'vendor/lib/libcairo-2.dll',
'vendor/lib/libcairo-gobject-2.dll',
'vendor/lib/libcairo-script-interpreter-2.dll',
'vendor/lib/libcharset-1.dll',
'vendor/lib/libcroco-0.6-3.dll',
'vendor/lib/libexif-12.dll',
'vendor/lib/libexpat-1.dll',
'vendor/lib/libffi-6.dll',
'vendor/lib/libfftw3-3.dll',
'vendor/lib/libfontconfig-1.dll',
'vendor/lib/libfreetype-6.dll',
'vendor/lib/libgcc_s_seh-1.dll',
'vendor/lib/libgdk_pixbuf-2.0-0.dll',
'vendor/lib/libgif-7.dll',
'vendor/lib/libgio-2.0-0.dll',
'vendor/lib/libglib-2.0-0.dll',
'vendor/lib/libgmodule-2.0-0.dll',
'vendor/lib/libgobject-2.0-0.dll',
'vendor/lib/libgsf-1-114.dll',
'vendor/lib/libgthread-2.0-0.dll',
'vendor/lib/libiconv-2.dll',
'vendor/lib/libintl-8.dll',
'vendor/lib/libjpeg-62.dll',
'vendor/lib/liblcms2-2.dll',
'vendor/lib/libpango-1.0-0.dll',
'vendor/lib/libpangocairo-1.0-0.dll',
'vendor/lib/libpangowin32-1.0-0.dll',
'vendor/lib/libpixman-1-0.dll',
'vendor/lib/libpng16-16.dll',
'vendor/lib/libquadmath-0.dll',
'vendor/lib/librsvg-2-2.dll',
'vendor/lib/libssp-0.dll',
'vendor/lib/libstdc++-6.dll',
'vendor/lib/libtiff-5.dll',
'vendor/lib/libvips-42.dll',
'vendor/lib/libwebp-7.dll',
'vendor/lib/libxml2-2.dll',
'vendor/lib/zlib1.dll'
]
}]
}]
]
}]
}

View File

@@ -1,129 +0,0 @@
'use strict';
const fs = require('fs');
const os = require('os');
const path = require('path');
const caw = require('caw');
const simpleGet = require('simple-get');
const semver = require('semver');
const tar = require('tar');
const detectLibc = require('detect-libc');
const distBaseUrl = process.env.SHARP_DIST_BASE_URL || 'https://dl.bintray.com/lovell/sharp/';
// Use NPM-provided environment variable where available, falling back to require-based method for Electron
const minimumLibvipsVersion = process.env.npm_package_config_libvips || require('./package.json').config.libvips;
const platform = process.env.npm_config_platform || process.platform;
const arch = process.env.npm_config_arch || process.arch;
// -- Helpers
// Does this file exist?
const isFile = function (file) {
try {
return fs.statSync(file).isFile();
} catch (err) {}
};
const unpack = function (tarPath, done) {
const vendorPath = path.join(__dirname, 'vendor');
fs.mkdirSync(vendorPath);
tar
.extract({
file: tarPath,
cwd: vendorPath,
strict: true
})
.then(done)
.catch(error);
};
const platformId = function () {
const platformId = [platform];
if (arch === 'arm' || arch === 'armhf' || arch === 'arm64') {
const armVersion = (arch === 'arm64') ? '8' : process.env.npm_config_armv || process.config.variables.arm_version || '6';
platformId.push('armv' + armVersion);
} else {
platformId.push(arch);
}
return platformId.join('-');
};
// Error
const error = function (msg) {
if (msg instanceof Error) {
msg = msg.message;
}
process.stderr.write('ERROR: ' + msg + '\n');
process.exit(1);
};
// -- Binary downloaders
module.exports.download_vips = function () {
// Has vips been installed locally?
const vipsHeaderPath = path.join(__dirname, 'vendor', 'include', 'vips', 'vips.h');
if (!isFile(vipsHeaderPath)) {
// Ensure Intel 64-bit or ARM
if (arch === 'ia32') {
error('Intel Architecture 32-bit systems require manual installation of libvips - please see http://sharp.dimens.io/page/install');
}
// Ensure glibc Linux
if (detectLibc.isNonGlibcLinux) {
error(`Use with ${detectLibc.family} libc requires manual installation of libvips - please see http://sharp.dimens.io/page/install`);
}
// Ensure glibc >= 2.13
if (detectLibc.family === detectLibc.GLIBC && detectLibc.version && semver.lt(`${detectLibc.version}.0`, '2.13.0')) {
error(`Use with glibc version ${detectLibc.version} requires manual installation of libvips - please see http://sharp.dimens.io/page/install`);
}
// Arch/platform-specific .tar.gz
const tarFilename = ['libvips', minimumLibvipsVersion, platformId()].join('-') + '.tar.gz';
const tarPathLocal = path.join(__dirname, 'packaging', tarFilename);
if (isFile(tarPathLocal)) {
unpack(tarPathLocal);
} else {
// Download to per-process temporary file
const tarPathTemp = path.join(os.tmpdir(), process.pid + '-' + tarFilename);
const tmpFile = fs.createWriteStream(tarPathTemp).on('finish', function () {
unpack(tarPathTemp, function () {
// Attempt to remove temporary file
try {
fs.unlinkSync(tarPathTemp);
} catch (err) {}
});
});
const url = distBaseUrl + tarFilename;
const simpleGetOpt = {
url: url,
agent: caw(null, {
protocol: 'https'
})
};
simpleGet(simpleGetOpt, function (err, response) {
if (err) {
error('Download of ' + url + ' failed: ' + err.message);
}
if (response.statusCode !== 200) {
error(url + ' status code ' + response.statusCode);
}
response.pipe(tmpFile);
});
}
}
};
module.exports.use_global_vips = function () {
const globalVipsVersion = process.env.GLOBAL_VIPS_VERSION;
if (globalVipsVersion) {
const useGlobalVips = semver.gte(
globalVipsVersion,
minimumLibvipsVersion
);
process.stdout.write(useGlobalVips ? 'true' : 'false');
} else {
process.stdout.write('false');
}
};

View File

@@ -1,8 +0,0 @@
machine:
node:
version: v4.8.4
services:
- docker
test:
override:
- ./packaging/test-linux-x64.sh

View File

@@ -1,20 +1,30 @@
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
### Table of Contents
## removeAlpha
- [extractChannel](#extractchannel)
- [joinChannel](#joinchannel)
- [bandbool](#bandbool)
Remove alpha channel, if any. This is a no-op if the image does not have an alpha channel.
### Examples
```javascript
sharp('rgba.png')
.removeAlpha()
.toFile('rgb.png', function(err, info) {
// rgb.png is a 3 channel image without an alpha channel
});
```
Returns **Sharp**
## extractChannel
Extract a single channel from a multi-channel image.
**Parameters**
### Parameters
- `channel` **([Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) \| [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String))** zero-indexed band number to extract, or `red`, `green` or `blue` as alternative to `0`, `1` or `2` respectively.
- `channel` **([Number][1] \| [String][2])** zero-indexed band number to extract, or `red`, `green` or `blue` as alternative to `0`, `1` or `2` respectively.
**Examples**
### Examples
```javascript
sharp(input)
@@ -25,7 +35,7 @@ sharp(input)
});
```
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid channel
- Throws **[Error][3]** Invalid channel
Returns **Sharp**
@@ -42,13 +52,13 @@ Channel ordering follows vips convention:
Buffers may be any of the image formats supported by sharp: JPEG, PNG, WebP, GIF, SVG, TIFF or raw pixel image data.
For raw pixel input, the `options` object should contain a `raw` attribute, which follows the format of the attribute of the same name in the `sharp()` constructor.
**Parameters**
### Parameters
- `images` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;([String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Buffer](https://nodejs.org/api/buffer.html))> | [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Buffer](https://nodejs.org/api/buffer.html))** one or more images (file paths, Buffers).
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** image options, see `sharp()` constructor.
- `images` **([Array][4]&lt;([String][2] \| [Buffer][5])> | [String][2] \| [Buffer][5])** one or more images (file paths, Buffers).
- `options` **[Object][6]** image options, see `sharp()` constructor.
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameters
- Throws **[Error][3]** Invalid parameters
Returns **Sharp**
@@ -56,11 +66,11 @@ Returns **Sharp**
Perform a bitwise boolean operation on all input image channels (bands) to produce a single channel output image.
**Parameters**
### Parameters
- `boolOp` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** one of `and`, `or` or `eor` to perform that bitwise operation, like the C logic operators `&`, `|` and `^` respectively.
- `boolOp` **[String][2]** one of `and`, `or` or `eor` to perform that bitwise operation, like the C logic operators `&`, `|` and `^` respectively.
**Examples**
### Examples
```javascript
sharp('3-channel-rgb-input.png')
@@ -72,6 +82,18 @@ sharp('3-channel-rgb-input.png')
});
```
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameters
- Throws **[Error][3]** Invalid parameters
Returns **Sharp**
[1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
[5]: https://nodejs.org/api/buffer.html
[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object

View File

@@ -1,13 +1,5 @@
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
### Table of Contents
- [background](#background)
- [greyscale](#greyscale)
- [grayscale](#grayscale)
- [toColourspace](#tocolourspace)
- [toColorspace](#tocolorspace)
## background
Set the background for the `embed`, `flatten` and `extend` operations.
@@ -17,12 +9,26 @@ Delegates to the _color_ module, which can throw an Error
but is liberal in what it accepts, clipping values to sensible min/max.
The alpha value is a float between `0` (transparent) and `1` (opaque).
**Parameters**
### Parameters
- `rgba` **([String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object))** parsed by the [color](https://www.npmjs.org/package/color) module to extract values for red, green, blue and alpha.
- `rgba` **([String][1] \| [Object][2])** parsed by the [color][3] module to extract values for red, green, blue and alpha.
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameter
- Throws **[Error][4]** Invalid parameter
Returns **Sharp**
## tint
Tint the image using the provided chroma while preserving the image luminance.
An alpha channel may be present and will be unchanged by the operation.
### Parameters
- `rgb` **([String][1] \| [Object][2])** parsed by the [color][3] module to extract chroma values.
- Throws **[Error][4]** Invalid parameter
Returns **Sharp**
@@ -35,9 +41,9 @@ This may be overridden by other sharp operations such as `toColourspace('b-w')`,
which will produce an output image containing one color channel.
An alpha channel may be present, and will be unchanged by the operation.
**Parameters**
### Parameters
- `greyscale` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** (optional, default `true`)
- `greyscale` **[Boolean][5]** (optional, default `true`)
Returns **Sharp**
@@ -45,9 +51,9 @@ Returns **Sharp**
Alternative spelling of `greyscale`.
**Parameters**
### Parameters
- `grayscale` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** (optional, default `true`)
- `grayscale` **[Boolean][5]** (optional, default `true`)
Returns **Sharp**
@@ -56,12 +62,12 @@ Returns **Sharp**
Set the output colourspace.
By default output image will be web-friendly sRGB, with additional channels interpreted as alpha channels.
**Parameters**
### Parameters
- `colourspace` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** output colourspace e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://github.com/jcupitt/libvips/blob/master/libvips/iofuncs/enumtypes.c#L568)
- `colourspace` **[String][1]?** output colourspace e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...][6]
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameters
- Throws **[Error][4]** Invalid parameters
Returns **Sharp**
@@ -69,11 +75,23 @@ Returns **Sharp**
Alternative spelling of `toColourspace`.
**Parameters**
### Parameters
- `colorspace` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** output colorspace.
- `colorspace` **[String][1]?** output colorspace.
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameters
- Throws **[Error][4]** Invalid parameters
Returns **Sharp**
[1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[3]: https://www.npmjs.org/package/color
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[6]: https://github.com/jcupitt/libvips/blob/master/libvips/iofuncs/enumtypes.c#L568

View File

@@ -1,9 +1,5 @@
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
### Table of Contents
- [overlayWith](#overlaywith)
## overlayWith
Overlay (composite) an image over the processed (resized, extracted etc.) image.
@@ -13,27 +9,27 @@ If both `top` and `left` options are provided, they take precedence over `gravit
If the overlay image contains an alpha channel then composition with premultiplication will occur.
**Parameters**
### Parameters
- `overlay` **([Buffer](https://nodejs.org/api/buffer.html) \| [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String))** Buffer containing image data or String containing the path to an image file.
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)?**
- `options.gravity` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** gravity at which to place the overlay. (optional, default `'centre'`)
- `options.top` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** the pixel offset from the top edge.
- `options.left` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** the pixel offset from the left edge.
- `options.tile` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** set to true to repeat the overlay image across the entire image with the given `gravity`. (optional, default `false`)
- `options.cutout` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** 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. (optional, default `false`)
- `options.density` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** integral number representing the DPI for vector overlay image. (optional, default `72`)
- `options.raw` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)?** describes overlay when using raw pixel data.
- `options.raw.width` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
- `options.raw.height` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
- `options.raw.channels` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
- `options.create` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)?** describes a blank overlay to be created.
- `options.create.width` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
- `options.create.height` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
- `options.create.channels` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** 3-4
- `options.create.background` **([String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object))?** parsed by the [color](https://www.npmjs.org/package/color) module to extract values for red, green, blue and alpha.
- `overlay` **([Buffer][1] \| [String][2])** Buffer containing image data or String containing the path to an image file.
- `options` **[Object][3]?**
- `options.gravity` **[String][2]** gravity at which to place the overlay. (optional, default `'centre'`)
- `options.top` **[Number][4]?** the pixel offset from the top edge.
- `options.left` **[Number][4]?** the pixel offset from the left edge.
- `options.tile` **[Boolean][5]** set to true to repeat the overlay image across the entire image with the given `gravity`. (optional, default `false`)
- `options.cutout` **[Boolean][5]** 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. (optional, default `false`)
- `options.density` **[Number][4]** integral number representing the DPI for vector overlay image. (optional, default `72`)
- `options.raw` **[Object][3]?** describes overlay when using raw pixel data.
- `options.raw.width` **[Number][4]?**
- `options.raw.height` **[Number][4]?**
- `options.raw.channels` **[Number][4]?**
- `options.create` **[Object][3]?** describes a blank overlay to be created.
- `options.create.width` **[Number][4]?**
- `options.create.height` **[Number][4]?**
- `options.create.channels` **[Number][4]?** 3-4
- `options.create.background` **([String][2] \| [Object][3])?** parsed by the [color][6] module to extract values for red, green, blue and alpha.
**Examples**
### Examples
```javascript
sharp('input.png')
@@ -44,8 +40,7 @@ sharp('input.png')
.overlayWith('overlay.png', { gravity: sharp.gravity.southeast } )
.sharpen()
.withMetadata()
.quality(90)
.webp()
.webp( { quality: 90 } )
.toBuffer()
.then(function(outputBuffer) {
// outputBuffer contains upside down, 300px wide, alpha channel flattened
@@ -54,6 +49,20 @@ sharp('input.png')
});
```
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameters
- Throws **[Error][7]** Invalid parameters
Returns **Sharp**
[1]: https://nodejs.org/api/buffer.html
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[6]: https://www.npmjs.org/package/color
[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error

View File

@@ -1,33 +1,30 @@
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
### Table of Contents
- [Sharp](#sharp)
- [format](#format)
- [versions](#versions)
- [queue](#queue)
## Sharp
**Parameters**
### Parameters
- `input` **([Buffer](https://nodejs.org/api/buffer.html) \| [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String))?** if present, can be
- `input` **([Buffer][1] \| [String][2])?** if present, can be
a Buffer containing JPEG, PNG, WebP, GIF, SVG, TIFF or raw pixel image data, or
a String containing the path to an JPEG, PNG, WebP, GIF, SVG or TIFF image file.
JPEG, PNG, WebP, GIF, SVG, TIFF or raw pixel image data can be streamed into the object when not present.
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)?** if present, is an Object with optional attributes.
- `options.density` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** integral number representing the DPI for vector images. (optional, default `72`)
- `options.raw` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)?** describes raw pixel input image data. See `raw()` for pixel ordering.
- `options.raw.width` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
- `options.raw.height` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
- `options.raw.channels` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** 1-4
- `options.create` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)?** describes a new image to be created.
- `options.create.width` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
- `options.create.height` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
- `options.create.channels` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** 3-4
- `options.create.background` **([String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object))?** parsed by the [color](https://www.npmjs.org/package/color) module to extract values for red, green, blue and alpha.
- `options` **[Object][3]?** if present, is an Object with optional attributes.
- `options.failOnError` **[Boolean][4]** by default apply a "best effort"
to decode images, even if the data is corrupt or invalid. Set this flag to true
if you'd rather halt processing and raise an error when loading invalid images. (optional, default `false`)
- `options.density` **[Number][5]** integral number representing the DPI for vector images. (optional, default `72`)
- `options.page` **[Number][5]** page number to extract for multi-page input (GIF, TIFF) (optional, default `0`)
- `options.raw` **[Object][3]?** describes raw pixel input image data. See `raw()` for pixel ordering.
- `options.raw.width` **[Number][5]?**
- `options.raw.height` **[Number][5]?**
- `options.raw.channels` **[Number][5]?** 1-4
- `options.create` **[Object][3]?** describes a new image to be created.
- `options.create.width` **[Number][5]?**
- `options.create.height` **[Number][5]?**
- `options.create.channels` **[Number][5]?** 3-4
- `options.create.background` **([String][2] \| [Object][3])?** parsed by the [color][6] module to extract values for red, green, blue and alpha.
**Examples**
### Examples
```javascript
sharp('input.jpg')
@@ -58,7 +55,7 @@ sharp({
width: 300,
height: 200,
channels: 4,
background: { r: 255, g: 0, b: 0, alpha: 128 }
background: { r: 255, g: 0, b: 0, alpha: 0.5 }
}
})
.png()
@@ -66,27 +63,27 @@ sharp({
.then( ... );
```
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameters
- Throws **[Error][7]** Invalid parameters
Returns **[Sharp](#sharp)**
Returns **[Sharp][8]**
### format
An Object containing nested boolean values representing the available input and output formats/methods.
**Examples**
#### Examples
```javascript
console.log(sharp.format);
```
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)**
Returns **[Object][3]**
### versions
An Object containing the version numbers of libvips and its dependencies.
**Examples**
#### Examples
```javascript
console.log(sharp.versions);
@@ -99,10 +96,26 @@ An EventEmitter that emits a `change` event when a task is either:
- queued, waiting for _libuv_ to provide a worker thread
- complete
**Examples**
### Examples
```javascript
sharp.queue.on('change', function(queueLength) {
console.log('Queue contains ' + queueLength + ' task(s)');
});
```
[1]: https://nodejs.org/api/buffer.html
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[6]: https://www.npmjs.org/package/color
[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[8]: #sharp

View File

@@ -1,19 +1,12 @@
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
### Table of Contents
- [clone](#clone)
- [metadata](#metadata)
- [limitInputPixels](#limitinputpixels)
- [sequentialRead](#sequentialread)
## clone
Take a "snapshot" of the Sharp instance, returning a new instance.
Cloned instances inherit the input of their parent instance.
This allows multiple output Streams and therefore multiple processing pipelines to share a single input Stream.
**Examples**
### Examples
```javascript
const pipeline = sharp().rotate();
@@ -32,23 +25,25 @@ Fast access to (uncached) image metadata without decoding any compressed image d
A Promises/A+ promise is returned when `callback` is not provided.
- `format`: Name of decoder used to decompress image data e.g. `jpeg`, `png`, `webp`, `gif`, `svg`
- `width`: Number of pixels wide
- `height`: Number of pixels high
- `space`: Name of colour space interpretation e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://github.com/jcupitt/libvips/blob/master/libvips/iofuncs/enumtypes.c#L636)
- `width`: Number of pixels wide (EXIF orientation is not taken into consideration)
- `height`: Number of pixels high (EXIF orientation is not taken into consideration)
- `space`: Name of colour space interpretation e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...][1]
- `channels`: Number of bands e.g. `3` for sRGB, `4` for CMYK
- `depth`: Name of pixel depth format e.g. `uchar`, `char`, `ushort`, `float` [...](https://github.com/jcupitt/libvips/blob/master/libvips/iofuncs/enumtypes.c#L672)
- `depth`: Name of pixel depth format e.g. `uchar`, `char`, `ushort`, `float` [...][2]
- `density`: Number of pixels per inch (DPI), if present
- `hasProfile`: Boolean indicating the presence of an embedded ICC profile
- `hasAlpha`: Boolean indicating the presence of an alpha transparency channel
- `orientation`: Number value of the EXIF Orientation header, if present
- `exif`: Buffer containing raw EXIF data, if present
- `icc`: Buffer containing raw [ICC](https://www.npmjs.com/package/icc) profile data, if present
- `icc`: Buffer containing raw [ICC][3] profile data, if present
- `iptc`: Buffer containing raw IPTC data, if present
- `xmp`: Buffer containing raw XMP data, if present
**Parameters**
### Parameters
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)?** called with the arguments `(err, metadata)`
- `callback` **[Function][4]?** called with the arguments `(err, metadata)`
**Examples**
### Examples
```javascript
const image = sharp(inputJpg);
@@ -65,7 +60,43 @@ image
});
```
Returns **([Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)&lt;[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)> | Sharp)**
Returns **([Promise][5]&lt;[Object][6]> | Sharp)**
## stats
Access to pixel-derived image statistics for every channel in the image.
A Promise is returned when `callback` is not provided.
- `channels`: Array of channel statistics for each channel in the image. Each channel statistic contains
- `min` (minimum value in the channel)
- `max` (maximum value in the channel)
- `sum` (sum of all values in a channel)
- `squaresSum` (sum of squared values in a channel)
- `mean` (mean of the values in a channel)
- `stdev` (standard deviation for the values in a channel)
- `minX` (x-coordinate of one of the pixel where the minimum lies)
- `minY` (y-coordinate of one of the pixel where the minimum lies)
- `maxX` (x-coordinate of one of the pixel where the maximum lies)
- `maxY` (y-coordinate of one of the pixel where the maximum lies)
- `isOpaque`: Value to identify if the image is opaque or transparent, based on the presence and use of alpha channel
- `entropy`: Histogram-based estimation of greyscale entropy, discarding alpha channel if any (experimental)
### Parameters
- `callback` **[Function][4]?** called with the arguments `(err, stats)`
### Examples
```javascript
const image = sharp(inputJpg);
image
.stats()
.then(function(stats) {
// stats contains the channel-wise statistics array and the isOpaque value
});
```
Returns **[Promise][5]&lt;[Object][6]>**
## limitInputPixels
@@ -73,12 +104,12 @@ Do not process input images where the number of pixels (width _ height) exceeds
Assumes image dimensions contained in the input metadata can be trusted.
The default limit is 268402689 (0x3FFF _ 0x3FFF) pixels.
**Parameters**
### Parameters
- `limit` **([Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** an integral Number of pixels, zero or false to remove limit, true to use default limit.
- `limit` **([Number][7] \| [Boolean][8])** an integral Number of pixels, zero or false to remove limit, true to use default limit.
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid limit
- Throws **[Error][9]** Invalid limit
Returns **Sharp**
@@ -87,8 +118,28 @@ Returns **Sharp**
An advanced setting that switches the libvips access method to `VIPS_ACCESS_SEQUENTIAL`.
This will reduce memory usage and can improve performance on some systems.
**Parameters**
The default behaviour _before_ function call is `false`, meaning the libvips access method is not sequential.
- `sequentialRead` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** (optional, default `true`)
### Parameters
- `sequentialRead` **[Boolean][8]** (optional, default `true`)
Returns **Sharp**
[1]: https://github.com/jcupitt/libvips/blob/master/libvips/iofuncs/enumtypes.c#L636
[2]: https://github.com/jcupitt/libvips/blob/master/libvips/iofuncs/enumtypes.c#L672
[3]: https://www.npmjs.com/package/icc
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise
[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error

View File

@@ -1,24 +1,5 @@
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
### Table of Contents
- [rotate](#rotate)
- [extract](#extract)
- [flip](#flip)
- [flop](#flop)
- [sharpen](#sharpen)
- [blur](#blur)
- [extend](#extend)
- [flatten](#flatten)
- [trim](#trim)
- [gamma](#gamma)
- [negate](#negate)
- [normalise](#normalise)
- [normalize](#normalize)
- [convolve](#convolve)
- [threshold](#threshold)
- [boolean](#boolean)
## rotate
Rotate the output image by either an explicit angle
@@ -35,11 +16,11 @@ The use of `rotate` implies the removal of the EXIF `Orientation` tag, if any.
Method order is important when both rotating and extracting regions,
for example `rotate(x).extract(y)` will produce a different result to `extract(y).rotate(x)`.
**Parameters**
### Parameters
- `angle` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** angle of rotation, must be a multiple of 90. (optional, default `auto`)
- `angle` **[Number][1]** angle of rotation, must be a multiple of 90. (optional, default `auto`)
**Examples**
### Examples
```javascript
const pipeline = sharp()
@@ -53,7 +34,7 @@ const pipeline = sharp()
readableStream.pipe(pipeline);
```
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
@@ -65,15 +46,15 @@ Extract a region of the image.
- Use `extract` after `resize` for post-resize extraction.
- Use `extract` before and after for both.
**Parameters**
### Parameters
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)**
- `options.left` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** zero-indexed offset from left edge
- `options.top` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** zero-indexed offset from top edge
- `options.width` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** dimension of extracted image
- `options.height` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** dimension of extracted image
- `options` **[Object][3]**
- `options.left` **[Number][1]** zero-indexed offset from left edge
- `options.top` **[Number][1]** zero-indexed offset from top edge
- `options.width` **[Number][1]** dimension of extracted image
- `options.height` **[Number][1]** dimension of extracted image
**Examples**
### Examples
```javascript
sharp(input)
@@ -93,7 +74,7 @@ sharp(input)
});
```
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
@@ -102,9 +83,9 @@ Returns **Sharp**
Flip the image about the vertical Y axis. This always occurs after rotation, if any.
The use of `flip` implies the removal of the EXIF `Orientation` tag, if any.
**Parameters**
### Parameters
- `flip` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** (optional, default `true`)
- `flip` **[Boolean][4]** (optional, default `true`)
Returns **Sharp**
@@ -113,9 +94,9 @@ Returns **Sharp**
Flop the image about the horizontal X axis. This always occurs after rotation, if any.
The use of `flop` implies the removal of the EXIF `Orientation` tag, if any.
**Parameters**
### Parameters
- `flop` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** (optional, default `true`)
- `flop` **[Boolean][4]** (optional, default `true`)
Returns **Sharp**
@@ -126,14 +107,28 @@ When used without parameters, performs a fast, mild sharpen of the output image.
When a `sigma` is provided, performs a slower, more accurate sharpen of the L channel in the LAB colour space.
Separate control over the level of sharpening in "flat" and "jagged" areas is available.
**Parameters**
### Parameters
- `sigma` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`.
- `flat` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** the level of sharpening to apply to "flat" areas. (optional, default `1.0`)
- `jagged` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** the level of sharpening to apply to "jagged" areas. (optional, default `2.0`)
- `sigma` **[Number][1]?** the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`.
- `flat` **[Number][1]** the level of sharpening to apply to "flat" areas. (optional, default `1.0`)
- `jagged` **[Number][1]** the level of sharpening to apply to "jagged" areas. (optional, default `2.0`)
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
## median
Apply median filter.
When used without parameters the default window is 3x3.
### Parameters
- `size` **[Number][1]** square mask size: size x size (optional, default `3`)
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
@@ -143,12 +138,12 @@ Blur the image.
When used without parameters, performs a fast, mild blur of the output image.
When a `sigma` is provided, performs a slower, more accurate Gaussian blur.
**Parameters**
### Parameters
- `sigma` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** a value between 0.3 and 1000 representing the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`.
- `sigma` **[Number][1]?** a value between 0.3 and 1000 representing the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`.
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
@@ -157,15 +152,15 @@ Returns **Sharp**
Extends/pads the edges of the image with the colour provided to the `background` method.
This operation will always occur after resizing and extraction, if any.
**Parameters**
### Parameters
- `extend` **([Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) \| [Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object))** single pixel count to add to all edges or an Object with per-edge counts
- `extend.top` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
- `extend.left` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
- `extend.bottom` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
- `extend.right` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
- `extend` **([Number][1] \| [Object][3])** single pixel count to add to all edges or an Object with per-edge counts
- `extend.top` **[Number][1]?**
- `extend.left` **[Number][1]?**
- `extend.bottom` **[Number][1]?**
- `extend.right` **[Number][1]?**
**Examples**
### Examples
```javascript
// Resize to 140 pixels wide, then add 10 transparent pixels
@@ -177,7 +172,7 @@ sharp(input)
...
```
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
@@ -185,9 +180,9 @@ Returns **Sharp**
Merge alpha transparency channel, if any, with `background`.
**Parameters**
### Parameters
- `flatten` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** (optional, default `true`)
- `flatten` **[Boolean][4]** (optional, default `true`)
Returns **Sharp**
@@ -195,12 +190,12 @@ Returns **Sharp**
Trim "boring" pixels from all edges that contain values within a percentage similarity of the top-left pixel.
**Parameters**
### Parameters
- `tolerance` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** value between 1 and 99 representing the percentage similarity. (optional, default `10`)
- `tolerance` **[Number][1]** value between 1 and 99 representing the percentage similarity. (optional, default `10`)
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
@@ -212,12 +207,12 @@ This can improve the perceived brightness of a resized image in non-linear colou
JPEG and WebP input images will not take advantage of the shrink-on-load performance optimisation
when applying a gamma correction.
**Parameters**
### Parameters
- `gamma` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** value between 1.0 and 3.0. (optional, default `2.2`)
- `gamma` **[Number][1]** value between 1.0 and 3.0. (optional, default `2.2`)
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
@@ -225,9 +220,9 @@ Returns **Sharp**
Produce the "negative" of the image.
**Parameters**
### Parameters
- `negate` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** (optional, default `true`)
- `negate` **[Boolean][4]** (optional, default `true`)
Returns **Sharp**
@@ -235,9 +230,9 @@ Returns **Sharp**
Enhance output image contrast by stretching its luminance to cover the full dynamic range.
**Parameters**
### Parameters
- `normalise` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** (optional, default `true`)
- `normalise` **[Boolean][4]** (optional, default `true`)
Returns **Sharp**
@@ -245,9 +240,9 @@ Returns **Sharp**
Alternative spelling of normalise.
**Parameters**
### Parameters
- `normalize` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** (optional, default `true`)
- `normalize` **[Boolean][4]** (optional, default `true`)
Returns **Sharp**
@@ -255,16 +250,16 @@ Returns **Sharp**
Convolve the image with the specified kernel.
**Parameters**
### Parameters
- `kernel` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)**
- `kernel.width` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** width of the kernel in pixels.
- `kernel.height` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** width of the kernel in pixels.
- `kernel.kernel` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)>** Array of length `width*height` containing the kernel values.
- `kernel.scale` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** the scale of the kernel in pixels. (optional, default `sum`)
- `kernel.offset` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** the offset of the kernel in pixels. (optional, default `0`)
- `kernel` **[Object][3]**
- `kernel.width` **[Number][1]** width of the kernel in pixels.
- `kernel.height` **[Number][1]** width of the kernel in pixels.
- `kernel.kernel` **[Array][5]&lt;[Number][1]>** Array of length `width*height` containing the kernel values.
- `kernel.scale` **[Number][1]** the scale of the kernel in pixels. (optional, default `sum`)
- `kernel.offset` **[Number][1]** the offset of the kernel in pixels. (optional, default `0`)
**Examples**
### Examples
```javascript
sharp(input)
@@ -280,7 +275,7 @@ sharp(input)
});
```
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
@@ -288,15 +283,15 @@ Returns **Sharp**
Any pixel value greather than or equal to the threshold value will be set to 255, otherwise it will be set to 0.
**Parameters**
### Parameters
- `threshold` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** a value in the range 0-255 representing the level at which the threshold will be applied. (optional, default `128`)
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)?**
- `options.greyscale` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** convert to single channel greyscale. (optional, default `true`)
- `options.grayscale` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** alternative spelling for greyscale. (optional, default `true`)
- `threshold` **[Number][1]** a value in the range 0-255 representing the level at which the threshold will be applied. (optional, default `128`)
- `options` **[Object][3]?**
- `options.greyscale` **[Boolean][4]** convert to single channel greyscale. (optional, default `true`)
- `options.grayscale` **[Boolean][4]** alternative spelling for greyscale. (optional, default `true`)
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
@@ -307,17 +302,45 @@ Perform a bitwise boolean operation with operand image.
This operation creates an output image where each pixel is the result of
the selected bitwise boolean `operation` between the corresponding pixels of the input images.
**Parameters**
### Parameters
- `operand` **([Buffer](https://nodejs.org/api/buffer.html) \| [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String))** Buffer containing image data or String containing the path to an image file.
- `operator` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** one of `and`, `or` or `eor` to perform that bitwise operation, like the C logic operators `&`, `|` and `^` respectively.
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)?**
- `options.raw` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)?** describes operand when using raw pixel data.
- `options.raw.width` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
- `options.raw.height` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
- `options.raw.channels` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
- `operand` **([Buffer][6] \| [String][7])** Buffer containing image data or String containing the path to an image file.
- `operator` **[String][7]** one of `and`, `or` or `eor` to perform that bitwise operation, like the C logic operators `&`, `|` and `^` respectively.
- `options` **[Object][3]?**
- `options.raw` **[Object][3]?** describes operand when using raw pixel data.
- `options.raw.width` **[Number][1]?**
- `options.raw.height` **[Number][1]?**
- `options.raw.channels` **[Number][1]?**
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
## linear
Apply the linear formula a \* input + b to the image (levels adjustment)
### Parameters
- `a` **[Number][1]** multiplier (optional, default `1.0`)
- `b` **[Number][1]** offset (optional, default `0.0`)
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
[1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
[6]: https://nodejs.org/api/buffer.html
[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String

View File

@@ -1,18 +1,5 @@
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
### Table of Contents
- [toFile](#tofile)
- [toBuffer](#tobuffer)
- [withMetadata](#withmetadata)
- [jpeg](#jpeg)
- [png](#png)
- [webp](#webp)
- [tiff](#tiff)
- [raw](#raw)
- [toFormat](#toformat)
- [tile](#tile)
## toFile
Write output image data to a file.
@@ -21,19 +8,33 @@ If an explicit output format is not selected, it will be inferred from the exten
with JPEG, PNG, WebP, TIFF, DZI, and libvips' V format supported.
Note that raw pixel data is only supported for buffer output.
A Promises/A+ promise is returned when `callback` is not provided.
A `Promise` is returned when `callback` is not provided.
**Parameters**
### Parameters
- `fileOut` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** the path to write the image data to.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)?** called on completion with two arguments `(err, info)`.
- `fileOut` **[String][1]** the path to write the image data to.
- `callback` **[Function][2]?** called on completion with two arguments `(err, info)`.
`info` contains the output image `format`, `size` (bytes), `width`, `height`,
`channels` and `premultiplied` (indicating if premultiplication was used).
When using a crop strategy also contains `cropOffsetLeft` and `cropOffsetTop`.
### Examples
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameters
```javascript
sharp(input)
.toFile('output.png', (err, info) => { ... });
```
Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)&lt;[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)>** when no callback is provided
```javascript
sharp(input)
.toFile('output.png')
.then(info => { ... })
.catch(err => { ... });
```
- Throws **[Error][3]** Invalid parameters
Returns **[Promise][4]&lt;[Object][5]>** when no callback is provided
## toBuffer
@@ -47,15 +48,38 @@ By default, the format will match the input image, except GIF and SVG input whic
- `data` is the output image data.
- `info` contains the output image `format`, `size` (bytes), `width`, `height`,
`channels` and `premultiplied` (indicating if premultiplication was used).
A Promise is returned when `callback` is not provided.
When using a crop strategy also contains `cropOffsetLeft` and `cropOffsetTop`.
**Parameters**
A `Promise` is returned when `callback` is not provided.
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)?**
- `options.resolveWithObject` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Resolve the Promise with an Object containing `data` and `info` properties instead of resolving only with `data`.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)?**
### Parameters
Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)&lt;[Buffer](https://nodejs.org/api/buffer.html)>** when no callback is provided
- `options` **[Object][5]?**
- `options.resolveWithObject` **[Boolean][6]?** Resolve the Promise with an Object containing `data` and `info` properties instead of resolving only with `data`.
- `callback` **[Function][2]?**
### Examples
```javascript
sharp(input)
.toBuffer((err, data, info) => { ... });
```
```javascript
sharp(input)
.toBuffer()
.then(data => { ... })
.catch(err => { ... });
```
```javascript
sharp(input)
.toBuffer({ resolveWithObject: true })
.then(({ data, info }) => { ... })
.catch(err => { ... });
```
Returns **[Promise][4]&lt;[Buffer][7]>** when no callback is provided
## withMetadata
@@ -63,13 +87,21 @@ Include all metadata (EXIF, XMP, IPTC) from the input image in the output image.
The default behaviour, when `withMetadata` is not used, is to strip all metadata and convert to the device-independent sRGB colour space.
This will also convert to and add a web-friendly sRGB ICC profile.
**Parameters**
### Parameters
- `withMetadata` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)?**
- `withMetadata.orientation` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** value between 1 and 8, used to update the EXIF `Orientation` tag.
- `withMetadata` **[Object][5]?**
- `withMetadata.orientation` **[Number][8]?** value between 1 and 8, used to update the EXIF `Orientation` tag.
### Examples
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameters
```javascript
sharp('input.jpg')
.withMetadata()
.toFile('output-with-metadata.jpg')
.then(info => { ... });
```
- Throws **[Error][3]** Invalid parameters
Returns **Sharp**
@@ -77,20 +109,35 @@ Returns **Sharp**
Use these JPEG options for output image.
**Parameters**
### Parameters
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)?** output options
- `options.quality` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** quality, integer 1-100 (optional, default `80`)
- `options.progressive` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** use progressive (interlace) scan (optional, default `false`)
- `options.chromaSubsampling` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** set to '4:4:4' to prevent chroma subsampling when quality &lt;= 90 (optional, default `'4:2:0'`)
- `options.trellisQuantisation` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** apply trellis quantisation, requires mozjpeg (optional, default `false`)
- `options.overshootDeringing` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** apply overshoot deringing, requires mozjpeg (optional, default `false`)
- `options.optimiseScans` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** optimise progressive scans, forces progressive, requires mozjpeg (optional, default `false`)
- `options.optimizeScans` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** alternative spelling of optimiseScans (optional, default `false`)
- `options.force` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** force JPEG output, otherwise attempt to use input format (optional, default `true`)
- `options` **[Object][5]?** output options
- `options.quality` **[Number][8]** quality, integer 1-100 (optional, default `80`)
- `options.progressive` **[Boolean][6]** use progressive (interlace) scan (optional, default `false`)
- `options.chromaSubsampling` **[String][1]** set to '4:4:4' to prevent chroma subsampling when quality &lt;= 90 (optional, default `'4:2:0'`)
- `options.trellisQuantisation` **[Boolean][6]** apply trellis quantisation, requires mozjpeg (optional, default `false`)
- `options.overshootDeringing` **[Boolean][6]** apply overshoot deringing, requires mozjpeg (optional, default `false`)
- `options.optimiseScans` **[Boolean][6]** optimise progressive scans, forces progressive, requires mozjpeg (optional, default `false`)
- `options.optimizeScans` **[Boolean][6]** alternative spelling of optimiseScans (optional, default `false`)
- `options.optimiseCoding` **[Boolean][6]** optimise Huffman coding tables (optional, default `true`)
- `options.optimizeCoding` **[Boolean][6]** alternative spelling of optimiseCoding (optional, default `true`)
- `options.quantisationTable` **[Number][8]** quantization table to use, integer 0-8, requires mozjpeg (optional, default `0`)
- `options.quantizationTable` **[Number][8]** alternative spelling of quantisationTable (optional, default `0`)
- `options.force` **[Boolean][6]** force JPEG output, otherwise attempt to use input format (optional, default `true`)
### Examples
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid options
```javascript
// Convert any input to very high quality JPEG output
const data = await sharp(input)
.jpeg({
quality: 100,
chromaSubsampling: '4:4:4'
})
.toBuffer();
```
- Throws **[Error][3]** Invalid options
Returns **Sharp**
@@ -98,16 +145,27 @@ Returns **Sharp**
Use these PNG options for output image.
**Parameters**
PNG output is always full colour at 8 or 16 bits per pixel.
Indexed PNG input at 1, 2 or 4 bits per pixel is converted to 8 bits per pixel.
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)?**
- `options.progressive` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** use progressive (interlace) scan (optional, default `false`)
- `options.compressionLevel` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** zlib compression level (optional, default `6`)
- `options.adaptiveFiltering` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** use adaptive row filtering (optional, default `true`)
- `options.force` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** force PNG output, otherwise attempt to use input format (optional, default `true`)
### Parameters
- `options` **[Object][5]?**
- `options.progressive` **[Boolean][6]** use progressive (interlace) scan (optional, default `false`)
- `options.compressionLevel` **[Number][8]** zlib compression level, 0-9 (optional, default `9`)
- `options.adaptiveFiltering` **[Boolean][6]** use adaptive row filtering (optional, default `false`)
- `options.force` **[Boolean][6]** force PNG output, otherwise attempt to use input format (optional, default `true`)
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid options
### Examples
```javascript
// Convert any input to PNG output
const data = await sharp(input)
.png()
.toBuffer();
```
- Throws **[Error][3]** Invalid options
Returns **Sharp**
@@ -115,17 +173,25 @@ Returns **Sharp**
Use these WebP options for output image.
**Parameters**
### Parameters
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)?** output options
- `options.quality` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** quality, integer 1-100 (optional, default `80`)
- `options.alphaQuality` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** quality of alpha layer, integer 0-100 (optional, default `100`)
- `options.lossless` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** use lossless compression mode (optional, default `false`)
- `options.nearLossless` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** use near_lossless compression mode (optional, default `false`)
- `options.force` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** force WebP output, otherwise attempt to use input format (optional, default `true`)
- `options` **[Object][5]?** output options
- `options.quality` **[Number][8]** quality, integer 1-100 (optional, default `80`)
- `options.alphaQuality` **[Number][8]** quality of alpha layer, integer 0-100 (optional, default `100`)
- `options.lossless` **[Boolean][6]** use lossless compression mode (optional, default `false`)
- `options.nearLossless` **[Boolean][6]** use near_lossless compression mode (optional, default `false`)
- `options.force` **[Boolean][6]** force WebP output, otherwise attempt to use input format (optional, default `true`)
### Examples
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid options
```javascript
// Convert any input to lossless WebP output
const data = await sharp(input)
.webp({ lossless: true })
.toBuffer();
```
- Throws **[Error][3]** Invalid options
Returns **Sharp**
@@ -133,19 +199,31 @@ Returns **Sharp**
Use these TIFF options for output image.
**Parameters**
### Parameters
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)?** output options
- `options.quality` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** quality, integer 1-100 (optional, default `80`)
- `options.force` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** force TIFF output, otherwise attempt to use input format (optional, default `true`)
- `options.compression` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** compression options: lzw, deflate, jpeg (optional, default `'jpeg'`)
- `options.predictor` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** compression predictor options: none, horizontal, float (optional, default `'none'`)
- `options.xres` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** horizontal resolution in pixels/mm (optional, default `1.0`)
- `options.yres` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** vertical resolution in pixels/mm (optional, default `1.0`)
- `options.squash` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** squash 8-bit images down to 1 bit (optional, default `false`)
- `options` **[Object][5]?** output options
- `options.quality` **[Number][8]** quality, integer 1-100 (optional, default `80`)
- `options.force` **[Boolean][6]** force TIFF output, otherwise attempt to use input format (optional, default `true`)
- `options.compression` **[Boolean][6]** compression options: lzw, deflate, jpeg, ccittfax4 (optional, default `'jpeg'`)
- `options.predictor` **[Boolean][6]** compression predictor options: none, horizontal, float (optional, default `'horizontal'`)
- `options.xres` **[Number][8]** horizontal resolution in pixels/mm (optional, default `1.0`)
- `options.yres` **[Number][8]** vertical resolution in pixels/mm (optional, default `1.0`)
- `options.squash` **[Boolean][6]** squash 8-bit images down to 1 bit (optional, default `false`)
### Examples
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid options
```javascript
// Convert SVG input to LZW-compressed, 1 bit per pixel TIFF output
sharp('input.svg')
.tiff({
compression: 'lzw',
squash: true
})
.toFile('1-bpp-output.tiff')
.then(info => { ... });
```
- Throws **[Error][3]** Invalid options
Returns **Sharp**
@@ -153,19 +231,36 @@ Returns **Sharp**
Force output to be raw, uncompressed uint8 pixel data.
### Examples
```javascript
// Extract raw RGB pixel data from JPEG input
const { data, info } = await sharp('input.jpg')
.raw()
.toBuffer({ resolveWithObject: true });
```
Returns **Sharp**
## toFormat
Force output to a given format.
**Parameters**
### Parameters
- `format` **([String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object))** as a String or an Object with an 'id' attribute
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** output options
- `format` **([String][1] \| [Object][5])** as a String or an Object with an 'id' attribute
- `options` **[Object][5]** output options
### Examples
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** unsupported format or options
```javascript
// Convert any input to PNG output
const data = await sharp(input)
.toFormat('png')
.toBuffer();
```
- Throws **[Error][3]** unsupported format or options
Returns **Sharp**
@@ -175,15 +270,19 @@ Use tile-based deep zoom (image pyramid) output.
Set the format and options for tile images via the `toFormat`, `jpeg`, `png` or `webp` functions.
Use a `.zip` or `.szi` file extension with `toFile` to write to a compressed archive file format.
**Parameters**
Warning: multiple sharp instances concurrently producing tile output can expose a possible race condition in some versions of libgsf.
- `tile` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)?**
- `tile.size` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** tile size in pixels, a value between 1 and 8192. (optional, default `256`)
- `tile.overlap` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** tile overlap in pixels, a value between 0 and 8192. (optional, default `0`)
- `tile.container` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** tile container, with value `fs` (filesystem) or `zip` (compressed file). (optional, default `'fs'`)
- `tile.layout` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** filesystem layout, possible values are `dz`, `zoomify` or `google`. (optional, default `'dz'`)
### Parameters
**Examples**
- `tile` **[Object][5]?**
- `tile.size` **[Number][8]** tile size in pixels, a value between 1 and 8192. (optional, default `256`)
- `tile.overlap` **[Number][8]** tile overlap in pixels, a value between 0 and 8192. (optional, default `0`)
- `tile.angle` **[Number][8]** tile angle of rotation, must be a multiple of 90. (optional, default `0`)
- `tile.depth` **[String][1]?** how deep to make the pyramid, possible values are `onepixel`, `onetile` or `one`, default based on layout.
- `tile.container` **[String][1]** tile container, with value `fs` (filesystem) or `zip` (compressed file). (optional, default `'fs'`)
- `tile.layout` **[String][1]** filesystem layout, possible values are `dz`, `zoomify` or `google`. (optional, default `'dz'`)
### Examples
```javascript
sharp('input.tiff')
@@ -197,6 +296,22 @@ sharp('input.tiff')
});
```
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameters
- Throws **[Error][3]** Invalid parameters
Returns **Sharp**
[1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[7]: https://nodejs.org/api/buffer.html
[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number

View File

@@ -1,65 +1,43 @@
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
### Table of Contents
- [resize](#resize)
- [crop](#crop)
- [embed](#embed)
- [max](#max)
- [min](#min)
- [ignoreAspectRatio](#ignoreaspectratio)
- [withoutEnlargement](#withoutenlargement)
## resize
Resize image to `width` x `height`.
By default, the resized image is centre cropped to the exact size specified.
Possible reduction kernels are:
Possible kernels are:
- `nearest`: Use [nearest neighbour interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation).
- `cubic`: Use a [Catmull-Rom spline](https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline).
- `lanczos2`: Use a [Lanczos kernel](https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel) with `a=2`.
- `nearest`: Use [nearest neighbour interpolation][1].
- `cubic`: Use a [Catmull-Rom spline][2].
- `lanczos2`: Use a [Lanczos kernel][3] with `a=2`.
- `lanczos3`: Use a Lanczos kernel with `a=3` (the default).
Possible enlargement interpolators are:
### Parameters
- `nearest`: Use [nearest neighbour interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation).
- `bilinear`: Use [bilinear interpolation](http://en.wikipedia.org/wiki/Bilinear_interpolation), faster than bicubic but with less smooth results.
- `vertexSplitQuadraticBasisSpline`: Use the smoother [VSQBS interpolation](https://github.com/jcupitt/libvips/blob/master/libvips/resample/vsqbs.cpp#L48) to prevent "staircasing" when enlarging.
- `bicubic`: Use [bicubic interpolation](http://en.wikipedia.org/wiki/Bicubic_interpolation) (the default).
- `locallyBoundedBicubic`: Use [LBB interpolation](https://github.com/jcupitt/libvips/blob/master/libvips/resample/lbb.cpp#L100), which prevents some "[acutance](http://en.wikipedia.org/wiki/Acutance)" but typically reduces performance by a factor of 2.
- `nohalo`: Use [Nohalo interpolation](http://eprints.soton.ac.uk/268086/), which prevents acutance but typically reduces performance by a factor of 3.
- `width` **[Number][4]?** pixels wide the resultant image should be. Use `null` or `undefined` to auto-scale the width to match the height.
- `height` **[Number][4]?** pixels high the resultant image should be. Use `null` or `undefined` to auto-scale the height to match the width.
- `options` **[Object][5]?**
- `options.kernel` **[String][6]** the kernel to use for image reduction. (optional, default `'lanczos3'`)
- `options.fastShrinkOnLoad` **[Boolean][7]** take greater advantage of the JPEG and WebP shrink-on-load feature, which can lead to a slight moiré pattern on some images. (optional, default `true`)
**Parameters**
- `width` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** pixels wide the resultant image should be. Use `null` or `undefined` to auto-scale the width to match the height.
- `height` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** pixels high the resultant image should be. Use `null` or `undefined` to auto-scale the height to match the width.
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)?**
- `options.kernel` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** the kernel to use for image reduction. (optional, default `'lanczos3'`)
- `options.interpolator` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** the interpolator to use for image enlargement. (optional, default `'bicubic'`)
- `options.centreSampling` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** use \*magick centre sampling convention instead of corner sampling. (optional, default `false`)
- `options.centerSampling` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** alternative spelling of centreSampling. (optional, default `false`)
**Examples**
### Examples
```javascript
sharp(inputBuffer)
.resize(200, 300, {
kernel: sharp.kernel.lanczos2,
interpolator: sharp.interpolator.nohalo
kernel: sharp.kernel.nearest
})
.background('white')
.embed()
.toFile('output.tiff')
.then(function() {
// output.tiff is a 200 pixels wide and 300 pixels high image
// containing a lanczos2/nohalo scaled version, embedded on a white canvas,
// containing a nearest-neighbour scaled version, embedded on a white canvas,
// of the image data in inputBuffer
});
```
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameters
- Throws **[Error][8]** Invalid parameters
Returns **Sharp**
@@ -73,14 +51,14 @@ Possible attributes of the optional `sharp.gravity` are `north`, `northeast`, `e
The experimental strategy-based approach resizes so one dimension is at its target length
then repeatedly ranks edge regions, discarding the edge with the lowest score based on the selected strategy.
- `entropy`: focus on the region with the highest [Shannon entropy](https://en.wikipedia.org/wiki/Entropy_%28information_theory%29).
- `entropy`: focus on the region with the highest [Shannon entropy][9].
- `attention`: focus on the region with the highest luminance frequency, colour saturation and presence of skin tones.
**Parameters**
### Parameters
- `crop` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** A member of `sharp.gravity` to crop to an edge/corner or `sharp.strategy` to crop dynamically. (optional, default `'centre'`)
- `crop` **[String][6]** A member of `sharp.gravity` to crop to an edge/corner or `sharp.strategy` to crop dynamically. (optional, default `'centre'`)
**Examples**
### Examples
```javascript
const transformer = sharp()
@@ -94,7 +72,7 @@ const transformer = sharp()
readableStream.pipe(transformer).pipe(writableStream);
```
- Throws **[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)** Invalid parameters
- Throws **[Error][8]** Invalid parameters
Returns **Sharp**
@@ -106,7 +84,11 @@ then embed on a background of the exact `width` and `height` specified.
If the background contains an alpha value then WebP and PNG format output images will
contain an alpha channel, even when the input image does not.
**Examples**
### Parameters
- `embed` **[String][6]** A member of `sharp.gravity` to embed to an edge/corner. (optional, default `'centre'`)
### Examples
```javascript
sharp('input.gif')
@@ -123,6 +105,8 @@ sharp('input.gif')
});
```
- Throws **[Error][8]** Invalid parameters
Returns **Sharp**
## max
@@ -132,7 +116,7 @@ while ensuring its dimensions are less than or equal to the `width` and `height`
Both `width` and `height` must be provided via `resize` otherwise the behaviour will default to `crop`.
**Examples**
### Examples
```javascript
sharp(inputBuffer)
@@ -169,9 +153,30 @@ Returns **Sharp**
Do not enlarge the output image if the input image width _or_ height are already less than the required dimensions.
This is equivalent to GraphicsMagick's `>` geometry option:
"_change the dimensions of the image only if its width or height exceeds the geometry specification_".
Use with `max()` to preserve the image's aspect ratio.
**Parameters**
The default behaviour _before_ function call is `false`, meaning the image will be enlarged.
- `withoutEnlargement` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** (optional, default `true`)
### Parameters
- `withoutEnlargement` **[Boolean][7]** (optional, default `true`)
Returns **Sharp**
[1]: http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation
[2]: https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline
[3]: https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[9]: https://en.wikipedia.org/wiki/Entropy_%28information_theory%29

View File

@@ -1,12 +1,5 @@
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
### Table of Contents
- [cache](#cache)
- [concurrency](#concurrency)
- [counters](#counters)
- [simd](#simd)
## cache
Gets or, when options are provided, sets the limits of _libvips'_ operation cache.
@@ -14,14 +7,14 @@ Existing entries in the cache will be trimmed after any change in limits.
This method always returns cache statistics,
useful for determining how much working memory is required for a particular task.
**Parameters**
### Parameters
- `options` **([Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** Object with the following attributes, or Boolean where true uses default cache settings and false removes all caching (optional, default `true`)
- `options.memory` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** is the maximum memory in MB to use for this cache (optional, default `50`)
- `options.files` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** is the maximum number of files to hold open (optional, default `20`)
- `options.items` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** is the maximum number of operations to cache (optional, default `100`)
- `options` **([Object][1] \| [Boolean][2])** Object with the following attributes, or Boolean where true uses default cache settings and false removes all caching (optional, default `true`)
- `options.memory` **[Number][3]** is the maximum memory in MB to use for this cache (optional, default `50`)
- `options.files` **[Number][3]** is the maximum number of files to hold open (optional, default `20`)
- `options.items` **[Number][3]** is the maximum number of operations to cache (optional, default `100`)
**Examples**
### Examples
```javascript
const stats = sharp.cache();
@@ -33,7 +26,7 @@ sharp.cache( { files: 0 } );
sharp.cache(false);
```
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)**
Returns **[Object][1]**
## concurrency
@@ -47,11 +40,11 @@ is limited by libuv's `UV_THREADPOOL_SIZE` environment variable.
This method always returns the current concurrency.
**Parameters**
### Parameters
- `concurrency` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
- `concurrency` **[Number][3]?**
**Examples**
### Examples
```javascript
const threads = sharp.concurrency(); // 4
@@ -59,7 +52,7 @@ sharp.concurrency(2); // 2
sharp.concurrency(0); // 4
```
Returns **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** concurrency
Returns **[Number][3]** concurrency
## counters
@@ -68,13 +61,13 @@ Provides access to internal task counters.
- queue is the number of tasks this module has queued waiting for _libuv_ to provide a worker thread from its pool.
- process is the number of resize tasks currently being processed.
**Examples**
### Examples
```javascript
const counters = sharp.counters(); // { queue: 2, process: 4 }
```
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)**
Returns **[Object][1]**
## simd
@@ -87,11 +80,11 @@ by taking advantage of the SIMD vector unit of the CPU, e.g. Intel SSE and ARM N
This feature is currently off by default but future versions may reverse this.
Versions of liborc prior to 0.4.25 are known to segfault under heavy load.
**Parameters**
### Parameters
- `simd` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** (optional, default `false`)
- `simd` **[Boolean][2]** (optional, default `false`)
**Examples**
### Examples
```javascript
const simd = sharp.simd();
@@ -103,4 +96,10 @@ const simd = sharp.simd(true);
// attempts to enable the use of SIMD, returning true if available
```
Returns **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
Returns **[Boolean][2]**
[1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number

View File

@@ -1,9 +1,175 @@
# Changelog
### v0.20 - "*prebuild*"
Requires libvips v8.6.1.
#### v0.20.7 - 21<sup>st</sup> August 2018
* Use copy+unlink if rename operation fails during installation.
[#1345](https://github.com/lovell/sharp/issues/1345)
#### v0.20.6 - 20<sup>th</sup> August 2018
* Add removeAlpha operation to remove alpha channel, if any.
[#1248](https://github.com/lovell/sharp/issues/1248)
* Expose mozjpeg quant_table flag.
[#1285](https://github.com/lovell/sharp/pull/1285)
[@rexxars](https://github.com/rexxars)
* Allow full WebP alphaQuality range of 0-100.
[#1290](https://github.com/lovell/sharp/pull/1290)
[@sylvaindumont](https://github.com/sylvaindumont)
* Cache libvips binaries to reduce re-install time.
[#1301](https://github.com/lovell/sharp/issues/1301)
* Ensure vendor platform mismatch throws error at install time.
[#1303](https://github.com/lovell/sharp/issues/1303)
* Improve install time error messages for FreeBSD users.
[#1310](https://github.com/lovell/sharp/issues/1310)
* Ensure extractChannel works with 16-bit images.
[#1330](https://github.com/lovell/sharp/issues/1330)
* Expose depth option for tile-based output.
[#1342](https://github.com/lovell/sharp/pull/1342)
[@alundavies](https://github.com/alundavies)
* Add experimental entropy field to stats response.
#### v0.20.5 - 27<sup>th</sup> June 2018
* Expose libjpeg optimize_coding flag.
[#1265](https://github.com/lovell/sharp/pull/1265)
[@tomlokhorst](https://github.com/tomlokhorst)
#### v0.20.4 - 20<sup>th</sup> June 2018
* Prevent possible rounding error when using shrink-on-load and 90/270 degree rotation.
[#1241](https://github.com/lovell/sharp/issues/1241)
[@anahit42](https://github.com/anahit42)
* Ensure extractChannel sets correct single-channel colour space interpretation.
[#1257](https://github.com/lovell/sharp/issues/1257)
[@jeremychone](https://github.com/jeremychone)
#### v0.20.3 - 29<sup>th</sup> May 2018
* Fix tint operation by ensuring LAB interpretation and allowing negative values.
[#1235](https://github.com/lovell/sharp/issues/1235)
[@wezside](https://github.com/wezside)
#### v0.20.2 - 28<sup>th</sup> April 2018
* Add tint operation to set image chroma.
[#825](https://github.com/lovell/sharp/pull/825)
[@rikh42](https://github.com/rikh42)
* Add environment variable to ignore globally-installed libvips.
[#1165](https://github.com/lovell/sharp/pull/1165)
[@oncletom](https://github.com/oncletom)
* Add support for page selection with multi-page input (GIF/TIFF).
[#1204](https://github.com/lovell/sharp/pull/1204)
[@woolite64](https://github.com/woolite64)
* Add support for Group4 (CCITTFAX4) compression with TIFF output.
[#1208](https://github.com/lovell/sharp/pull/1208)
[@woolite64](https://github.com/woolite64)
#### v0.20.1 - 17<sup>th</sup> March 2018
* Improve installation experience when a globally-installed libvips below the minimum required version is found.
[#1148](https://github.com/lovell/sharp/issues/1148)
* Prevent smartcrop error when cumulative rounding is below target size.
[#1154](https://github.com/lovell/sharp/issues/1154)
[@ralrom](https://github.com/ralrom)
* Expose libvips' median filter operation.
[#1161](https://github.com/lovell/sharp/pull/1161)
[@BiancoA](https://github.com/BiancoA)
#### v0.20.0 - 5<sup>th</sup> March 2018
* Add support for prebuilt sharp binaries on common platforms.
[#186](https://github.com/lovell/sharp/issues/186)
### v0.19 - "*suit*"
Requires libvips v8.6.1.
#### v0.19.1 - 24<sup>th</sup> February 2018
* Expose libvips' linear transform feature.
[#1024](https://github.com/lovell/sharp/pull/1024)
[@3epnm](https://github.com/3epnm)
* Expose angle option for tile-based output.
[#1121](https://github.com/lovell/sharp/pull/1121)
[@BiancoA](https://github.com/BiancoA)
* Prevent crop operation when image already at or below target dimensions.
[#1134](https://github.com/lovell/sharp/issues/1134)
[@pieh](https://github.com/pieh)
#### v0.19.0 - 11<sup>th</sup> January 2018
* Expose offset coordinates of strategy-based crop.
[#868](https://github.com/lovell/sharp/issues/868)
[@mirohristov-com](https://github.com/mirohristov-com)
* PNG output now defaults to adaptiveFiltering=false, compressionLevel=9
[#872](https://github.com/lovell/sharp/issues/872)
[@wmertens](https://github.com/wmertens)
* Add stats feature for pixel-derived image statistics.
[#915](https://github.com/lovell/sharp/pull/915)
[@rnanwani](https://github.com/rnanwani)
* Add failOnError option to fail-fast on bad input image data.
[#976](https://github.com/lovell/sharp/pull/976)
[@mceachen](https://github.com/mceachen)
* Resize: switch to libvips' implementation, make fastShrinkOnLoad optional, remove interpolator and centreSampling options.
[#977](https://github.com/lovell/sharp/pull/977)
[@jardakotesovec](https://github.com/jardakotesovec)
* Attach finish event listener to a clone only for Stream-based input.
[#995](https://github.com/lovell/sharp/issues/995)
[@whmountains](https://github.com/whmountains)
* Add tilecache before smartcrop to avoid over-computation of previous operations.
[#1028](https://github.com/lovell/sharp/issues/1028)
[@coffeebite](https://github.com/coffeebite)
* Prevent toFile extension taking precedence over requested format.
[#1037](https://github.com/lovell/sharp/issues/1037)
[@tomgallagher](https://github.com/tomgallagher)
* Add support for gravity option to existing embed feature.
[#1038](https://github.com/lovell/sharp/pull/1038)
[@AzureByte](https://github.com/AzureByte)
* Expose IPTC and XMP metadata when available.
[#1079](https://github.com/lovell/sharp/pull/1079)
[@oaleynik](https://github.com/oaleynik)
* TIFF output: switch default predictor from 'none' to 'horizontal' to match libvips' behaviour.
### v0.18 - "*ridge*"
Requires libvips v8.5.5.
#### v0.18.4 - 18<sup>th</sup> September 2017
* Ensure input Buffer really is marked as Persistent, prevents mark-sweep GC.
[#950](https://github.com/lovell/sharp/issues/950)
[@lfdoherty](https://github.com/lfdoherty)
#### v0.18.3 - 13<sup>th</sup> September 2017
* Skip shrink-on-load when trimming.

5
docs/css/extra.css Normal file
View File

@@ -0,0 +1,5 @@
/* Nest document subheadings in navigation */
ul.subnav ul:not(.subnav) {
padding-left: 2em;
font-size: 80%;
}

View File

@@ -13,8 +13,9 @@ Lanczos resampling ensures quality is not sacrificed for speed.
As well as image resizing, operations such as
rotation, extraction, compositing and gamma correction are available.
OS X, Windows (x64), Linux (x64, ARM) systems do not require
the installation of any external runtime dependencies.
Most 64-bit OS X, Windows and Linux (glibc) systems running
Node versions 4, 6, 8 and 10
do not require any additional install or runtime dependencies.
[![Test Coverage](https://coveralls.io/repos/lovell/sharp/badge.png?branch=master)](https://coveralls.io/r/lovell/sharp?branch=master)
@@ -46,7 +47,7 @@ are held in memory and processed at a time,
taking full advantage of multiple CPU cores and L1/L2/L3 cache.
Everything remains non-blocking thanks to _libuv_,
no child processes are spawned and Promises/A+ are supported.
no child processes are spawned and Promises/async/await are supported.
### Optimal
@@ -55,9 +56,9 @@ without having to use separate command line tools like
[jpegoptim](https://github.com/tjko/jpegoptim) and
[jpegtran](http://jpegclub.org/jpegtran/).
PNG filtering can be disabled,
PNG filtering is disabled by default,
which for diagrams and line art often produces the same result
as [pngcrush](http://pmt.sourceforge.net/pngcrush/).
as [pngcrush](https://pmt.sourceforge.io/pngcrush/).
### Contributing
@@ -102,12 +103,25 @@ the help and code contributions of the following people:
* [Yves Bos](https://github.com/YvesBos)
* [Nicolas Coden](https://github.com/ncoden)
* [Matt Parrish](https://github.com/pbomb)
* [Matthew McEachen](https://github.com/mceachen)
* [Jarda Kotěšovec](https://github.com/jardakotesovec)
* [Kenric D'Souza](https://github.com/AzureByte)
* [Oleh Aleinyk](https://github.com/oaleynik)
* [Marcel Bretschneider](https://github.com/3epnm)
* [Andrea Bianco](https://github.com/BiancoA)
* [Rik Heywood](https://github.com/rikh42)
* [Thomas Parisot](https://github.com/oncletom)
* [Nathan Graves](https://github.com/woolite64)
* [Tom Lokhorst](https://github.com/tomlokhorst)
* [Espen Hovlandsdal](https://github.com/rexxars)
* [Sylvain Dumont](https://github.com/sylvaindumont)
* [Alun Davies](https://github.com/alundavies)
Thank you!
### Licence
Copyright 2013, 2014, 2015, 2016, 2017 Lovell Fuller and contributors.
Copyright 2013, 2014, 2015, 2016, 2017, 2018 Lovell Fuller and contributors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -8,37 +8,53 @@ npm install sharp
yarn add sharp
```
### Prerequisites
## Prerequisites
* Node v4.5.0+
### Building from source
Pre-compiled binaries for sharp are provided for use with
Node versions 4, 6, 8 and 10 on
64-bit Windows, OS X and Linux platforms.
Sharp will be built from source at install time when:
* a globally-installed libvips is detected,
* pre-compiled binaries do not exist for the current platform and Node version, or
* when the `npm install --build-from-source` flag is used.
Building from source requires:
* C++11 compatible compiler such as gcc 4.8+, clang 3.0+ or MSVC 2013+
* [node-gyp](https://github.com/TooTallNate/node-gyp#installation) and its dependencies (includes Python)
## libvips
### Linux
[![Ubuntu 14.04 Build Status](https://travis-ci.org/lovell/sharp.png?branch=master)](https://travis-ci.org/lovell/sharp)
[![Linux Build Status](https://circleci.com/gh/lovell/sharp.svg?style=svg&circle-token=6cb6d1d287a51af83722b19ed8885377fbc85e5c)](https://circleci.com/gh/lovell/sharp)
[![Ubuntu 16.04 Build Status](https://travis-ci.org/lovell/sharp.png?branch=master)](https://travis-ci.org/lovell/sharp)
libvips and its dependencies are fetched and stored within `node_modules/sharp/vendor` during `npm install`.
This involves an automated HTTPS download of approximately 7MB.
Most recent Linux-based operating systems with glibc running on x64 and ARMv6+ CPUs should "just work", e.g.:
* Debian 7, 8
* Ubuntu 12.04, 14.04, 16.04
* Centos 7
* Debian 7+
* Ubuntu 14.04+
* Centos 7+
* Fedora
* openSUSE 13.2
* openSUSE 13.2+
* Archlinux
* Raspbian Jessie
* Amazon Linux 2016.03, 2016.09
* Amazon Linux
* Solus
To use a globally-installed version of libvips instead of the provided binaries,
make sure it is at least the version listed under `config.libvips` in the `package.json` file
and that it can be located using `pkg-config --modversion vips-cpp`.
If you are using non-stadard paths (anything other than `/usr` or `/usr/local`),
If you are using non-standard paths (anything other than `/usr` or `/usr/local`),
you might need to set `PKG_CONFIG_PATH` during `npm install`
and `LD_LIBRARY_PATH` at runtime.
@@ -64,7 +80,7 @@ via `sharp.cache(false)` to avoid a stack overflow.
### Mac OS
[![OS X 10.9.5 Build Status](https://travis-ci.org/lovell/sharp.png?branch=master)](https://travis-ci.org/lovell/sharp)
[![OS X 10.12 Build Status](https://travis-ci.org/lovell/sharp.png?branch=master)](https://travis-ci.org/lovell/sharp)
libvips and its dependencies are fetched and stored within `node_modules/sharp/vendor` during `npm install`.
This involves an automated HTTPS download of approximately 7MB.
@@ -78,14 +94,19 @@ that it can be located using `pkg-config --modversion vips-cpp`.
[![Windows x64 Build Status](https://ci.appveyor.com/api/projects/status/pgtul704nkhhg6sg)](https://ci.appveyor.com/project/lovell/sharp)
libvips and its dependencies are fetched and stored within `node_modules\sharp\vendor` during `npm install`.
This involves an automated HTTPS download of approximately 11MB.
This involves an automated HTTPS download of approximately 12MB.
Only 64-bit (x64) `node.exe` is supported.
### FreeBSD
libvips must be installed before `npm install` is run.
This can be achieved via [FreshPorts](https://www.freshports.org/graphics/vips/):
This can be achieved via package or ports:
```sh
pkg install -y pkgconf vips
```
```sh
cd /usr/ports/graphics/vips/ && make install clean
@@ -127,36 +148,40 @@ docker pull tailor/docker-libvips
### AWS Lambda
In order to use sharp on AWS Lambda, you need to [create a deployment package](http://docs.aws.amazon.com/lambda/latest/dg/nodejs-create-deployment-pkg.html). Because sharp
downloads and links libraries for the current platform during `npm install` you have to
do this on a system similar to the [Lambda Execution Environment](http://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html). The easiest ways to do this, is to setup a
small t2.micro instance using the AMI ID listed in the previous link, ssh into it as ec2-user
and follow the instructions below.
Install dependencies:
A [deployment package](http://docs.aws.amazon.com/lambda/latest/dg/nodejs-create-deployment-pkg.html) for the
[Lambda Execution Environment](http://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html)
can be built using Docker.
```sh
curl -s https://rpm.nodesource.com/setup_4.x | sudo bash -
sudo yum install -y gcc-c++ nodejs
rm -rf node_modules/sharp
docker run -v "$PWD":/var/task lambci/lambda:build-nodejs6.10 npm install
```
Copy your code and package.json to the instance using `scp` and create a deployment package:
Set the Lambda runtime to Node.js 6.10.
To get the best performance select the largest memory available. A 1536 MB function provides ~12x more CPU time than a 128 MB function.
### NW.js
Run the `nw-gyp` tool after installation.
```sh
cd sharp-lambda-example
npm install
zip -ur9 ../sharp-lambda-example.zip index.js node_modules
cd node-modules/sharp
nw-gyp rebuild --arch=x64 --target=[your nw version]
node node_modules/sharp/install/dll-copy
```
You can now download your deployment ZIP using `scp` and upload it to Lambda. Be sure to set your Lambda runtime to Node.js 4.3.
**Performance Tip:** To get the best performance on Lambda choose the largest memory available because this also gives you the most cpu time (a 1536 MB function is 12x faster than a 128 MB function).
See also http://docs.nwjs.io/en/latest/For%20Users/Advanced/Use%20Native%20Node%20Modules/
### Build tools
* [gulp-responsive](https://www.npmjs.com/package/gulp-responsive)
* [grunt-sharp](https://www.npmjs.com/package/grunt-sharp)
### Coding tools
* [Sharp TypeScript Types](https://www.npmjs.com/package/@types/sharp)
### CLI tools
* [sharp-cli](https://www.npmjs.com/package/sharp-cli)
@@ -198,13 +223,20 @@ to the directory containing the `policy.xml` file.
### Pre-compiled libvips binaries
If a global installation of libvips that meets the
minimum version requirement cannot be found,
this module will attempt to download a pre-compiled bundle of libvips
and its dependencies on Linux and Windows machines.
This module will attempt to download a pre-compiled bundle of libvips
and its dependencies on Linux and Windows machines under either of these
conditions:
1. If a global installation of libvips that meets the
minimum version requirement cannot be found;
1. If `SHARP_IGNORE_GLOBAL_LIBVIPS` environment variable is set.
```sh
SHARP_IGNORE_GLOBAL_LIBVIPS=1 npm install sharp
```
Should you need to manually download and inspect these files,
you can do so via https://dl.bintray.com/lovell/sharp/
you can do so via https://github.com/lovell/sharp-libvips/releases
Should you wish to install these from your own location,
set the `SHARP_DIST_BASE_URL` environment variable, e.g.

View File

@@ -2,19 +2,20 @@
### Test environment
* AWS EC2 eu-central-1 [c4.xlarge](http://aws.amazon.com/ec2/instance-types/#c4) (4x E5-2666 v3 @ 2.90GHz)
* Ubuntu 16.04.1 LTS (HVM, SSD, 20161115, ami-82cf0aed)
* Node.js v6.9.1
* AWS EC2 eu-west-1 [c5.large](https://aws.amazon.com/ec2/instance-types/c5/) (2x Xeon Platinum 8124M CPU @ 3.00GHz)
* Ubuntu 17.10 (hvm:ebs-ssd, 20180102, ami-0741d47e)
* Node.js v8.9.4
### The contenders
* [jimp](https://www.npmjs.com/package/jimp) v0.2.27 - Image processing in pure JavaScript. Bilinear interpolation only.
* [lwip](https://www.npmjs.com/package/lwip) v0.0.9 - Wrapper around CImg. Compiles outdated, insecure dependencies from source.
* [mapnik](https://www.npmjs.org/package/mapnik) v3.5.14 - Whilst primarily a map renderer, Mapnik contains bitmap image utilities.
* [jimp](https://www.npmjs.com/package/jimp) v0.2.28 - Image processing in pure JavaScript. Bilinear interpolation only.
* [pajk-lwip](https://www.npmjs.com/package/pajk-lwip) v0.2.0 (fork) - Wrapper around CImg that compiles dependencies from source.
* [mapnik](https://www.npmjs.org/package/mapnik) v3.6.2 - Whilst primarily a map renderer, Mapnik contains bitmap image utilities.
* [imagemagick-native](https://www.npmjs.com/package/imagemagick-native) v1.9.3 - Wrapper around libmagick++, supports Buffers only.
* [imagemagick](https://www.npmjs.com/package/imagemagick) v0.1.3 - Supports filesystem only and "*has been unmaintained for a long time*".
* [gm](https://www.npmjs.com/package/gm) v1.23.0 - Fully featured wrapper around GraphicsMagick's `gm` command line utility.
* sharp v0.17.0 / libvips v8.4.2 - Caching within libvips disabled to ensure a fair comparison.
* [gm](https://www.npmjs.com/package/gm) v1.23.1 - Fully featured wrapper around GraphicsMagick's `gm` command line utility.
* [images](https://www.npmjs.com/package/images) v3.0.1 - Compiles dependencies from source. Provides bicubic interpolation.
* sharp v0.19.0 / libvips v8.6.1 - Caching within libvips disabled to ensure a fair comparison.
### The task
@@ -26,18 +27,19 @@ then compress to JPEG at a "quality" setting of 80.
| Module | Input | Output | Ops/sec | Speed-up |
| :----------------- | :----- | :----- | ------: | -------: |
| jimp (bilinear) | buffer | buffer | 1.06 | 1.0 |
| lwip | buffer | buffer | 1.87 | 1.8 |
| mapnik | buffer | buffer | 2.91 | 2.7 |
| imagemagick-native | buffer | buffer | 4.03 | 3.8 |
| imagemagick | file | file | 7.10 | 6.7 |
| gm | buffer | buffer | 7.08 | 6.7 |
| gm | file | file | 7.10 | 6.7 |
| sharp | stream | stream | 27.61 | 26.0 |
| sharp | file | file | 28.41 | 26.8 |
| sharp | buffer | file | 28.71 | 27.1 |
| sharp | file | buffer | 28.60 | 27.0 |
| sharp | buffer | buffer | 29.08 | 27.4 |
| jimp (bilinear) | buffer | buffer | 1.14 | 1.0 |
| lwip | buffer | buffer | 1.86 | 1.6 |
| mapnik | buffer | buffer | 3.34 | 2.9 |
| imagemagick-native | buffer | buffer | 4.13 | 3.6 |
| gm | buffer | buffer | 4.21 | 3.7 |
| gm | file | file | 4.27 | 3.7 |
| imagemagick | file | file | 4.67 | 4.1 |
| images (bicubic) | file | file | 6.22 | 5.5 |
| sharp | stream | stream | 24.43 | 21.4 |
| sharp | file | file | 25.97 | 22.7 |
| sharp | file | buffer | 26.00 | 22.8 |
| sharp | buffer | file | 26.33 | 23.0 |
| sharp | buffer | buffer | 26.43 | 23.1 |
Greater libvips performance can be expected with caching enabled (default)
and using 8+ core machines, especially those with larger L1/L2 CPU caches.
@@ -46,19 +48,20 @@ The I/O limits of the relevant (de)compression library will generally determine
### Benchmark test prerequisites
Requires both _ImageMagick_ and _GraphicsMagick_:
Requires _ImageMagick_, _GraphicsMagick_ and _Mapnik_:
```sh
brew install imagemagick
brew install graphicsmagick
brew install mapnik
```
```sh
sudo apt-get install imagemagick libmagick++-dev graphicsmagick
sudo apt-get install imagemagick libmagick++-dev graphicsmagick mapnik-dev
```
```sh
sudo yum install ImageMagick-devel ImageMagick-c++-devel GraphicsMagick
sudo yum install ImageMagick-devel ImageMagick-c++-devel GraphicsMagick mapnik-devel
```
### Running the benchmark test

34
install/dll-copy.js Normal file
View File

@@ -0,0 +1,34 @@
'use strict';
const fs = require('fs');
const path = require('path');
const copyFileSync = require('fs-copy-file-sync');
const npmLog = require('npmlog');
if (process.platform === 'win32') {
const buildDir = path.join(__dirname, '..', 'build');
const buildReleaseDir = path.join(buildDir, 'Release');
npmLog.info('sharp', `Creating ${buildReleaseDir}`);
try {
fs.mkdirSync(buildDir);
fs.mkdirSync(buildReleaseDir);
} catch (err) {}
const vendorLibDir = path.join(__dirname, '..', 'vendor', 'lib');
npmLog.info('sharp', `Copying DLLs from ${vendorLibDir} to ${buildReleaseDir}`);
try {
fs
.readdirSync(vendorLibDir)
.filter(function (filename) {
return /\.dll$/.test(filename);
})
.forEach(function (filename) {
copyFileSync(
path.join(vendorLibDir, filename),
path.join(buildReleaseDir, filename)
);
});
} catch (err) {
npmLog.error('sharp', err.message);
}
}

102
install/libvips.js Normal file
View File

@@ -0,0 +1,102 @@
'use strict';
const fs = require('fs');
const os = require('os');
const path = require('path');
const detectLibc = require('detect-libc');
const npmLog = require('npmlog');
const semver = require('semver');
const simpleGet = require('simple-get');
const tar = require('tar');
const copyFileSync = require('fs-copy-file-sync');
const agent = require('../lib/agent');
const libvips = require('../lib/libvips');
const platform = require('../lib/platform');
const minimumLibvipsVersion = libvips.minimumLibvipsVersion;
const distBaseUrl = process.env.SHARP_DIST_BASE_URL || `https://github.com/lovell/sharp-libvips/releases/download/v${minimumLibvipsVersion}/`;
const extractTarball = function (tarPath) {
const vendorPath = path.join(__dirname, '..', 'vendor');
if (!fs.existsSync(vendorPath)) {
fs.mkdirSync(vendorPath);
}
tar
.extract({
file: tarPath,
cwd: vendorPath,
strict: true
})
.catch(function (err) {
throw err;
});
};
try {
const useGlobalLibvips = libvips.useGlobalLibvips();
if (useGlobalLibvips) {
const globalLibvipsVersion = libvips.globalLibvipsVersion();
npmLog.info('sharp', `Detected globally-installed libvips v${globalLibvipsVersion}`);
npmLog.info('sharp', 'Building from source via node-gyp');
process.exit(1);
} else if (libvips.hasVendoredLibvips()) {
npmLog.info('sharp', `Using existing vendored libvips v${minimumLibvipsVersion}`);
} else {
// Is this arch/platform supported?
const arch = process.env.npm_config_arch || process.arch;
const platformAndArch = platform();
if (platformAndArch === 'win32-ia32') {
throw new Error('Windows x86 (32-bit) node.exe is not supported');
}
if (arch === 'ia32') {
throw new Error(`Intel Architecture 32-bit systems require manual installation of libvips >= ${minimumLibvipsVersion}`);
}
if (platformAndArch === 'freebsd-x64') {
throw new Error(`FreeBSD systems require manual installation of libvips >= ${minimumLibvipsVersion}`);
}
if (detectLibc.isNonGlibcLinux) {
throw new Error(`Use with ${detectLibc.family} libc requires manual installation of libvips >= ${minimumLibvipsVersion}`);
}
if (detectLibc.family === detectLibc.GLIBC && detectLibc.version && semver.lt(`${detectLibc.version}.0`, '2.13.0')) {
throw new Error(`Use with glibc version ${detectLibc.version} requires manual installation of libvips >= ${minimumLibvipsVersion}`);
}
// Download to per-process temporary file
const tarFilename = ['libvips', minimumLibvipsVersion, platformAndArch].join('-') + '.tar.gz';
const tarPathCache = path.join(libvips.cachePath(), tarFilename);
if (fs.existsSync(tarPathCache)) {
npmLog.info('sharp', `Using cached ${tarPathCache}`);
extractTarball(tarPathCache);
} else {
const tarPathTemp = path.join(os.tmpdir(), `${process.pid}-${tarFilename}`);
const tmpFile = fs.createWriteStream(tarPathTemp);
const url = distBaseUrl + tarFilename;
npmLog.info('sharp', `Downloading ${url}`);
simpleGet({ url: url, agent: agent() }, function (err, response) {
if (err) {
throw err;
}
if (response.statusCode !== 200) {
throw new Error(`Status ${response.statusCode}`);
}
response.pipe(tmpFile);
});
tmpFile.on('close', function () {
try {
// Attempt to rename
fs.renameSync(tarPathTemp, tarPathCache);
} catch (err) {
// Fall back to copy and unlink
copyFileSync(tarPathTemp, tarPathCache);
fs.unlinkSync(tarPathTemp);
}
extractTarball(tarPathCache);
});
}
}
} catch (err) {
npmLog.error('sharp', err.message);
npmLog.error('sharp', 'Please see http://sharp.pixelplumbing.com/page/install');
process.exit(1);
}

37
lib/agent.js Normal file
View File

@@ -0,0 +1,37 @@
'use strict';
const url = require('url');
const tunnelAgent = require('tunnel-agent');
const is = require('./is');
const proxies = [
'HTTPS_PROXY',
'https_proxy',
'HTTP_PROXY',
'http_proxy',
'npm_config_https_proxy',
'npm_config_proxy'
];
function env (key) {
return process.env[key];
}
module.exports = function () {
try {
const proxy = url.parse(proxies.map(env).find(is.string));
const tunnel = proxy.protocol === 'https:'
? tunnelAgent.httpsOverHttps
: tunnelAgent.httpsOverHttp;
return tunnel({
proxy: {
port: Number(proxy.port),
host: proxy.hostname,
proxyAuth: proxy.auth
}
});
} catch (err) {
return null;
}
};

View File

@@ -12,6 +12,23 @@ const bool = {
eor: 'eor'
};
/**
* Remove alpha channel, if any. This is a no-op if the image does not have an alpha channel.
*
* @example
* sharp('rgba.png')
* .removeAlpha()
* .toFile('rgb.png', function(err, info) {
* // rgb.png is a 3 channel image without an alpha channel
* });
*
* @returns {Sharp}
*/
function removeAlpha () {
this.options.removeAlpha = true;
return this;
}
/**
* Extract a single channel from a multi-channel image.
*
@@ -102,6 +119,7 @@ function bandbool (boolOp) {
module.exports = function (Sharp) {
// Public instance functions
[
removeAlpha,
extractChannel,
joinChannel,
bandbool

View File

@@ -38,6 +38,21 @@ function background (rgba) {
return this;
}
/**
* Tint the image using the provided chroma while preserving the image luminance.
* An alpha channel may be present and will be unchanged by the operation.
*
* @param {String|Object} rgb - parsed by the [color](https://www.npmjs.org/package/color) module to extract chroma values.
* @returns {Sharp}
* @throws {Error} Invalid parameter
*/
function tint (rgb) {
const colour = color(rgb);
this.options.tintA = colour.a();
this.options.tintB = colour.b();
return this;
}
/**
* Convert to 8-bit greyscale; 256 shades of grey.
* This is a linear operation. If the input image is in a non-linear colour space such as sRGB, use `gamma()` with `greyscale()` for the best results.
@@ -95,6 +110,7 @@ module.exports = function (Sharp) {
// Public instance functions
[
background,
tint,
greyscale,
grayscale,
toColourspace,

View File

@@ -19,8 +19,7 @@ const is = require('./is');
* .overlayWith('overlay.png', { gravity: sharp.gravity.southeast } )
* .sharpen()
* .withMetadata()
* .quality(90)
* .webp()
* .webp( { quality: 90 } )
* .toBuffer()
* .then(function(outputBuffer) {
* // outputBuffer contains upside down, 300px wide, alpha channel flattened

View File

@@ -6,8 +6,24 @@ const stream = require('stream');
const events = require('events');
const semver = require('semver');
const is = require('./is');
const platform = require('./platform');
const sharp = require('../build/Release/sharp.node');
// Vendor platform
(function () {
let vendorPlatformId;
try {
vendorPlatformId = require('../vendor/platform.json');
} catch (err) {
return;
}
const currentPlatformId = platform();
/* istanbul ignore if */
if (currentPlatformId !== vendorPlatformId) {
throw new Error(`'${vendorPlatformId}' binaries cannot be used on the '${currentPlatformId}' platform. Please remove the 'node_modules/sharp/vendor' directory and run 'npm rebuild'.`);
}
})();
// Versioning
let versions = {
vips: sharp.libvipsVersion()
@@ -21,7 +37,7 @@ let versions = {
}
// Include versions of dependencies, if present
try {
versions = require('../vendor/lib/versions.json');
versions = require('../vendor/versions.json');
} catch (err) {}
})();
@@ -65,7 +81,7 @@ const debuglog = util.debuglog('sharp');
* width: 300,
* height: 200,
* channels: 4,
* background: { r: 255, g: 0, b: 0, alpha: 128 }
* background: { r: 255, g: 0, b: 0, alpha: 0.5 }
* }
* })
* .png()
@@ -77,7 +93,11 @@ const debuglog = util.debuglog('sharp');
* a String containing the path to an JPEG, PNG, WebP, GIF, SVG or TIFF image file.
* JPEG, PNG, WebP, GIF, SVG, TIFF or raw pixel image data can be streamed into the object when not present.
* @param {Object} [options] - if present, is an Object with optional attributes.
* @param {Boolean} [options.failOnError=false] - by default apply a "best effort"
* to decode images, even if the data is corrupt or invalid. Set this flag to true
* if you'd rather halt processing and raise an error when loading invalid images.
* @param {Number} [options.density=72] - integral number representing the DPI for vector images.
* @param {Number} [options.page=0] - page number to extract for multi-page input (GIF, TIFF)
* @param {Object} [options.raw] - describes raw pixel input image data. See `raw()` for pixel ordering.
* @param {Number} [options.raw.width]
* @param {Number} [options.raw.height]
@@ -117,6 +137,7 @@ const Sharp = function (input, options) {
height: -1,
canvas: 'crop',
crop: 0,
embed: 0,
useExifOrientation: false,
angle: 0,
rotateBeforePreExtract: false,
@@ -128,12 +149,14 @@ const Sharp = function (input, options) {
extendRight: 0,
withoutEnlargement: false,
kernel: 'lanczos3',
interpolator: 'bicubic',
centreSampling: false,
fastShrinkOnLoad: true,
// operations
background: [0, 0, 0, 255],
tintA: 128,
tintB: 128,
flatten: false,
negate: false,
medianSize: 0,
blurSigma: 0,
sharpenSigma: 0,
sharpenFlat: 1,
@@ -148,6 +171,7 @@ const Sharp = function (input, options) {
booleanFileIn: '',
joinChannelIn: [],
extractChannel: -1,
removeAlpha: false,
colourspace: 'srgb',
// overlay
overlayGravity: 0,
@@ -169,21 +193,25 @@ const Sharp = function (input, options) {
jpegTrellisQuantisation: false,
jpegOvershootDeringing: false,
jpegOptimiseScans: false,
jpegOptimiseCoding: true,
jpegQuantisationTable: 0,
pngProgressive: false,
pngCompressionLevel: 6,
pngAdaptiveFiltering: true,
pngCompressionLevel: 9,
pngAdaptiveFiltering: false,
webpQuality: 80,
webpAlphaQuality: 100,
webpLossless: false,
webpNearLossless: false,
tiffQuality: 80,
tiffCompression: 'jpeg',
tiffPredictor: 'none',
tiffPredictor: 'horizontal',
tiffSquash: false,
tiffXres: 1.0,
tiffYres: 1.0,
tileSize: 256,
tileOverlap: 0,
linearA: 1,
linearB: 0,
// Function to notify of libvips warnings
debuglog: debuglog,
// Function to notify of queue length changes

View File

@@ -1,17 +1,13 @@
'use strict';
const Sharp = require('./constructor');
[
'input',
'resize',
'composite',
'operation',
'colour',
'channel',
'output',
'utility'
].forEach(function (decorator) {
require('./' + decorator)(Sharp);
});
require('./input')(Sharp);
require('./resize')(Sharp);
require('./composite')(Sharp);
require('./operation')(Sharp);
require('./colour')(Sharp);
require('./channel')(Sharp);
require('./output')(Sharp);
require('./utility')(Sharp);
module.exports = Sharp;

View File

@@ -9,7 +9,7 @@ const sharp = require('../build/Release/sharp.node');
* @private
*/
function _createInputDescriptor (input, inputOptions, containerOptions) {
const inputDescriptor = {};
const inputDescriptor = { failOnError: false };
if (is.string(input)) {
// filesystem
inputDescriptor.file = input;
@@ -26,6 +26,14 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
throw new Error('Unsupported input ' + typeof input);
}
if (is.object(inputOptions)) {
// Fail on error
if (is.defined(inputOptions.failOnError)) {
if (is.bool(inputOptions.failOnError)) {
inputDescriptor.failOnError = inputOptions.failOnError;
} else {
throw new Error('Invalid failOnError (boolean) ' + inputOptions.failOnError);
}
}
// Density
if (is.defined(inputOptions.density)) {
if (is.integer(inputOptions.density) && is.inRange(inputOptions.density, 1, 2400)) {
@@ -49,6 +57,12 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
throw new Error('Expected width, height and channels for raw pixel input');
}
}
// Page input for multi-page TIFF
if (is.defined(inputOptions.page)) {
if (is.integer(inputOptions.page) && is.inRange(inputOptions.page, 0, 100000)) {
inputDescriptor.page = inputOptions.page;
}
}
// Create new image
if (is.defined(inputOptions.create)) {
if (
@@ -147,12 +161,14 @@ function clone () {
const clone = this.constructor.call();
clone.options = Object.assign({}, this.options);
// Pass 'finish' event to clone for Stream-based input
this.on('finish', function () {
// Clone inherits input data
that._flattenBufferIn();
clone.options.bufferIn = that.options.bufferIn;
clone.emit('finish');
});
if (this._isStreamInput()) {
this.on('finish', function () {
// Clone inherits input data
that._flattenBufferIn();
clone.options.bufferIn = that.options.bufferIn;
clone.emit('finish');
});
}
return clone;
}
@@ -161,8 +177,8 @@ function clone () {
* A Promises/A+ promise is returned when `callback` is not provided.
*
* - `format`: Name of decoder used to decompress image data e.g. `jpeg`, `png`, `webp`, `gif`, `svg`
* - `width`: Number of pixels wide
* - `height`: Number of pixels high
* - `width`: Number of pixels wide (EXIF orientation is not taken into consideration)
* - `height`: Number of pixels high (EXIF orientation is not taken into consideration)
* - `space`: Name of colour space interpretation e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://github.com/jcupitt/libvips/blob/master/libvips/iofuncs/enumtypes.c#L636)
* - `channels`: Number of bands e.g. `3` for sRGB, `4` for CMYK
* - `depth`: Name of pixel depth format e.g. `uchar`, `char`, `ushort`, `float` [...](https://github.com/jcupitt/libvips/blob/master/libvips/iofuncs/enumtypes.c#L672)
@@ -172,6 +188,8 @@ function clone () {
* - `orientation`: Number value of the EXIF Orientation header, if present
* - `exif`: Buffer containing raw EXIF data, if present
* - `icc`: Buffer containing raw [ICC](https://www.npmjs.com/package/icc) profile data, if present
* - `iptc`: Buffer containing raw IPTC data, if present
* - `xmp`: Buffer containing raw XMP data, if present
*
* @example
* const image = sharp(inputJpg);
@@ -230,6 +248,75 @@ function metadata (callback) {
}
}
/**
* Access to pixel-derived image statistics for every channel in the image.
* A Promise is returned when `callback` is not provided.
*
* - `channels`: Array of channel statistics for each channel in the image. Each channel statistic contains
* - `min` (minimum value in the channel)
* - `max` (maximum value in the channel)
* - `sum` (sum of all values in a channel)
* - `squaresSum` (sum of squared values in a channel)
* - `mean` (mean of the values in a channel)
* - `stdev` (standard deviation for the values in a channel)
* - `minX` (x-coordinate of one of the pixel where the minimum lies)
* - `minY` (y-coordinate of one of the pixel where the minimum lies)
* - `maxX` (x-coordinate of one of the pixel where the maximum lies)
* - `maxY` (y-coordinate of one of the pixel where the maximum lies)
* - `isOpaque`: Value to identify if the image is opaque or transparent, based on the presence and use of alpha channel
* - `entropy`: Histogram-based estimation of greyscale entropy, discarding alpha channel if any (experimental)
*
* @example
* const image = sharp(inputJpg);
* image
* .stats()
* .then(function(stats) {
* // stats contains the channel-wise statistics array and the isOpaque value
* });
*
* @param {Function} [callback] - called with the arguments `(err, stats)`
* @returns {Promise<Object>}
*/
function stats (callback) {
const that = this;
if (is.fn(callback)) {
if (this._isStreamInput()) {
this.on('finish', function () {
that._flattenBufferIn();
sharp.stats(that.options, callback);
});
} else {
sharp.stats(this.options, callback);
}
return this;
} else {
if (this._isStreamInput()) {
return new Promise(function (resolve, reject) {
that.on('finish', function () {
that._flattenBufferIn();
sharp.stats(that.options, function (err, stats) {
if (err) {
reject(err);
} else {
resolve(stats);
}
});
});
});
} else {
return new Promise(function (resolve, reject) {
sharp.stats(that.options, function (err, stats) {
if (err) {
reject(err);
} else {
resolve(stats);
}
});
});
}
}
}
/**
* Do not process input images where the number of pixels (width * height) exceeds this limit.
* Assumes image dimensions contained in the input metadata can be trusted.
@@ -256,6 +343,9 @@ function limitInputPixels (limit) {
/**
* An advanced setting that switches the libvips access method to `VIPS_ACCESS_SEQUENTIAL`.
* This will reduce memory usage and can improve performance on some systems.
*
* The default behaviour *before* function call is `false`, meaning the libvips access method is not sequential.
*
* @param {Boolean} [sequentialRead=true]
* @returns {Sharp}
*/
@@ -278,6 +368,7 @@ module.exports = function (Sharp) {
// Public
clone,
metadata,
stats,
limitInputPixels,
sequentialRead
].forEach(function (f) {

82
lib/libvips.js Normal file
View File

@@ -0,0 +1,82 @@
'use strict';
const fs = require('fs');
const os = require('os');
const path = require('path');
const spawnSync = require('child_process').spawnSync;
const semver = require('semver');
const platform = require('./platform');
const env = process.env;
const minimumLibvipsVersion = env.npm_package_config_libvips || require('../package.json').config.libvips;
const spawnSyncOptions = {
encoding: 'utf8',
shell: true
};
const cachePath = function () {
const npmCachePath = env.npm_config_cache || (env.APPDATA ? path.join(env.APPDATA, 'npm-cache') : path.join(os.homedir(), '.npm'));
if (!fs.existsSync(npmCachePath)) {
fs.mkdirSync(npmCachePath);
}
const libvipsCachePath = path.join(npmCachePath, '_libvips');
if (!fs.existsSync(libvipsCachePath)) {
fs.mkdirSync(libvipsCachePath);
}
return libvipsCachePath;
};
const globalLibvipsVersion = function () {
if (process.platform !== 'win32') {
const globalLibvipsVersion = spawnSync(`PKG_CONFIG_PATH="${pkgConfigPath()}" pkg-config --modversion vips-cpp`, spawnSyncOptions).stdout || '';
return globalLibvipsVersion.trim();
} else {
return '';
}
};
const hasVendoredLibvips = function () {
const currentPlatformId = platform();
let vendorPlatformId;
try {
vendorPlatformId = require(path.join(__dirname, '..', 'vendor', 'platform.json'));
} catch (err) {}
if (vendorPlatformId) {
if (currentPlatformId === vendorPlatformId) {
return true;
} else {
throw new Error(`'${vendorPlatformId}' binaries cannot be used on the '${currentPlatformId}' platform. Please remove the 'node_modules/sharp/vendor' directory and run 'npm install'.`);
}
}
return false;
};
const pkgConfigPath = function () {
if (process.platform !== 'win32') {
const brewPkgConfigPath = spawnSync('which brew >/dev/null 2>&1 && eval $(brew --env) && echo $PKG_CONFIG_LIBDIR', spawnSyncOptions).stdout || '';
return [brewPkgConfigPath.trim(), env.PKG_CONFIG_PATH, '/usr/local/lib/pkgconfig', '/usr/lib/pkgconfig']
.filter(function (p) { return !!p; })
.join(':');
} else {
return '';
}
};
const useGlobalLibvips = function () {
if (Boolean(env.SHARP_IGNORE_GLOBAL_LIBVIPS) === true) {
return false;
}
const globalVipsVersion = globalLibvipsVersion();
return !!globalVipsVersion && semver.gte(globalVipsVersion, minimumLibvipsVersion);
};
module.exports = {
minimumLibvipsVersion: minimumLibvipsVersion,
cachePath: cachePath,
globalLibvipsVersion: globalLibvipsVersion,
hasVendoredLibvips: hasVendoredLibvips,
pkgConfigPath: pkgConfigPath,
useGlobalLibvips: useGlobalLibvips
};

View File

@@ -156,6 +156,26 @@ function sharpen (sigma, flat, jagged) {
return this;
}
/**
* Apply median filter.
* When used without parameters the default window is 3x3.
* @param {Number} [size=3] square mask size: size x size
* @returns {Sharp}
* @throws {Error} Invalid parameters
*/
function median (size) {
if (!is.defined(size)) {
// No arguments: default to 3x3
this.options.medianSize = 3;
} else if (is.integer(size) && is.inRange(size, 1, 1000)) {
// Numeric argument: specific sigma
this.options.medianSize = size;
} else {
throw new Error('Invalid median size ' + size);
}
return this;
}
/**
* Blur the image.
* When used without parameters, performs a fast, mild blur of the output image.
@@ -332,7 +352,7 @@ function convolve (kernel) {
!is.integer(kernel.width) || !is.integer(kernel.height) ||
!is.inRange(kernel.width, 3, 1001) || !is.inRange(kernel.height, 3, 1001) ||
kernel.height * kernel.width !== kernel.kernel.length
) {
) {
// must pass in a kernel
throw new Error('Invalid convolution kernel');
}
@@ -406,6 +426,33 @@ function boolean (operand, operator, options) {
return this;
}
/**
* Apply the linear formula a * input + b to the image (levels adjustment)
* @param {Number} [a=1.0] multiplier
* @param {Number} [b=0.0] offset
* @returns {Sharp}
* @throws {Error} Invalid parameters
*/
function linear (a, b) {
if (!is.defined(a)) {
this.options.linearA = 1.0;
} else if (is.number(a)) {
this.options.linearA = a;
} else {
throw new Error('Invalid linear transform multiplier ' + a);
}
if (!is.defined(b)) {
this.options.linearB = 0.0;
} else if (is.number(b)) {
this.options.linearB = b;
} else {
throw new Error('Invalid linear transform offset ' + b);
}
return this;
}
/**
* Decorate the Sharp prototype with operation-related functions.
* @private
@@ -417,6 +464,7 @@ module.exports = function (Sharp) {
flip,
flop,
sharpen,
median,
blur,
extend,
flatten,
@@ -427,7 +475,8 @@ module.exports = function (Sharp) {
normalize,
convolve,
threshold,
boolean
boolean,
linear
].forEach(function (f) {
Sharp.prototype[f.name] = f;
});

View File

@@ -10,12 +10,23 @@ const sharp = require('../build/Release/sharp.node');
* with JPEG, PNG, WebP, TIFF, DZI, and libvips' V format supported.
* Note that raw pixel data is only supported for buffer output.
*
* A Promises/A+ promise is returned when `callback` is not provided.
* A `Promise` is returned when `callback` is not provided.
*
* @example
* sharp(input)
* .toFile('output.png', (err, info) => { ... });
*
* @example
* sharp(input)
* .toFile('output.png')
* .then(info => { ... })
* .catch(err => { ... });
*
* @param {String} fileOut - the path to write the image data to.
* @param {Function} [callback] - called on completion with two arguments `(err, info)`.
* `info` contains the output image `format`, `size` (bytes), `width`, `height`,
* `channels` and `premultiplied` (indicating if premultiplication was used).
* When using a crop strategy also contains `cropOffsetLeft` and `cropOffsetTop`.
* @returns {Promise<Object>} - when no callback is provided
* @throws {Error} Invalid parameters
*/
@@ -53,7 +64,25 @@ function toFile (fileOut, callback) {
* - `data` is the output image data.
* - `info` contains the output image `format`, `size` (bytes), `width`, `height`,
* `channels` and `premultiplied` (indicating if premultiplication was used).
* A Promise is returned when `callback` is not provided.
* When using a crop strategy also contains `cropOffsetLeft` and `cropOffsetTop`.
*
* A `Promise` is returned when `callback` is not provided.
*
* @example
* sharp(input)
* .toBuffer((err, data, info) => { ... });
*
* @example
* sharp(input)
* .toBuffer()
* .then(data => { ... })
* .catch(err => { ... });
*
* @example
* sharp(input)
* .toBuffer({ resolveWithObject: true })
* .then(({ data, info }) => { ... })
* .catch(err => { ... });
*
* @param {Object} [options]
* @param {Boolean} [options.resolveWithObject] Resolve the Promise with an Object containing `data` and `info` properties instead of resolving only with `data`.
@@ -73,6 +102,13 @@ function toBuffer (options, callback) {
* Include all metadata (EXIF, XMP, IPTC) from the input image in the output image.
* The default behaviour, when `withMetadata` is not used, is to strip all metadata and convert to the device-independent sRGB colour space.
* This will also convert to and add a web-friendly sRGB ICC profile.
*
* @example
* sharp('input.jpg')
* .withMetadata()
* .toFile('output-with-metadata.jpg')
* .then(info => { ... });
*
* @param {Object} [withMetadata]
* @param {Number} [withMetadata.orientation] value between 1 and 8, used to update the EXIF `Orientation` tag.
* @returns {Sharp}
@@ -94,6 +130,16 @@ function withMetadata (withMetadata) {
/**
* Use these JPEG options for output image.
*
* @example
* // Convert any input to very high quality JPEG output
* const data = await sharp(input)
* .jpeg({
* quality: 100,
* chromaSubsampling: '4:4:4'
* })
* .toBuffer();
*
* @param {Object} [options] - output options
* @param {Number} [options.quality=80] - quality, integer 1-100
* @param {Boolean} [options.progressive=false] - use progressive (interlace) scan
@@ -102,6 +148,10 @@ function withMetadata (withMetadata) {
* @param {Boolean} [options.overshootDeringing=false] - apply overshoot deringing, requires mozjpeg
* @param {Boolean} [options.optimiseScans=false] - optimise progressive scans, forces progressive, requires mozjpeg
* @param {Boolean} [options.optimizeScans=false] - alternative spelling of optimiseScans
* @param {Boolean} [options.optimiseCoding=true] - optimise Huffman coding tables
* @param {Boolean} [options.optimizeCoding=true] - alternative spelling of optimiseCoding
* @param {Number} [options.quantisationTable=0] - quantization table to use, integer 0-8, requires mozjpeg
* @param {Number} [options.quantizationTable=0] - alternative spelling of quantisationTable
* @param {Boolean} [options.force=true] - force JPEG output, otherwise attempt to use input format
* @returns {Sharp}
* @throws {Error} Invalid options
@@ -139,16 +189,38 @@ function jpeg (options) {
this.options.jpegProgressive = true;
}
}
options.optimiseCoding = is.bool(options.optimizeCoding) ? options.optimizeCoding : options.optimiseCoding;
if (is.defined(options.optimiseCoding)) {
this._setBooleanOption('jpegOptimiseCoding', options.optimiseCoding);
}
options.quantisationTable = is.number(options.quantizationTable) ? options.quantizationTable : options.quantisationTable;
if (is.defined(options.quantisationTable)) {
if (is.integer(options.quantisationTable) && is.inRange(options.quantisationTable, 0, 8)) {
this.options.jpegQuantisationTable = options.quantisationTable;
} else {
throw new Error('Invalid quantisation table (integer, 0-8) ' + options.quantisationTable);
}
}
}
return this._updateFormatOut('jpeg', options);
}
/**
* Use these PNG options for output image.
*
* PNG output is always full colour at 8 or 16 bits per pixel.
* Indexed PNG input at 1, 2 or 4 bits per pixel is converted to 8 bits per pixel.
*
* @example
* // Convert any input to PNG output
* const data = await sharp(input)
* .png()
* .toBuffer();
*
* @param {Object} [options]
* @param {Boolean} [options.progressive=false] - use progressive (interlace) scan
* @param {Number} [options.compressionLevel=6] - zlib compression level
* @param {Boolean} [options.adaptiveFiltering=true] - use adaptive row filtering
* @param {Number} [options.compressionLevel=9] - zlib compression level, 0-9
* @param {Boolean} [options.adaptiveFiltering=false] - use adaptive row filtering
* @param {Boolean} [options.force=true] - force PNG output, otherwise attempt to use input format
* @returns {Sharp}
* @throws {Error} Invalid options
@@ -174,6 +246,13 @@ function png (options) {
/**
* Use these WebP options for output image.
*
* @example
* // Convert any input to lossless WebP output
* const data = await sharp(input)
* .webp({ lossless: true })
* .toBuffer();
*
* @param {Object} [options] - output options
* @param {Number} [options.quality=80] - quality, integer 1-100
* @param {Number} [options.alphaQuality=100] - quality of alpha layer, integer 0-100
@@ -192,10 +271,10 @@ function webp (options) {
}
}
if (is.object(options) && is.defined(options.alphaQuality)) {
if (is.integer(options.alphaQuality) && is.inRange(options.alphaQuality, 1, 100)) {
if (is.integer(options.alphaQuality) && is.inRange(options.alphaQuality, 0, 100)) {
this.options.webpAlphaQuality = options.alphaQuality;
} else {
throw new Error('Invalid webp alpha quality (integer, 1-100) ' + options.alphaQuality);
throw new Error('Invalid webp alpha quality (integer, 0-100) ' + options.alphaQuality);
}
}
if (is.object(options) && is.defined(options.lossless)) {
@@ -209,11 +288,22 @@ function webp (options) {
/**
* Use these TIFF options for output image.
*
* @example
* // Convert SVG input to LZW-compressed, 1 bit per pixel TIFF output
* sharp('input.svg')
* .tiff({
* compression: 'lzw',
* squash: true
* })
* .toFile('1-bpp-output.tiff')
* .then(info => { ... });
*
* @param {Object} [options] - output options
* @param {Number} [options.quality=80] - quality, integer 1-100
* @param {Boolean} [options.force=true] - force TIFF output, otherwise attempt to use input format
* @param {Boolean} [options.compression='jpeg'] - compression options: lzw, deflate, jpeg
* @param {Boolean} [options.predictor='none'] - compression predictor options: none, horizontal, float
* @param {Boolean} [options.compression='jpeg'] - compression options: lzw, deflate, jpeg, ccittfax4
* @param {Boolean} [options.predictor='horizontal'] - compression predictor options: none, horizontal, float
* @param {Number} [options.xres=1.0] - horizontal resolution in pixels/mm
* @param {Number} [options.yres=1.0] - vertical resolution in pixels/mm
* @param {Boolean} [options.squash=false] - squash 8-bit images down to 1 bit
@@ -252,10 +342,10 @@ function tiff (options) {
}
// compression
if (is.defined(options) && is.defined(options.compression)) {
if (is.string(options.compression) && is.inArray(options.compression, ['lzw', 'deflate', 'jpeg', 'none'])) {
if (is.string(options.compression) && is.inArray(options.compression, ['lzw', 'deflate', 'jpeg', 'ccittfax4', 'none'])) {
this.options.tiffCompression = options.compression;
} else {
const message = `Invalid compression option "${options.compression}". Should be one of: lzw, deflate, jpeg, none`;
const message = `Invalid compression option "${options.compression}". Should be one of: lzw, deflate, jpeg, ccittfax4, none`;
throw new Error(message);
}
}
@@ -273,6 +363,13 @@ function tiff (options) {
/**
* Force output to be raw, uncompressed uint8 pixel data.
*
* @example
* // Extract raw RGB pixel data from JPEG input
* const { data, info } = await sharp('input.jpg')
* .raw()
* .toBuffer({ resolveWithObject: true });
*
* @returns {Sharp}
*/
function raw () {
@@ -281,6 +378,13 @@ function raw () {
/**
* Force output to a given format.
*
* @example
* // Convert any input to PNG output
* const data = await sharp(input)
* .toFormat('png')
* .toBuffer();
*
* @param {(String|Object)} format - as a String or an Object with an 'id' attribute
* @param {Object} options - output options
* @returns {Sharp}
@@ -302,6 +406,8 @@ function toFormat (format, options) {
* Set the format and options for tile images via the `toFormat`, `jpeg`, `png` or `webp` functions.
* Use a `.zip` or `.szi` file extension with `toFile` to write to a compressed archive file format.
*
* Warning: multiple sharp instances concurrently producing tile output can expose a possible race condition in some versions of libgsf.
*
* @example
* sharp('input.tiff')
* .png()
@@ -316,6 +422,8 @@ function toFormat (format, options) {
* @param {Object} [tile]
* @param {Number} [tile.size=256] tile size in pixels, a value between 1 and 8192.
* @param {Number} [tile.overlap=0] tile overlap in pixels, a value between 0 and 8192.
* @param {Number} [tile.angle=0] tile angle of rotation, must be a multiple of 90.
* @param {String} [tile.depth] how deep to make the pyramid, possible values are `onepixel`, `onetile` or `one`, default based on layout.
* @param {String} [tile.container='fs'] tile container, with value `fs` (filesystem) or `zip` (compressed file).
* @param {String} [tile.layout='dz'] filesystem layout, possible values are `dz`, `zoomify` or `google`.
* @returns {Sharp}
@@ -358,6 +466,24 @@ function tile (tile) {
throw new Error('Invalid tile layout ' + tile.layout);
}
}
// Angle of rotation,
if (is.defined(tile.angle)) {
if (is.integer(tile.angle) && !(tile.angle % 90)) {
this.options.tileAngle = tile.angle;
} else {
throw new Error('Unsupported angle: angle must be a positive/negative multiple of 90 ' + tile.angle);
}
}
// Depth of tiles
if (is.defined(tile.depth)) {
if (is.string(tile.depth) && is.inArray(tile.depth, ['onepixel', 'onetile', 'one'])) {
this.options.tileDepth = tile.depth;
} else {
throw new Error("Invalid tile depth '" + tile.depth + "', should be one of 'onepixel', 'onetile' or 'one'");
}
}
}
// Format
if (is.inArray(this.options.formatOut, ['jpeg', 'png', 'webp'])) {
@@ -365,6 +491,7 @@ function tile (tile) {
} else if (this.options.formatOut !== 'input') {
throw new Error('Invalid tile format ' + this.options.formatOut);
}
return this._updateFormatOut('dz');
}

15
lib/platform.js Normal file
View File

@@ -0,0 +1,15 @@
'use strict';
module.exports = function () {
const arch = process.env.npm_config_arch || process.arch;
const platform = process.env.npm_config_platform || process.platform;
const platformId = [platform];
if (arch === 'arm' || arch === 'armhf' || arch === 'arm64') {
const armVersion = (arch === 'arm64') ? '8' : process.env.npm_config_armv || process.config.variables.arm_version || '6';
platformId.push(`armv${armVersion}`);
} else {
platformId.push(arch);
}
return platformId.join('-');
};

View File

@@ -42,52 +42,27 @@ const kernel = {
lanczos3: 'lanczos3'
};
/**
* Enlargement interpolators.
* @member
* @private
*/
const interpolator = {
nearest: 'nearest',
bilinear: 'bilinear',
bicubic: 'bicubic',
nohalo: 'nohalo',
lbb: 'lbb',
locallyBoundedBicubic: 'lbb',
vsqbs: 'vsqbs',
vertexSplitQuadraticBasisSpline: 'vsqbs'
};
/**
* Resize image to `width` x `height`.
* By default, the resized image is centre cropped to the exact size specified.
*
* Possible reduction kernels are:
* Possible kernels are:
* - `nearest`: Use [nearest neighbour interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation).
* - `cubic`: Use a [Catmull-Rom spline](https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline).
* - `lanczos2`: Use a [Lanczos kernel](https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel) with `a=2`.
* - `lanczos3`: Use a Lanczos kernel with `a=3` (the default).
*
* Possible enlargement interpolators are:
* - `nearest`: Use [nearest neighbour interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation).
* - `bilinear`: Use [bilinear interpolation](http://en.wikipedia.org/wiki/Bilinear_interpolation), faster than bicubic but with less smooth results.
* - `vertexSplitQuadraticBasisSpline`: Use the smoother [VSQBS interpolation](https://github.com/jcupitt/libvips/blob/master/libvips/resample/vsqbs.cpp#L48) to prevent "staircasing" when enlarging.
* - `bicubic`: Use [bicubic interpolation](http://en.wikipedia.org/wiki/Bicubic_interpolation) (the default).
* - `locallyBoundedBicubic`: Use [LBB interpolation](https://github.com/jcupitt/libvips/blob/master/libvips/resample/lbb.cpp#L100), which prevents some "[acutance](http://en.wikipedia.org/wiki/Acutance)" but typically reduces performance by a factor of 2.
* - `nohalo`: Use [Nohalo interpolation](http://eprints.soton.ac.uk/268086/), which prevents acutance but typically reduces performance by a factor of 3.
*
* @example
* sharp(inputBuffer)
* .resize(200, 300, {
* kernel: sharp.kernel.lanczos2,
* interpolator: sharp.interpolator.nohalo
* kernel: sharp.kernel.nearest
* })
* .background('white')
* .embed()
* .toFile('output.tiff')
* .then(function() {
* // output.tiff is a 200 pixels wide and 300 pixels high image
* // containing a lanczos2/nohalo scaled version, embedded on a white canvas,
* // containing a nearest-neighbour scaled version, embedded on a white canvas,
* // of the image data in inputBuffer
* });
*
@@ -95,9 +70,7 @@ const interpolator = {
* @param {Number} [height] - pixels high the resultant image should be. Use `null` or `undefined` to auto-scale the height to match the width.
* @param {Object} [options]
* @param {String} [options.kernel='lanczos3'] - the kernel to use for image reduction.
* @param {String} [options.interpolator='bicubic'] - the interpolator to use for image enlargement.
* @param {Boolean} [options.centreSampling=false] - use *magick centre sampling convention instead of corner sampling.
* @param {Boolean} [options.centerSampling=false] - alternative spelling of centreSampling.
* @param {Boolean} [options.fastShrinkOnLoad=true] - take greater advantage of the JPEG and WebP shrink-on-load feature, which can lead to a slight moiré pattern on some images.
* @returns {Sharp}
* @throws {Error} Invalid parameters
*/
@@ -129,18 +102,9 @@ function resize (width, height, options) {
throw is.invalidParameterError('kernel', 'valid kernel name', options.kernel);
}
}
// Interpolator
if (is.defined(options.interpolator)) {
if (is.string(interpolator[options.interpolator])) {
this.options.interpolator = interpolator[options.interpolator];
} else {
throw is.invalidParameterError('interpolator', 'valid interpolator name', options.interpolator);
}
}
// Centre sampling
options.centreSampling = is.bool(options.centerSampling) ? options.centerSampling : options.centreSampling;
if (is.defined(options.centreSampling)) {
this._setBooleanOption('centreSampling', options.centreSampling);
// Shrink on load
if (is.defined(options.fastShrinkOnLoad)) {
this._setBooleanOption('fastShrinkOnLoad', options.fastShrinkOnLoad);
}
}
return this;
@@ -215,11 +179,26 @@ function crop (crop) {
* // outputBuffer contains WebP image data of a 200 pixels wide and 300 pixels high
* // containing a scaled version, embedded on a transparent canvas, of input.gif
* });
*
* @param {String} [embed='centre'] - A member of `sharp.gravity` to embed to an edge/corner.
* @returns {Sharp}
* @throws {Error} Invalid parameters
*/
function embed () {
function embed (embed) {
this.options.canvas = 'embed';
if (!is.defined(embed)) {
// Default
this.options.embed = gravity.center;
} else if (is.integer(embed) && is.inRange(embed, 0, 8)) {
// Gravity (numeric)
this.options.embed = embed;
} else if (is.string(embed) && is.integer(gravity[embed])) {
// Gravity (string)
this.options.embed = gravity[embed];
} else {
throw is.invalidParameterError('embed', 'valid embed id/name', embed);
}
return this;
}
@@ -274,6 +253,10 @@ function ignoreAspectRatio () {
* Do not enlarge the output image if the input image width *or* height are already less than the required dimensions.
* This is equivalent to GraphicsMagick's `>` geometry option:
* "*change the dimensions of the image only if its width or height exceeds the geometry specification*".
* Use with `max()` to preserve the image's aspect ratio.
*
* The default behaviour *before* function call is `false`, meaning the image will be enlarged.
*
* @param {Boolean} [withoutEnlargement=true]
* @returns {Sharp}
*/
@@ -302,5 +285,4 @@ module.exports = function (Sharp) {
Sharp.gravity = gravity;
Sharp.strategy = strategy;
Sharp.kernel = kernel;
Sharp.interpolator = interpolator;
};

View File

@@ -5,6 +5,8 @@ site_description: High performance Node.js image processing, the fastest module
copyright: <a href="https://pixelplumbing.com/">pixelplumbing.com</a>
google_analytics: ['UA-13034748-12', 'sharp.pixelplumbing.com']
theme: readthedocs
extra_css:
- css/extra.css
markdown_extensions:
- toc:
permalink: True

View File

@@ -1,7 +1,7 @@
{
"name": "sharp",
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP and TIFF images",
"version": "0.18.3",
"version": "0.20.7",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://github.com/lovell/sharp",
"contributors": [
@@ -38,14 +38,29 @@
"YvesBos <yves_bos@outlook.com>",
"Guy Maliar <guy@tailorbrands.com>",
"Nicolas Coden <nicolas@ncoden.fr>",
"Matt Parrish <matt.r.parrish@gmail.com>"
"Matt Parrish <matt.r.parrish@gmail.com>",
"Marcel Bretschneider <marcel.bretschneider@gmail.com>",
"Matthew McEachen <matthew+github@mceachen.org>",
"Jarda Kotěšovec <jarda.kotesovec@gmail.com>",
"Kenric D'Souza <kenric.dsouza@gmail.com>",
"Oleh Aleinyk <oleg.aleynik@gmail.com>",
"Marcel Bretschneider <marcel.bretschneider@gmail.com>",
"Andrea Bianco <andrea.bianco@unibas.ch>",
"Rik Heywood <rik@rik.org>",
"Thomas Parisot <hi@oncletom.io>",
"Nathan Graves <nathanrgraves+github@gmail.com>",
"Tom Lokhorst <tom@lokhorst.eu>",
"Espen Hovlandsdal <espen@hovlandsdal.com>",
"Sylvain Dumont <sylvain.dumont35@gmail.com>",
"Alun Davies <alun.owain.davies@googlemail.com>"
],
"scripts": {
"install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node-gyp rebuild && node install/dll-copy)",
"clean": "rm -rf node_modules/ build/ vendor/ coverage/ test/fixtures/output.*",
"test": "semistandard && cc && nyc --reporter=lcov --branches=99 mocha --slow=5000 --timeout=60000 ./test/unit/*.js",
"test": "semistandard && cc && nyc --reporter=lcov --branches=99 mocha --slow=5000 --timeout=60000 ./test/unit/*.js && prebuild-ci",
"coverage": "./test/coverage/report.sh",
"test-leak": "./test/leak/leak.sh",
"test-packaging": "./packaging/test-linux-x64.sh",
"docs": "for m in constructor input resize composite operation colour channel output utility; do documentation build --shallow --format=md lib/$m.js >docs/api-$m.md; done"
"docs": "for m in constructor input resize composite operation colour channel output utility; do documentation build --shallow --format=md --markdown-toc=false lib/$m.js >docs/api-$m.md; done"
},
"main": "lib/index.js",
"repository": {
@@ -64,33 +79,39 @@
"resize",
"thumbnail",
"crop",
"embed",
"libvips",
"vips"
],
"dependencies": {
"caw": "^2.0.0",
"color": "^2.0.0",
"detect-libc": "^0.2.0",
"nan": "^2.6.2",
"semver": "^5.3.0",
"simple-get": "^2.7.0",
"tar": "^3.1.5"
"color": "^3.0.0",
"detect-libc": "^1.0.3",
"nan": "^2.10.0",
"fs-copy-file-sync": "^1.1.1",
"npmlog": "^4.1.2",
"prebuild-install": "^4.0.0",
"semver": "^5.5.1",
"simple-get": "^2.8.1",
"tar": "^4.4.6",
"tunnel-agent": "^0.6.0"
},
"devDependencies": {
"async": "^2.5.0",
"cc": "^1.0.1",
"documentation": "^4.0.0-rc.1",
"async": "^2.6.1",
"cc": "^1.0.2",
"decompress-zip": "^0.3.1",
"documentation": "^8.1.1",
"exif-reader": "^1.0.2",
"icc": "^1.0.0",
"mocha": "^3.4.2",
"nyc": "^11.0.3",
"rimraf": "^2.6.1",
"semistandard": "^11.0.0",
"unzip": "^0.1.11"
"mocha": "^5.2.0",
"nyc": "^12.0.2",
"prebuild": "^7.6.2",
"prebuild-ci": "^2.2.3",
"rimraf": "^2.6.2",
"semistandard": "^12.0.1"
},
"license": "Apache-2.0",
"config": {
"libvips": "8.5.5"
"libvips": "8.6.1"
},
"engines": {
"node": ">=4.5.0"
@@ -105,7 +126,8 @@
"filter": [
"build/c++11",
"build/include",
"runtime/indentation_namespace"
"runtime/indentation_namespace",
"runtime/references"
]
}
}

View File

@@ -1,57 +0,0 @@
# Packaging scripts
libvips and its dependencies are provided as pre-compiled shared libraries
for the most common operating systems and CPU architectures.
During `npm install`, these binaries are fetched as tarballs from
[Bintray](https://dl.bintray.com/lovell/sharp/) via HTTPS
and stored locally within `node_modules/sharp`.
## Using a custom tarball
A custom tarball stored on the local filesystem can be used instead.
Place it in the following location, where `x.y.z` is the libvips version,
`platform` is the value of `process.platform` and
`arch` is the value of `process.arch` (plus the version number for ARM).
`node_modules/sharp/packaging/libvips-x.y.z-platform-arch.tar.gz`
For example, for libvips v8.3.3 on an ARMv6 Linux machine, use:
`node_modules/sharp/packaging/libvips-8.3.3-linux-armv6.tar.gz`
Remove any `sharp/lib` and `sharp/include` directories
before running `npm install` again.
## Creating a tarball
Most people will not need to do this; proceed with caution.
The `packaging` directory contains the top-level [build script](build.sh).
### Linux
One [build script](build/lin.sh) is used to (cross-)compile
the same shared libraries within multiple containers.
* [x64](linux-x64/Dockerfile)
* [ARMv6](linux-armv6/Dockerfile)
* [ARMv7-A](linux-armv7/Dockerfile)
* [ARMv8-A](linux-armv8/Dockerfile)
The QEMU user mode emulation binaries are required to build for
the ARMv6 platform as the Debian armhf cross-compiler erroneously
generates unsupported Thumb 2 instructions.
```sh
sudo apt-get install qemu-user-static
```
### Windows
The output of libvips' [build-win64](https://github.com/jcupitt/build-win64)
"web" target is [post-processed](build/win.sh) within a [container](win32-x64/Dockerfile).
### OS X
See [package-libvips-darwin](https://github.com/lovell/package-libvips-darwin).

View File

@@ -1,48 +0,0 @@
#!/bin/sh
set -e
if [ $# -lt 1 ]; then
echo
echo "Usage: $0 VERSION [PLATFORM]"
echo "Build shared libraries for libvips and its dependencies via containers"
echo
echo "Please specify the libvips VERSION, e.g. 8.3.3"
echo
echo "Optionally build for only one PLATFORM, defaults to building for all"
echo "Possible values for PLATFORM are: win32-x64, linux-x64, linux-armv6,"
echo "linux-armv7, linux-armv8"
echo
exit 1
fi
VERSION_VIPS="$1"
PLATFORM="${2:-all}"
# Is docker available?
if ! type docker >/dev/null; then
echo "Please install docker"
exit 1
fi
# Update base images
for baseimage in debian:wheezy debian:jessie debian:stretch socialdefect/raspbian-jessie-core; do
docker pull $baseimage
done
# Windows (x64)
if [ $PLATFORM = "all" ] || [ $PLATFORM = "win32-x64" ]; then
echo "Building win32-x64..."
docker build -t vips-dev-win32-x64 win32-x64
docker run --rm -e "VERSION_VIPS=${VERSION_VIPS}" -v $PWD:/packaging vips-dev-win32-x64 sh -c "/packaging/build/win.sh"
fi
# Linux (x64, ARMv6, ARMv7, ARMv8)
for flavour in linux-x64 linux-armv6 linux-armv7 linux-armv8; do
if [ $PLATFORM = "all" ] || [ $PLATFORM = $flavour ]; then
echo "Building $flavour..."
docker build -t vips-dev-$flavour $flavour
docker run --rm -e "VERSION_VIPS=${VERSION_VIPS}" -v $PWD:/packaging vips-dev-$flavour sh -c "/packaging/build/lin.sh"
fi
done
# Display checksums
sha256sum *.tar.gz

View File

@@ -1,256 +0,0 @@
#!/bin/sh
set -e
# Working directories
DEPS=/deps
TARGET=/target
mkdir ${DEPS}
mkdir ${TARGET}
# Common build paths and flags
export PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:${TARGET}/lib/pkgconfig"
export PATH="${PATH}:${TARGET}/bin"
export CPPFLAGS="-I${TARGET}/include"
export LDFLAGS="-L${TARGET}/lib"
export CFLAGS="${FLAGS}"
export CXXFLAGS="${FLAGS}"
# Dependency version numbers
VERSION_ZLIB=1.2.11
VERSION_FFI=3.2.1
VERSION_GLIB=2.53.1
VERSION_XML2=2.9.4
VERSION_GSF=1.14.41
VERSION_EXIF=0.6.21
VERSION_LCMS2=2.8
VERSION_JPEG=1.5.1
VERSION_PNG16=1.6.29
VERSION_WEBP=0.6.0
VERSION_TIFF=4.0.7
VERSION_ORC=0.4.26
VERSION_GDKPIXBUF=2.36.6
VERSION_FREETYPE=2.8
VERSION_EXPAT=2.2.0
VERSION_FONTCONFIG=2.12.1
VERSION_HARFBUZZ=1.4.6
VERSION_PIXMAN=0.34.0
VERSION_CAIRO=1.14.8
VERSION_PANGO=1.40.5
VERSION_CROCO=0.6.12
VERSION_SVG=2.40.17
VERSION_GIF=5.1.4
# Least out-of-sync Sourceforge mirror
SOURCEFORGE_MIRROR=netix
mkdir ${DEPS}/zlib
curl -Ls http://zlib.net/zlib-${VERSION_ZLIB}.tar.xz | tar xJC ${DEPS}/zlib --strip-components=1
cd ${DEPS}/zlib
./configure --prefix=${TARGET} --uname=linux
make install
rm ${TARGET}/lib/libz.a
mkdir ${DEPS}/ffi
curl -Ls ftp://sourceware.org/pub/libffi/libffi-${VERSION_FFI}.tar.gz | tar xzC ${DEPS}/ffi --strip-components=1
cd ${DEPS}/ffi
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking --disable-builddir
make install-strip
mkdir ${DEPS}/glib
curl -Ls https://download.gnome.org/sources/glib/2.53/glib-${VERSION_GLIB}.tar.xz | tar xJC ${DEPS}/glib --strip-components=1
cd ${DEPS}/glib
echo glib_cv_stack_grows=no >>glib.cache
echo glib_cv_uscore=no >>glib.cache
./configure --cache-file=glib.cache --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking \
--with-pcre=internal --disable-libmount
make install-strip
mkdir ${DEPS}/xml2
curl -Ls http://xmlsoft.org/sources/libxml2-${VERSION_XML2}.tar.gz | tar xzC ${DEPS}/xml2 --strip-components=1
cd ${DEPS}/xml2
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking \
--without-python --without-debug --without-docbook --without-ftp --without-html --without-legacy \
--without-pattern --without-push --without-regexps --without-schemas --without-schematron --with-zlib=${TARGET}
make install-strip
mkdir ${DEPS}/gsf
curl -Ls https://download.gnome.org/sources/libgsf/1.14/libgsf-${VERSION_GSF}.tar.xz | tar xJC ${DEPS}/gsf --strip-components=1
cd ${DEPS}/gsf
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking
make install-strip
mkdir ${DEPS}/exif
curl -Ls http://${SOURCEFORGE_MIRROR}.dl.sourceforge.net/project/libexif/libexif/${VERSION_EXIF}/libexif-${VERSION_EXIF}.tar.bz2 | tar xjC ${DEPS}/exif --strip-components=1
cd ${DEPS}/exif
autoreconf -fiv
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking
make install-strip
mkdir ${DEPS}/lcms2
curl -Ls http://${SOURCEFORGE_MIRROR}.dl.sourceforge.net/project/lcms/lcms/${VERSION_LCMS2}/lcms2-${VERSION_LCMS2}.tar.gz | tar xzC ${DEPS}/lcms2 --strip-components=1
cd ${DEPS}/lcms2
# Apply patches for lcms2 vulnerabilities reported since v2.8
VERSION_LCMS2_GIT_MASTER_SHA=$(curl -Ls https://api.github.com/repos/mm2/Little-CMS/git/refs/heads/master | jq -r '.object.sha' | head -c7)
curl -Ls https://github.com/mm2/Little-CMS/compare/lcms2.8...master.patch | patch -p1 -t || true
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking
make install-strip
mkdir ${DEPS}/jpeg
curl -Ls https://github.com/libjpeg-turbo/libjpeg-turbo/archive/${VERSION_JPEG}.tar.gz | tar xzC ${DEPS}/jpeg --strip-components=1
cd ${DEPS}/jpeg
autoreconf -fiv
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking --with-jpeg8 --without-turbojpeg
make install-strip
mkdir ${DEPS}/png16
curl -Ls http://${SOURCEFORGE_MIRROR}.dl.sourceforge.net/project/libpng/libpng16/${VERSION_PNG16}/libpng-${VERSION_PNG16}.tar.xz | tar xJC ${DEPS}/png16 --strip-components=1
cd ${DEPS}/png16
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking
make install-strip
mkdir ${DEPS}/webp
curl -Ls http://downloads.webmproject.org/releases/webp/libwebp-${VERSION_WEBP}.tar.gz | tar xzC ${DEPS}/webp --strip-components=1
cd ${DEPS}/webp
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking \
--disable-neon --enable-libwebpmux
make install-strip
mkdir ${DEPS}/tiff
curl -Ls http://download.osgeo.org/libtiff/tiff-${VERSION_TIFF}.tar.gz | tar xzC ${DEPS}/tiff --strip-components=1
cd ${DEPS}/tiff
# Apply patches for libtiff vulnerabilities reported since v4.0.7
VERSION_TIFF_GIT_MASTER_SHA=$(curl -Ls https://api.github.com/repos/vadz/libtiff/git/refs/heads/master | jq -r '.object.sha' | head -c7)
curl -Ls https://github.com/vadz/libtiff/compare/Release-v4-0-7...master.patch | patch -p1 -t || true
if [ -n "${CHOST}" ]; then autoreconf -fiv; fi
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking --disable-mdi --disable-pixarlog --disable-cxx
make install-strip
mkdir ${DEPS}/orc
curl -Ls http://gstreamer.freedesktop.org/data/src/orc/orc-${VERSION_ORC}.tar.xz | tar xJC ${DEPS}/orc --strip-components=1
cd ${DEPS}/orc
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking
make install-strip
cd ${TARGET}/lib
rm -rf liborc-test-*
mkdir ${DEPS}/gdkpixbuf
curl -Ls https://download.gnome.org/sources/gdk-pixbuf/2.36/gdk-pixbuf-${VERSION_GDKPIXBUF}.tar.xz | tar xJC ${DEPS}/gdkpixbuf --strip-components=1
cd ${DEPS}/gdkpixbuf
touch gdk-pixbuf/loaders.cache
LD_LIBRARY_PATH=${TARGET}/lib \
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking \
--disable-introspection --disable-modules --disable-gio-sniffing \
--without-libtiff --without-gdiplus --with-included-loaders=png,jpeg
make install-strip
mkdir ${DEPS}/freetype
curl -Ls http://${SOURCEFORGE_MIRROR}.dl.sourceforge.net/project/freetype/freetype2/${VERSION_FREETYPE}/freetype-${VERSION_FREETYPE}.tar.gz | tar xzC ${DEPS}/freetype --strip-components=1
cd ${DEPS}/freetype
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static
make install
mkdir ${DEPS}/expat
curl -Ls http://${SOURCEFORGE_MIRROR}.dl.sourceforge.net/project/expat/expat/${VERSION_EXPAT}/expat-${VERSION_EXPAT}.tar.bz2 | tar xjC ${DEPS}/expat --strip-components=1
cd ${DEPS}/expat
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static
make install
mkdir ${DEPS}/fontconfig
curl -Ls https://www.freedesktop.org/software/fontconfig/release/fontconfig-${VERSION_FONTCONFIG}.tar.bz2 | tar xjC ${DEPS}/fontconfig --strip-components=1
cd ${DEPS}/fontconfig
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking \
--with-expat-includes=${TARGET}/include --with-expat-lib=${TARGET}/lib --sysconfdir=/etc
make install-strip
mkdir ${DEPS}/harfbuzz
curl -Ls https://www.freedesktop.org/software/harfbuzz/release/harfbuzz-${VERSION_HARFBUZZ}.tar.bz2 | tar xjC ${DEPS}/harfbuzz --strip-components=1
cd ${DEPS}/harfbuzz
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking
make install-strip
mkdir ${DEPS}/pixman
curl -Ls http://cairographics.org/releases/pixman-${VERSION_PIXMAN}.tar.gz | tar xzC ${DEPS}/pixman --strip-components=1
cd ${DEPS}/pixman
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking --disable-libpng --disable-arm-iwmmxt
make install-strip
mkdir ${DEPS}/cairo
curl -Ls http://cairographics.org/releases/cairo-${VERSION_CAIRO}.tar.xz | tar xJC ${DEPS}/cairo --strip-components=1
cd ${DEPS}/cairo
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking \
--disable-xlib --disable-xcb --disable-quartz --disable-win32 --disable-egl --disable-glx --disable-wgl \
--disable-script --disable-ps --disable-gobject --disable-trace --disable-interpreter
make install-strip
mkdir ${DEPS}/pango
curl -Ls https://download.gnome.org/sources/pango/1.40/pango-${VERSION_PANGO}.tar.xz | tar xJC ${DEPS}/pango --strip-components=1
cd ${DEPS}/pango
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking
make install-strip
mkdir ${DEPS}/croco
curl -Ls https://download.gnome.org/sources/libcroco/0.6/libcroco-${VERSION_CROCO}.tar.xz | tar xJC ${DEPS}/croco --strip-components=1
cd ${DEPS}/croco
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking
make install-strip
mkdir ${DEPS}/svg
curl -Ls https://download.gnome.org/sources/librsvg/2.40/librsvg-${VERSION_SVG}.tar.xz | tar xJC ${DEPS}/svg --strip-components=1
cd ${DEPS}/svg
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking --disable-introspection --disable-tools --disable-pixbuf-loader
make install-strip
mkdir ${DEPS}/gif
curl -Ls http://${SOURCEFORGE_MIRROR}.dl.sourceforge.net/project/giflib/giflib-${VERSION_GIF}.tar.gz | tar xzC ${DEPS}/gif --strip-components=1
cd ${DEPS}/gif
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking
make install-strip
mkdir ${DEPS}/vips
curl -Ls https://github.com/jcupitt/libvips/releases/download/v${VERSION_VIPS}/vips-${VERSION_VIPS}.tar.gz | tar xzC ${DEPS}/vips --strip-components=1
cd ${DEPS}/vips
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking \
--disable-debug --disable-introspection --without-python --without-fftw \
--without-magick --without-pangoft2 --without-ppm --without-analyze --without-radiance \
--with-zip-includes=${TARGET}/include --with-zip-libraries=${TARGET}/lib \
--with-jpeg-includes=${TARGET}/include --with-jpeg-libraries=${TARGET}/lib
make install-strip
# Remove the old C++ bindings
cd ${TARGET}/include
rm -rf vips/vipsc++.h vips/vipscpp.h
cd ${TARGET}/lib
rm -rf pkgconfig .libs *.la libvipsCC*
# Create JSON file of version numbers
cd ${TARGET}
echo "{\n\
\"cairo\": \"${VERSION_CAIRO}\",\n\
\"croco\": \"${VERSION_CROCO}\",\n\
\"exif\": \"${VERSION_EXIF}\",\n\
\"expat\": \"${VERSION_EXPAT}\",\n\
\"ffi\": \"${VERSION_FFI}\",\n\
\"fontconfig\": \"${VERSION_FONTCONFIG}\",\n\
\"freetype\": \"${VERSION_FREETYPE}\",\n\
\"gdkpixbuf\": \"${VERSION_GDKPIXBUF}\",\n\
\"gif\": \"${VERSION_GIF}\",\n\
\"glib\": \"${VERSION_GLIB}\",\n\
\"gsf\": \"${VERSION_GSF}\",\n\
\"harfbuzz\": \"${VERSION_HARFBUZZ}\",\n\
\"jpeg\": \"${VERSION_JPEG}\",\n\
\"lcms\": \"${VERSION_LCMS2}-${VERSION_LCMS2_GIT_MASTER_SHA}\",\n\
\"orc\": \"${VERSION_ORC}\",\n\
\"pango\": \"${VERSION_PANGO}\",\n\
\"pixman\": \"${VERSION_PIXMAN}\",\n\
\"png\": \"${VERSION_PNG16}\",\n\
\"svg\": \"${VERSION_SVG}\",\n\
\"tiff\": \"${VERSION_TIFF}-${VERSION_TIFF_GIT_MASTER_SHA}\",\n\
\"vips\": \"${VERSION_VIPS}\",\n\
\"webp\": \"${VERSION_WEBP}\",\n\
\"xml\": \"${VERSION_XML2}\",\n\
\"zlib\": \"${VERSION_ZLIB}\"\n\
}" >lib/versions.json
# Create .tar.gz
tar czf /packaging/libvips-${VERSION_VIPS}-${PLATFORM}.tar.gz include lib
advdef --recompress --shrink-insane /packaging/libvips-${VERSION_VIPS}-${PLATFORM}.tar.gz

View File

@@ -1,19 +0,0 @@
#!/bin/sh
set -e
# Fetch and unzip
mkdir /vips
cd /vips
curl -L -O https://github.com/lovell/build-win64/releases/download/v${VERSION_VIPS}/vips-dev-w64-web-${VERSION_VIPS}.zip
unzip vips-dev-w64-web-${VERSION_VIPS}.zip
# Clean and zip
cd /vips/vips-dev-8.5
rm bin/libvipsCC-42.dll bin/libvips-cpp-42.dll bin/libgsf-win32-1-114.dll
cp bin/*.dll lib/
cp -r lib64/* lib/
echo "Creating tarball"
tar czf /packaging/libvips-${VERSION_VIPS}-${PLATFORM}.tar.gz include lib/glib-2.0 lib/libvips.lib lib/libglib-2.0.lib lib/libgobject-2.0.lib lib/*.dll
echo "Shrinking tarball"
advdef --recompress --shrink-insane /packaging/libvips-${VERSION_VIPS}-${PLATFORM}.tar.gz

View File

@@ -1,15 +0,0 @@
FROM socialdefect/raspbian-jessie-core
MAINTAINER Lovell Fuller <npm@lovell.info>
# Create Rasbian-based container suitable for compiling Linux ARMv6 binaries
# Requires the QEMU user mode emulation binaries on the host machine
# Build dependencies
RUN \
apt-get update && \
apt-get install -y build-essential curl autoconf libtool nasm gtk-doc-tools texinfo advancecomp libglib2.0-dev jq
# Compiler settings
ENV \
PLATFORM=linux-armv6 \
FLAGS="-Os"

View File

@@ -1,20 +0,0 @@
FROM debian:jessie
MAINTAINER Lovell Fuller <npm@lovell.info>
# Create Debian-based container suitable for cross-compiling Linux ARMv7-A binaries
# Build dependencies
RUN \
apt-get update && \
apt-get install -y curl && \
echo "deb http://emdebian.org/tools/debian/ jessie main" | tee /etc/apt/sources.list.d/crosstools.list && \
curl http://emdebian.org/tools/debian/emdebian-toolchain-archive.key | apt-key add - && \
dpkg --add-architecture armhf && \
apt-get update && \
apt-get install -y crossbuild-essential-armhf autoconf libtool nasm gtk-doc-tools texinfo advancecomp libglib2.0-dev jq
# Compiler settings
ENV \
PLATFORM=linux-armv7 \
CHOST=arm-linux-gnueabihf \
FLAGS="-marm -march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard -Os"

View File

@@ -1,18 +0,0 @@
FROM debian:stretch
MAINTAINER Lovell Fuller <npm@lovell.info>
# Create Debian-based container suitable for cross-compiling Linux ARMv8-A binaries
# Build dependencies
RUN \
apt-get update && \
apt-get install -y curl && \
dpkg --add-architecture arm64 && \
apt-get update && \
apt-get install -y crossbuild-essential-arm64 autoconf libtool nasm gtk-doc-tools texinfo advancecomp libglib2.0-dev jq gettext intltool autopoint
# Compiler settings
ENV \
PLATFORM=linux-armv8 \
CHOST=aarch64-linux-gnu \
FLAGS="-march=armv8-a -Os -D_GLIBCXX_USE_CXX11_ABI=0"

View File

@@ -1,16 +0,0 @@
FROM debian:wheezy
MAINTAINER Lovell Fuller <npm@lovell.info>
# Create Debian-based container suitable for building Linux x64 binaries
# Build dependencies
RUN \
echo "deb http://ftp.debian.org/debian wheezy-backports main" | tee /etc/apt/sources.list.d/wheezy-backports.list && \
apt-get update && \
apt-get install -y build-essential autoconf libtool nasm gtk-doc-tools texinfo advancecomp && \
apt-get -t wheezy-backports install -y jq
# Compiler settings
ENV \
PLATFORM="linux-x64" \
FLAGS="-O3"

View File

@@ -1,28 +0,0 @@
#!/bin/sh
if [ $# -lt 1 ]; then
echo "Usage: $0 IP"
echo "Test sharp on ARM using Docker, where IP is"
echo "the address of a Raspberry Pi running HypriotOS"
exit 1
fi
IP="$1"
echo "Verifying connectivity to $IP"
if ! ping -c 1 $IP; then
echo "Could not connect to $IP"
exit 1
fi
if ! type sshpass >/dev/null; then
echo "Please install sshpass"
exit 1
fi
export SSHPASS=hypriot
echo "Copying sharp source to device"
sshpass -e scp -o PreferredAuthentications=password -r ../../sharp pirate@${IP}:/home/pirate/sharp
echo "Compile and test within container"
sshpass -e ssh -o PreferredAuthentications=password -t pirate@${IP} "docker run --rm -v \${PWD}/sharp:/s hypriot/rpi-node:6 sh -c 'cd /s && npm install --unsafe-perm && npm test'"

View File

@@ -1,36 +0,0 @@
#!/bin/sh
# Verify docker is available
if ! type docker >/dev/null; then
echo "Please install docker"
exit 1
fi
test="npm run clean; npm install --unsafe-perm; npm test"
# Debian 7, 8
# Ubuntu 14.04, 16.04
for dist in debian:jessie debian:stretch ubuntu:trusty ubuntu:xenial; do
echo "Testing $dist..."
docker pull $dist
if docker run -i -t --rm -v $PWD:/v $dist >packaging/$dist.log 2>&1 sh -c "cd /v; ./packaging/test/debian.sh; $test";
then echo "$dist OK"
else echo "$dist fail" && cat packaging/$dist.log
fi
done
# Centos 7
echo "Testing centos7..."
docker pull centos:7
if docker run -i -t --rm -v $PWD:/v centos:7 >packaging/centos7.log 2>&1 sh -c "cd /v; ./packaging/test/centos.sh; $test";
then echo "centos7 OK"
else echo "centos7 fail" && cat packaging/centos7.log
fi
# Archlinux latest
echo "Testing archlinux..."
docker pull pritunl/archlinux:latest
if docker run -i -t --rm -v $PWD:/v pritunl/archlinux:latest >packaging/archlinux.log 2>&1 sh -c "cd /v; ./packaging/test/archlinux.sh; $test";
then echo "archlinux OK"
else echo "archlinux fail" && cat packaging/archlinux.log
fi

View File

@@ -1,5 +0,0 @@
#!/bin/sh
# Install Node.js on Archlinux
pacman -Sy --noconfirm gcc make python2 nodejs npm | cat
ln -s /usr/bin/python2 /usr/bin/python

View File

@@ -1,4 +0,0 @@
#!/bin/sh
curl -sL https://rpm.nodesource.com/setup_6.x | bash -
yum install -y gcc-c++ make nodejs

View File

@@ -1,6 +0,0 @@
#!/bin/sh
apt-get update
apt-get install -y build-essential python pkg-config curl
curl -sL https://deb.nodesource.com/setup_6.x | bash -
apt-get install -y nodejs

View File

@@ -1,8 +0,0 @@
FROM debian:stretch
MAINTAINER Lovell Fuller <npm@lovell.info>
# Create Debian-based container suitable for post-processing Windows x64 binaries
RUN apt-get update && apt-get install -y curl zip advancecomp
ENV PLATFORM=win32-x64

View File

@@ -40,7 +40,7 @@ namespace sharp {
// Create an InputDescriptor instance from a v8::Object describing an input image
InputDescriptor* CreateInputDescriptor(
v8::Handle<v8::Object> input, std::vector<v8::Local<v8::Object>> buffersToPersist
v8::Handle<v8::Object> input, std::vector<v8::Local<v8::Object>> &buffersToPersist
) {
Nan::HandleScope();
InputDescriptor *descriptor = new InputDescriptor;
@@ -52,6 +52,7 @@ namespace sharp {
descriptor->buffer = node::Buffer::Data(buffer);
buffersToPersist.push_back(buffer);
}
descriptor->failOnError = AttrTo<bool>(input, "failOnError");
// Density for vector-based input
if (HasAttr(input, "density")) {
descriptor->density = AttrTo<uint32_t>(input, "density");
@@ -62,6 +63,10 @@ namespace sharp {
descriptor->rawWidth = AttrTo<uint32_t>(input, "rawWidth");
descriptor->rawHeight = AttrTo<uint32_t>(input, "rawHeight");
}
// Page input for multi-page TIFF
if (HasAttr(input, "page")) {
descriptor->page = AttrTo<uint32_t>(input, "page");
}
// Create new image
if (HasAttr(input, "createChannels")) {
descriptor->createChannels = AttrTo<uint32_t>(input, "createChannels");
@@ -219,13 +224,18 @@ namespace sharp {
imageType = DetermineImageType(descriptor->buffer, descriptor->bufferLength);
if (imageType != ImageType::UNKNOWN) {
try {
vips::VOption *option = VImage::option()->set("access", accessMethod);
vips::VOption *option = VImage::option()
->set("access", accessMethod)
->set("fail", descriptor->failOnError);
if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
option->set("dpi", static_cast<double>(descriptor->density));
}
if (imageType == ImageType::MAGICK) {
option->set("density", std::to_string(descriptor->density).data());
}
if (imageType == ImageType::TIFF) {
option->set("page", descriptor->page);
}
image = VImage::new_from_buffer(descriptor->buffer, descriptor->bufferLength, nullptr, option);
if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) {
SetDensity(image, descriptor->density);
@@ -256,13 +266,18 @@ namespace sharp {
imageType = DetermineImageType(descriptor->file.data());
if (imageType != ImageType::UNKNOWN) {
try {
vips::VOption *option = VImage::option()->set("access", accessMethod);
vips::VOption *option = VImage::option()
->set("access", accessMethod)
->set("fail", descriptor->failOnError);
if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
option->set("dpi", static_cast<double>(descriptor->density));
}
if (imageType == ImageType::MAGICK) {
option->set("density", std::to_string(descriptor->density).data());
}
if (imageType == ImageType::TIFF) {
option->set("page", descriptor->page);
}
image = VImage::new_from_file(descriptor->file.data(), option);
if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) {
SetDensity(image, descriptor->density);
@@ -404,7 +419,62 @@ namespace sharp {
/*
Calculate the (left, top) coordinates of the output image
within the input image, applying the given gravity.
within the input image, applying the given gravity during an embed.
@Azurebyte: We are basically swapping the inWidth and outWidth, inHeight and outHeight from the CalculateCrop function.
*/
std::tuple<int, int> CalculateEmbedPosition(int const inWidth, int const inHeight,
int const outWidth, int const outHeight, int const gravity) {
int left = 0;
int top = 0;
switch (gravity) {
case 1:
// North
left = (outWidth - inWidth) / 2;
break;
case 2:
// East
left = outWidth - inWidth;
top = (outHeight - inHeight) / 2;
break;
case 3:
// South
left = (outWidth - inWidth) / 2;
top = outHeight - inHeight;
break;
case 4:
// West
top = (outHeight - inHeight) / 2;
break;
case 5:
// Northeast
left = outWidth - inWidth;
break;
case 6:
// Southeast
left = outWidth - inWidth;
top = outHeight - inHeight;
break;
case 7:
// Southwest
top = outHeight - inHeight;
break;
case 8:
// Northwest
// Which is the default is 0,0 so we do not assign anything here.
break;
default:
// Centre
left = (outWidth - inWidth) / 2;
top = (outHeight - inHeight) / 2;
}
return std::make_tuple(left, top);
}
/*
Calculate the (left, top) coordinates of the output image
within the input image, applying the given gravity during a crop.
*/
std::tuple<int, int> CalculateCrop(int const inWidth, int const inHeight,
int const outWidth, int const outHeight, int const gravity) {

View File

@@ -25,17 +25,17 @@
// Verify platform and compiler compatibility
#if (VIPS_MAJOR_VERSION < 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 5))
#error libvips version 8.5.x required - see sharp.dimens.io/page/install
#if (VIPS_MAJOR_VERSION < 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 6))
#error libvips version 8.6.1+ is required - see sharp.pixelplumbing.com/page/install
#endif
#if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)))
#error GCC version 4.6+ is required for C++11 features - see sharp.dimens.io/page/install#prerequisites
#error GCC version 4.6+ is required for C++11 features - see sharp.pixelplumbing.com/page/install#prerequisites
#endif
#if (defined(__clang__) && defined(__has_feature))
#if (!__has_feature(cxx_range_for))
#error clang version 3.0+ is required for C++11 features - see sharp.dimens.io/page/install#prerequisites
#error clang version 3.0+ is required for C++11 features - see sharp.pixelplumbing.com/page/install#prerequisites
#endif
#endif
@@ -47,11 +47,13 @@ namespace sharp {
std::string name;
std::string file;
char *buffer;
bool failOnError;
size_t bufferLength;
int density;
int rawChannels;
int rawWidth;
int rawHeight;
int page;
int createChannels;
int createWidth;
int createHeight;
@@ -59,11 +61,13 @@ namespace sharp {
InputDescriptor():
buffer(nullptr),
failOnError(FALSE),
bufferLength(0),
density(72),
rawChannels(0),
rawWidth(0),
rawHeight(0),
page(0),
createChannels(0),
createWidth(0),
createHeight(0) {
@@ -89,7 +93,7 @@ namespace sharp {
// Create an InputDescriptor instance from a v8::Object describing an input image
InputDescriptor* CreateInputDescriptor(
v8::Handle<v8::Object> input, std::vector<v8::Local<v8::Object>> buffersToPersist);
v8::Handle<v8::Object> input, std::vector<v8::Local<v8::Object>> &buffersToPersist);
enum class ImageType {
JPEG,
@@ -204,6 +208,13 @@ namespace sharp {
*/
std::string VipsWarningPop();
/*
Calculate the (left, top) coordinates of the output image
within the input image, applying the given gravity during an embed.
*/
std::tuple<int, int> CalculateEmbedPosition(int const inWidth, int const inHeight,
int const outWidth, int const outHeight, int const gravity);
/*
Calculate the (left, top) coordinates of the output image
within the input image, applying the given gravity.

View File

@@ -205,6 +205,30 @@ VOption::set( const char *name, std::vector<double> value )
return( this );
}
// input int array
VOption *
VOption::set( const char *name, std::vector<int> value )
{
Pair *pair = new Pair( name );
int *array;
unsigned int i;
pair->input = true;
g_value_init( &pair->value, VIPS_TYPE_ARRAY_INT );
vips_value_set_array_int( &pair->value, NULL,
static_cast< int >( value.size() ) );
array = vips_value_get_array_int( &pair->value, NULL );
for( i = 0; i < value.size(); i++ )
array[i] = value[i];
options.push_back( pair );
return( this );
}
// input image array
VOption *
VOption::set( const char *name, std::vector<VImage> value )
@@ -465,8 +489,7 @@ VImage::call_option_string( const char *operation_name,
operation_name );
if( !(operation = vips_operation_new( operation_name )) ) {
if( options )
delete options;
delete options;
throw( VError() );
}
@@ -565,34 +588,6 @@ VImage::new_from_buffer( void *buf, size_t len, const char *option_string,
return( out );
}
VImage
VImage::new_from_image( std::vector<double> pixel )
{
VImage onepx = VImage::black( 1, 1,
VImage::option()->set( "bands", bands() ) );
onepx = (onepx + pixel).cast( format() );
VImage big = onepx.embed( 0, 0, width(), height(),
VImage::option()->set( "extend", VIPS_EXTEND_COPY ) );
big = big.copy(
VImage::option()->
set( "interpretation", interpretation() )->
set( "xres", xres() )->
set( "yres", yres() )->
set( "xoffset", xres() )->
set( "yoffset", yres() ) );
return( big );
}
VImage
VImage::new_from_image( double pixel )
{
return( new_from_image( to_vectorv( 1, pixel ) ) );
}
VImage
VImage::new_matrix( int width, int height )
{
@@ -693,10 +688,21 @@ VImage::bandsplit( VOption *options )
VImage
VImage::bandjoin( VImage other, VOption *options )
{
VImage v[2] = { *this, other };
std::vector<VImage> vec( v, v + VIPS_NUMBER( v ) );
VImage v[2] = { *this, other };
std::vector<VImage> vec( v, v + VIPS_NUMBER( v ) );
return( bandjoin( vec, options ) );
return( bandjoin( vec, options ) );
}
VImage
VImage::composite( VImage other, VipsBlendMode mode, VOption *options )
{
VImage v[2] = { *this, other };
std::vector<VImage> ivec( v, v + VIPS_NUMBER( v ) );
int m[1] = { static_cast<int>( mode ) };
std::vector<int> mvec( m, m + VIPS_NUMBER( m ) );
return( composite( ivec, mvec, options ) );
}
std::complex<double>

View File

@@ -1,5 +1,5 @@
// bodies for vips operations
// Mon 13 Mar 13:22:17 GMT 2017
// Sun 26 Nov 17:44:23 GMT 2017
// this file is generated automatically, do not edit!
void VImage::system( char * cmd_format , VOption *options )
@@ -487,6 +487,21 @@ std::vector<double> VImage::getpoint( int x , int y , VOption *options )
return( out_array );
}
int VImage::find_trim( int * top , int * width , int * height , VOption *options )
{
int left;
call( "find_trim" ,
(options ? options : VImage::option()) ->
set( "in", *this ) ->
set( "left", &left ) ->
set( "top", top ) ->
set( "width", width ) ->
set( "height", height ) );
return( left );
}
VImage VImage::copy( VOption *options )
{
VImage out;
@@ -563,6 +578,21 @@ VImage VImage::embed( int x , int y , int width , int height , VOption *options
return( out );
}
VImage VImage::gravity( VipsCompassDirection direction , int width , int height , VOption *options )
{
VImage out;
call( "gravity" ,
(options ? options : VImage::option()) ->
set( "in", *this ) ->
set( "out", &out ) ->
set( "direction", direction ) ->
set( "width", width ) ->
set( "height", height ) );
return( out );
}
VImage VImage::flip( VipsDirection direction , VOption *options )
{
VImage out;
@@ -988,6 +1018,19 @@ VImage VImage::gamma( VOption *options )
return( out );
}
VImage VImage::composite( std::vector<VImage> in , std::vector<int> mode , VOption *options )
{
VImage out;
call( "composite" ,
(options ? options : VImage::option()) ->
set( "in", in ) ->
set( "out", &out ) ->
set( "mode", mode ) );
return( out );
}
VImage VImage::black( int width , int height , VOption *options )
{
VImage out;
@@ -1904,6 +1947,19 @@ VImage VImage::thumbnail_buffer( VipsBlob * buffer , int width , VOption *option
return( out );
}
VImage VImage::thumbnail_image( int width , VOption *options )
{
VImage out;
call( "thumbnail_image" ,
(options ? options : VImage::option()) ->
set( "in", *this ) ->
set( "out", &out ) ->
set( "width", width ) );
return( out );
}
VImage VImage::mapim( VImage index , VOption *options )
{
VImage out;
@@ -2822,6 +2878,18 @@ VImage VImage::labelregions( VOption *options )
return( mask );
}
VImage VImage::fill_nearest( VOption *options )
{
VImage out;
call( "fill_nearest" ,
(options ? options : VImage::option()) ->
set( "in", *this ) ->
set( "out", &out ) );
return( out );
}
void VImage::draw_rect( std::vector<double> ink , int left , int top , int width , int height , VOption *options )
{
call( "draw_rect" ,

View File

@@ -27,7 +27,8 @@ class MetadataWorker : public Nan::AsyncWorker {
MetadataWorker(
Nan::Callback *callback, MetadataBaton *baton, Nan::Callback *debuglog,
std::vector<v8::Local<v8::Object>> const buffersToPersist) :
Nan::AsyncWorker(callback), baton(baton), debuglog(debuglog),
Nan::AsyncWorker(callback, "sharp:MetadataWorker"),
baton(baton), debuglog(debuglog),
buffersToPersist(buffersToPersist) {
// Protect Buffer objects from GC, keyed on index
std::accumulate(buffersToPersist.begin(), buffersToPersist.end(), 0,
@@ -81,6 +82,22 @@ class MetadataWorker : public Nan::AsyncWorker {
memcpy(baton->icc, icc, iccLength);
baton->iccLength = iccLength;
}
// IPTC
if (image.get_typeof(VIPS_META_IPTC_NAME) == VIPS_TYPE_BLOB) {
size_t iptcLength;
void const *iptc = image.get_blob(VIPS_META_IPTC_NAME, &iptcLength);
baton->iptc = static_cast<char *>(g_malloc(iptcLength));
memcpy(baton->iptc, iptc, iptcLength);
baton->iptcLength = iptcLength;
}
// XMP
if (image.get_typeof(VIPS_META_XMP_NAME) == VIPS_TYPE_BLOB) {
size_t xmpLength;
void const *xmp = image.get_blob(VIPS_META_XMP_NAME, &xmpLength);
baton->xmp = static_cast<char *>(g_malloc(xmpLength));
memcpy(baton->xmp, xmp, xmpLength);
baton->xmpLength = xmpLength;
}
}
// Clean up
@@ -123,6 +140,16 @@ class MetadataWorker : public Nan::AsyncWorker {
New("icc").ToLocalChecked(),
Nan::NewBuffer(baton->icc, baton->iccLength, sharp::FreeCallback, nullptr).ToLocalChecked());
}
if (baton->iptcLength > 0) {
Set(info,
New("iptc").ToLocalChecked(),
Nan::NewBuffer(baton->iptc, baton->iptcLength, sharp::FreeCallback, nullptr).ToLocalChecked());
}
if (baton->xmpLength > 0) {
Set(info,
New("xmp").ToLocalChecked(),
Nan::NewBuffer(baton->xmp, baton->xmpLength, sharp::FreeCallback, nullptr).ToLocalChecked());
}
argv[1] = info;
}
@@ -139,12 +166,12 @@ class MetadataWorker : public Nan::AsyncWorker {
std::string warning = sharp::VipsWarningPop();
while (!warning.empty()) {
v8::Local<v8::Value> message[1] = { New(warning).ToLocalChecked() };
debuglog->Call(1, message);
debuglog->Call(1, message, async_resource);
warning = sharp::VipsWarningPop();
}
// Return to JavaScript
callback->Call(2, argv);
callback->Call(2, argv, async_resource);
}
private:

View File

@@ -38,6 +38,10 @@ struct MetadataBaton {
size_t exifLength;
char *icc;
size_t iccLength;
char *iptc;
size_t iptcLength;
char *xmp;
size_t xmpLength;
std::string err;
MetadataBaton():
@@ -52,7 +56,11 @@ struct MetadataBaton {
exif(nullptr),
exifLength(0),
icc(nullptr),
iccLength(0) {}
iccLength(0),
iptc(nullptr),
iptcLength(0),
xmp(nullptr),
xmpLength(0) {}
};
NAN_METHOD(metadata);

View File

@@ -28,6 +28,16 @@ using vips::VError;
namespace sharp {
/*
Removes alpha channel, if any.
*/
VImage RemoveAlpha(VImage image) {
if (HasAlpha(image)) {
image = image.extract_band(0, VImage::option()->set("n", image.bands() - 1));
}
return image;
}
/*
Composite overlayImage over image at given position
Assumes alpha channels are already premultiplied and will be unpremultiplied after
@@ -152,6 +162,33 @@ namespace sharp {
return dst.bandjoin(mask.cast(dst.format()));
}
/*
* Tint an image using the specified chroma, preserving the original image luminance
*/
VImage Tint(VImage image, double const a, double const b) {
// Get original colourspace
VipsInterpretation typeBeforeTint = image.interpretation();
if (typeBeforeTint == VIPS_INTERPRETATION_RGB) {
typeBeforeTint = VIPS_INTERPRETATION_sRGB;
}
// Extract luminance
VImage luminance = image.colourspace(VIPS_INTERPRETATION_LAB)[0];
// Create the tinted version by combining the L from the original and the chroma from the tint
std::vector<double> chroma {a, b};
VImage tinted = luminance
.bandjoin(chroma)
.copy(VImage::option()->set("interpretation", VIPS_INTERPRETATION_LAB))
.colourspace(typeBeforeTint);
// Attach original alpha channel, if any
if (HasAlpha(image)) {
// Extract original alpha channel
VImage alpha = image[image.bands() - 1];
// Join alpha channel to normalised image
tinted = tinted.bandjoin(alpha);
}
return tinted;
}
/*
* Stretch luminance to cover full dynamic range.
*/
@@ -196,10 +233,8 @@ namespace sharp {
VImage Gamma(VImage image, double const exponent) {
if (HasAlpha(image)) {
// Separate alpha channel
VImage imageWithoutAlpha = image.extract_band(0,
VImage::option()->set("n", image.bands() - 1));
VImage alpha = image[image.bands() - 1];
return imageWithoutAlpha.gamma(VImage::option()->set("exponent", exponent)).bandjoin(alpha);
return RemoveAlpha(image).gamma(VImage::option()->set("exponent", exponent)).bandjoin(alpha);
} else {
return image.gamma(VImage::option()->set("exponent", exponent));
}
@@ -267,23 +302,6 @@ namespace sharp {
}
}
/*
Insert a tile cache to prevent over-computation of any previous operations in the pipeline
*/
VImage TileCache(VImage image, double const factor) {
int tile_width;
int tile_height;
int scanline_count;
vips_get_tile_size(image.get_image(), &tile_width, &tile_height, &scanline_count);
double const need_lines = 1.2 * scanline_count / factor;
return image.tilecache(VImage::option()
->set("tile_width", image.width())
->set("tile_height", 10)
->set("max_tiles", static_cast<int>(round(1.0 + need_lines / 10.0)))
->set("access", VIPS_ACCESS_SEQUENTIAL)
->set("threaded", TRUE));
}
VImage Threshold(VImage image, double const threshold, bool const thresholdGrayscale) {
if (!thresholdGrayscale) {
return image >= threshold;
@@ -358,4 +376,16 @@ namespace sharp {
return image.extract_area(left, top, width, height);
}
/*
* Calculate (a * in + b)
*/
VImage Linear(VImage image, double const a, double const b) {
if (HasAlpha(image)) {
// Separate alpha channel
VImage alpha = image[image.bands() - 1];
return RemoveAlpha(image).linear(a, b).bandjoin(alpha);
} else {
return image.linear(a, b);
}
}
} // namespace sharp

View File

@@ -25,6 +25,11 @@ using vips::VImage;
namespace sharp {
/*
Removes alpha channel, if any.
*/
VImage RemoveAlpha(VImage image);
/*
Alpha composite src over dst with given gravity.
Assumes alpha channels are already premultiplied and will be unpremultiplied after.
@@ -46,6 +51,11 @@ namespace sharp {
*/
VImage Cutout(VImage src, VImage dst, const int gravity);
/*
* Tint an image using the specified chroma, preserving the original image luminance
*/
VImage Tint(VImage image, double const a, double const b);
/*
* Stretch luminance to cover full dynamic range.
*/
@@ -72,11 +82,6 @@ namespace sharp {
*/
VImage Sharpen(VImage image, double const sigma, double const flat, double const jagged);
/*
Insert a tile cache to prevent over-computation of any previous operations in the pipeline
*/
VImage TileCache(VImage image, double const factor);
/*
Threshold an image
*/
@@ -97,6 +102,11 @@ namespace sharp {
*/
VImage Trim(VImage image, int const tolerance);
/*
* Linear adjustment (a * in + b)
*/
VImage Linear(VImage image, double const a, double const b);
} // namespace sharp
#endif // SRC_OPERATIONS_H_

View File

@@ -35,7 +35,8 @@ class PipelineWorker : public Nan::AsyncWorker {
PipelineWorker(
Nan::Callback *callback, PipelineBaton *baton, Nan::Callback *debuglog, Nan::Callback *queueListener,
std::vector<v8::Local<v8::Object>> const buffersToPersist) :
Nan::AsyncWorker(callback), baton(baton), debuglog(debuglog), queueListener(queueListener),
Nan::AsyncWorker(callback, "sharp:PipelineWorker"),
baton(baton), debuglog(debuglog), queueListener(queueListener),
buffersToPersist(buffersToPersist) {
// Protect Buffer objects from GC, keyed on index
std::accumulate(buffersToPersist.begin(), buffersToPersist.end(), 0,
@@ -222,20 +223,27 @@ class PipelineWorker : public Nan::AsyncWorker {
// If integral x and y shrink are equal, try to use shrink-on-load for JPEG and WebP,
// but not when applying gamma correction, pre-resize extract or trim
int shrink_on_load = 1;
int shrink_on_load_factor = 1;
// Leave at least a factor of two for the final resize step, when fastShrinkOnLoad: false
// for more consistent results and avoid occasional small image shifting
if (!baton->fastShrinkOnLoad) {
shrink_on_load_factor = 2;
}
if (
xshrink == yshrink && xshrink >= 2 &&
xshrink == yshrink && xshrink >= 2 * shrink_on_load_factor &&
(inputImageType == ImageType::JPEG || inputImageType == ImageType::WEBP) &&
baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimTolerance == 0
) {
if (xshrink >= 8) {
if (xshrink >= 8 * shrink_on_load_factor) {
xfactor = xfactor / 8;
yfactor = yfactor / 8;
shrink_on_load = 8;
} else if (xshrink >= 4) {
} else if (xshrink >= 4 * shrink_on_load_factor) {
xfactor = xfactor / 4;
yfactor = yfactor / 4;
shrink_on_load = 4;
} else if (xshrink >= 2) {
} else if (xshrink >= 2 * shrink_on_load_factor) {
xfactor = xfactor / 2;
yfactor = yfactor / 2;
shrink_on_load = 2;
@@ -249,7 +257,10 @@ class PipelineWorker : public Nan::AsyncWorker {
}
if (shrink_on_load > 1) {
// Reload input using shrink-on-load
vips::VOption *option = VImage::option()->set("shrink", shrink_on_load);
vips::VOption *option = VImage::option()
->set("access", baton->accessMethod)
->set("shrink", shrink_on_load)
->set("fail", baton->input->failOnError);
if (baton->input->buffer != nullptr) {
VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);
if (inputImageType == ImageType::JPEG) {
@@ -270,32 +281,17 @@ class PipelineWorker : public Nan::AsyncWorker {
}
}
// Recalculate integral shrink and double residual
int shrunkOnLoadWidth = image.width();
int shrunkOnLoadHeight = image.height();
int const shrunkOnLoadWidth = image.width();
int const shrunkOnLoadHeight = image.height();
if (!baton->rotateBeforePreExtract &&
(rotation == VIPS_ANGLE_D90 || rotation == VIPS_ANGLE_D270)) {
// Swap input output width and height when rotating by 90 or 270 degrees
std::swap(shrunkOnLoadWidth, shrunkOnLoadHeight);
// Swap when rotating by 90 or 270 degrees
xfactor = static_cast<double>(shrunkOnLoadWidth) / static_cast<double>(targetResizeHeight);
yfactor = static_cast<double>(shrunkOnLoadHeight) / static_cast<double>(targetResizeWidth);
} else {
xfactor = static_cast<double>(shrunkOnLoadWidth) / static_cast<double>(targetResizeWidth);
yfactor = static_cast<double>(shrunkOnLoadHeight) / static_cast<double>(targetResizeHeight);
}
xfactor = static_cast<double>(shrunkOnLoadWidth) / static_cast<double>(targetResizeWidth);
yfactor = static_cast<double>(shrunkOnLoadHeight) / static_cast<double>(targetResizeHeight);
xshrink = std::max(1, static_cast<int>(floor(xfactor)));
yshrink = std::max(1, static_cast<int>(floor(yfactor)));
xresidual = static_cast<double>(xshrink) / xfactor;
yresidual = static_cast<double>(yshrink) / yfactor;
if (
!baton->rotateBeforePreExtract &&
(rotation == VIPS_ANGLE_D90 || rotation == VIPS_ANGLE_D270)
) {
std::swap(xresidual, yresidual);
}
}
// Help ensure a final kernel-based reduction to prevent shrink aliasing
if (xshrink > 1 && yshrink > 1 && (xresidual == 1.0 || yresidual == 1.0)) {
xshrink = xshrink / 2;
yshrink = yshrink / 2;
xresidual = static_cast<double>(xshrink) / xfactor;
yresidual = static_cast<double>(yshrink) / yfactor;
}
// Ensure we're using a device-independent colour space
@@ -361,13 +357,14 @@ class PipelineWorker : public Nan::AsyncWorker {
}
}
bool const shouldShrink = xshrink > 1 || yshrink > 1;
bool const shouldReduce = xresidual != 1.0 || yresidual != 1.0;
bool const shouldResize = xfactor != 1.0 || yfactor != 1.0;
bool const shouldBlur = baton->blurSigma != 0.0;
bool const shouldConv = baton->convKernelWidth * baton->convKernelHeight > 0;
bool const shouldSharpen = baton->sharpenSigma != 0.0;
bool const shouldApplyMedian = baton->medianSize > 0;
bool const shouldPremultiplyAlpha = HasAlpha(image) &&
(shouldShrink || shouldReduce || shouldBlur || shouldConv || shouldSharpen || shouldOverlayWithAlpha);
(shouldResize || shouldBlur || shouldConv || shouldSharpen || shouldOverlayWithAlpha);
// Premultiply image alpha channel before all transformations to avoid
// dark fringing around bright pixels
@@ -376,79 +373,19 @@ class PipelineWorker : public Nan::AsyncWorker {
image = image.premultiply();
}
// Fast, integral box-shrink
if (shouldShrink) {
if (yshrink > 1) {
image = image.shrinkv(yshrink);
}
if (xshrink > 1) {
image = image.shrinkh(xshrink);
}
// Recalculate residual float based on dimensions of required vs shrunk images
int shrunkWidth = image.width();
int shrunkHeight = image.height();
if (!baton->rotateBeforePreExtract &&
(rotation == VIPS_ANGLE_D90 || rotation == VIPS_ANGLE_D270)) {
// Swap input output width and height when rotating by 90 or 270 degrees
std::swap(shrunkWidth, shrunkHeight);
}
xresidual = static_cast<double>(targetResizeWidth) / static_cast<double>(shrunkWidth);
yresidual = static_cast<double>(targetResizeHeight) / static_cast<double>(shrunkHeight);
// Resize
if (shouldResize) {
VipsKernel kernel = static_cast<VipsKernel>(
vips_enum_from_nick(nullptr, VIPS_TYPE_KERNEL, baton->kernel.data()));
if (
!baton->rotateBeforePreExtract &&
(rotation == VIPS_ANGLE_D90 || rotation == VIPS_ANGLE_D270)
kernel != VIPS_KERNEL_NEAREST && kernel != VIPS_KERNEL_CUBIC && kernel != VIPS_KERNEL_LANCZOS2 &&
kernel != VIPS_KERNEL_LANCZOS3
) {
std::swap(xresidual, yresidual);
}
}
// Use affine increase or kernel reduce with the remaining float part
if (xresidual != 1.0 || yresidual != 1.0) {
// Insert tile cache to prevent over-computation of previous operations
if (baton->accessMethod == VIPS_ACCESS_SEQUENTIAL) {
image = sharp::TileCache(image, yresidual);
}
// Perform kernel-based reduction
if (yresidual < 1.0 || xresidual < 1.0) {
VipsKernel kernel = static_cast<VipsKernel>(
vips_enum_from_nick(nullptr, VIPS_TYPE_KERNEL, baton->kernel.data()));
if (
kernel != VIPS_KERNEL_NEAREST && kernel != VIPS_KERNEL_CUBIC && kernel != VIPS_KERNEL_LANCZOS2 &&
kernel != VIPS_KERNEL_LANCZOS3
) {
throw vips::VError("Unknown kernel");
}
if (yresidual < 1.0) {
image = image.reducev(1.0 / yresidual, VImage::option()
->set("kernel", kernel)
->set("centre", baton->centreSampling));
}
if (xresidual < 1.0) {
image = image.reduceh(1.0 / xresidual, VImage::option()
->set("kernel", kernel)
->set("centre", baton->centreSampling));
}
}
// Perform enlargement
if (yresidual > 1.0 || xresidual > 1.0) {
if (trunc(xresidual) == xresidual && trunc(yresidual) == yresidual && baton->interpolator == "nearest") {
// Fast, integral nearest neighbour enlargement
image = image.zoom(static_cast<int>(xresidual), static_cast<int>(yresidual));
} else {
// Floating point affine transformation
vips::VInterpolate interpolator = vips::VInterpolate::new_from_name(baton->interpolator.data());
if (yresidual > 1.0 && xresidual > 1.0) {
image = image.affine({xresidual, 0.0, 0.0, yresidual}, VImage::option()
->set("interpolate", interpolator));
} else if (yresidual > 1.0) {
image = image.affine({1.0, 0.0, 0.0, yresidual}, VImage::option()
->set("interpolate", interpolator));
} else if (xresidual > 1.0) {
image = image.affine({xresidual, 0.0, 0.0, 1.0}, VImage::option()
->set("interpolate", interpolator));
}
}
throw vips::VError("Unknown kernel");
}
image = image.resize(1.0 / xfactor, VImage::option()
->set("vscale", 1.0 / yfactor)
->set("kernel", kernel));
}
// Rotate
@@ -513,13 +450,29 @@ class PipelineWorker : public Nan::AsyncWorker {
image = image.bandjoin(
VImage::new_matrix(image.width(), image.height()).new_from_image(255 * multiplier));
}
// Embed
int left = static_cast<int>(round((baton->width - image.width()) / 2));
int top = static_cast<int>(round((baton->height - image.height()) / 2));
image = image.embed(left, top, baton->width, baton->height, VImage::option()
// Calculate where to position the embeded image if gravity specified, else center.
int left;
int top;
left = static_cast<int>(round((baton->width - image.width()) / 2));
top = static_cast<int>(round((baton->height - image.height()) / 2));
int width = std::max(image.width(), baton->width);
int height = std::max(image.height(), baton->height);
std::tie(left, top) = sharp::CalculateEmbedPosition(
image.width(), image.height(), baton->width, baton->height, baton->embed);
image = image.embed(left, top, width, height, VImage::option()
->set("extend", VIPS_EXTEND_BACKGROUND)
->set("background", background));
} else if (baton->canvas != Canvas::IGNORE_ASPECT) {
} else if (
baton->canvas != Canvas::IGNORE_ASPECT &&
(image.width() > baton->width || image.height() > baton->height)
) {
// Crop/max/min
if (baton->crop < 9) {
// Gravity-based crop
@@ -532,8 +485,20 @@ class PipelineWorker : public Nan::AsyncWorker {
image = image.extract_area(left, top, width, height);
} else {
// Attention-based or Entropy-based crop
if (baton->width > image.width()) {
baton->width = image.width();
}
if (baton->height > image.height()) {
baton->height = image.height();
}
image = image.tilecache(VImage::option()
->set("access", baton->accessMethod)
->set("threaded", TRUE));
image = image.smartcrop(baton->width, baton->height, VImage::option()
->set("interesting", baton->crop == 16 ? VIPS_INTERESTING_ENTROPY : VIPS_INTERESTING_ATTENTION));
baton->hasCropOffset = true;
baton->cropOffsetLeft = static_cast<int>(image.xoffset());
baton->cropOffsetTop = static_cast<int>(image.yoffset());
}
}
}
@@ -582,7 +547,10 @@ class PipelineWorker : public Nan::AsyncWorker {
image = image.embed(baton->extendLeft, baton->extendTop, baton->width, baton->height,
VImage::option()->set("extend", VIPS_EXTEND_BACKGROUND)->set("background", background));
}
// Median - must happen before blurring, due to the utility of blurring after thresholding
if (shouldApplyMedian) {
image = image.median(baton->medianSize);
}
// Threshold - must happen before blurring, due to the utility of blurring after thresholding
if (baton->threshold != 0) {
image = sharp::Threshold(image, baton->threshold, baton->thresholdGrayscale);
@@ -692,6 +660,11 @@ class PipelineWorker : public Nan::AsyncWorker {
image = sharp::Gamma(image, baton->gamma);
}
// Linear adjustment (a * in + b)
if (baton->linearA != 1.0 || baton->linearB != 0.0) {
image = sharp::Linear(image, baton->linearA, baton->linearB);
}
// Apply normalisation - stretch luminance to cover full dynamic range
if (baton->normalise) {
image = sharp::Normalise(image);
@@ -710,14 +683,30 @@ class PipelineWorker : public Nan::AsyncWorker {
image = sharp::Bandbool(image, baton->bandBoolOp);
}
// Tint the image
if (baton->tintA < 128.0 || baton->tintB < 128.0) {
image = sharp::Tint(image, baton->tintA, baton->tintB);
}
// Extract an image channel (aka vips band)
if (baton->extractChannel > -1) {
if (baton->extractChannel >= image.bands()) {
(baton->err).append("Cannot extract channel from image. Too few channels in image.");
return Error();
}
image = image.extract_band(baton->extractChannel);
VipsInterpretation const interpretation = sharp::Is16Bit(image.interpretation())
? VIPS_INTERPRETATION_GREY16
: VIPS_INTERPRETATION_B_W;
image = image
.extract_band(baton->extractChannel)
.copy(VImage::option()->set("interpretation", interpretation));
}
// Remove alpha channel, if any
if (baton->removeAlpha) {
image = sharp::RemoveAlpha(image);
}
// Convert image to sRGB, if not already
if (sharp::Is16Bit(image.interpretation())) {
image = image.cast(VIPS_FORMAT_USHORT);
@@ -753,9 +742,10 @@ class PipelineWorker : public Nan::AsyncWorker {
->set("interlace", baton->jpegProgressive)
->set("no_subsample", baton->jpegChromaSubsampling == "4:4:4")
->set("trellis_quant", baton->jpegTrellisQuantisation)
->set("quant_table", baton->jpegQuantisationTable)
->set("overshoot_deringing", baton->jpegOvershootDeringing)
->set("optimize_scans", baton->jpegOptimiseScans)
->set("optimize_coding", TRUE)));
->set("optimize_coding", baton->jpegOptimiseCoding)));
baton->bufferOut = static_cast<char*>(area->data);
baton->bufferOutLength = area->length;
area->free_fn = nullptr;
@@ -856,9 +846,10 @@ class PipelineWorker : public Nan::AsyncWorker {
bool const isDz = sharp::IsDz(baton->fileOut);
bool const isDzZip = sharp::IsDzZip(baton->fileOut);
bool const isV = sharp::IsV(baton->fileOut);
bool const matchInput = baton->formatOut == "input" &&
!(isJpeg || isPng || isWebp || isTiff || isDz || isDzZip || isV);
if (baton->formatOut == "jpeg" || isJpeg || (matchInput && inputImageType == ImageType::JPEG)) {
bool const mightMatchInput = baton->formatOut == "input";
bool const willMatchInput = mightMatchInput && !(isJpeg || isPng || isWebp || isTiff || isDz || isDzZip || isV);
if (baton->formatOut == "jpeg" || (mightMatchInput && isJpeg) ||
(willMatchInput && inputImageType == ImageType::JPEG)) {
// Write JPEG to file
sharp::AssertImageTypeDimensions(image, ImageType::JPEG);
image.jpegsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
@@ -867,12 +858,13 @@ class PipelineWorker : public Nan::AsyncWorker {
->set("interlace", baton->jpegProgressive)
->set("no_subsample", baton->jpegChromaSubsampling == "4:4:4")
->set("trellis_quant", baton->jpegTrellisQuantisation)
->set("quant_table", baton->jpegQuantisationTable)
->set("overshoot_deringing", baton->jpegOvershootDeringing)
->set("optimize_scans", baton->jpegOptimiseScans)
->set("optimize_coding", TRUE));
->set("optimize_coding", baton->jpegOptimiseCoding));
baton->formatOut = "jpeg";
baton->channels = std::min(baton->channels, 3);
} else if (baton->formatOut == "png" || isPng || (matchInput &&
} else if (baton->formatOut == "png" || (mightMatchInput && isPng) || (willMatchInput &&
(inputImageType == ImageType::PNG || inputImageType == ImageType::GIF || inputImageType == ImageType::SVG))) {
// Write PNG to file
sharp::AssertImageTypeDimensions(image, ImageType::PNG);
@@ -885,9 +877,10 @@ class PipelineWorker : public Nan::AsyncWorker {
->set("compression", baton->pngCompressionLevel)
->set("filter", baton->pngAdaptiveFiltering ? VIPS_FOREIGN_PNG_FILTER_ALL : VIPS_FOREIGN_PNG_FILTER_NONE));
baton->formatOut = "png";
} else if (baton->formatOut == "webp" || isWebp || (matchInput && inputImageType == ImageType::WEBP)) {
} else if (baton->formatOut == "webp" || (mightMatchInput && isWebp) ||
(willMatchInput && inputImageType == ImageType::WEBP)) {
// Write WEBP to file
AssertImageTypeDimensions(image, ImageType::WEBP);
sharp::AssertImageTypeDimensions(image, ImageType::WEBP);
image.webpsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
->set("strip", !baton->withMetadata)
->set("Q", baton->webpQuality)
@@ -895,7 +888,8 @@ class PipelineWorker : public Nan::AsyncWorker {
->set("near_lossless", baton->webpNearLossless)
->set("alpha_q", baton->webpAlphaQuality));
baton->formatOut = "webp";
} else if (baton->formatOut == "tiff" || isTiff || (matchInput && inputImageType == ImageType::TIFF)) {
} else if (baton->formatOut == "tiff" || (mightMatchInput && isTiff) ||
(willMatchInput && inputImageType == ImageType::TIFF)) {
// Write TIFF to file
if (baton->tiffCompression == VIPS_FOREIGN_TIFF_COMPRESSION_JPEG) {
sharp::AssertImageTypeDimensions(image, ImageType::JPEG);
@@ -944,22 +938,33 @@ class PipelineWorker : public Nan::AsyncWorker {
{"interlace", baton->jpegProgressive ? "TRUE" : "FALSE"},
{"no_subsample", baton->jpegChromaSubsampling == "4:4:4" ? "TRUE": "FALSE"},
{"trellis_quant", baton->jpegTrellisQuantisation ? "TRUE" : "FALSE"},
{"quant_table", std::to_string(baton->jpegQuantisationTable)},
{"overshoot_deringing", baton->jpegOvershootDeringing ? "TRUE": "FALSE"},
{"optimize_scans", baton->jpegOptimiseScans ? "TRUE": "FALSE"},
{"optimize_coding", "TRUE"}
{"optimize_coding", baton->jpegOptimiseCoding ? "TRUE": "FALSE"}
};
suffix = AssembleSuffixString(extname, options);
}
// Write DZ to file
image.dzsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
->set("strip", !baton->withMetadata)
->set("tile_size", baton->tileSize)
->set("overlap", baton->tileOverlap)
->set("container", baton->tileContainer)
->set("layout", baton->tileLayout)
->set("suffix", const_cast<char*>(suffix.data())));
vips::VOption *options = VImage::option()
->set("strip", !baton->withMetadata)
->set("tile_size", baton->tileSize)
->set("overlap", baton->tileOverlap)
->set("container", baton->tileContainer)
->set("layout", baton->tileLayout)
->set("suffix", const_cast<char*>(suffix.data()))
->set("angle", CalculateAngleRotation(baton->tileAngle));
// libvips chooses a default depth based on layout. Instead of replicating that logic here by
// not passing anything - libvips will handle choice
if (baton->tileDepth < VIPS_FOREIGN_DZ_DEPTH_LAST) {
options->set("depth", baton->tileDepth);
}
image.dzsave(const_cast<char*>(baton->fileOut.data()), options);
baton->formatOut = "dz";
} else if (baton->formatOut == "v" || isV || (matchInput && inputImageType == ImageType::VIPS)) {
} else if (baton->formatOut == "v" || (mightMatchInput && isV) ||
(willMatchInput && inputImageType == ImageType::VIPS)) {
// Write V to file
image.vipssave(const_cast<char*>(baton->fileOut.data()), VImage::option()
->set("strip", !baton->withMetadata));
@@ -1005,9 +1010,11 @@ class PipelineWorker : public Nan::AsyncWorker {
Set(info, New("height").ToLocalChecked(), New<v8::Uint32>(static_cast<uint32_t>(height)));
Set(info, New("channels").ToLocalChecked(), New<v8::Uint32>(static_cast<uint32_t>(baton->channels)));
Set(info, New("premultiplied").ToLocalChecked(), New<v8::Boolean>(baton->premultiplied));
if (baton->cropCalcLeft != -1 && baton->cropCalcLeft != -1) {
Set(info, New("cropCalcLeft").ToLocalChecked(), New<v8::Uint32>(static_cast<uint32_t>(baton->cropCalcLeft)));
Set(info, New("cropCalcTop").ToLocalChecked(), New<v8::Uint32>(static_cast<uint32_t>(baton->cropCalcTop)));
if (baton->hasCropOffset) {
Set(info, New("cropOffsetLeft").ToLocalChecked(),
New<v8::Int32>(static_cast<int32_t>(baton->cropOffsetLeft)));
Set(info, New("cropOffsetTop").ToLocalChecked(),
New<v8::Int32>(static_cast<int32_t>(baton->cropOffsetTop)));
}
if (baton->bufferOutLength > 0) {
@@ -1047,18 +1054,18 @@ class PipelineWorker : public Nan::AsyncWorker {
std::string warning = sharp::VipsWarningPop();
while (!warning.empty()) {
v8::Local<v8::Value> message[1] = { New(warning).ToLocalChecked() };
debuglog->Call(1, message);
debuglog->Call(1, message, async_resource);
warning = sharp::VipsWarningPop();
}
// Decrement processing task counter
g_atomic_int_dec_and_test(&sharp::counterProcess);
v8::Local<v8::Value> queueLength[1] = { New<v8::Uint32>(sharp::counterQueue) };
queueListener->Call(1, queueLength);
queueListener->Call(1, queueLength, async_resource);
delete queueListener;
// Return to JavaScript
callback->Call(3, argv);
callback->Call(3, argv, async_resource);
}
private:
@@ -1188,6 +1195,9 @@ NAN_METHOD(pipeline) {
for (unsigned int i = 0; i < 4; i++) {
baton->background[i] = AttrTo<double>(background, i);
}
// Tint chroma
baton->tintA = AttrTo<double>(options, "tintA");
baton->tintB = AttrTo<double>(options, "tintB");
// Overlay options
if (HasAttr(options, "overlay")) {
baton->overlay = CreateInputDescriptor(AttrAs<v8::Object>(options, "overlay"), buffersToPersist);
@@ -1200,9 +1210,9 @@ NAN_METHOD(pipeline) {
// Resize options
baton->withoutEnlargement = AttrTo<bool>(options, "withoutEnlargement");
baton->crop = AttrTo<int32_t>(options, "crop");
baton->embed = AttrTo<int32_t>(options, "embed");
baton->kernel = AttrAsStr(options, "kernel");
baton->interpolator = AttrAsStr(options, "interpolator");
baton->centreSampling = AttrTo<bool>(options, "centreSampling");
baton->fastShrinkOnLoad = AttrTo<bool>(options, "fastShrinkOnLoad");
// Join Channel Options
if (HasAttr(options, "joinChannelIn")) {
v8::Local<v8::Object> joinChannelObject = Nan::Get(options, Nan::New("joinChannelIn").ToLocalChecked())
@@ -1220,6 +1230,7 @@ NAN_METHOD(pipeline) {
baton->flatten = AttrTo<bool>(options, "flatten");
baton->negate = AttrTo<bool>(options, "negate");
baton->blurSigma = AttrTo<double>(options, "blurSigma");
baton->medianSize = AttrTo<uint32_t>(options, "medianSize");
baton->sharpenSigma = AttrTo<double>(options, "sharpenSigma");
baton->sharpenFlat = AttrTo<double>(options, "sharpenFlat");
baton->sharpenJagged = AttrTo<double>(options, "sharpenJagged");
@@ -1227,6 +1238,8 @@ NAN_METHOD(pipeline) {
baton->thresholdGrayscale = AttrTo<bool>(options, "thresholdGrayscale");
baton->trimTolerance = AttrTo<int32_t>(options, "trimTolerance");
baton->gamma = AttrTo<double>(options, "gamma");
baton->linearA = AttrTo<double>(options, "linearA");
baton->linearB = AttrTo<double>(options, "linearB");
baton->greyscale = AttrTo<bool>(options, "greyscale");
baton->normalise = AttrTo<bool>(options, "normalise");
baton->useExifOrientation = AttrTo<bool>(options, "useExifOrientation");
@@ -1239,6 +1252,7 @@ NAN_METHOD(pipeline) {
baton->extendLeft = AttrTo<int32_t>(options, "extendLeft");
baton->extendRight = AttrTo<int32_t>(options, "extendRight");
baton->extractChannel = AttrTo<int32_t>(options, "extractChannel");
baton->removeAlpha = AttrTo<bool>(options, "removeAlpha");
if (HasAttr(options, "boolean")) {
baton->boolean = CreateInputDescriptor(AttrAs<v8::Object>(options, "boolean"), buffersToPersist);
baton->booleanOp = sharp::GetBooleanOperation(AttrAsStr(options, "booleanOp"));
@@ -1273,8 +1287,10 @@ NAN_METHOD(pipeline) {
baton->jpegProgressive = AttrTo<bool>(options, "jpegProgressive");
baton->jpegChromaSubsampling = AttrAsStr(options, "jpegChromaSubsampling");
baton->jpegTrellisQuantisation = AttrTo<bool>(options, "jpegTrellisQuantisation");
baton->jpegQuantisationTable = AttrTo<uint32_t>(options, "jpegQuantisationTable");
baton->jpegOvershootDeringing = AttrTo<bool>(options, "jpegOvershootDeringing");
baton->jpegOptimiseScans = AttrTo<bool>(options, "jpegOptimiseScans");
baton->jpegOptimiseCoding = AttrTo<bool>(options, "jpegOptimiseCoding");
baton->pngProgressive = AttrTo<bool>(options, "pngProgressive");
baton->pngCompressionLevel = AttrTo<uint32_t>(options, "pngCompressionLevel");
baton->pngAdaptiveFiltering = AttrTo<bool>(options, "pngAdaptiveFiltering");
@@ -1298,6 +1314,7 @@ NAN_METHOD(pipeline) {
baton->tileSize = AttrTo<uint32_t>(options, "tileSize");
baton->tileOverlap = AttrTo<uint32_t>(options, "tileOverlap");
std::string tileContainer = AttrAsStr(options, "tileContainer");
baton->tileAngle = AttrTo<int32_t>(options, "tileAngle");
if (tileContainer == "zip") {
baton->tileContainer = VIPS_FOREIGN_DZ_CONTAINER_ZIP;
} else {
@@ -1312,6 +1329,17 @@ NAN_METHOD(pipeline) {
baton->tileLayout = VIPS_FOREIGN_DZ_LAYOUT_DZ;
}
baton->tileFormat = AttrAsStr(options, "tileFormat");
std::string tileDepth = AttrAsStr(options, "tileDepth");
if (tileDepth == "onetile") {
baton->tileDepth = VIPS_FOREIGN_DZ_DEPTH_ONETILE;
} else if (tileDepth == "one") {
baton->tileDepth = VIPS_FOREIGN_DZ_DEPTH_ONE;
} else if (tileDepth == "onepixel") {
baton->tileDepth = VIPS_FOREIGN_DZ_DEPTH_ONEPIXEL;
} else {
// signal that we do not want to pass any value to dzSave
baton->tileDepth = VIPS_FOREIGN_DZ_DEPTH_LAST;
}
// Force random access for certain operations
if (baton->accessMethod == VIPS_ACCESS_SEQUENTIAL && (
baton->trimTolerance != 0 || baton->normalise ||
@@ -1332,5 +1360,6 @@ NAN_METHOD(pipeline) {
// Increment queued task counter
g_atomic_int_inc(&sharp::counterQueue);
v8::Local<v8::Value> queueLength[1] = { Nan::New<v8::Uint32>(sharp::counterQueue) };
queueListener->Call(1, queueLength);
v8::Local<v8::Object> recv = Nan::New<v8::Object>();
Nan::Call(*queueListener, recv, 1, queueLength);
}

View File

@@ -62,22 +62,28 @@ struct PipelineBaton {
int channels;
Canvas canvas;
int crop;
int cropCalcLeft;
int cropCalcTop;
int embed;
bool hasCropOffset;
int cropOffsetLeft;
int cropOffsetTop;
bool premultiplied;
std::string kernel;
std::string interpolator;
bool centreSampling;
bool fastShrinkOnLoad;
double background[4];
double tintA;
double tintB;
bool flatten;
bool negate;
double blurSigma;
int medianSize;
double sharpenSigma;
double sharpenFlat;
double sharpenJagged;
int threshold;
bool thresholdGrayscale;
int trimTolerance;
double linearA;
double linearB;
double gamma;
bool greyscale;
bool normalise;
@@ -96,8 +102,10 @@ struct PipelineBaton {
bool jpegProgressive;
std::string jpegChromaSubsampling;
bool jpegTrellisQuantisation;
int jpegQuantisationTable;
bool jpegOvershootDeringing;
bool jpegOptimiseScans;
bool jpegOptimiseCoding;
bool pngProgressive;
int pngCompressionLevel;
bool pngAdaptiveFiltering;
@@ -123,12 +131,15 @@ struct PipelineBaton {
VipsOperationBoolean booleanOp;
VipsOperationBoolean bandBoolOp;
int extractChannel;
bool removeAlpha;
VipsInterpretation colourspace;
int tileSize;
int tileOverlap;
VipsForeignDzContainer tileContainer;
VipsForeignDzLayout tileLayout;
std::string tileFormat;
int tileAngle;
VipsForeignDzDepth tileDepth;
PipelineBaton():
input(nullptr),
@@ -145,19 +156,25 @@ struct PipelineBaton {
channels(0),
canvas(Canvas::CROP),
crop(0),
cropCalcLeft(-1),
cropCalcTop(-1),
embed(0),
hasCropOffset(false),
cropOffsetLeft(0),
cropOffsetTop(0),
premultiplied(false),
centreSampling(false),
tintA(128.0),
tintB(128.0),
flatten(false),
negate(false),
blurSigma(0.0),
medianSize(0),
sharpenSigma(0.0),
sharpenFlat(1.0),
sharpenJagged(2.0),
threshold(0),
thresholdGrayscale(true),
trimTolerance(0),
linearA(1.0),
linearB(0.0),
gamma(0.0),
greyscale(false),
normalise(false),
@@ -174,15 +191,17 @@ struct PipelineBaton {
jpegProgressive(false),
jpegChromaSubsampling("4:2:0"),
jpegTrellisQuantisation(false),
jpegQuantisationTable(0),
jpegOvershootDeringing(false),
jpegOptimiseScans(false),
jpegOptimiseCoding(true),
pngProgressive(false),
pngCompressionLevel(6),
pngAdaptiveFiltering(true),
pngCompressionLevel(9),
pngAdaptiveFiltering(false),
webpQuality(80),
tiffQuality(80),
tiffCompression(VIPS_FOREIGN_TIFF_COMPRESSION_JPEG),
tiffPredictor(VIPS_FOREIGN_TIFF_PREDICTOR_NONE),
tiffPredictor(VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL),
tiffSquash(false),
tiffXres(1.0),
tiffYres(1.0),
@@ -196,11 +215,14 @@ struct PipelineBaton {
booleanOp(VIPS_OPERATION_BOOLEAN_LAST),
bandBoolOp(VIPS_OPERATION_BOOLEAN_LAST),
extractChannel(-1),
removeAlpha(false),
colourspace(VIPS_INTERPRETATION_LAST),
tileSize(256),
tileOverlap(0),
tileContainer(VIPS_FOREIGN_DZ_CONTAINER_FS),
tileLayout(VIPS_FOREIGN_DZ_LAYOUT_DZ) {
tileLayout(VIPS_FOREIGN_DZ_LAYOUT_DZ),
tileAngle(0),
tileDepth(VIPS_FOREIGN_DZ_DEPTH_LAST){
background[0] = 0.0;
background[1] = 0.0;
background[2] = 0.0;

View File

@@ -20,6 +20,7 @@
#include "metadata.h"
#include "pipeline.h"
#include "utilities.h"
#include "stats.h"
NAN_MODULE_INIT(init) {
vips_init("sharp");
@@ -46,6 +47,8 @@ NAN_MODULE_INIT(init) {
Nan::GetFunction(Nan::New<v8::FunctionTemplate>(format)).ToLocalChecked());
Nan::Set(target, Nan::New("_maxColourDistance").ToLocalChecked(),
Nan::GetFunction(Nan::New<v8::FunctionTemplate>(_maxColourDistance)).ToLocalChecked());
Nan::Set(target, Nan::New("stats").ToLocalChecked(),
Nan::GetFunction(Nan::New<v8::FunctionTemplate>(stats)).ToLocalChecked());
}
NODE_MODULE(sharp, init)

192
src/stats.cc Normal file
View File

@@ -0,0 +1,192 @@
// Copyright 2013, 2014, 2015, 2016, 2017 Lovell Fuller and contributors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <numeric>
#include <vector>
#include <iostream>
#include <node.h>
#include <nan.h>
#include <vips/vips8>
#include "common.h"
#include "stats.h"
class StatsWorker : public Nan::AsyncWorker {
public:
StatsWorker(
Nan::Callback *callback, StatsBaton *baton, Nan::Callback *debuglog,
std::vector<v8::Local<v8::Object>> const buffersToPersist) :
Nan::AsyncWorker(callback, "sharp:StatsWorker"),
baton(baton), debuglog(debuglog),
buffersToPersist(buffersToPersist) {
// Protect Buffer objects from GC, keyed on index
std::accumulate(buffersToPersist.begin(), buffersToPersist.end(), 0,
[this](uint32_t index, v8::Local<v8::Object> const buffer) -> uint32_t {
SaveToPersistent(index, buffer);
return index + 1;
});
}
~StatsWorker() {}
const int STAT_MIN_INDEX = 0;
const int STAT_MAX_INDEX = 1;
const int STAT_SUM_INDEX = 2;
const int STAT_SQ_SUM_INDEX = 3;
const int STAT_MEAN_INDEX = 4;
const int STAT_STDEV_INDEX = 5;
const int STAT_MINX_INDEX = 6;
const int STAT_MINY_INDEX = 7;
const int STAT_MAXX_INDEX = 8;
const int STAT_MAXY_INDEX = 9;
void Execute() {
// Decrement queued task counter
g_atomic_int_dec_and_test(&sharp::counterQueue);
using Nan::New;
using Nan::Set;
using sharp::MaximumImageAlpha;
vips::VImage image;
sharp::ImageType imageType = sharp::ImageType::UNKNOWN;
try {
std::tie(image, imageType) = OpenInput(baton->input, baton->accessMethod);
} catch (vips::VError const &err) {
(baton->err).append(err.what());
}
if (imageType != sharp::ImageType::UNKNOWN) {
try {
vips::VImage stats = image.stats();
int const bands = image.bands();
for (int b = 1; b <= bands; b++) {
ChannelStats cStats(static_cast<int>(stats.getpoint(STAT_MIN_INDEX, b).front()),
static_cast<int>(stats.getpoint(STAT_MAX_INDEX, b).front()),
stats.getpoint(STAT_SUM_INDEX, b).front(), stats.getpoint(STAT_SQ_SUM_INDEX, b).front(),
stats.getpoint(STAT_MEAN_INDEX, b).front(), stats.getpoint(STAT_STDEV_INDEX, b).front(),
static_cast<int>(stats.getpoint(STAT_MINX_INDEX, b).front()),
static_cast<int>(stats.getpoint(STAT_MINY_INDEX, b).front()),
static_cast<int>(stats.getpoint(STAT_MAXX_INDEX, b).front()),
static_cast<int>(stats.getpoint(STAT_MAXY_INDEX, b).front()));
baton->channelStats.push_back(cStats);
}
// Image is not opaque when alpha layer is present and contains a non-mamixa value
if (sharp::HasAlpha(image)) {
double const minAlpha = static_cast<double>(stats.getpoint(STAT_MIN_INDEX, bands).front());
if (minAlpha != MaximumImageAlpha(image.interpretation())) {
baton->isOpaque = false;
}
}
// Estimate entropy via histogram of greyscale value frequency
baton->entropy = std::abs(image.colourspace(VIPS_INTERPRETATION_B_W)[0].hist_find().hist_entropy());
} catch (vips::VError const &err) {
(baton->err).append(err.what());
}
}
// Clean up
vips_error_clear();
vips_thread_shutdown();
}
void HandleOKCallback() {
using Nan::New;
using Nan::Set;
Nan::HandleScope();
v8::Local<v8::Value> argv[2] = { Nan::Null(), Nan::Null() };
if (!baton->err.empty()) {
argv[0] = Nan::Error(baton->err.data());
} else {
// Stats Object
v8::Local<v8::Object> info = New<v8::Object>();
v8::Local<v8::Array> channels = New<v8::Array>();
std::vector<ChannelStats>::iterator it;
int i = 0;
for (it=baton->channelStats.begin() ; it < baton->channelStats.end(); it++, i++) {
v8::Local<v8::Object> channelStat = New<v8::Object>();
Set(channelStat, New("min").ToLocalChecked(), New<v8::Number>(it->min));
Set(channelStat, New("max").ToLocalChecked(), New<v8::Number>(it->max));
Set(channelStat, New("sum").ToLocalChecked(), New<v8::Number>(it->sum));
Set(channelStat, New("squaresSum").ToLocalChecked(), New<v8::Number>(it->squaresSum));
Set(channelStat, New("mean").ToLocalChecked(), New<v8::Number>(it->mean));
Set(channelStat, New("stdev").ToLocalChecked(), New<v8::Number>(it->stdev));
Set(channelStat, New("minX").ToLocalChecked(), New<v8::Number>(it->minX));
Set(channelStat, New("minY").ToLocalChecked(), New<v8::Number>(it->minY));
Set(channelStat, New("maxX").ToLocalChecked(), New<v8::Number>(it->maxX));
Set(channelStat, New("maxY").ToLocalChecked(), New<v8::Number>(it->maxY));
channels->Set(i, channelStat);
}
Set(info, New("channels").ToLocalChecked(), channels);
Set(info, New("isOpaque").ToLocalChecked(), New<v8::Boolean>(baton->isOpaque));
Set(info, New("entropy").ToLocalChecked(), New<v8::Number>(baton->entropy));
argv[1] = info;
}
// Dispose of Persistent wrapper around input Buffers so they can be garbage collected
std::accumulate(buffersToPersist.begin(), buffersToPersist.end(), 0,
[this](uint32_t index, v8::Local<v8::Object> const buffer) -> uint32_t {
GetFromPersistent(index);
return index + 1;
});
delete baton->input;
delete baton;
// Handle warnings
std::string warning = sharp::VipsWarningPop();
while (!warning.empty()) {
v8::Local<v8::Value> message[1] = { New(warning).ToLocalChecked() };
debuglog->Call(1, message, async_resource);
warning = sharp::VipsWarningPop();
}
// Return to JavaScript
callback->Call(2, argv, async_resource);
}
private:
StatsBaton* baton;
Nan::Callback *debuglog;
std::vector<v8::Local<v8::Object>> buffersToPersist;
};
/*
stats(options, callback)
*/
NAN_METHOD(stats) {
using sharp::AttrTo;
// Input Buffers must not undergo GC compaction during processing
std::vector<v8::Local<v8::Object>> buffersToPersist;
// V8 objects are converted to non-V8 types held in the baton struct
StatsBaton *baton = new StatsBaton;
v8::Local<v8::Object> options = info[0].As<v8::Object>();
// Input
baton->input = sharp::CreateInputDescriptor(sharp::AttrAs<v8::Object>(options, "input"), buffersToPersist);
baton->accessMethod = AttrTo<bool>(options, "sequentialRead") ? VIPS_ACCESS_SEQUENTIAL : VIPS_ACCESS_RANDOM;
// Function to notify of libvips warnings
Nan::Callback *debuglog = new Nan::Callback(sharp::AttrAs<v8::Function>(options, "debuglog"));
// Join queue for worker thread
Nan::Callback *callback = new Nan::Callback(info[1].As<v8::Function>());
Nan::AsyncQueueWorker(new StatsWorker(callback, baton, debuglog, buffersToPersist));
// Increment queued task counter
g_atomic_int_inc(&sharp::counterQueue);
}

67
src/stats.h Normal file
View File

@@ -0,0 +1,67 @@
// Copyright 2013, 2014, 2015, 2016, 2017 Lovell Fuller and contributors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SRC_STATS_H_
#define SRC_STATS_H_
#include <string>
#include <nan.h>
#include "./common.h"
struct ChannelStats {
// stats per channel
int min;
int max;
double sum;
double squaresSum;
double mean;
double stdev;
int minX;
int minY;
int maxX;
int maxY;
ChannelStats():
min(0), max(0), sum(0), squaresSum(0), mean(0), stdev(0)
, minX(0), minY(0), maxX(0), maxY(0) {}
ChannelStats(int minVal, int maxVal, double sumVal, double squaresSumVal,
double meanVal, double stdevVal, int minXVal, int minYVal, int maxXVal, int maxYVal):
min(minVal), max(maxVal), sum(sumVal), squaresSum(squaresSumVal),
mean(meanVal), stdev(stdevVal), minX(minXVal), minY(minYVal), maxX(maxXVal), maxY(maxYVal) {}
};
struct StatsBaton {
// Input
sharp::InputDescriptor *input;
VipsAccess accessMethod;
// Output
std::vector<ChannelStats> channelStats;
bool isOpaque;
double entropy;
std::string err;
StatsBaton():
input(nullptr),
isOpaque(true),
entropy(0.0)
{}
};
NAN_METHOD(stats);
#endif // SRC_STATS_H_

View File

@@ -8,16 +8,16 @@
"test": "node perf && node random && node parallel"
},
"devDependencies": {
"async": "^2.5.0",
"async": "^2.6.0",
"benchmark": "^2.1.4",
"gm": "^1.23.0",
"gm": "^1.23.1",
"imagemagick": "^0.1.3",
"imagemagick-native": "^1.9.3",
"images": "^3.0.0",
"images": "^3.0.1",
"jimp": "^0.2.28",
"mapnik": "^3.6.2",
"pajk-lwip": "^0.2.0",
"semver": "^5.3.0"
"semver": "^5.4.1"
},
"license": "Apache-2.0",
"engines": {

View File

@@ -31,6 +31,7 @@ async.mapSeries([1, 1, 2, 4, 8, 16, 32, 64], function (parallelism, next) {
function (err, ids) {
assert(!err);
assert(ids.length === parallelism);
ids.sort();
const mean = ids.reduce(function (a, b) {
return a + b;
}) / ids.length;

View File

@@ -601,7 +601,7 @@ async.series({
callback(null, this.filter('fastest').map('name'));
}).run();
},
// Comparitive speed of kernels
// Comparative speed of kernels
kernels: function (callback) {
const inputJpgBuffer = fs.readFileSync(fixtures.inputJpg);
(new Benchmark.Suite('kernels')).add('sharp-cubic', {
@@ -911,12 +911,12 @@ async.series({
}
});
}
}).add('sharp-withoutAdaptiveFiltering', {
}).add('sharp-adaptiveFiltering', {
defer: true,
fn: function (deferred) {
sharp(inputPngBuffer)
.resize(width, height)
.png({ adaptiveFiltering: false })
.png({ adaptiveFiltering: true })
.toBuffer(function (err, buffer) {
if (err) {
throw err;

6
test/coverage/report.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/sh
CPPFLAGS="--coverage" LDFLAGS="--coverage" npm rebuild
npm test
geninfo --no-external --base-directory src --output-file coverage/sharp.info build/Release/obj.target/sharp/src
genhtml --title sharp --demangle-cpp --output-directory coverage/sharp coverage/*.info

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 MiB

BIN
test/fixtures/G31D_MULTI.TIF vendored Normal file

Binary file not shown.

BIN
test/fixtures/Landscape_9.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

BIN
test/fixtures/centered_image.jpeg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
test/fixtures/embedgravitybird.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 476 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 222 KiB

After

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 987 B

After

Width:  |  Height:  |  Size: 910 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 762 B

After

Width:  |  Height:  |  Size: 857 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 670 B

After

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 813 B

After

Width:  |  Height:  |  Size: 855 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Some files were not shown because too many files have changed in this diff Show More