mirror of
https://github.com/lovell/sharp.git
synced 2026-02-07 07:06:16 +01:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
34d5252242 | ||
|
|
f31e4d2869 | ||
|
|
c695c40abc | ||
|
|
fd1ca1dbb2 | ||
|
|
f25dbd5f61 | ||
|
|
541e7104fd | ||
|
|
94945cf6ac | ||
|
|
db76e655f8 | ||
|
|
d43c7b581d | ||
|
|
383b933e26 | ||
|
|
d26ccf6294 | ||
|
|
6f9699f605 | ||
|
|
1e9093d781 | ||
|
|
9dc6492e52 | ||
|
|
d22f7cae6a | ||
|
|
473afaab45 | ||
|
|
dcd68303a4 | ||
|
|
03394556b5 | ||
|
|
1c4f6f75f3 | ||
|
|
f00928dedb | ||
|
|
a48f8fbb61 | ||
|
|
1fa388370e | ||
|
|
95ef6b3f71 | ||
|
|
de11d36d00 | ||
|
|
d77c2adabe | ||
|
|
c89c055ae0 | ||
|
|
dac8117f32 | ||
|
|
937b091bab |
25
.travis.yml
25
.travis.yml
@@ -21,6 +21,14 @@ matrix:
|
|||||||
after_success:
|
after_success:
|
||||||
- npm install coveralls
|
- npm install coveralls
|
||||||
- cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
|
- cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
|
||||||
|
- name: "Linux (glibc) - Node 11 (Experimental)"
|
||||||
|
os: linux
|
||||||
|
dist: trusty
|
||||||
|
sudo: false
|
||||||
|
language: node_js
|
||||||
|
node_js: "11"
|
||||||
|
before_install:
|
||||||
|
- unset PREBUILD_TOKEN
|
||||||
- name: "Linux (musl) - Node 8"
|
- name: "Linux (musl) - Node 8"
|
||||||
os: linux
|
os: linux
|
||||||
dist: trusty
|
dist: trusty
|
||||||
@@ -41,6 +49,16 @@ matrix:
|
|||||||
- sudo docker exec sharp apk add build-base git python2 --update-cache
|
- sudo docker exec sharp apk add build-base git python2 --update-cache
|
||||||
install: sudo docker exec sharp sh -c "npm install --unsafe-perm"
|
install: sudo docker exec sharp sh -c "npm install --unsafe-perm"
|
||||||
script: sudo docker exec sharp sh -c "npm test"
|
script: sudo docker exec sharp sh -c "npm test"
|
||||||
|
- name: "Linux (musl) - Node 11 (Experimental)"
|
||||||
|
os: linux
|
||||||
|
dist: trusty
|
||||||
|
sudo: true
|
||||||
|
language: minimal
|
||||||
|
before_install:
|
||||||
|
- sudo docker run -dit --name sharp --env CI --volume "${PWD}:/mnt/sharp" --workdir /mnt/sharp node:11-alpine
|
||||||
|
- sudo docker exec sharp apk add build-base git python2 --update-cache
|
||||||
|
install: sudo docker exec sharp sh -c "npm install --unsafe-perm"
|
||||||
|
script: sudo docker exec sharp sh -c "npm test"
|
||||||
- name: "OS X - Node 6"
|
- name: "OS X - Node 6"
|
||||||
os: osx
|
os: osx
|
||||||
osx_image: xcode9.2
|
osx_image: xcode9.2
|
||||||
@@ -56,3 +74,10 @@ matrix:
|
|||||||
osx_image: xcode9.2
|
osx_image: xcode9.2
|
||||||
language: node_js
|
language: node_js
|
||||||
node_js: "10"
|
node_js: "10"
|
||||||
|
- name: "OS X - Node 11 (Experimental)"
|
||||||
|
os: osx
|
||||||
|
osx_image: xcode9.2
|
||||||
|
language: node_js
|
||||||
|
node_js: "11"
|
||||||
|
before_install:
|
||||||
|
- unset PREBUILD_TOKEN
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ environment:
|
|||||||
- nodejs_version: "6"
|
- nodejs_version: "6"
|
||||||
- nodejs_version: "8"
|
- nodejs_version: "8"
|
||||||
- nodejs_version: "10"
|
- nodejs_version: "10"
|
||||||
|
- nodejs_version: "11"
|
||||||
|
PREBUILD_TOKEN: ""
|
||||||
install:
|
install:
|
||||||
- ps: Install-Product node $env:nodejs_version x64
|
- ps: Install-Product node $env:nodejs_version x64
|
||||||
- npm install -g npm@5
|
- npm install -g npm@5
|
||||||
|
|||||||
12
binding.gyp
12
binding.gyp
@@ -183,13 +183,23 @@
|
|||||||
},
|
},
|
||||||
'configurations': {
|
'configurations': {
|
||||||
'Release': {
|
'Release': {
|
||||||
|
'cflags_cc': [
|
||||||
|
'-Wno-cast-function-type',
|
||||||
|
'-Wno-deprecated-declarations'
|
||||||
|
],
|
||||||
|
'xcode_settings': {
|
||||||
|
'OTHER_CPLUSPLUSFLAGS': [
|
||||||
|
'-Wno-deprecated-declarations'
|
||||||
|
]
|
||||||
|
},
|
||||||
'msvs_settings': {
|
'msvs_settings': {
|
||||||
'VCCLCompilerTool': {
|
'VCCLCompilerTool': {
|
||||||
'ExceptionHandling': 1
|
'ExceptionHandling': 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'msvs_disabled_warnings': [
|
'msvs_disabled_warnings': [
|
||||||
4275
|
4275,
|
||||||
|
4996
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -118,7 +118,8 @@ Merge alpha transparency channel, if any, with a background.
|
|||||||
|
|
||||||
### Parameters
|
### Parameters
|
||||||
|
|
||||||
- `options`
|
- `options` **[Object][2]?**
|
||||||
|
- `options.background` **([String][3] \| [Object][2])** background colour, parsed by the [color][4] module, defaults to black. (optional, default `{r:0,g:0,b:0}`)
|
||||||
|
|
||||||
Returns **Sharp**
|
Returns **Sharp**
|
||||||
|
|
||||||
@@ -130,9 +131,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
|
JPEG and WebP input images will not take advantage of the shrink-on-load performance optimisation
|
||||||
when applying a gamma correction.
|
when applying a gamma correction.
|
||||||
|
|
||||||
|
Supply a second argument to use a different output gamma value, otherwise the first value is used in both cases.
|
||||||
|
|
||||||
### Parameters
|
### Parameters
|
||||||
|
|
||||||
- `gamma` **[Number][1]** 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`)
|
||||||
|
- `gammaOut` **[Number][1]?** value between 1.0 and 3.0. (optional, defaults to same as `gamma`)
|
||||||
|
|
||||||
|
|
||||||
- Throws **[Error][5]** Invalid parameters
|
- Throws **[Error][5]** Invalid parameters
|
||||||
@@ -250,6 +254,35 @@ Apply the linear formula a \* input + b to the image (levels adjustment)
|
|||||||
- `b` **[Number][1]** offset (optional, default `0.0`)
|
- `b` **[Number][1]** offset (optional, default `0.0`)
|
||||||
|
|
||||||
|
|
||||||
|
- Throws **[Error][5]** Invalid parameters
|
||||||
|
|
||||||
|
Returns **Sharp**
|
||||||
|
|
||||||
|
## recomb
|
||||||
|
|
||||||
|
Recomb the image with the specified matrix.
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
- `inputMatrix`
|
||||||
|
- `3x3` **[Array][7]<[Array][7]<[Number][1]>>** Recombination matrix
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
sharp(input)
|
||||||
|
.recomb([
|
||||||
|
[0.3588, 0.7044, 0.1368],
|
||||||
|
[0.2990, 0.5870, 0.1140],
|
||||||
|
[0.2392, 0.4696, 0.0912],
|
||||||
|
])
|
||||||
|
.raw()
|
||||||
|
.toBuffer(function(err, data, info) {
|
||||||
|
// data contains the raw pixel data after applying the recomb
|
||||||
|
// With this example input, a sepia filter has been applied
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
- Throws **[Error][5]** Invalid parameters
|
- Throws **[Error][5]** Invalid parameters
|
||||||
|
|
||||||
Returns **Sharp**
|
Returns **Sharp**
|
||||||
|
|||||||
@@ -206,6 +206,10 @@ Use these TIFF options for output image.
|
|||||||
- `options.force` **[Boolean][6]** force TIFF output, otherwise attempt to use input format (optional, default `true`)
|
- `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.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.predictor` **[Boolean][6]** compression predictor options: none, horizontal, float (optional, default `'horizontal'`)
|
||||||
|
- `options.pyramid` **[Boolean][6]** write an image pyramid (optional, default `false`)
|
||||||
|
- `options.tile` **[Boolean][6]** write a tiled tiff (optional, default `false`)
|
||||||
|
- `options.tileWidth` **[Boolean][6]** horizontal tile size (optional, default `256`)
|
||||||
|
- `options.tileHeight` **[Boolean][6]** vertical tile size (optional, default `256`)
|
||||||
- `options.xres` **[Number][8]** horizontal resolution in pixels/mm (optional, default `1.0`)
|
- `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.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`)
|
- `options.squash` **[Boolean][6]** squash 8-bit images down to 1 bit (optional, default `false`)
|
||||||
|
|||||||
@@ -30,22 +30,23 @@ Possible interpolation kernels are:
|
|||||||
|
|
||||||
- `nearest`: Use [nearest neighbour interpolation][4].
|
- `nearest`: Use [nearest neighbour interpolation][4].
|
||||||
- `cubic`: Use a [Catmull-Rom spline][5].
|
- `cubic`: Use a [Catmull-Rom spline][5].
|
||||||
- `lanczos2`: Use a [Lanczos kernel][6] with `a=2`.
|
- `mitchell`: Use a [Mitchell-Netravali spline][6].
|
||||||
|
- `lanczos2`: Use a [Lanczos kernel][7] with `a=2`.
|
||||||
- `lanczos3`: Use a Lanczos kernel with `a=3` (the default).
|
- `lanczos3`: Use a Lanczos kernel with `a=3` (the default).
|
||||||
|
|
||||||
### Parameters
|
### Parameters
|
||||||
|
|
||||||
- `width` **[Number][7]?** pixels wide the resultant image should be. Use `null` or `undefined` to auto-scale the width to match the height.
|
- `width` **[Number][8]?** pixels wide the resultant image should be. Use `null` or `undefined` to auto-scale the width to match the height.
|
||||||
- `height` **[Number][7]?** pixels high the resultant image should be. Use `null` or `undefined` to auto-scale the height to match the width.
|
- `height` **[Number][8]?** pixels high the resultant image should be. Use `null` or `undefined` to auto-scale the height to match the width.
|
||||||
- `options` **[Object][8]?**
|
- `options` **[Object][9]?**
|
||||||
- `options.width` **[String][9]?** alternative means of specifying `width`. If both are present this take priority.
|
- `options.width` **[String][10]?** alternative means of specifying `width`. If both are present this take priority.
|
||||||
- `options.height` **[String][9]?** alternative means of specifying `height`. If both are present this take priority.
|
- `options.height` **[String][10]?** alternative means of specifying `height`. If both are present this take priority.
|
||||||
- `options.fit` **[String][9]** how the image should be resized to fit both provided dimensions, one of `cover`, `contain`, `fill`, `inside` or `outside`. (optional, default `'cover'`)
|
- `options.fit` **[String][10]** how the image should be resized to fit both provided dimensions, one of `cover`, `contain`, `fill`, `inside` or `outside`. (optional, default `'cover'`)
|
||||||
- `options.position` **[String][9]** position, gravity or strategy to use when `fit` is `cover` or `contain`. (optional, default `'centre'`)
|
- `options.position` **[String][10]** position, gravity or strategy to use when `fit` is `cover` or `contain`. (optional, default `'centre'`)
|
||||||
- `options.background` **([String][9] \| [Object][8])** background colour when using a `fit` of `contain`, parsed by the [color][10] module, defaults to black without transparency. (optional, default `{r:0,g:0,b:0,alpha:1}`)
|
- `options.background` **([String][10] \| [Object][9])** background colour when using a `fit` of `contain`, parsed by the [color][11] module, defaults to black without transparency. (optional, default `{r:0,g:0,b:0,alpha:1}`)
|
||||||
- `options.kernel` **[String][9]** the kernel to use for image reduction. (optional, default `'lanczos3'`)
|
- `options.kernel` **[String][10]** the kernel to use for image reduction. (optional, default `'lanczos3'`)
|
||||||
- `options.withoutEnlargement` **[Boolean][11]** do not enlarge if the width _or_ height are already less than the specified dimensions, equivalent to GraphicsMagick's `>` geometry option. (optional, default `false`)
|
- `options.withoutEnlargement` **[Boolean][12]** do not enlarge if the width _or_ height are already less than the specified dimensions, equivalent to GraphicsMagick's `>` geometry option. (optional, default `false`)
|
||||||
- `options.fastShrinkOnLoad` **[Boolean][11]** 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`)
|
- `options.fastShrinkOnLoad` **[Boolean][12]** 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`)
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
@@ -113,7 +114,7 @@ sharp(input)
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
- Throws **[Error][12]** Invalid parameters
|
- Throws **[Error][13]** Invalid parameters
|
||||||
|
|
||||||
Returns **Sharp**
|
Returns **Sharp**
|
||||||
|
|
||||||
@@ -124,12 +125,12 @@ This operation will always occur after resizing and extraction, if any.
|
|||||||
|
|
||||||
### Parameters
|
### Parameters
|
||||||
|
|
||||||
- `extend` **([Number][7] \| [Object][8])** single pixel count to add to all edges or an Object with per-edge counts
|
- `extend` **([Number][8] \| [Object][9])** single pixel count to add to all edges or an Object with per-edge counts
|
||||||
- `extend.top` **[Number][7]?**
|
- `extend.top` **[Number][8]?**
|
||||||
- `extend.left` **[Number][7]?**
|
- `extend.left` **[Number][8]?**
|
||||||
- `extend.bottom` **[Number][7]?**
|
- `extend.bottom` **[Number][8]?**
|
||||||
- `extend.right` **[Number][7]?**
|
- `extend.right` **[Number][8]?**
|
||||||
- `extend.background` **([String][9] \| [Object][8])** background colour, parsed by the [color][10] module, defaults to black without transparency. (optional, default `{r:0,g:0,b:0,alpha:1}`)
|
- `extend.background` **([String][10] \| [Object][9])** background colour, parsed by the [color][11] module, defaults to black without transparency. (optional, default `{r:0,g:0,b:0,alpha:1}`)
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
@@ -138,7 +139,6 @@ This operation will always occur after resizing and extraction, if any.
|
|||||||
// to the top, left and right edges and 20 to the bottom edge
|
// to the top, left and right edges and 20 to the bottom edge
|
||||||
sharp(input)
|
sharp(input)
|
||||||
.resize(140)
|
.resize(140)
|
||||||
.)
|
|
||||||
.extend({
|
.extend({
|
||||||
top: 10,
|
top: 10,
|
||||||
bottom: 20,
|
bottom: 20,
|
||||||
@@ -149,7 +149,7 @@ sharp(input)
|
|||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
- Throws **[Error][12]** Invalid parameters
|
- Throws **[Error][13]** Invalid parameters
|
||||||
|
|
||||||
Returns **Sharp**
|
Returns **Sharp**
|
||||||
|
|
||||||
@@ -163,11 +163,11 @@ Extract a region of the image.
|
|||||||
|
|
||||||
### Parameters
|
### Parameters
|
||||||
|
|
||||||
- `options` **[Object][8]**
|
- `options` **[Object][9]**
|
||||||
- `options.left` **[Number][7]** zero-indexed offset from left edge
|
- `options.left` **[Number][8]** zero-indexed offset from left edge
|
||||||
- `options.top` **[Number][7]** zero-indexed offset from top edge
|
- `options.top` **[Number][8]** zero-indexed offset from top edge
|
||||||
- `options.width` **[Number][7]** dimension of extracted image
|
- `options.width` **[Number][8]** dimension of extracted image
|
||||||
- `options.height` **[Number][7]** dimension of extracted image
|
- `options.height` **[Number][8]** dimension of extracted image
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
@@ -189,7 +189,7 @@ sharp(input)
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
- Throws **[Error][12]** Invalid parameters
|
- Throws **[Error][13]** Invalid parameters
|
||||||
|
|
||||||
Returns **Sharp**
|
Returns **Sharp**
|
||||||
|
|
||||||
@@ -200,10 +200,10 @@ The `info` response Object will contain `trimOffsetLeft` and `trimOffsetTop` pro
|
|||||||
|
|
||||||
### Parameters
|
### Parameters
|
||||||
|
|
||||||
- `threshold` **[Number][7]** the allowed difference from the top-left pixel, a number greater than zero. (optional, default `10`)
|
- `threshold` **[Number][8]** the allowed difference from the top-left pixel, a number greater than zero. (optional, default `10`)
|
||||||
|
|
||||||
|
|
||||||
- Throws **[Error][12]** Invalid parameters
|
- Throws **[Error][13]** Invalid parameters
|
||||||
|
|
||||||
Returns **Sharp**
|
Returns **Sharp**
|
||||||
|
|
||||||
@@ -217,16 +217,18 @@ Returns **Sharp**
|
|||||||
|
|
||||||
[5]: https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline
|
[5]: https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline
|
||||||
|
|
||||||
[6]: https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel
|
[6]: https://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf
|
||||||
|
|
||||||
[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
|
[7]: https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel
|
||||||
|
|
||||||
[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
|
[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
|
||||||
|
|
||||||
[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
|
[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
|
||||||
|
|
||||||
[10]: https://www.npmjs.org/package/color
|
[10]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
|
||||||
|
|
||||||
[11]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
|
[11]: https://www.npmjs.org/package/color
|
||||||
|
|
||||||
[12]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
|
[12]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
|
||||||
|
|
||||||
|
[13]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
|
||||||
|
|||||||
@@ -4,6 +4,35 @@
|
|||||||
|
|
||||||
Requires libvips v8.7.0.
|
Requires libvips v8.7.0.
|
||||||
|
|
||||||
|
#### v0.21.1 - 7<sup>th</sup> December 2018
|
||||||
|
|
||||||
|
* Install: support `sharp_dist_base_url` npm config, like existing `SHARP_DIST_BASE_URL`.
|
||||||
|
[#1422](https://github.com/lovell/sharp/pull/1422)
|
||||||
|
[@SethWen](https://github.com/SethWen)
|
||||||
|
|
||||||
|
* Ensure `channel` metadata is correct for raw, greyscale output.
|
||||||
|
[#1425](https://github.com/lovell/sharp/issues/1425)
|
||||||
|
|
||||||
|
* Add support for the "mitchell" kernel for image reductions.
|
||||||
|
[#1438](https://github.com/lovell/sharp/pull/1438)
|
||||||
|
[@Daiz](https://github.com/Daiz)
|
||||||
|
|
||||||
|
* Allow separate parameters for gamma encoding and decoding.
|
||||||
|
[#1439](https://github.com/lovell/sharp/pull/1439)
|
||||||
|
[@Daiz](https://github.com/Daiz)
|
||||||
|
|
||||||
|
* Build prototype with `Object.assign` to allow minification.
|
||||||
|
[#1475](https://github.com/lovell/sharp/pull/1475)
|
||||||
|
[@jaubourg](https://github.com/jaubourg)
|
||||||
|
|
||||||
|
* Expose libvips' recombination matrix operation.
|
||||||
|
[#1477](https://github.com/lovell/sharp/pull/1477)
|
||||||
|
[@fromkeith](https://github.com/fromkeith)
|
||||||
|
|
||||||
|
* Expose libvips' pyramid/tile options for TIFF output.
|
||||||
|
[#1483](https://github.com/lovell/sharp/pull/1483)
|
||||||
|
[@mbklein](https://github.com/mbklein)
|
||||||
|
|
||||||
#### v0.21.0 - 4<sup>th</sup> October 2018
|
#### v0.21.0 - 4<sup>th</sup> October 2018
|
||||||
|
|
||||||
* Deprecate the following resize-related functions:
|
* Deprecate the following resize-related functions:
|
||||||
|
|||||||
@@ -119,6 +119,9 @@ the help and code contributions of the following people:
|
|||||||
* [Aidan Hoolachan](https://github.com/ajhool)
|
* [Aidan Hoolachan](https://github.com/ajhool)
|
||||||
* [Axel Eirola](https://github.com/aeirola)
|
* [Axel Eirola](https://github.com/aeirola)
|
||||||
* [Freezy](https://github.com/freezy)
|
* [Freezy](https://github.com/freezy)
|
||||||
|
* [Julian Aubourg](https://github.com/jaubourg)
|
||||||
|
* [Keith Belovay](https://github.com/fromkeith)
|
||||||
|
* [Michael B. Klein](https://github.com/mbklein)
|
||||||
|
|
||||||
Thank you!
|
Thank you!
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,9 @@ libvips is available in the
|
|||||||
[testing repository](https://pkgs.alpinelinux.org/packages?name=vips-dev):
|
[testing repository](https://pkgs.alpinelinux.org/packages?name=vips-dev):
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
apk add vips-dev fftw-dev build-base --update-cache --repository https://dl-3.alpinelinux.org/alpine/edge/testing/
|
apk add vips-dev fftw-dev build-base --update-cache \
|
||||||
|
--repository https://alpine.global.ssl.fastly.net/alpine/edge/testing/ \
|
||||||
|
--repository https://alpine.global.ssl.fastly.net/alpine/edge/main
|
||||||
```
|
```
|
||||||
|
|
||||||
The smaller stack size of musl libc means
|
The smaller stack size of musl libc means
|
||||||
@@ -95,7 +97,8 @@ that it can be located using `pkg-config --modversion vips-cpp`.
|
|||||||
[](https://ci.appveyor.com/project/lovell/sharp)
|
[](https://ci.appveyor.com/project/lovell/sharp)
|
||||||
|
|
||||||
libvips and its dependencies are fetched and stored within `node_modules\sharp\vendor` during `npm install`.
|
libvips and its dependencies are fetched and stored within `node_modules\sharp\vendor` during `npm install`.
|
||||||
This involves an automated HTTPS download of approximately 13MB.
|
This involves an automated HTTPS download of approximately 13MB. If you are having issues during
|
||||||
|
installation consider removing the directory ```C:\Users\[user]\AppData\Roaming\npm-cache\_libvips```.
|
||||||
|
|
||||||
Only 64-bit (x64) `node.exe` is supported.
|
Only 64-bit (x64) `node.exe` is supported.
|
||||||
|
|
||||||
@@ -146,16 +149,25 @@ docker pull tailor/docker-libvips
|
|||||||
|
|
||||||
### AWS Lambda
|
### AWS Lambda
|
||||||
|
|
||||||
A [deployment package](http://docs.aws.amazon.com/lambda/latest/dg/nodejs-create-deployment-pkg.html) for the
|
Set the Lambda runtime to Node.js 8.10.
|
||||||
[Lambda Execution Environment](http://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html)
|
|
||||||
can be built using Docker.
|
The binaries in the `node_modules` directory of the
|
||||||
|
[deployment package](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-create-deployment-pkg.html)
|
||||||
|
must be for the Linux x64 platform/architecture.
|
||||||
|
|
||||||
|
On non-Linux machines such as OS X and Windows run the following:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
rm -rf node_modules/sharp
|
rm -rf node_modules/sharp
|
||||||
docker run -v "$PWD":/var/task lambci/lambda:build-nodejs8.10 npm install
|
npm install --arch=x64 --platform=linux --target=8.10.0 sharp
|
||||||
```
|
```
|
||||||
|
|
||||||
Set the Lambda runtime to Node.js 8.10.
|
Alternatively a Docker container closely matching the Lambda runtime can be used:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
rm -rf node_modules/sharp
|
||||||
|
docker run -v "$PWD":/var/task lambci/lambda:build-nodejs8.10 npm install sharp
|
||||||
|
```
|
||||||
|
|
||||||
To get the best performance select the largest memory available.
|
To get the best performance select the largest memory available.
|
||||||
A 1536 MB function provides ~12x more CPU time than a 128 MB function.
|
A 1536 MB function provides ~12x more CPU time than a 128 MB function.
|
||||||
@@ -217,7 +229,14 @@ you can do so via
|
|||||||
[https://github.com/lovell/sharp-libvips/releases](https://github.com/lovell/sharp-libvips/releases)
|
[https://github.com/lovell/sharp-libvips/releases](https://github.com/lovell/sharp-libvips/releases)
|
||||||
|
|
||||||
Should you wish to install these from your own location,
|
Should you wish to install these from your own location,
|
||||||
set the `SHARP_DIST_BASE_URL` environment variable, e.g.
|
set the `sharp_dist_base_url` npm config option, e.g.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm config set sharp_dist_base_url "https://hostname/path/"
|
||||||
|
npm install sharp
|
||||||
|
```
|
||||||
|
|
||||||
|
or set the `SHARP_DIST_BASE_URL` environment variable, e.g.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
SHARP_DIST_BASE_URL="https://hostname/path/" npm install sharp
|
SHARP_DIST_BASE_URL="https://hostname/path/" npm install sharp
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ const libvips = require('../lib/libvips');
|
|||||||
const platform = require('../lib/platform');
|
const platform = require('../lib/platform');
|
||||||
|
|
||||||
const minimumLibvipsVersion = libvips.minimumLibvipsVersion;
|
const minimumLibvipsVersion = libvips.minimumLibvipsVersion;
|
||||||
const distBaseUrl = process.env.SHARP_DIST_BASE_URL || `https://github.com/lovell/sharp-libvips/releases/download/v${minimumLibvipsVersion}/`;
|
const distBaseUrl = process.env.npm_config_sharp_dist_base_url || process.env.SHARP_DIST_BASE_URL || `https://github.com/lovell/sharp-libvips/releases/download/v${minimumLibvipsVersion}/`;
|
||||||
|
|
||||||
const fail = function (err) {
|
const fail = function (err) {
|
||||||
npmLog.error('sharp', err.message);
|
npmLog.error('sharp', err.message);
|
||||||
@@ -55,8 +55,8 @@ try {
|
|||||||
if (arch === 'ia32') {
|
if (arch === 'ia32') {
|
||||||
throw new Error(`Intel Architecture 32-bit systems require manual installation of libvips >= ${minimumLibvipsVersion}`);
|
throw new Error(`Intel Architecture 32-bit systems require manual installation of libvips >= ${minimumLibvipsVersion}`);
|
||||||
}
|
}
|
||||||
if (platformAndArch === 'freebsd-x64') {
|
if (platformAndArch === 'freebsd-x64' || platformAndArch === 'openbsd-x64' || platformAndArch === 'sunos-x64') {
|
||||||
throw new Error(`FreeBSD systems require manual installation of libvips >= ${minimumLibvipsVersion}`);
|
throw new Error(`BSD/SunOS systems require manual installation of libvips >= ${minimumLibvipsVersion}`);
|
||||||
}
|
}
|
||||||
if (detectLibc.family === detectLibc.GLIBC && detectLibc.version && semver.lt(`${detectLibc.version}.0`, '2.13.0')) {
|
if (detectLibc.family === detectLibc.GLIBC && detectLibc.version && semver.lt(`${detectLibc.version}.0`, '2.13.0')) {
|
||||||
throw new Error(`Use with glibc version ${detectLibc.version} requires manual installation of libvips >= ${minimumLibvipsVersion}`);
|
throw new Error(`Use with glibc version ${detectLibc.version} requires manual installation of libvips >= ${minimumLibvipsVersion}`);
|
||||||
|
|||||||
@@ -117,14 +117,12 @@ function bandbool (boolOp) {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
module.exports = function (Sharp) {
|
module.exports = function (Sharp) {
|
||||||
|
Object.assign(Sharp.prototype, {
|
||||||
// Public instance functions
|
// Public instance functions
|
||||||
[
|
|
||||||
removeAlpha,
|
removeAlpha,
|
||||||
extractChannel,
|
extractChannel,
|
||||||
joinChannel,
|
joinChannel,
|
||||||
bandbool
|
bandbool
|
||||||
].forEach(function (f) {
|
|
||||||
Sharp.prototype[f.name] = f;
|
|
||||||
});
|
});
|
||||||
// Class attributes
|
// Class attributes
|
||||||
Sharp.bool = bool;
|
Sharp.bool = bool;
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ function _setColourOption (key, val) {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
module.exports = function (Sharp) {
|
module.exports = function (Sharp) {
|
||||||
[
|
Object.assign(Sharp.prototype, {
|
||||||
// Public
|
// Public
|
||||||
tint,
|
tint,
|
||||||
greyscale,
|
greyscale,
|
||||||
@@ -132,8 +132,6 @@ module.exports = function (Sharp) {
|
|||||||
toColorspace,
|
toColorspace,
|
||||||
// Private
|
// Private
|
||||||
_setColourOption
|
_setColourOption
|
||||||
].forEach(function (f) {
|
|
||||||
Sharp.prototype[f.name] = f;
|
|
||||||
});
|
});
|
||||||
// Class attributes
|
// Class attributes
|
||||||
Sharp.colourspace = colourspace;
|
Sharp.colourspace = colourspace;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const events = require('events');
|
|||||||
const is = require('./is');
|
const is = require('./is');
|
||||||
|
|
||||||
require('./libvips').hasVendoredLibvips();
|
require('./libvips').hasVendoredLibvips();
|
||||||
const sharp = require('../build/Release/sharp.node');
|
const sharp = require('bindings')('sharp.node');
|
||||||
|
|
||||||
// Use NODE_DEBUG=sharp to enable libvips warnings
|
// Use NODE_DEBUG=sharp to enable libvips warnings
|
||||||
const debuglog = util.debuglog('sharp');
|
const debuglog = util.debuglog('sharp');
|
||||||
@@ -136,6 +136,7 @@ const Sharp = function (input, options) {
|
|||||||
thresholdGrayscale: true,
|
thresholdGrayscale: true,
|
||||||
trimThreshold: 0,
|
trimThreshold: 0,
|
||||||
gamma: 0,
|
gamma: 0,
|
||||||
|
gammaOut: 0,
|
||||||
greyscale: false,
|
greyscale: false,
|
||||||
normalise: 0,
|
normalise: 0,
|
||||||
booleanBufferIn: null,
|
booleanBufferIn: null,
|
||||||
@@ -176,7 +177,11 @@ const Sharp = function (input, options) {
|
|||||||
tiffQuality: 80,
|
tiffQuality: 80,
|
||||||
tiffCompression: 'jpeg',
|
tiffCompression: 'jpeg',
|
||||||
tiffPredictor: 'horizontal',
|
tiffPredictor: 'horizontal',
|
||||||
|
tiffPyramid: false,
|
||||||
tiffSquash: false,
|
tiffSquash: false,
|
||||||
|
tiffTile: false,
|
||||||
|
tiffTileHeight: 256,
|
||||||
|
tiffTileWidth: 256,
|
||||||
tiffXres: 1.0,
|
tiffXres: 1.0,
|
||||||
tiffYres: 1.0,
|
tiffYres: 1.0,
|
||||||
tileSize: 256,
|
tileSize: 256,
|
||||||
|
|||||||
@@ -362,7 +362,7 @@ function sequentialRead (sequentialRead) {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
module.exports = function (Sharp) {
|
module.exports = function (Sharp) {
|
||||||
[
|
Object.assign(Sharp.prototype, {
|
||||||
// Private
|
// Private
|
||||||
_createInputDescriptor,
|
_createInputDescriptor,
|
||||||
_write,
|
_write,
|
||||||
@@ -374,7 +374,5 @@ module.exports = function (Sharp) {
|
|||||||
stats,
|
stats,
|
||||||
limitInputPixels,
|
limitInputPixels,
|
||||||
sequentialRead
|
sequentialRead
|
||||||
].forEach(function (f) {
|
|
||||||
Sharp.prototype[f.name] = f;
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -172,6 +172,7 @@ function blur (sigma) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Merge alpha transparency channel, if any, with a background.
|
* Merge alpha transparency channel, if any, with a background.
|
||||||
|
* @param {Object} [options]
|
||||||
* @param {String|Object} [options.background={r: 0, g: 0, b: 0}] - background colour, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to black.
|
* @param {String|Object} [options.background={r: 0, g: 0, b: 0}] - background colour, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to black.
|
||||||
* @returns {Sharp}
|
* @returns {Sharp}
|
||||||
*/
|
*/
|
||||||
@@ -189,11 +190,15 @@ function flatten (options) {
|
|||||||
* This can improve the perceived brightness of a resized image in non-linear colour spaces.
|
* This can improve the perceived brightness of a resized image in non-linear colour spaces.
|
||||||
* JPEG and WebP input images will not take advantage of the shrink-on-load performance optimisation
|
* JPEG and WebP input images will not take advantage of the shrink-on-load performance optimisation
|
||||||
* when applying a gamma correction.
|
* when applying a gamma correction.
|
||||||
|
*
|
||||||
|
* Supply a second argument to use a different output gamma value, otherwise the first value is used in both cases.
|
||||||
|
*
|
||||||
* @param {Number} [gamma=2.2] value between 1.0 and 3.0.
|
* @param {Number} [gamma=2.2] value between 1.0 and 3.0.
|
||||||
|
* @param {Number} [gammaOut] value between 1.0 and 3.0. (optional, defaults to same as `gamma`)
|
||||||
* @returns {Sharp}
|
* @returns {Sharp}
|
||||||
* @throws {Error} Invalid parameters
|
* @throws {Error} Invalid parameters
|
||||||
*/
|
*/
|
||||||
function gamma (gamma) {
|
function gamma (gamma, gammaOut) {
|
||||||
if (!is.defined(gamma)) {
|
if (!is.defined(gamma)) {
|
||||||
// Default gamma correction of 2.2 (sRGB)
|
// Default gamma correction of 2.2 (sRGB)
|
||||||
this.options.gamma = 2.2;
|
this.options.gamma = 2.2;
|
||||||
@@ -202,6 +207,14 @@ function gamma (gamma) {
|
|||||||
} else {
|
} else {
|
||||||
throw new Error('Invalid gamma correction (1.0 to 3.0) ' + gamma);
|
throw new Error('Invalid gamma correction (1.0 to 3.0) ' + gamma);
|
||||||
}
|
}
|
||||||
|
if (!is.defined(gammaOut)) {
|
||||||
|
// Default gamma correction for output is same as input
|
||||||
|
this.options.gammaOut = this.options.gamma;
|
||||||
|
} else if (is.number(gammaOut) && is.inRange(gammaOut, 1, 3)) {
|
||||||
|
this.options.gammaOut = gammaOut;
|
||||||
|
} else {
|
||||||
|
throw new Error('Invalid output gamma correction (1.0 to 3.0) ' + gammaOut);
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,12 +378,49 @@ function linear (a, b) {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recomb the image with the specified matrix.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* sharp(input)
|
||||||
|
* .recomb([
|
||||||
|
* [0.3588, 0.7044, 0.1368],
|
||||||
|
* [0.2990, 0.5870, 0.1140],
|
||||||
|
* [0.2392, 0.4696, 0.0912],
|
||||||
|
* ])
|
||||||
|
* .raw()
|
||||||
|
* .toBuffer(function(err, data, info) {
|
||||||
|
* // data contains the raw pixel data after applying the recomb
|
||||||
|
* // With this example input, a sepia filter has been applied
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* @param {Array<Array<Number>>} 3x3 Recombination matrix
|
||||||
|
* @returns {Sharp}
|
||||||
|
* @throws {Error} Invalid parameters
|
||||||
|
*/
|
||||||
|
function recomb (inputMatrix) {
|
||||||
|
if (!Array.isArray(inputMatrix) || inputMatrix.length !== 3 ||
|
||||||
|
inputMatrix[0].length !== 3 ||
|
||||||
|
inputMatrix[1].length !== 3 ||
|
||||||
|
inputMatrix[2].length !== 3
|
||||||
|
) {
|
||||||
|
// must pass in a kernel
|
||||||
|
throw new Error('Invalid Recomb Matrix');
|
||||||
|
}
|
||||||
|
this.options.recombMatrix = [
|
||||||
|
inputMatrix[0][0], inputMatrix[0][1], inputMatrix[0][2],
|
||||||
|
inputMatrix[1][0], inputMatrix[1][1], inputMatrix[1][2],
|
||||||
|
inputMatrix[2][0], inputMatrix[2][1], inputMatrix[2][2]
|
||||||
|
].map(Number);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decorate the Sharp prototype with operation-related functions.
|
* Decorate the Sharp prototype with operation-related functions.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
module.exports = function (Sharp) {
|
module.exports = function (Sharp) {
|
||||||
[
|
Object.assign(Sharp.prototype, {
|
||||||
rotate,
|
rotate,
|
||||||
flip,
|
flip,
|
||||||
flop,
|
flop,
|
||||||
@@ -385,8 +435,7 @@ module.exports = function (Sharp) {
|
|||||||
convolve,
|
convolve,
|
||||||
threshold,
|
threshold,
|
||||||
boolean,
|
boolean,
|
||||||
linear
|
linear,
|
||||||
].forEach(function (f) {
|
recomb
|
||||||
Sharp.prototype[f.name] = f;
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -304,6 +304,10 @@ function webp (options) {
|
|||||||
* @param {Boolean} [options.force=true] - force TIFF output, otherwise attempt to use input format
|
* @param {Boolean} [options.force=true] - force TIFF output, otherwise attempt to use input format
|
||||||
* @param {Boolean} [options.compression='jpeg'] - compression options: lzw, deflate, jpeg, ccittfax4
|
* @param {Boolean} [options.compression='jpeg'] - compression options: lzw, deflate, jpeg, ccittfax4
|
||||||
* @param {Boolean} [options.predictor='horizontal'] - compression predictor options: none, horizontal, float
|
* @param {Boolean} [options.predictor='horizontal'] - compression predictor options: none, horizontal, float
|
||||||
|
* @param {Boolean} [options.pyramid=false] - write an image pyramid
|
||||||
|
* @param {Boolean} [options.tile=false] - write a tiled tiff
|
||||||
|
* @param {Boolean} [options.tileWidth=256] - horizontal tile size
|
||||||
|
* @param {Boolean} [options.tileHeight=256] - vertical tile size
|
||||||
* @param {Number} [options.xres=1.0] - horizontal resolution in pixels/mm
|
* @param {Number} [options.xres=1.0] - horizontal resolution in pixels/mm
|
||||||
* @param {Number} [options.yres=1.0] - vertical 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
|
* @param {Boolean} [options.squash=false] - squash 8-bit images down to 1 bit
|
||||||
@@ -311,29 +315,60 @@ function webp (options) {
|
|||||||
* @throws {Error} Invalid options
|
* @throws {Error} Invalid options
|
||||||
*/
|
*/
|
||||||
function tiff (options) {
|
function tiff (options) {
|
||||||
if (is.object(options) && is.defined(options.quality)) {
|
if (is.object(options)) {
|
||||||
|
if (is.defined(options.quality)) {
|
||||||
if (is.integer(options.quality) && is.inRange(options.quality, 1, 100)) {
|
if (is.integer(options.quality) && is.inRange(options.quality, 1, 100)) {
|
||||||
this.options.tiffQuality = options.quality;
|
this.options.tiffQuality = options.quality;
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Invalid quality (integer, 1-100) ' + options.quality);
|
throw new Error('Invalid quality (integer, 1-100) ' + options.quality);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is.object(options) && is.defined(options.squash)) {
|
if (is.defined(options.squash)) {
|
||||||
if (is.bool(options.squash)) {
|
if (is.bool(options.squash)) {
|
||||||
this.options.tiffSquash = options.squash;
|
this.options.tiffSquash = options.squash;
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Invalid Value for squash ' + options.squash + ' Only Boolean Values allowed for options.squash.');
|
throw new Error('Invalid Value for squash ' + options.squash + ' Only Boolean Values allowed for options.squash.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// tiling
|
||||||
|
if (is.defined(options.tile)) {
|
||||||
|
if (is.bool(options.tile)) {
|
||||||
|
this.options.tiffTile = options.tile;
|
||||||
|
} else {
|
||||||
|
throw new Error('Invalid Value for tile ' + options.tile + ' Only Boolean values allowed for options.tile');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (is.defined(options.tileWidth)) {
|
||||||
|
if (is.number(options.tileWidth) && options.tileWidth > 0) {
|
||||||
|
this.options.tiffTileWidth = options.tileWidth;
|
||||||
|
} else {
|
||||||
|
throw new Error('Invalid Value for tileWidth ' + options.tileWidth + ' Only positive numeric values allowed for options.tileWidth');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (is.defined(options.tileHeight)) {
|
||||||
|
if (is.number(options.tileHeight) && options.tileHeight > 0) {
|
||||||
|
this.options.tiffTileHeight = options.tileHeight;
|
||||||
|
} else {
|
||||||
|
throw new Error('Invalid Value for tileHeight ' + options.tileHeight + ' Only positive numeric values allowed for options.tileHeight');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// pyramid
|
||||||
|
if (is.defined(options.pyramid)) {
|
||||||
|
if (is.bool(options.pyramid)) {
|
||||||
|
this.options.tiffPyramid = options.pyramid;
|
||||||
|
} else {
|
||||||
|
throw new Error('Invalid Value for pyramid ' + options.pyramid + ' Only Boolean values allowed for options.pyramid');
|
||||||
|
}
|
||||||
|
}
|
||||||
// resolution
|
// resolution
|
||||||
if (is.object(options) && is.defined(options.xres)) {
|
if (is.defined(options.xres)) {
|
||||||
if (is.number(options.xres)) {
|
if (is.number(options.xres)) {
|
||||||
this.options.tiffXres = options.xres;
|
this.options.tiffXres = options.xres;
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Invalid Value for xres ' + options.xres + ' Only numeric values allowed for options.xres');
|
throw new Error('Invalid Value for xres ' + options.xres + ' Only numeric values allowed for options.xres');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is.object(options) && is.defined(options.yres)) {
|
if (is.defined(options.yres)) {
|
||||||
if (is.number(options.yres)) {
|
if (is.number(options.yres)) {
|
||||||
this.options.tiffYres = options.yres;
|
this.options.tiffYres = options.yres;
|
||||||
} else {
|
} else {
|
||||||
@@ -341,7 +376,7 @@ function tiff (options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// compression
|
// compression
|
||||||
if (is.defined(options) && is.defined(options.compression)) {
|
if (is.defined(options.compression)) {
|
||||||
if (is.string(options.compression) && is.inArray(options.compression, ['lzw', 'deflate', 'jpeg', 'ccittfax4', 'none'])) {
|
if (is.string(options.compression) && is.inArray(options.compression, ['lzw', 'deflate', 'jpeg', 'ccittfax4', 'none'])) {
|
||||||
this.options.tiffCompression = options.compression;
|
this.options.tiffCompression = options.compression;
|
||||||
} else {
|
} else {
|
||||||
@@ -350,7 +385,7 @@ function tiff (options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// predictor
|
// predictor
|
||||||
if (is.defined(options) && is.defined(options.predictor)) {
|
if (is.defined(options.predictor)) {
|
||||||
if (is.string(options.predictor) && is.inArray(options.predictor, ['none', 'horizontal', 'float'])) {
|
if (is.string(options.predictor) && is.inArray(options.predictor, ['none', 'horizontal', 'float'])) {
|
||||||
this.options.tiffPredictor = options.predictor;
|
this.options.tiffPredictor = options.predictor;
|
||||||
} else {
|
} else {
|
||||||
@@ -358,6 +393,7 @@ function tiff (options) {
|
|||||||
throw new Error(message);
|
throw new Error(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return this._updateFormatOut('tiff', options);
|
return this._updateFormatOut('tiff', options);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -641,7 +677,7 @@ function _pipeline (callback) {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
module.exports = function (Sharp) {
|
module.exports = function (Sharp) {
|
||||||
[
|
Object.assign(Sharp.prototype, {
|
||||||
// Public
|
// Public
|
||||||
toFile,
|
toFile,
|
||||||
toBuffer,
|
toBuffer,
|
||||||
@@ -658,7 +694,5 @@ module.exports = function (Sharp) {
|
|||||||
_setBooleanOption,
|
_setBooleanOption,
|
||||||
_read,
|
_read,
|
||||||
_pipeline
|
_pipeline
|
||||||
].forEach(function (f) {
|
|
||||||
Sharp.prototype[f.name] = f;
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ const strategy = {
|
|||||||
const kernel = {
|
const kernel = {
|
||||||
nearest: 'nearest',
|
nearest: 'nearest',
|
||||||
cubic: 'cubic',
|
cubic: 'cubic',
|
||||||
|
mitchell: 'mitchell',
|
||||||
lanczos2: 'lanczos2',
|
lanczos2: 'lanczos2',
|
||||||
lanczos3: 'lanczos3'
|
lanczos3: 'lanczos3'
|
||||||
};
|
};
|
||||||
@@ -110,6 +111,7 @@ const mapFitToCanvas = {
|
|||||||
* Possible interpolation kernels are:
|
* Possible interpolation kernels are:
|
||||||
* - `nearest`: Use [nearest neighbour interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation).
|
* - `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).
|
* - `cubic`: Use a [Catmull-Rom spline](https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline).
|
||||||
|
* - `mitchell`: Use a [Mitchell-Netravali spline](https://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf).
|
||||||
* - `lanczos2`: Use a [Lanczos kernel](https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel) with `a=2`.
|
* - `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).
|
* - `lanczos3`: Use a Lanczos kernel with `a=3` (the default).
|
||||||
*
|
*
|
||||||
@@ -269,7 +271,6 @@ function resize (width, height, options) {
|
|||||||
* // to the top, left and right edges and 20 to the bottom edge
|
* // to the top, left and right edges and 20 to the bottom edge
|
||||||
* sharp(input)
|
* sharp(input)
|
||||||
* .resize(140)
|
* .resize(140)
|
||||||
* .)
|
|
||||||
* .extend({
|
* .extend({
|
||||||
* top: 10,
|
* top: 10,
|
||||||
* bottom: 20,
|
* bottom: 20,
|
||||||
@@ -468,13 +469,11 @@ function withoutEnlargement (withoutEnlargement) {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
module.exports = function (Sharp) {
|
module.exports = function (Sharp) {
|
||||||
[
|
Object.assign(Sharp.prototype, {
|
||||||
resize,
|
resize,
|
||||||
extend,
|
extend,
|
||||||
extract,
|
extract,
|
||||||
trim
|
trim
|
||||||
].forEach(function (f) {
|
|
||||||
Sharp.prototype[f.name] = f;
|
|
||||||
});
|
});
|
||||||
// Class attributes
|
// Class attributes
|
||||||
Sharp.gravity = gravity;
|
Sharp.gravity = gravity;
|
||||||
|
|||||||
32
package.json
32
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "sharp",
|
"name": "sharp",
|
||||||
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP and TIFF images",
|
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP and TIFF images",
|
||||||
"version": "0.21.0",
|
"version": "0.21.1",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://github.com/lovell/sharp",
|
"homepage": "https://github.com/lovell/sharp",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
@@ -55,13 +55,19 @@
|
|||||||
"Alun Davies <alun.owain.davies@googlemail.com>",
|
"Alun Davies <alun.owain.davies@googlemail.com>",
|
||||||
"Aidan Hoolachan <ajhoolachan21@gmail.com>",
|
"Aidan Hoolachan <ajhoolachan21@gmail.com>",
|
||||||
"Axel Eirola <axel.eirola@iki.fi>",
|
"Axel Eirola <axel.eirola@iki.fi>",
|
||||||
"Freezy <freezy@xbmc.org>"
|
"Freezy <freezy@xbmc.org>",
|
||||||
|
"Daiz <taneli.vatanen@gmail.com>",
|
||||||
|
"Julian Aubourg <j@ubourg.net>",
|
||||||
|
"Keith Belovay <keith@picthrive.com>",
|
||||||
|
"Michael B. Klein <mbklein@gmail.com>"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node-gyp rebuild && node install/dll-copy)",
|
"install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node-gyp rebuild && node install/dll-copy)",
|
||||||
"clean": "rm -rf node_modules/ build/ vendor/ .nyc_output/ coverage/ test/fixtures/output.*",
|
"clean": "rm -rf node_modules/ build/ vendor/ .nyc_output/ coverage/ test/fixtures/output.*",
|
||||||
"test": "semistandard && cc && nyc --reporter=lcov --branches=99 mocha --slow=5000 --timeout=60000 ./test/unit/*.js && prebuild-ci",
|
"test": "semistandard && cc && npm run test-unit && npm run test-licensing && prebuild-ci",
|
||||||
"coverage": "./test/coverage/report.sh",
|
"test-unit": "nyc --reporter=lcov --branches=99 mocha --slow=5000 --timeout=60000 ./test/unit/*.js",
|
||||||
|
"test-licensing": "license-checker --production --summary --onlyAllow=\"Apache-2.0;BSD;ISC;MIT\"",
|
||||||
|
"test-coverage": "./test/coverage/report.sh",
|
||||||
"test-leak": "./test/leak/leak.sh",
|
"test-leak": "./test/leak/leak.sh",
|
||||||
"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"
|
"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"
|
||||||
},
|
},
|
||||||
@@ -87,15 +93,16 @@
|
|||||||
"vips"
|
"vips"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"color": "^3.0.0",
|
"bindings": "^1.3.1",
|
||||||
|
"color": "^3.1.0",
|
||||||
"detect-libc": "^1.0.3",
|
"detect-libc": "^1.0.3",
|
||||||
"nan": "^2.11.1",
|
|
||||||
"fs-copy-file-sync": "^1.1.1",
|
"fs-copy-file-sync": "^1.1.1",
|
||||||
|
"nan": "^2.11.1",
|
||||||
"npmlog": "^4.1.2",
|
"npmlog": "^4.1.2",
|
||||||
"prebuild-install": "^5.2.0",
|
"prebuild-install": "^5.2.2",
|
||||||
"semver": "^5.5.1",
|
"semver": "^5.6.0",
|
||||||
"simple-get": "^3.0.3",
|
"simple-get": "^3.0.3",
|
||||||
"tar": "^4.4.6",
|
"tar": "^4.4.8",
|
||||||
"tunnel-agent": "^0.6.0"
|
"tunnel-agent": "^0.6.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -105,13 +112,14 @@
|
|||||||
"documentation": "^8.1.2",
|
"documentation": "^8.1.2",
|
||||||
"exif-reader": "^1.0.2",
|
"exif-reader": "^1.0.2",
|
||||||
"icc": "^1.0.0",
|
"icc": "^1.0.0",
|
||||||
|
"license-checker": "^24.0.1",
|
||||||
"mocha": "^5.2.0",
|
"mocha": "^5.2.0",
|
||||||
"mock-fs": "^4.7.0",
|
"mock-fs": "^4.7.0",
|
||||||
"nyc": "^13.1.0",
|
"nyc": "^13.1.0",
|
||||||
"prebuild": "^8.1.0",
|
"prebuild": "^8.1.2",
|
||||||
"prebuild-ci": "^2.2.3",
|
"prebuild-ci": "^2.3.0",
|
||||||
"rimraf": "^2.6.2",
|
"rimraf": "^2.6.2",
|
||||||
"semistandard": "^12.0.1"
|
"semistandard": "^13.0.1"
|
||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"config": {
|
"config": {
|
||||||
|
|||||||
@@ -278,6 +278,25 @@ namespace sharp {
|
|||||||
return image.conv(kernel);
|
return image.conv(kernel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Recomb with a Matrix of the given bands/channel size.
|
||||||
|
* Eg. RGB will be a 3x3 matrix.
|
||||||
|
*/
|
||||||
|
VImage Recomb(VImage image, std::unique_ptr<double[]> const &matrix) {
|
||||||
|
double *m = matrix.get();
|
||||||
|
return image
|
||||||
|
.colourspace(VIPS_INTERPRETATION_sRGB)
|
||||||
|
.recomb(image.bands() == 3
|
||||||
|
? VImage::new_from_memory(
|
||||||
|
m, 9 * sizeof(double), 3, 3, 1, VIPS_FORMAT_DOUBLE
|
||||||
|
)
|
||||||
|
: VImage::new_matrixv(4, 4,
|
||||||
|
m[0], m[1], m[2], 0.0,
|
||||||
|
m[3], m[4], m[5], 0.0,
|
||||||
|
m[6], m[7], m[8], 0.0,
|
||||||
|
0.0, 0.0, 0.0, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sharpen flat and jagged areas. Use sigma of -1.0 for fast sharpen.
|
* Sharpen flat and jagged areas. Use sigma of -1.0 for fast sharpen.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -107,6 +107,12 @@ namespace sharp {
|
|||||||
*/
|
*/
|
||||||
VImage Linear(VImage image, double const a, double const b);
|
VImage Linear(VImage image, double const a, double const b);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Recomb with a Matrix of the given bands/channel size.
|
||||||
|
* Eg. RGB will be a 3x3 matrix.
|
||||||
|
*/
|
||||||
|
VImage Recomb(VImage image, std::unique_ptr<double[]> const &matrix);
|
||||||
|
|
||||||
} // namespace sharp
|
} // namespace sharp
|
||||||
|
|
||||||
#endif // SRC_OPERATIONS_H_
|
#endif // SRC_OPERATIONS_H_
|
||||||
|
|||||||
@@ -381,7 +381,7 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|||||||
vips_enum_from_nick(nullptr, VIPS_TYPE_KERNEL, baton->kernel.data()));
|
vips_enum_from_nick(nullptr, VIPS_TYPE_KERNEL, baton->kernel.data()));
|
||||||
if (
|
if (
|
||||||
kernel != VIPS_KERNEL_NEAREST && kernel != VIPS_KERNEL_CUBIC && kernel != VIPS_KERNEL_LANCZOS2 &&
|
kernel != VIPS_KERNEL_NEAREST && kernel != VIPS_KERNEL_CUBIC && kernel != VIPS_KERNEL_LANCZOS2 &&
|
||||||
kernel != VIPS_KERNEL_LANCZOS3
|
kernel != VIPS_KERNEL_LANCZOS3 && kernel != VIPS_KERNEL_MITCHELL
|
||||||
) {
|
) {
|
||||||
throw vips::VError("Unknown kernel");
|
throw vips::VError("Unknown kernel");
|
||||||
}
|
}
|
||||||
@@ -525,6 +525,11 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|||||||
baton->convKernel);
|
baton->convKernel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Recomb
|
||||||
|
if (baton->recombMatrix != NULL) {
|
||||||
|
image = sharp::Recomb(image, baton->recombMatrix);
|
||||||
|
}
|
||||||
|
|
||||||
// Sharpen
|
// Sharpen
|
||||||
if (shouldSharpen) {
|
if (shouldSharpen) {
|
||||||
image = sharp::Sharpen(image, baton->sharpenSigma, baton->sharpenFlat, baton->sharpenJagged);
|
image = sharp::Sharpen(image, baton->sharpenSigma, baton->sharpenFlat, baton->sharpenJagged);
|
||||||
@@ -612,8 +617,8 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|||||||
baton->premultiplied = shouldPremultiplyAlpha;
|
baton->premultiplied = shouldPremultiplyAlpha;
|
||||||
|
|
||||||
// Gamma decoding (brighten)
|
// Gamma decoding (brighten)
|
||||||
if (baton->gamma >= 1 && baton->gamma <= 3) {
|
if (baton->gammaOut >= 1 && baton->gammaOut <= 3) {
|
||||||
image = sharp::Gamma(image, baton->gamma);
|
image = sharp::Gamma(image, baton->gammaOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Linear adjustment (a * in + b)
|
// Linear adjustment (a * in + b)
|
||||||
@@ -758,6 +763,10 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|||||||
->set("squash", baton->tiffSquash)
|
->set("squash", baton->tiffSquash)
|
||||||
->set("compression", baton->tiffCompression)
|
->set("compression", baton->tiffCompression)
|
||||||
->set("predictor", baton->tiffPredictor)
|
->set("predictor", baton->tiffPredictor)
|
||||||
|
->set("pyramid", baton->tiffPyramid)
|
||||||
|
->set("tile", baton->tiffTile)
|
||||||
|
->set("tile_height", baton->tiffTileHeight)
|
||||||
|
->set("tile_width", baton->tiffTileWidth)
|
||||||
->set("xres", baton->tiffXres)
|
->set("xres", baton->tiffXres)
|
||||||
->set("yres", baton->tiffYres)));
|
->set("yres", baton->tiffYres)));
|
||||||
baton->bufferOut = static_cast<char*>(area->data);
|
baton->bufferOut = static_cast<char*>(area->data);
|
||||||
@@ -771,6 +780,7 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|||||||
if (baton->greyscale || image.interpretation() == VIPS_INTERPRETATION_B_W) {
|
if (baton->greyscale || image.interpretation() == VIPS_INTERPRETATION_B_W) {
|
||||||
// Extract first band for greyscale image
|
// Extract first band for greyscale image
|
||||||
image = image[0];
|
image = image[0];
|
||||||
|
baton->channels = 1;
|
||||||
}
|
}
|
||||||
if (image.format() != VIPS_FORMAT_UCHAR) {
|
if (image.format() != VIPS_FORMAT_UCHAR) {
|
||||||
// Cast pixels to uint8 (unsigned char)
|
// Cast pixels to uint8 (unsigned char)
|
||||||
@@ -856,6 +866,10 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|||||||
->set("squash", baton->tiffSquash)
|
->set("squash", baton->tiffSquash)
|
||||||
->set("compression", baton->tiffCompression)
|
->set("compression", baton->tiffCompression)
|
||||||
->set("predictor", baton->tiffPredictor)
|
->set("predictor", baton->tiffPredictor)
|
||||||
|
->set("pyramid", baton->tiffPyramid)
|
||||||
|
->set("tile", baton->tiffTile)
|
||||||
|
->set("tile_height", baton->tiffTileHeight)
|
||||||
|
->set("tile_width", baton->tiffTileWidth)
|
||||||
->set("xres", baton->tiffXres)
|
->set("xres", baton->tiffXres)
|
||||||
->set("yres", baton->tiffYres));
|
->set("yres", baton->tiffYres));
|
||||||
baton->formatOut = "tiff";
|
baton->formatOut = "tiff";
|
||||||
@@ -1193,6 +1207,7 @@ NAN_METHOD(pipeline) {
|
|||||||
baton->thresholdGrayscale = AttrTo<bool>(options, "thresholdGrayscale");
|
baton->thresholdGrayscale = AttrTo<bool>(options, "thresholdGrayscale");
|
||||||
baton->trimThreshold = AttrTo<double>(options, "trimThreshold");
|
baton->trimThreshold = AttrTo<double>(options, "trimThreshold");
|
||||||
baton->gamma = AttrTo<double>(options, "gamma");
|
baton->gamma = AttrTo<double>(options, "gamma");
|
||||||
|
baton->gammaOut = AttrTo<double>(options, "gammaOut");
|
||||||
baton->linearA = AttrTo<double>(options, "linearA");
|
baton->linearA = AttrTo<double>(options, "linearA");
|
||||||
baton->linearB = AttrTo<double>(options, "linearB");
|
baton->linearB = AttrTo<double>(options, "linearB");
|
||||||
baton->greyscale = AttrTo<bool>(options, "greyscale");
|
baton->greyscale = AttrTo<bool>(options, "greyscale");
|
||||||
@@ -1232,6 +1247,13 @@ NAN_METHOD(pipeline) {
|
|||||||
baton->convKernel[i] = AttrTo<double>(kdata, i);
|
baton->convKernel[i] = AttrTo<double>(kdata, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (HasAttr(options, "recombMatrix")) {
|
||||||
|
baton->recombMatrix = std::unique_ptr<double[]>(new double[9]);
|
||||||
|
v8::Local<v8::Array> recombMatrix = AttrAs<v8::Array>(options, "recombMatrix");
|
||||||
|
for (unsigned int i = 0; i < 9; i++) {
|
||||||
|
baton->recombMatrix[i] = AttrTo<double>(recombMatrix, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
baton->colourspace = sharp::GetInterpretation(AttrAsStr(options, "colourspace"));
|
baton->colourspace = sharp::GetInterpretation(AttrAsStr(options, "colourspace"));
|
||||||
if (baton->colourspace == VIPS_INTERPRETATION_ERROR) {
|
if (baton->colourspace == VIPS_INTERPRETATION_ERROR) {
|
||||||
baton->colourspace = VIPS_INTERPRETATION_sRGB;
|
baton->colourspace = VIPS_INTERPRETATION_sRGB;
|
||||||
@@ -1258,7 +1280,11 @@ NAN_METHOD(pipeline) {
|
|||||||
baton->webpLossless = AttrTo<bool>(options, "webpLossless");
|
baton->webpLossless = AttrTo<bool>(options, "webpLossless");
|
||||||
baton->webpNearLossless = AttrTo<bool>(options, "webpNearLossless");
|
baton->webpNearLossless = AttrTo<bool>(options, "webpNearLossless");
|
||||||
baton->tiffQuality = AttrTo<uint32_t>(options, "tiffQuality");
|
baton->tiffQuality = AttrTo<uint32_t>(options, "tiffQuality");
|
||||||
|
baton->tiffPyramid = AttrTo<bool>(options, "tiffPyramid");
|
||||||
baton->tiffSquash = AttrTo<bool>(options, "tiffSquash");
|
baton->tiffSquash = AttrTo<bool>(options, "tiffSquash");
|
||||||
|
baton->tiffTile = AttrTo<bool>(options, "tiffTile");
|
||||||
|
baton->tiffTileWidth = AttrTo<uint32_t>(options, "tiffTileWidth");
|
||||||
|
baton->tiffTileHeight = AttrTo<uint32_t>(options, "tiffTileHeight");
|
||||||
baton->tiffXres = AttrTo<double>(options, "tiffXres");
|
baton->tiffXres = AttrTo<double>(options, "tiffXres");
|
||||||
baton->tiffYres = AttrTo<double>(options, "tiffYres");
|
baton->tiffYres = AttrTo<double>(options, "tiffYres");
|
||||||
// tiff compression options
|
// tiff compression options
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ struct PipelineBaton {
|
|||||||
double linearA;
|
double linearA;
|
||||||
double linearB;
|
double linearB;
|
||||||
double gamma;
|
double gamma;
|
||||||
|
double gammaOut;
|
||||||
bool greyscale;
|
bool greyscale;
|
||||||
bool normalise;
|
bool normalise;
|
||||||
bool useExifOrientation;
|
bool useExifOrientation;
|
||||||
@@ -121,7 +122,11 @@ struct PipelineBaton {
|
|||||||
int tiffQuality;
|
int tiffQuality;
|
||||||
VipsForeignTiffCompression tiffCompression;
|
VipsForeignTiffCompression tiffCompression;
|
||||||
VipsForeignTiffPredictor tiffPredictor;
|
VipsForeignTiffPredictor tiffPredictor;
|
||||||
|
bool tiffPyramid;
|
||||||
bool tiffSquash;
|
bool tiffSquash;
|
||||||
|
bool tiffTile;
|
||||||
|
int tiffTileHeight;
|
||||||
|
int tiffTileWidth;
|
||||||
double tiffXres;
|
double tiffXres;
|
||||||
double tiffYres;
|
double tiffYres;
|
||||||
std::string err;
|
std::string err;
|
||||||
@@ -145,6 +150,7 @@ struct PipelineBaton {
|
|||||||
std::string tileFormat;
|
std::string tileFormat;
|
||||||
int tileAngle;
|
int tileAngle;
|
||||||
VipsForeignDzDepth tileDepth;
|
VipsForeignDzDepth tileDepth;
|
||||||
|
std::unique_ptr<double[]> recombMatrix;
|
||||||
|
|
||||||
PipelineBaton():
|
PipelineBaton():
|
||||||
input(nullptr),
|
input(nullptr),
|
||||||
@@ -213,7 +219,11 @@ struct PipelineBaton {
|
|||||||
tiffQuality(80),
|
tiffQuality(80),
|
||||||
tiffCompression(VIPS_FOREIGN_TIFF_COMPRESSION_JPEG),
|
tiffCompression(VIPS_FOREIGN_TIFF_COMPRESSION_JPEG),
|
||||||
tiffPredictor(VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL),
|
tiffPredictor(VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL),
|
||||||
|
tiffPyramid(false),
|
||||||
tiffSquash(false),
|
tiffSquash(false),
|
||||||
|
tiffTile(false),
|
||||||
|
tiffTileHeight(256),
|
||||||
|
tiffTileWidth(256),
|
||||||
tiffXres(1.0),
|
tiffXres(1.0),
|
||||||
tiffYres(1.0),
|
tiffYres(1.0),
|
||||||
withMetadata(false),
|
withMetadata(false),
|
||||||
|
|||||||
BIN
test/fixtures/expected/Landscape_1-recomb-saturation.jpg
vendored
Normal file
BIN
test/fixtures/expected/Landscape_1-recomb-saturation.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 82 KiB |
BIN
test/fixtures/expected/Landscape_1-recomb-sepia.jpg
vendored
Normal file
BIN
test/fixtures/expected/Landscape_1-recomb-sepia.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 77 KiB |
BIN
test/fixtures/expected/Landscape_1-recomb-sepia2.jpg
vendored
Normal file
BIN
test/fixtures/expected/Landscape_1-recomb-sepia2.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 85 KiB |
BIN
test/fixtures/expected/alpha-recomb-sepia.png
vendored
Normal file
BIN
test/fixtures/expected/alpha-recomb-sepia.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 209 KiB |
BIN
test/fixtures/expected/gamma-in-2.2-out-3.0.jpg
vendored
Normal file
BIN
test/fixtures/expected/gamma-in-2.2-out-3.0.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
@@ -49,8 +49,8 @@ describe('failOnError', function () {
|
|||||||
it('returns errors to callback for truncated JPEG when failOnError is set', function (done) {
|
it('returns errors to callback for truncated JPEG when failOnError is set', function (done) {
|
||||||
sharp(fixtures.inputJpgTruncated, { failOnError: true }).toBuffer(function (err, data, info) {
|
sharp(fixtures.inputJpgTruncated, { failOnError: true }).toBuffer(function (err, data, info) {
|
||||||
assert.ok(err.message.includes('VipsJpeg: Premature end of JPEG file'), err);
|
assert.ok(err.message.includes('VipsJpeg: Premature end of JPEG file'), err);
|
||||||
assert.equal(data, null);
|
assert.strictEqual(data, null);
|
||||||
assert.equal(info, null);
|
assert.strictEqual(info, null);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -58,8 +58,8 @@ describe('failOnError', function () {
|
|||||||
it('returns errors to callback for truncated PNG when failOnError is set', function (done) {
|
it('returns errors to callback for truncated PNG when failOnError is set', function (done) {
|
||||||
sharp(fixtures.inputPngTruncated, { failOnError: true }).toBuffer(function (err, data, info) {
|
sharp(fixtures.inputPngTruncated, { failOnError: true }).toBuffer(function (err, data, info) {
|
||||||
assert.ok(err.message.includes('vipspng: libpng read error'), err);
|
assert.ok(err.message.includes('vipspng: libpng read error'), err);
|
||||||
assert.equal(data, null);
|
assert.strictEqual(data, null);
|
||||||
assert.equal(info, null);
|
assert.strictEqual(info, null);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -44,6 +44,19 @@ describe('Gamma correction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('input value of 2.2, output value of 3.0', function (done) {
|
||||||
|
sharp(fixtures.inputJpgWithGammaHoliness)
|
||||||
|
.resize(129, 111)
|
||||||
|
.gamma(2.2, 3.0)
|
||||||
|
.toBuffer(function (err, data, info) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual('jpeg', info.format);
|
||||||
|
assert.strictEqual(129, info.width);
|
||||||
|
assert.strictEqual(111, info.height);
|
||||||
|
fixtures.assertSimilar(fixtures.expected('gamma-in-2.2-out-3.0.jpg'), data, { threshold: 6 }, done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('alpha transparency', function (done) {
|
it('alpha transparency', function (done) {
|
||||||
sharp(fixtures.inputPngOverlayLayer1)
|
sharp(fixtures.inputPngOverlayLayer1)
|
||||||
.resize(320)
|
.resize(320)
|
||||||
@@ -57,9 +70,15 @@ describe('Gamma correction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invalid value', function () {
|
it('invalid first parameter value', function () {
|
||||||
assert.throws(function () {
|
assert.throws(function () {
|
||||||
sharp(fixtures.inputJpgWithGammaHoliness).gamma(4);
|
sharp(fixtures.inputJpgWithGammaHoliness).gamma(4);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('invalid second parameter value', function () {
|
||||||
|
assert.throws(function () {
|
||||||
|
sharp(fixtures.inputJpgWithGammaHoliness).gamma(2.2, 4);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -817,7 +817,7 @@ describe('Input/output', function () {
|
|||||||
assert.strictEqual(320, withInfo.width);
|
assert.strictEqual(320, withInfo.width);
|
||||||
assert.strictEqual(240, withInfo.height);
|
assert.strictEqual(240, withInfo.height);
|
||||||
// Verify image is of a different size (progressive output even without mozjpeg)
|
// Verify image is of a different size (progressive output even without mozjpeg)
|
||||||
assert.notEqual(withData.length, withoutData.length);
|
assert.notStrictEqual(withData.length, withoutData.length);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1285,6 +1285,84 @@ describe('Input/output', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('TIFF tiled pyramid image without compression enlarges test file', function (done) {
|
||||||
|
const startSize = fs.statSync(fixtures.inputTiffUncompressed).size;
|
||||||
|
sharp(fixtures.inputTiffUncompressed)
|
||||||
|
.tiff({
|
||||||
|
compression: 'none',
|
||||||
|
pyramid: true,
|
||||||
|
tile: true,
|
||||||
|
tileHeight: 256,
|
||||||
|
tileWidth: 256
|
||||||
|
})
|
||||||
|
.toFile(fixtures.outputTiff, (err, info) => {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual('tiff', info.format);
|
||||||
|
assert(info.size > startSize);
|
||||||
|
rimraf(fixtures.outputTiff, done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('TIFF pyramid true value does not throw error', function () {
|
||||||
|
assert.doesNotThrow(function () {
|
||||||
|
sharp().tiff({ pyramid: true });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Invalid TIFF pyramid value throws error', function () {
|
||||||
|
assert.throws(function () {
|
||||||
|
sharp().tiff({ pyramid: 'true' });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Invalid TIFF tile value throws error', function () {
|
||||||
|
assert.throws(function () {
|
||||||
|
sharp().tiff({ tile: 'true' });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('TIFF tile true value does not throw error', function () {
|
||||||
|
assert.doesNotThrow(function () {
|
||||||
|
sharp().tiff({ tile: true });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Valid TIFF tileHeight value does not throw error', function () {
|
||||||
|
assert.doesNotThrow(function () {
|
||||||
|
sharp().tiff({ tileHeight: 512 });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Valid TIFF tileWidth value does not throw error', function () {
|
||||||
|
assert.doesNotThrow(function () {
|
||||||
|
sharp().tiff({ tileWidth: 512 });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Invalid TIFF tileHeight value throws error', function () {
|
||||||
|
assert.throws(function () {
|
||||||
|
sharp().tiff({ tileHeight: '256' });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Invalid TIFF tileWidth value throws error', function () {
|
||||||
|
assert.throws(function () {
|
||||||
|
sharp().tiff({ tileWidth: '256' });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Invalid TIFF tileHeight value throws error', function () {
|
||||||
|
assert.throws(function () {
|
||||||
|
sharp().tiff({ tileHeight: 0 });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Invalid TIFF tileWidth value throws error', function () {
|
||||||
|
assert.throws(function () {
|
||||||
|
sharp().tiff({ tileWidth: 0 });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Input and output formats match when not forcing', function (done) {
|
it('Input and output formats match when not forcing', function (done) {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
@@ -1388,6 +1466,7 @@ describe('Input/output', function () {
|
|||||||
assert.strictEqual('raw', info.format);
|
assert.strictEqual('raw', info.format);
|
||||||
assert.strictEqual(32, info.width);
|
assert.strictEqual(32, info.width);
|
||||||
assert.strictEqual(24, info.height);
|
assert.strictEqual(24, info.height);
|
||||||
|
assert.strictEqual(1, info.channels);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
135
test/unit/recomb.js
Normal file
135
test/unit/recomb.js
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const assert = require('assert');
|
||||||
|
|
||||||
|
const sharp = require('../../');
|
||||||
|
const fixtures = require('../fixtures');
|
||||||
|
|
||||||
|
describe('Recomb', function () {
|
||||||
|
it('applies a sepia filter using recomb', function (done) {
|
||||||
|
const output = fixtures.path('output.recomb-sepia.jpg');
|
||||||
|
sharp(fixtures.inputJpgWithLandscapeExif1)
|
||||||
|
.recomb([
|
||||||
|
[0.3588, 0.7044, 0.1368],
|
||||||
|
[0.299, 0.587, 0.114],
|
||||||
|
[0.2392, 0.4696, 0.0912]
|
||||||
|
])
|
||||||
|
.toFile(output, function (err, info) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual('jpeg', info.format);
|
||||||
|
assert.strictEqual(600, info.width);
|
||||||
|
assert.strictEqual(450, info.height);
|
||||||
|
fixtures.assertMaxColourDistance(
|
||||||
|
output,
|
||||||
|
fixtures.expected('Landscape_1-recomb-sepia.jpg'),
|
||||||
|
17
|
||||||
|
);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('applies a sepia filter using recomb to an PNG with Alpha', function (done) {
|
||||||
|
const output = fixtures.path('output.recomb-sepia.png');
|
||||||
|
sharp(fixtures.inputPngAlphaPremultiplicationSmall)
|
||||||
|
.recomb([
|
||||||
|
[0.3588, 0.7044, 0.1368],
|
||||||
|
[0.299, 0.587, 0.114],
|
||||||
|
[0.2392, 0.4696, 0.0912]
|
||||||
|
])
|
||||||
|
.toFile(output, function (err, info) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual('png', info.format);
|
||||||
|
assert.strictEqual(1024, info.width);
|
||||||
|
assert.strictEqual(768, info.height);
|
||||||
|
fixtures.assertMaxColourDistance(
|
||||||
|
output,
|
||||||
|
fixtures.expected('alpha-recomb-sepia.png'),
|
||||||
|
17
|
||||||
|
);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('applies a different sepia filter using recomb', function (done) {
|
||||||
|
const output = fixtures.path('output.recomb-sepia2.jpg');
|
||||||
|
sharp(fixtures.inputJpgWithLandscapeExif1)
|
||||||
|
.recomb([
|
||||||
|
[0.393, 0.769, 0.189],
|
||||||
|
[0.349, 0.686, 0.168],
|
||||||
|
[0.272, 0.534, 0.131]
|
||||||
|
])
|
||||||
|
.toFile(output, function (err, info) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual('jpeg', info.format);
|
||||||
|
assert.strictEqual(600, info.width);
|
||||||
|
assert.strictEqual(450, info.height);
|
||||||
|
fixtures.assertMaxColourDistance(
|
||||||
|
output,
|
||||||
|
fixtures.expected('Landscape_1-recomb-sepia2.jpg'),
|
||||||
|
17
|
||||||
|
);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('increases the saturation of the image', function (done) {
|
||||||
|
const saturationLevel = 1;
|
||||||
|
const output = fixtures.path('output.recomb-saturation.jpg');
|
||||||
|
sharp(fixtures.inputJpgWithLandscapeExif1)
|
||||||
|
.recomb([
|
||||||
|
[
|
||||||
|
saturationLevel + 1 - 0.2989,
|
||||||
|
-0.587 * saturationLevel,
|
||||||
|
-0.114 * saturationLevel
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-0.2989 * saturationLevel,
|
||||||
|
saturationLevel + 1 - 0.587,
|
||||||
|
-0.114 * saturationLevel
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-0.2989 * saturationLevel,
|
||||||
|
-0.587 * saturationLevel,
|
||||||
|
saturationLevel + 1 - 0.114
|
||||||
|
]
|
||||||
|
])
|
||||||
|
.toFile(output, function (err, info) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual('jpeg', info.format);
|
||||||
|
assert.strictEqual(600, info.width);
|
||||||
|
assert.strictEqual(450, info.height);
|
||||||
|
fixtures.assertMaxColourDistance(
|
||||||
|
output,
|
||||||
|
fixtures.expected('Landscape_1-recomb-saturation.jpg'),
|
||||||
|
37
|
||||||
|
);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('invalid matrix specification', function () {
|
||||||
|
it('missing', function () {
|
||||||
|
assert.throws(function () {
|
||||||
|
sharp(fixtures.inputJpg).recomb();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('incorrect flat data', function () {
|
||||||
|
assert.throws(function () {
|
||||||
|
sharp(fixtures.inputJpg).recomb([1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('incorrect sub size', function () {
|
||||||
|
assert.throws(function () {
|
||||||
|
sharp(fixtures.inputJpg).recomb([
|
||||||
|
[1, 2, 3, 4],
|
||||||
|
[5, 6, 7, 8],
|
||||||
|
[1, 2, 9, 6]
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('incorrect top size', function () {
|
||||||
|
assert.throws(function () {
|
||||||
|
sharp(fixtures.inputJpg).recomb([[1, 2, 3, 4], [5, 6, 7, 8]]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -497,6 +497,7 @@ describe('Resize dimensions', function () {
|
|||||||
[
|
[
|
||||||
sharp.kernel.nearest,
|
sharp.kernel.nearest,
|
||||||
sharp.kernel.cubic,
|
sharp.kernel.cubic,
|
||||||
|
sharp.kernel.mitchell,
|
||||||
sharp.kernel.lanczos2,
|
sharp.kernel.lanczos2,
|
||||||
sharp.kernel.lanczos3
|
sharp.kernel.lanczos3
|
||||||
].forEach(function (kernel) {
|
].forEach(function (kernel) {
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ describe('Threshold', function () {
|
|||||||
it('color threshold', function (done) {
|
it('color threshold', function (done) {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
.threshold(128, {'grayscale': false})
|
.threshold(128, { grayscale: false })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer(function (err, data, info) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
|
|||||||
Reference in New Issue
Block a user