Compare commits

..

21 Commits

Author SHA1 Message Date
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
36 changed files with 922 additions and 800 deletions

View File

@@ -8,6 +8,7 @@ test
.travis.yml
appveyor.yml
mkdocs.yml
docs/css/
vendor
.prebuildrc
.nyc_output

View File

@@ -48,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>'
);

View File

@@ -1,15 +1,20 @@
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
### Table of Contents
## removeAlpha
- [extractChannel][1]
- [Parameters][2]
- [Examples][3]
- [joinChannel][4]
- [Parameters][5]
- [bandbool][6]
- [Parameters][7]
- [Examples][8]
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
@@ -17,7 +22,7 @@ Extract a single channel from a multi-channel image.
### Parameters
- `channel` **([Number][9] \| [String][10])** 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
@@ -30,7 +35,7 @@ sharp(input)
});
```
- Throws **[Error][11]** Invalid channel
- Throws **[Error][3]** Invalid channel
Returns **Sharp**
@@ -49,11 +54,11 @@ For raw pixel input, the `options` object should contain a `raw` attribute, whic
### Parameters
- `images` **([Array][12]&lt;([String][10] \| [Buffer][13])> | [String][10] \| [Buffer][13])** one or more images (file paths, Buffers).
- `options` **[Object][14]** 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][11]** Invalid parameters
- Throws **[Error][3]** Invalid parameters
Returns **Sharp**
@@ -63,7 +68,7 @@ Perform a bitwise boolean operation on all input image channels (bands) to produ
### Parameters
- `boolOp` **[String][10]** 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
@@ -77,34 +82,18 @@ sharp('3-channel-rgb-input.png')
});
```
- Throws **[Error][11]** Invalid parameters
- Throws **[Error][3]** Invalid parameters
Returns **Sharp**
[1]: #extractchannel
[1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[2]: #parameters
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[3]: #examples
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[4]: #joinchannel
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
[5]: #parameters-1
[5]: https://nodejs.org/api/buffer.html
[6]: #bandbool
[7]: #parameters-2
[8]: #examples-1
[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[10]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[11]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[12]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
[13]: https://nodejs.org/api/buffer.html
[14]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object

View File

@@ -1,20 +1,5 @@
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
### Table of Contents
- [background][1]
- [Parameters][2]
- [tint][3]
- [Parameters][4]
- [greyscale][5]
- [Parameters][6]
- [grayscale][7]
- [Parameters][8]
- [toColourspace][9]
- [Parameters][10]
- [toColorspace][11]
- [Parameters][12]
## background
Set the background for the `embed`, `flatten` and `extend` operations.
@@ -26,10 +11,10 @@ The alpha value is a float between `0` (transparent) and `1` (opaque).
### Parameters
- `rgba` **([String][13] \| [Object][14])** parsed by the [color][15] 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][16]** Invalid parameter
- Throws **[Error][4]** Invalid parameter
Returns **Sharp**
@@ -40,10 +25,10 @@ An alpha channel may be present and will be unchanged by the operation.
### Parameters
- `rgb` **([String][13] \| [Object][14])** parsed by the [color][15] module to extract chroma values.
- `rgb` **([String][1] \| [Object][2])** parsed by the [color][3] module to extract chroma values.
- Throws **[Error][16]** Invalid parameter
- Throws **[Error][4]** Invalid parameter
Returns **Sharp**
@@ -58,7 +43,7 @@ An alpha channel may be present, and will be unchanged by the operation.
### Parameters
- `greyscale` **[Boolean][17]** (optional, default `true`)
- `greyscale` **[Boolean][5]** (optional, default `true`)
Returns **Sharp**
@@ -68,7 +53,7 @@ Alternative spelling of `greyscale`.
### Parameters
- `grayscale` **[Boolean][17]** (optional, default `true`)
- `grayscale` **[Boolean][5]** (optional, default `true`)
Returns **Sharp**
@@ -79,10 +64,10 @@ By default output image will be web-friendly sRGB, with additional channels inte
### Parameters
- `colourspace` **[String][13]?** output colourspace e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...][18]
- `colourspace` **[String][1]?** output colourspace e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...][6]
- Throws **[Error][16]** Invalid parameters
- Throws **[Error][4]** Invalid parameters
Returns **Sharp**
@@ -92,45 +77,21 @@ Alternative spelling of `toColourspace`.
### Parameters
- `colorspace` **[String][13]?** output colorspace.
- `colorspace` **[String][1]?** output colorspace.
- Throws **[Error][16]** Invalid parameters
- Throws **[Error][4]** Invalid parameters
Returns **Sharp**
[1]: #background
[1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[2]: #parameters
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[3]: #tint
[3]: https://www.npmjs.org/package/color
[4]: #parameters-1
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[5]: #greyscale
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[6]: #parameters-2
[7]: #grayscale
[8]: #parameters-3
[9]: #tocolourspace
[10]: #parameters-4
[11]: #tocolorspace
[12]: #parameters-5
[13]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[14]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[15]: https://www.npmjs.org/package/color
[16]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[17]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[18]: https://github.com/jcupitt/libvips/blob/master/libvips/iofuncs/enumtypes.c#L568
[6]: https://github.com/jcupitt/libvips/blob/master/libvips/iofuncs/enumtypes.c#L568

View File

@@ -1,11 +1,5 @@
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
### Table of Contents
- [overlayWith][1]
- [Parameters][2]
- [Examples][3]
## overlayWith
Overlay (composite) an image over the processed (resized, extracted etc.) image.
@@ -17,23 +11,23 @@ If the overlay image contains an alpha channel then composition with premultipli
### Parameters
- `overlay` **([Buffer][4] \| [String][5])** Buffer containing image data or String containing the path to an image file.
- `options` **[Object][6]?**
- `options.gravity` **[String][5]** gravity at which to place the overlay. (optional, default `'centre'`)
- `options.top` **[Number][7]?** the pixel offset from the top edge.
- `options.left` **[Number][7]?** the pixel offset from the left edge.
- `options.tile` **[Boolean][8]** set to true to repeat the overlay image across the entire image with the given `gravity`. (optional, default `false`)
- `options.cutout` **[Boolean][8]** 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][7]** integral number representing the DPI for vector overlay image. (optional, default `72`)
- `options.raw` **[Object][6]?** describes overlay when using raw pixel data.
- `options.raw.width` **[Number][7]?**
- `options.raw.height` **[Number][7]?**
- `options.raw.channels` **[Number][7]?**
- `options.create` **[Object][6]?** describes a blank overlay to be created.
- `options.create.width` **[Number][7]?**
- `options.create.height` **[Number][7]?**
- `options.create.channels` **[Number][7]?** 3-4
- `options.create.background` **([String][5] \| [Object][6])?** parsed by the [color][9] 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
@@ -46,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
@@ -56,26 +49,20 @@ sharp('input.png')
});
```
- Throws **[Error][10]** Invalid parameters
- Throws **[Error][7]** Invalid parameters
Returns **Sharp**
[1]: #overlaywith
[1]: https://nodejs.org/api/buffer.html
[2]: #parameters
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[3]: #examples
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[4]: https://nodejs.org/api/buffer.html
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[6]: https://www.npmjs.org/package/color
[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://www.npmjs.org/package/color
[10]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error

View File

@@ -1,40 +1,28 @@
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
### Table of Contents
- [Sharp][1]
- [Parameters][2]
- [Examples][3]
- [format][4]
- [Examples][5]
- [versions][6]
- [Examples][7]
- [queue][8]
- [Examples][9]
## Sharp
### Parameters
- `input` **([Buffer][10] \| [String][11])?** 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][12]?** if present, is an Object with optional attributes.
- `options.failOnError` **[Boolean][13]** by default apply a "best effort"
- `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][14]** integral number representing the DPI for vector images. (optional, default `72`)
- `options.page` **[Number][14]** page number to extract for multi-page input (GIF, TIFF) (optional, default `0`)
- `options.raw` **[Object][12]?** describes raw pixel input image data. See `raw()` for pixel ordering.
- `options.raw.width` **[Number][14]?**
- `options.raw.height` **[Number][14]?**
- `options.raw.channels` **[Number][14]?** 1-4
- `options.create` **[Object][12]?** describes a new image to be created.
- `options.create.width` **[Number][14]?**
- `options.create.height` **[Number][14]?**
- `options.create.channels` **[Number][14]?** 3-4
- `options.create.background` **([String][11] \| [Object][12])?** parsed by the [color][15] module to extract values for red, green, blue and alpha.
- `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
@@ -67,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()
@@ -75,9 +63,9 @@ sharp({
.then( ... );
```
- Throws **[Error][16]** Invalid parameters
- Throws **[Error][7]** Invalid parameters
Returns **[Sharp][17]**
Returns **[Sharp][8]**
### format
@@ -89,7 +77,7 @@ An Object containing nested boolean values representing the available input and
console.log(sharp.format);
```
Returns **[Object][12]**
Returns **[Object][3]**
### versions
@@ -116,36 +104,18 @@ sharp.queue.on('change', function(queueLength) {
});
```
[1]: #sharp
[1]: https://nodejs.org/api/buffer.html
[2]: #parameters
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[3]: #examples
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[4]: #format
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[5]: #examples-1
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[6]: #versions
[6]: https://www.npmjs.org/package/color
[7]: #examples-2
[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[8]: #queue
[9]: #examples-3
[10]: https://nodejs.org/api/buffer.html
[11]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[12]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[13]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[14]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[15]: https://www.npmjs.org/package/color
[16]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[17]: #sharp
[8]: #sharp

View File

@@ -1,20 +1,5 @@
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
### Table of Contents
- [clone][1]
- [Examples][2]
- [metadata][3]
- [Parameters][4]
- [Examples][5]
- [stats][6]
- [Parameters][7]
- [Examples][8]
- [limitInputPixels][9]
- [Parameters][10]
- [sequentialRead][11]
- [Parameters][12]
## clone
Take a "snapshot" of the Sharp instance, returning a new instance.
@@ -42,21 +27,21 @@ 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 (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` [...][13]
- `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` [...][14]
- `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][15] 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
- `callback` **[Function][16]?** called with the arguments `(err, metadata)`
- `callback` **[Function][4]?** called with the arguments `(err, metadata)`
### Examples
@@ -75,7 +60,7 @@ image
});
```
Returns **([Promise][17]&lt;[Object][18]> | Sharp)**
Returns **([Promise][5]&lt;[Object][6]> | Sharp)**
## stats
@@ -94,10 +79,11 @@ A Promise is returned when `callback` is not provided.
- `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][16]?** called with the arguments `(err, stats)`
- `callback` **[Function][4]?** called with the arguments `(err, stats)`
### Examples
@@ -110,7 +96,7 @@ image
});
```
Returns **[Promise][17]&lt;[Object][18]>**
Returns **[Promise][5]&lt;[Object][6]>**
## limitInputPixels
@@ -120,10 +106,10 @@ The default limit is 268402689 (0x3FFF _ 0x3FFF) pixels.
### Parameters
- `limit` **([Number][19] \| [Boolean][20])** 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][21]** Invalid limit
- Throws **[Error][9]** Invalid limit
Returns **Sharp**
@@ -136,48 +122,24 @@ The default behaviour _before_ function call is `false`, meaning the libvips acc
### Parameters
- `sequentialRead` **[Boolean][20]** (optional, default `true`)
- `sequentialRead` **[Boolean][8]** (optional, default `true`)
Returns **Sharp**
[1]: #clone
[1]: https://github.com/jcupitt/libvips/blob/master/libvips/iofuncs/enumtypes.c#L636
[2]: #examples
[2]: https://github.com/jcupitt/libvips/blob/master/libvips/iofuncs/enumtypes.c#L672
[3]: #metadata
[3]: https://www.npmjs.com/package/icc
[4]: #parameters
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function
[5]: #examples-1
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise
[6]: #stats
[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[7]: #parameters-1
[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[8]: #examples-2
[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[9]: #limitinputpixels
[10]: #parameters-2
[11]: #sequentialread
[12]: #parameters-3
[13]: https://github.com/jcupitt/libvips/blob/master/libvips/iofuncs/enumtypes.c#L636
[14]: https://github.com/jcupitt/libvips/blob/master/libvips/iofuncs/enumtypes.c#L672
[15]: https://www.npmjs.com/package/icc
[16]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function
[17]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise
[18]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[19]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[20]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[21]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error

View File

@@ -1,48 +1,5 @@
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
### Table of Contents
- [rotate][1]
- [Parameters][2]
- [Examples][3]
- [extract][4]
- [Parameters][5]
- [Examples][6]
- [flip][7]
- [Parameters][8]
- [flop][9]
- [Parameters][10]
- [sharpen][11]
- [Parameters][12]
- [median][13]
- [Parameters][14]
- [blur][15]
- [Parameters][16]
- [extend][17]
- [Parameters][18]
- [Examples][19]
- [flatten][20]
- [Parameters][21]
- [trim][22]
- [Parameters][23]
- [gamma][24]
- [Parameters][25]
- [negate][26]
- [Parameters][27]
- [normalise][28]
- [Parameters][29]
- [normalize][30]
- [Parameters][31]
- [convolve][32]
- [Parameters][33]
- [Examples][34]
- [threshold][35]
- [Parameters][36]
- [boolean][37]
- [Parameters][38]
- [linear][39]
- [Parameters][40]
## rotate
Rotate the output image by either an explicit angle
@@ -61,7 +18,7 @@ for example `rotate(x).extract(y)` will produce a different result to `extract(y
### Parameters
- `angle` **[Number][41]** 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
@@ -77,7 +34,7 @@ const pipeline = sharp()
readableStream.pipe(pipeline);
```
- Throws **[Error][42]** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
@@ -91,11 +48,11 @@ Extract a region of the image.
### Parameters
- `options` **[Object][43]**
- `options.left` **[Number][41]** zero-indexed offset from left edge
- `options.top` **[Number][41]** zero-indexed offset from top edge
- `options.width` **[Number][41]** dimension of extracted image
- `options.height` **[Number][41]** 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
@@ -117,7 +74,7 @@ sharp(input)
});
```
- Throws **[Error][42]** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
@@ -128,7 +85,7 @@ The use of `flip` implies the removal of the EXIF `Orientation` tag, if any.
### Parameters
- `flip` **[Boolean][44]** (optional, default `true`)
- `flip` **[Boolean][4]** (optional, default `true`)
Returns **Sharp**
@@ -139,7 +96,7 @@ The use of `flop` implies the removal of the EXIF `Orientation` tag, if any.
### Parameters
- `flop` **[Boolean][44]** (optional, default `true`)
- `flop` **[Boolean][4]** (optional, default `true`)
Returns **Sharp**
@@ -152,12 +109,12 @@ Separate control over the level of sharpening in "flat" and "jagged" areas is av
### Parameters
- `sigma` **[Number][41]?** the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`.
- `flat` **[Number][41]** the level of sharpening to apply to "flat" areas. (optional, default `1.0`)
- `jagged` **[Number][41]** 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][42]** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
@@ -168,10 +125,10 @@ When used without parameters the default window is 3x3.
### Parameters
- `size` **[Number][41]** square mask size: size x size (optional, default `3`)
- `size` **[Number][1]** square mask size: size x size (optional, default `3`)
- Throws **[Error][42]** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
@@ -183,10 +140,10 @@ When a `sigma` is provided, performs a slower, more accurate Gaussian blur.
### Parameters
- `sigma` **[Number][41]?** 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][42]** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
@@ -197,11 +154,11 @@ This operation will always occur after resizing and extraction, if any.
### Parameters
- `extend` **([Number][41] \| [Object][43])** single pixel count to add to all edges or an Object with per-edge counts
- `extend.top` **[Number][41]?**
- `extend.left` **[Number][41]?**
- `extend.bottom` **[Number][41]?**
- `extend.right` **[Number][41]?**
- `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
@@ -215,7 +172,7 @@ sharp(input)
...
```
- Throws **[Error][42]** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
@@ -225,7 +182,7 @@ Merge alpha transparency channel, if any, with `background`.
### Parameters
- `flatten` **[Boolean][44]** (optional, default `true`)
- `flatten` **[Boolean][4]** (optional, default `true`)
Returns **Sharp**
@@ -235,10 +192,10 @@ Trim "boring" pixels from all edges that contain values within a percentage simi
### Parameters
- `tolerance` **[Number][41]** 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][42]** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
@@ -252,10 +209,10 @@ when applying a gamma correction.
### Parameters
- `gamma` **[Number][41]** 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][42]** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
@@ -265,7 +222,7 @@ Produce the "negative" of the image.
### Parameters
- `negate` **[Boolean][44]** (optional, default `true`)
- `negate` **[Boolean][4]** (optional, default `true`)
Returns **Sharp**
@@ -275,7 +232,7 @@ Enhance output image contrast by stretching its luminance to cover the full dyna
### Parameters
- `normalise` **[Boolean][44]** (optional, default `true`)
- `normalise` **[Boolean][4]** (optional, default `true`)
Returns **Sharp**
@@ -285,7 +242,7 @@ Alternative spelling of normalise.
### Parameters
- `normalize` **[Boolean][44]** (optional, default `true`)
- `normalize` **[Boolean][4]** (optional, default `true`)
Returns **Sharp**
@@ -295,12 +252,12 @@ Convolve the image with the specified kernel.
### Parameters
- `kernel` **[Object][43]**
- `kernel.width` **[Number][41]** width of the kernel in pixels.
- `kernel.height` **[Number][41]** width of the kernel in pixels.
- `kernel.kernel` **[Array][45]&lt;[Number][41]>** Array of length `width*height` containing the kernel values.
- `kernel.scale` **[Number][41]** the scale of the kernel in pixels. (optional, default `sum`)
- `kernel.offset` **[Number][41]** 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
@@ -318,7 +275,7 @@ sharp(input)
});
```
- Throws **[Error][42]** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
@@ -328,13 +285,13 @@ Any pixel value greather than or equal to the threshold value will be set to 255
### Parameters
- `threshold` **[Number][41]** a value in the range 0-255 representing the level at which the threshold will be applied. (optional, default `128`)
- `options` **[Object][43]?**
- `options.greyscale` **[Boolean][44]** convert to single channel greyscale. (optional, default `true`)
- `options.grayscale` **[Boolean][44]** 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][42]** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
@@ -347,16 +304,16 @@ the selected bitwise boolean `operation` between the corresponding pixels of the
### Parameters
- `operand` **([Buffer][46] \| [String][47])** Buffer containing image data or String containing the path to an image file.
- `operator` **[String][47]** one of `and`, `or` or `eor` to perform that bitwise operation, like the C logic operators `&`, `|` and `^` respectively.
- `options` **[Object][43]?**
- `options.raw` **[Object][43]?** describes operand when using raw pixel data.
- `options.raw.width` **[Number][41]?**
- `options.raw.height` **[Number][41]?**
- `options.raw.channels` **[Number][41]?**
- `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][42]** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
@@ -366,104 +323,24 @@ Apply the linear formula a \* input + b to the image (levels adjustment)
### Parameters
- `a` **[Number][41]** multiplier (optional, default `1.0`)
- `b` **[Number][41]** offset (optional, default `0.0`)
- `a` **[Number][1]** multiplier (optional, default `1.0`)
- `b` **[Number][1]** offset (optional, default `0.0`)
- Throws **[Error][42]** Invalid parameters
- Throws **[Error][2]** Invalid parameters
Returns **Sharp**
[1]: #rotate
[1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[2]: #parameters
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[3]: #examples
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[4]: #extract
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[5]: #parameters-1
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
[6]: #examples-1
[6]: https://nodejs.org/api/buffer.html
[7]: #flip
[8]: #parameters-2
[9]: #flop
[10]: #parameters-3
[11]: #sharpen
[12]: #parameters-4
[13]: #median
[14]: #parameters-5
[15]: #blur
[16]: #parameters-6
[17]: #extend
[18]: #parameters-7
[19]: #examples-2
[20]: #flatten
[21]: #parameters-8
[22]: #trim
[23]: #parameters-9
[24]: #gamma
[25]: #parameters-10
[26]: #negate
[27]: #parameters-11
[28]: #normalise
[29]: #parameters-12
[30]: #normalize
[31]: #parameters-13
[32]: #convolve
[33]: #parameters-14
[34]: #examples-3
[35]: #threshold
[36]: #parameters-15
[37]: #boolean
[38]: #parameters-16
[39]: #linear
[40]: #parameters-17
[41]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[42]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[43]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[44]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[45]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
[46]: https://nodejs.org/api/buffer.html
[47]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String

View File

@@ -1,37 +1,5 @@
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
### Table of Contents
- [toFile][1]
- [Parameters][2]
- [Examples][3]
- [toBuffer][4]
- [Parameters][5]
- [Examples][6]
- [withMetadata][7]
- [Parameters][8]
- [Examples][9]
- [jpeg][10]
- [Parameters][11]
- [Examples][12]
- [png][13]
- [Parameters][14]
- [Examples][15]
- [webp][16]
- [Parameters][17]
- [Examples][18]
- [tiff][19]
- [Parameters][20]
- [Examples][21]
- [raw][22]
- [Examples][23]
- [toFormat][24]
- [Parameters][25]
- [Examples][26]
- [tile][27]
- [Parameters][28]
- [Examples][29]
## toFile
Write output image data to a file.
@@ -44,8 +12,8 @@ A `Promise` is returned when `callback` is not provided.
### Parameters
- `fileOut` **[String][30]** the path to write the image data to.
- `callback` **[Function][31]?** 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`.
@@ -64,9 +32,9 @@ sharp(input)
.catch(err => { ... });
```
- Throws **[Error][32]** Invalid parameters
- Throws **[Error][3]** Invalid parameters
Returns **[Promise][33]&lt;[Object][34]>** when no callback is provided
Returns **[Promise][4]&lt;[Object][5]>** when no callback is provided
## toBuffer
@@ -86,9 +54,9 @@ A `Promise` is returned when `callback` is not provided.
### Parameters
- `options` **[Object][34]?**
- `options.resolveWithObject` **[Boolean][35]?** Resolve the Promise with an Object containing `data` and `info` properties instead of resolving only with `data`.
- `callback` **[Function][31]?**
- `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
@@ -111,7 +79,7 @@ sharp(input)
.catch(err => { ... });
```
Returns **[Promise][33]&lt;[Buffer][36]>** when no callback is provided
Returns **[Promise][4]&lt;[Buffer][7]>** when no callback is provided
## withMetadata
@@ -121,8 +89,8 @@ This will also convert to and add a web-friendly sRGB ICC profile.
### Parameters
- `withMetadata` **[Object][34]?**
- `withMetadata.orientation` **[Number][37]?** 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
@@ -133,7 +101,7 @@ sharp('input.jpg')
.then(info => { ... });
```
- Throws **[Error][32]** Invalid parameters
- Throws **[Error][3]** Invalid parameters
Returns **Sharp**
@@ -143,15 +111,19 @@ Use these JPEG options for output image.
### Parameters
- `options` **[Object][34]?** output options
- `options.quality` **[Number][37]** quality, integer 1-100 (optional, default `80`)
- `options.progressive` **[Boolean][35]** use progressive (interlace) scan (optional, default `false`)
- `options.chromaSubsampling` **[String][30]** set to '4:4:4' to prevent chroma subsampling when quality &lt;= 90 (optional, default `'4:2:0'`)
- `options.trellisQuantisation` **[Boolean][35]** apply trellis quantisation, requires mozjpeg (optional, default `false`)
- `options.overshootDeringing` **[Boolean][35]** apply overshoot deringing, requires mozjpeg (optional, default `false`)
- `options.optimiseScans` **[Boolean][35]** optimise progressive scans, forces progressive, requires mozjpeg (optional, default `false`)
- `options.optimizeScans` **[Boolean][35]** alternative spelling of optimiseScans (optional, default `false`)
- `options.force` **[Boolean][35]** 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
@@ -165,7 +137,7 @@ const data = await sharp(input)
.toBuffer();
```
- Throws **[Error][32]** Invalid options
- Throws **[Error][3]** Invalid options
Returns **Sharp**
@@ -178,11 +150,11 @@ Indexed PNG input at 1, 2 or 4 bits per pixel is converted to 8 bits per pixel.
### Parameters
- `options` **[Object][34]?**
- `options.progressive` **[Boolean][35]** use progressive (interlace) scan (optional, default `false`)
- `options.compressionLevel` **[Number][37]** zlib compression level, 0-9 (optional, default `9`)
- `options.adaptiveFiltering` **[Boolean][35]** use adaptive row filtering (optional, default `false`)
- `options.force` **[Boolean][35]** force PNG output, otherwise attempt to use input format (optional, default `true`)
- `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`)
### Examples
@@ -193,7 +165,7 @@ const data = await sharp(input)
.toBuffer();
```
- Throws **[Error][32]** Invalid options
- Throws **[Error][3]** Invalid options
Returns **Sharp**
@@ -203,12 +175,12 @@ Use these WebP options for output image.
### Parameters
- `options` **[Object][34]?** output options
- `options.quality` **[Number][37]** quality, integer 1-100 (optional, default `80`)
- `options.alphaQuality` **[Number][37]** quality of alpha layer, integer 0-100 (optional, default `100`)
- `options.lossless` **[Boolean][35]** use lossless compression mode (optional, default `false`)
- `options.nearLossless` **[Boolean][35]** use near_lossless compression mode (optional, default `false`)
- `options.force` **[Boolean][35]** 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
@@ -219,7 +191,7 @@ const data = await sharp(input)
.toBuffer();
```
- Throws **[Error][32]** Invalid options
- Throws **[Error][3]** Invalid options
Returns **Sharp**
@@ -229,14 +201,14 @@ Use these TIFF options for output image.
### Parameters
- `options` **[Object][34]?** output options
- `options.quality` **[Number][37]** quality, integer 1-100 (optional, default `80`)
- `options.force` **[Boolean][35]** force TIFF output, otherwise attempt to use input format (optional, default `true`)
- `options.compression` **[Boolean][35]** compression options: lzw, deflate, jpeg, ccittfax4 (optional, default `'jpeg'`)
- `options.predictor` **[Boolean][35]** compression predictor options: none, horizontal, float (optional, default `'horizontal'`)
- `options.xres` **[Number][37]** horizontal resolution in pixels/mm (optional, default `1.0`)
- `options.yres` **[Number][37]** vertical resolution in pixels/mm (optional, default `1.0`)
- `options.squash` **[Boolean][35]** 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
@@ -251,7 +223,7 @@ sharp('input.svg')
.then(info => { ... });
```
- Throws **[Error][32]** Invalid options
- Throws **[Error][3]** Invalid options
Returns **Sharp**
@@ -276,8 +248,8 @@ Force output to a given format.
### Parameters
- `format` **([String][30] \| [Object][34])** as a String or an Object with an 'id' attribute
- `options` **[Object][34]** output options
- `format` **([String][1] \| [Object][5])** as a String or an Object with an 'id' attribute
- `options` **[Object][5]** output options
### Examples
@@ -288,7 +260,7 @@ const data = await sharp(input)
.toBuffer();
```
- Throws **[Error][32]** unsupported format or options
- Throws **[Error][3]** unsupported format or options
Returns **Sharp**
@@ -302,12 +274,13 @@ Warning: multiple sharp instances concurrently producing tile output can expose
### Parameters
- `tile` **[Object][34]?**
- `tile.size` **[Number][37]** tile size in pixels, a value between 1 and 8192. (optional, default `256`)
- `tile.overlap` **[Number][37]** tile overlap in pixels, a value between 0 and 8192. (optional, default `0`)
- `tile.angle` **[Number][37]** tile angle of rotation, must be a multiple of 90. (optional, default `0`)
- `tile.container` **[String][30]** tile container, with value `fs` (filesystem) or `zip` (compressed file). (optional, default `'fs'`)
- `tile.layout` **[String][30]** filesystem layout, possible values are `dz`, `zoomify` or `google`. (optional, default `'dz'`)
- `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
@@ -323,80 +296,22 @@ sharp('input.tiff')
});
```
- Throws **[Error][32]** Invalid parameters
- Throws **[Error][3]** Invalid parameters
Returns **Sharp**
[1]: #tofile
[1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[2]: #parameters
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function
[3]: #examples
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[4]: #tobuffer
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise
[5]: #parameters-1
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[6]: #examples-1
[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[7]: #withmetadata
[7]: https://nodejs.org/api/buffer.html
[8]: #parameters-2
[9]: #examples-2
[10]: #jpeg
[11]: #parameters-3
[12]: #examples-3
[13]: #png
[14]: #parameters-4
[15]: #examples-4
[16]: #webp
[17]: #parameters-5
[18]: #examples-5
[19]: #tiff
[20]: #parameters-6
[21]: #examples-6
[22]: #raw
[23]: #examples-7
[24]: #toformat
[25]: #parameters-7
[26]: #examples-8
[27]: #tile
[28]: #parameters-8
[29]: #examples-9
[30]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[31]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function
[32]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[33]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise
[34]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[35]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[36]: https://nodejs.org/api/buffer.html
[37]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number

View File

@@ -1,23 +1,5 @@
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
### Table of Contents
- [resize][1]
- [Parameters][2]
- [Examples][3]
- [crop][4]
- [Parameters][5]
- [Examples][6]
- [embed][7]
- [Parameters][8]
- [Examples][9]
- [max][10]
- [Examples][11]
- [min][12]
- [ignoreAspectRatio][13]
- [withoutEnlargement][14]
- [Parameters][15]
## resize
Resize image to `width` x `height`.
@@ -25,18 +7,18 @@ By default, the resized image is centre cropped to the exact size specified.
Possible kernels are:
- `nearest`: Use [nearest neighbour interpolation][16].
- `cubic`: Use a [Catmull-Rom spline][17].
- `lanczos2`: Use a [Lanczos kernel][18] 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).
### Parameters
- `width` **[Number][19]?** pixels wide the resultant image should be. Use `null` or `undefined` to auto-scale the width to match the height.
- `height` **[Number][19]?** pixels high the resultant image should be. Use `null` or `undefined` to auto-scale the height to match the width.
- `options` **[Object][20]?**
- `options.kernel` **[String][21]** the kernel to use for image reduction. (optional, default `'lanczos3'`)
- `options.fastShrinkOnLoad` **[Boolean][22]** 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`)
- `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`)
### Examples
@@ -55,7 +37,7 @@ sharp(inputBuffer)
});
```
- Throws **[Error][23]** Invalid parameters
- Throws **[Error][8]** Invalid parameters
Returns **Sharp**
@@ -69,12 +51,12 @@ 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][24].
- `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
- `crop` **[String][21]** 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
@@ -90,7 +72,7 @@ const transformer = sharp()
readableStream.pipe(transformer).pipe(writableStream);
```
- Throws **[Error][23]** Invalid parameters
- Throws **[Error][8]** Invalid parameters
Returns **Sharp**
@@ -104,7 +86,7 @@ contain an alpha channel, even when the input image does not.
### Parameters
- `embed` **[String][21]** A member of `sharp.gravity` to embed to an edge/corner. (optional, default `'centre'`)
- `embed` **[String][6]** A member of `sharp.gravity` to embed to an edge/corner. (optional, default `'centre'`)
### Examples
@@ -123,7 +105,7 @@ sharp('input.gif')
});
```
- Throws **[Error][23]** Invalid parameters
- Throws **[Error][8]** Invalid parameters
Returns **Sharp**
@@ -177,54 +159,24 @@ The default behaviour _before_ function call is `false`, meaning the image will
### Parameters
- `withoutEnlargement` **[Boolean][22]** (optional, default `true`)
- `withoutEnlargement` **[Boolean][7]** (optional, default `true`)
Returns **Sharp**
[1]: #resize
[1]: http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation
[2]: #parameters
[2]: https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline
[3]: #examples
[3]: https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel
[4]: #crop
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[5]: #parameters-1
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[6]: #examples-1
[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[7]: #embed
[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[8]: #parameters-2
[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[9]: #examples-2
[10]: #max
[11]: #examples-3
[12]: #min
[13]: #ignoreaspectratio
[14]: #withoutenlargement
[15]: #parameters-3
[16]: http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation
[17]: https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline
[18]: https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel
[19]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[20]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[21]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[22]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[23]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
[24]: https://en.wikipedia.org/wiki/Entropy_%28information_theory%29
[9]: https://en.wikipedia.org/wiki/Entropy_%28information_theory%29

View File

@@ -1,19 +1,5 @@
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
### Table of Contents
- [cache][1]
- [Parameters][2]
- [Examples][3]
- [concurrency][4]
- [Parameters][5]
- [Examples][6]
- [counters][7]
- [Examples][8]
- [simd][9]
- [Parameters][10]
- [Examples][11]
## cache
Gets or, when options are provided, sets the limits of _libvips'_ operation cache.
@@ -23,10 +9,10 @@ useful for determining how much working memory is required for a particular task
### Parameters
- `options` **([Object][12] \| [Boolean][13])** Object with the following attributes, or Boolean where true uses default cache settings and false removes all caching (optional, default `true`)
- `options.memory` **[Number][14]** is the maximum memory in MB to use for this cache (optional, default `50`)
- `options.files` **[Number][14]** is the maximum number of files to hold open (optional, default `20`)
- `options.items` **[Number][14]** 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
@@ -40,7 +26,7 @@ sharp.cache( { files: 0 } );
sharp.cache(false);
```
Returns **[Object][12]**
Returns **[Object][1]**
## concurrency
@@ -56,7 +42,7 @@ This method always returns the current concurrency.
### Parameters
- `concurrency` **[Number][14]?**
- `concurrency` **[Number][3]?**
### Examples
@@ -66,7 +52,7 @@ sharp.concurrency(2); // 2
sharp.concurrency(0); // 4
```
Returns **[Number][14]** concurrency
Returns **[Number][3]** concurrency
## counters
@@ -81,7 +67,7 @@ Provides access to internal task counters.
const counters = sharp.counters(); // { queue: 2, process: 4 }
```
Returns **[Object][12]**
Returns **[Object][1]**
## simd
@@ -96,7 +82,7 @@ Versions of liborc prior to 0.4.25 are known to segfault under heavy load.
### Parameters
- `simd` **[Boolean][13]** (optional, default `false`)
- `simd` **[Boolean][2]** (optional, default `false`)
### Examples
@@ -110,32 +96,10 @@ const simd = sharp.simd(true);
// attempts to enable the use of SIMD, returning true if available
```
Returns **[Boolean][13]**
Returns **[Boolean][2]**
[1]: #cache
[1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[2]: #parameters
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[3]: #examples
[4]: #concurrency
[5]: #parameters-1
[6]: #examples-1
[7]: #counters
[8]: #examples-2
[9]: #simd
[10]: #parameters-2
[11]: #examples-3
[12]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[13]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[14]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number

View File

@@ -4,6 +4,43 @@
Requires libvips v8.6.1.
#### 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.

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

@@ -112,6 +112,10 @@ the help and code contributions of the following people:
* [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!

View File

@@ -17,6 +17,22 @@ 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) {
@@ -29,11 +45,15 @@ try {
} else {
// Is this arch/platform supported?
const arch = process.env.npm_config_arch || process.arch;
if (platform() === 'win32-ia32') {
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}\n`);
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}`);
@@ -42,38 +62,30 @@ try {
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, platform()].join('-') + '.tar.gz';
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 () {
const vendorPath = path.join(__dirname, '..', 'vendor');
fs.mkdirSync(vendorPath);
tar
.extract({
file: tarPathTemp,
cwd: vendorPath,
strict: true
})
.then(function () {
try {
fs.unlinkSync(tarPathTemp);
} catch (err) {}
})
.catch(function (err) {
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 () {
fs.renameSync(tarPathTemp, tarPathCache);
extractTarball(tarPathCache);
});
}
}
} catch (err) {
npmLog.error('sharp', err.message);

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

@@ -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

@@ -81,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()
@@ -171,6 +171,7 @@ const Sharp = function (input, options) {
booleanFileIn: '',
joinChannelIn: [],
extractChannel: -1,
removeAlpha: false,
colourspace: 'srgb',
// overlay
overlayGravity: 0,
@@ -192,6 +193,8 @@ const Sharp = function (input, options) {
jpegTrellisQuantisation: false,
jpegOvershootDeringing: false,
jpegOptimiseScans: false,
jpegOptimiseCoding: true,
jpegQuantisationTable: 0,
pngProgressive: false,
pngCompressionLevel: 9,
pngAdaptiveFiltering: false,

View File

@@ -264,6 +264,7 @@ function metadata (callback) {
* - `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);

View File

@@ -1,17 +1,32 @@
'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 minimumLibvipsVersion = process.env.npm_package_config_libvips || require('../package.json').config.libvips;
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 || '';
@@ -23,21 +38,24 @@ const globalLibvipsVersion = function () {
const hasVendoredLibvips = function () {
const currentPlatformId = platform();
let vendorPlatformId;
try {
const vendorPlatformId = require(path.join(__dirname, '..', 'vendor', 'platform.json'));
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'.`);
}
} catch (err) {}
}
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(), process.env.PKG_CONFIG_PATH, '/usr/local/lib/pkgconfig', '/usr/lib/pkgconfig']
return [brewPkgConfigPath.trim(), env.PKG_CONFIG_PATH, '/usr/local/lib/pkgconfig', '/usr/lib/pkgconfig']
.filter(function (p) { return !!p; })
.join(':');
} else {
@@ -46,7 +64,7 @@ const pkgConfigPath = function () {
};
const useGlobalLibvips = function () {
if (Boolean(process.env.SHARP_IGNORE_GLOBAL_LIBVIPS) === true) {
if (Boolean(env.SHARP_IGNORE_GLOBAL_LIBVIPS) === true) {
return false;
}
@@ -56,6 +74,7 @@ const useGlobalLibvips = function () {
module.exports = {
minimumLibvipsVersion: minimumLibvipsVersion,
cachePath: cachePath,
globalLibvipsVersion: globalLibvipsVersion,
hasVendoredLibvips: hasVendoredLibvips,
pkgConfigPath: pkgConfigPath,

View File

@@ -148,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
@@ -185,6 +189,18 @@ 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);
}
@@ -255,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)) {
@@ -407,6 +423,7 @@ function toFormat (format, options) {
* @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}
@@ -458,6 +475,15 @@ function tile (tile) {
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'])) {

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.20.4",
"version": "0.20.6",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://github.com/lovell/sharp",
"contributors": [
@@ -48,7 +48,11 @@
"Andrea Bianco <andrea.bianco@unibas.ch>",
"Rik Heywood <rik@rik.org>",
"Thomas Parisot <hi@oncletom.io>",
"Nathan Graves <nathanrgraves+github@gmail.com>"
"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)",
@@ -56,7 +60,7 @@
"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",
"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": {
@@ -86,21 +90,21 @@
"fs-copy-file-sync": "^1.1.1",
"npmlog": "^4.1.2",
"prebuild-install": "^4.0.0",
"semver": "^5.5.0",
"semver": "^5.5.1",
"simple-get": "^2.8.1",
"tar": "^4.4.4",
"tar": "^4.4.6",
"tunnel-agent": "^0.6.0"
},
"devDependencies": {
"async": "^2.6.1",
"cc": "^1.0.2",
"decompress-zip": "^0.3.1",
"documentation": "^8.0.0",
"documentation": "^8.1.1",
"exif-reader": "^1.0.2",
"icc": "^1.0.0",
"mocha": "^5.2.0",
"nyc": "^12.0.2",
"prebuild": "^7.6.0",
"prebuild": "^7.6.2",
"prebuild-ci": "^2.2.3",
"rimraf": "^2.6.2",
"semistandard": "^12.0.1"

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
@@ -223,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));
}
@@ -374,10 +382,8 @@ namespace sharp {
VImage Linear(VImage image, double const a, double const b) {
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.linear(a, b).bandjoin(alpha);
return RemoveAlpha(image).linear(a, b).bandjoin(alpha);
} else {
return image.linear(a, b);
}

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.

View File

@@ -694,10 +694,19 @@ class PipelineWorker : public Nan::AsyncWorker {
(baton->err).append("Cannot extract channel from image. Too few channels in image.");
return Error();
}
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", VIPS_INTERPRETATION_B_W));
.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);
@@ -733,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;
@@ -848,9 +858,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->formatOut = "jpeg";
baton->channels = std::min(baton->channels, 3);
} else if (baton->formatOut == "png" || (mightMatchInput && isPng) || (willMatchInput &&
@@ -927,21 +938,30 @@ 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()))
->set("angle", CalculateAngleRotation(baton->tileAngle)));
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" || (mightMatchInput && isV) ||
(willMatchInput && inputImageType == ImageType::VIPS)) {
@@ -1232,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"));
@@ -1266,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");
@@ -1306,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 ||

View File

@@ -102,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;
@@ -129,6 +131,7 @@ struct PipelineBaton {
VipsOperationBoolean booleanOp;
VipsOperationBoolean bandBoolOp;
int extractChannel;
bool removeAlpha;
VipsInterpretation colourspace;
int tileSize;
int tileOverlap;
@@ -136,6 +139,7 @@ struct PipelineBaton {
VipsForeignDzLayout tileLayout;
std::string tileFormat;
int tileAngle;
VipsForeignDzDepth tileDepth;
PipelineBaton():
input(nullptr),
@@ -187,8 +191,10 @@ struct PipelineBaton {
jpegProgressive(false),
jpegChromaSubsampling("4:2:0"),
jpegTrellisQuantisation(false),
jpegQuantisationTable(0),
jpegOvershootDeringing(false),
jpegOptimiseScans(false),
jpegOptimiseCoding(true),
pngProgressive(false),
pngCompressionLevel(9),
pngAdaptiveFiltering(false),
@@ -209,12 +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),
tileAngle(0){
tileAngle(0),
tileDepth(VIPS_FOREIGN_DZ_DEPTH_LAST){
background[0] = 0.0;
background[1] = 0.0;
background[2] = 0.0;

View File

@@ -59,7 +59,6 @@ class StatsWorker : public Nan::AsyncWorker {
using sharp::MaximumImageAlpha;
vips::VImage image;
vips::VImage stats;
sharp::ImageType imageType = sharp::ImageType::UNKNOWN;
try {
@@ -69,9 +68,8 @@ class StatsWorker : public Nan::AsyncWorker {
}
if (imageType != sharp::ImageType::UNKNOWN) {
try {
stats = image.stats();
int bands = image.bands();
double const max = MaximumImageAlpha(image.interpretation());
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()),
@@ -83,11 +81,15 @@ class StatsWorker : public Nan::AsyncWorker {
static_cast<int>(stats.getpoint(STAT_MAXY_INDEX, b).front()));
baton->channelStats.push_back(cStats);
}
// alpha layer is there and the last band i.e. alpha has its max value greater than 0)
if (sharp::HasAlpha(image) && stats.getpoint(STAT_MIN_INDEX, bands).front() != max) {
baton->isOpaque = false;
// 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());
}
@@ -130,6 +132,7 @@ class StatsWorker : public Nan::AsyncWorker {
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;
}

View File

@@ -51,12 +51,14 @@ struct StatsBaton {
// Output
std::vector<ChannelStats> channelStats;
bool isOpaque;
double entropy;
std::string err;
StatsBaton():
input(nullptr),
isOpaque(true)
isOpaque(true),
entropy(0.0)
{}
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 685 B

View File

@@ -81,35 +81,45 @@ describe('Alpha transparency', function () {
});
});
it('Enlargement with non-nearest neighbor interpolation shouldnt cause dark edges', function (done) {
it('Enlargement with non-nearest neighbor interpolation shouldnt cause dark edges', function () {
const base = 'alpha-premultiply-enlargement-2048x1536-paper.png';
const actual = fixtures.path('output.' + base);
const expected = fixtures.expected(base);
sharp(fixtures.inputPngAlphaPremultiplicationSmall)
return sharp(fixtures.inputPngAlphaPremultiplicationSmall)
.resize(2048, 1536)
.toFile(actual, function (err) {
if (err) {
done(err);
} else {
fixtures.assertMaxColourDistance(actual, expected, 102);
done();
}
.toFile(actual)
.then(function () {
fixtures.assertMaxColourDistance(actual, expected, 102);
});
});
it('Reduction with non-nearest neighbor interpolation shouldnt cause dark edges', function (done) {
it('Reduction with non-nearest neighbor interpolation shouldnt cause dark edges', function () {
const base = 'alpha-premultiply-reduction-1024x768-paper.png';
const actual = fixtures.path('output.' + base);
const expected = fixtures.expected(base);
sharp(fixtures.inputPngAlphaPremultiplicationLarge)
return sharp(fixtures.inputPngAlphaPremultiplicationLarge)
.resize(1024, 768)
.toFile(actual, function (err) {
if (err) {
done(err);
} else {
fixtures.assertMaxColourDistance(actual, expected, 102);
done();
}
.toFile(actual)
.then(function () {
fixtures.assertMaxColourDistance(actual, expected, 102);
});
});
it('Removes alpha from fixtures with transparency, ignores those without', function () {
return Promise.all([
fixtures.inputPngWithTransparency,
fixtures.inputPngWithTransparency16bit,
fixtures.inputWebPWithTransparency,
fixtures.inputJpg,
fixtures.inputPng,
fixtures.inputWebP
].map(function (input) {
return sharp(input)
.removeAlpha()
.toBuffer({ resolveWithObject: true })
.then(function (result) {
assert.strictEqual(3, result.info.channels);
});
}));
});
});

View File

@@ -69,6 +69,17 @@ describe('Image channel extraction', function () {
});
});
it('Alpha from 16-bit PNG', function (done) {
const output = fixtures.path('output.extract-alpha-16bit.jpg');
sharp(fixtures.inputPngWithTransparency16bit)
.extractChannel(3)
.toFile(output, function (err, info) {
if (err) throw err;
fixtures.assertMaxColourDistance(output, fixtures.expected('extract-alpha-16bit.jpg'));
done();
});
});
it('Invalid channel number', function () {
assert.throws(function () {
sharp(fixtures.inputJpg)

View File

@@ -389,6 +389,16 @@ describe('Input/output', function () {
});
});
describe('Invalid JPEG quantisation table', function () {
[-1, 88.2, 'test'].forEach(function (table) {
it(table.toString(), function () {
assert.throws(function () {
sharp().jpeg({ quantisationTable: table });
});
});
});
});
it('Progressive JPEG image', function (done) {
sharp(fixtures.inputJpg)
.resize(320, 240)
@@ -826,6 +836,67 @@ describe('Input/output', function () {
});
});
it('Optimise coding generates smaller output length', function (done) {
// First generate with optimize coding enabled (default)
sharp(fixtures.inputJpg)
.resize(320, 240)
.jpeg()
.toBuffer(function (err, withOptimiseCoding, withInfo) {
if (err) throw err;
assert.strictEqual(true, withOptimiseCoding.length > 0);
assert.strictEqual(withOptimiseCoding.length, withInfo.size);
assert.strictEqual('jpeg', withInfo.format);
assert.strictEqual(320, withInfo.width);
assert.strictEqual(240, withInfo.height);
// Then generate with coding disabled
sharp(fixtures.inputJpg)
.resize(320, 240)
.jpeg({ optimizeCoding: false })
.toBuffer(function (err, withoutOptimiseCoding, withoutInfo) {
if (err) throw err;
assert.strictEqual(true, withoutOptimiseCoding.length > 0);
assert.strictEqual(withoutOptimiseCoding.length, withoutInfo.size);
assert.strictEqual('jpeg', withoutInfo.format);
assert.strictEqual(320, withoutInfo.width);
assert.strictEqual(240, withoutInfo.height);
// Verify optimised image is of a smaller size
assert.strictEqual(true, withOptimiseCoding.length < withoutOptimiseCoding.length);
done();
});
});
});
it('Specifying quantisation table provides different JPEG', function (done) {
// First generate with default quantisation table
sharp(fixtures.inputJpg)
.resize(320, 240)
.jpeg({ optimiseCoding: false })
.toBuffer(function (err, withDefaultQuantisationTable, withInfo) {
if (err) throw err;
assert.strictEqual(true, withDefaultQuantisationTable.length > 0);
assert.strictEqual(withDefaultQuantisationTable.length, withInfo.size);
assert.strictEqual('jpeg', withInfo.format);
assert.strictEqual(320, withInfo.width);
assert.strictEqual(240, withInfo.height);
// Then generate with different quantisation table
sharp(fixtures.inputJpg)
.resize(320, 240)
.jpeg({ optimiseCoding: false, quantisationTable: 3 })
.toBuffer(function (err, withQuantTable3, withoutInfo) {
if (err) throw err;
assert.strictEqual(true, withQuantTable3.length > 0);
assert.strictEqual(withQuantTable3.length, withoutInfo.size);
assert.strictEqual('jpeg', withoutInfo.format);
assert.strictEqual(320, withoutInfo.width);
assert.strictEqual(240, withoutInfo.height);
// Verify image is same (as mozjpeg may not be present) size or less
assert.strictEqual(true, withQuantTable3.length <= withDefaultQuantisationTable.length);
done();
});
});
});
it('Convert SVG to PNG at default 72DPI', function (done) {
sharp(fixtures.inputSvg)
.resize(1024)

View File

@@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const fs = require('fs');
const semver = require('semver');
const libvips = require('../../lib/libvips');
@@ -66,5 +67,11 @@ describe('libvips binaries', function () {
delete process.env.SHARP_IGNORE_GLOBAL_LIBVIPS;
});
it('cachePath returns a valid path ending with _libvips', function () {
const cachePath = libvips.cachePath();
assert.strictEqual('string', typeof cachePath);
assert.strictEqual('_libvips', cachePath.substr(-8));
assert.strictEqual(true, fs.existsSync(cachePath));
});
});
});

View File

@@ -24,6 +24,7 @@ describe('Image Stats', function () {
if (err) throw err;
assert.strictEqual(true, stats.isOpaque);
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 7.319914765248541));
// red channel
assert.strictEqual(0, stats.channels[0]['min']);
@@ -82,6 +83,7 @@ describe('Image Stats', function () {
if (err) throw err;
assert.strictEqual(true, stats.isOpaque);
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 0.3409031108021736));
// red channel
assert.strictEqual(0, stats.channels[0]['min']);
@@ -105,7 +107,9 @@ describe('Image Stats', function () {
it('PNG with transparency', function (done) {
sharp(fixtures.inputPngWithTransparency).stats(function (err, stats) {
if (err) throw err;
assert.strictEqual(false, stats.isOpaque);
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 0.06778064835816622));
// red channel
assert.strictEqual(0, stats.channels[0]['min']);
@@ -180,6 +184,7 @@ describe('Image Stats', function () {
if (err) throw err;
assert.strictEqual(false, stats.isOpaque);
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 0));
// alpha channel
assert.strictEqual(0, stats.channels[3]['min']);
@@ -204,7 +209,9 @@ describe('Image Stats', function () {
it('Tiff', function (done) {
sharp(fixtures.inputTiff).stats(function (err, stats) {
if (err) throw err;
assert.strictEqual(true, stats.isOpaque);
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 0.3851250782608986));
// red channel
assert.strictEqual(0, stats.channels[0]['min']);
@@ -231,6 +238,7 @@ describe('Image Stats', function () {
if (err) throw err;
assert.strictEqual(true, stats.isOpaque);
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 7.51758075132966));
// red channel
assert.strictEqual(0, stats.channels[0]['min']);
@@ -289,6 +297,7 @@ describe('Image Stats', function () {
if (err) throw err;
assert.strictEqual(true, stats.isOpaque);
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 6.087309412541799));
// red channel
assert.strictEqual(35, stats.channels[0]['min']);
@@ -345,7 +354,9 @@ describe('Image Stats', function () {
it('Grayscale GIF with alpha', function (done) {
sharp(fixtures.inputGifGreyPlusAlpha).stats(function (err, stats) {
if (err) throw err;
assert.strictEqual(false, stats.isOpaque);
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 1));
// gray channel
assert.strictEqual(0, stats.channels[0]['min']);
@@ -387,7 +398,9 @@ describe('Image Stats', function () {
const readable = fs.createReadStream(fixtures.inputJpg);
const pipeline = sharp().stats(function (err, stats) {
if (err) throw err;
assert.strictEqual(true, stats.isOpaque);
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 7.319914765248541));
// red channel
assert.strictEqual(0, stats.channels[0]['min']);
@@ -449,6 +462,7 @@ describe('Image Stats', function () {
return pipeline.stats().then(function (stats) {
assert.strictEqual(true, stats.isOpaque);
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 7.319914765248541));
// red channel
assert.strictEqual(0, stats.channels[0]['min']);
@@ -505,6 +519,7 @@ describe('Image Stats', function () {
it('File in, Promise out', function () {
return sharp(fixtures.inputJpg).stats().then(function (stats) {
assert.strictEqual(true, stats.isOpaque);
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 7.319914765248541));
// red channel
assert.strictEqual(0, stats.channels[0]['min']);

View File

@@ -46,6 +46,51 @@ const assertDeepZoomTiles = function (directory, expectedSize, expectedLevels, d
}, done);
};
const assertZoomifyTiles = function (directory, expectedTileSize, expectedLevels, done) {
fs.stat(path.join(directory, 'ImageProperties.xml'), function (err, stat) {
if (err) throw err;
assert.ok(stat.isFile());
assert.ok(stat.size > 0);
let maxTileLevel = -1;
fs.readdirSync(path.join(directory, 'TileGroup0')).forEach(function (tile) {
// Verify tile file name
assert.ok(/^[0-9]+-[0-9]+-[0-9]+\.jpg$/.test(tile));
let level = parseInt(tile.split('-')[0]);
maxTileLevel = Math.max(maxTileLevel, level);
});
assert.strictEqual(maxTileLevel + 1, expectedLevels); // add one to account for zero level tile
done();
});
};
const assertGoogleTiles = function (directory, expectedTileSize, expectedLevels, done) {
const levels = fs.readdirSync(directory);
assert.strictEqual(expectedLevels, levels.length - 1); // subtract one to account for default blank tile
fs.stat(path.join(directory, 'blank.png'), function (err, stat) {
if (err) throw err;
assert.ok(stat.isFile());
assert.ok(stat.size > 0);
// Basic check to confirm lowest and highest level tiles exist
fs.stat(path.join(directory, '0', '0', '0.jpg'), function (err, stat) {
if (err) throw err;
assert.strictEqual(true, stat.isFile());
assert.strictEqual(true, stat.size > 0);
fs.stat(path.join(directory, (expectedLevels - 1).toString(), '0', '0.jpg'), function (err, stat) {
if (err) throw err;
assert.strictEqual(true, stat.isFile());
assert.strictEqual(true, stat.size > 0);
done();
});
});
});
};
describe('Tile', function () {
it('Valid size values pass', function () {
[1, 8192].forEach(function (size) {
@@ -144,6 +189,26 @@ describe('Tile', function () {
});
});
it('Valid depths pass', function () {
['onepixel', 'onetile', 'one'].forEach(function (depth) {
assert.doesNotThrow(function (depth) {
sharp().tile({
depth: depth
});
});
});
});
it('Invalid depths fail', function () {
['depth', 1].forEach(function (depth) {
assert.throws(function () {
sharp().tile({
depth: depth
});
});
});
});
it('Prevent larger overlap than default size', function () {
assert.throws(function () {
sharp().tile({
@@ -251,6 +316,54 @@ describe('Tile', function () {
});
});
it('Deep Zoom layout with depth of one', function (done) {
const directory = fixtures.path('output.512_depth_one.dzi_files');
rimraf(directory, function () {
sharp(fixtures.inputJpg)
.tile({
size: 512,
depth: 'one'
})
.toFile(fixtures.path('output.512_depth_one.dzi'), function (err, info) {
if (err) throw err;
// Verify only one depth generated
assertDeepZoomTiles(directory, 512, 1, done);
});
});
});
it('Deep Zoom layout with depth of onepixel', function (done) {
const directory = fixtures.path('output.512_depth_onepixel.dzi_files');
rimraf(directory, function () {
sharp(fixtures.inputJpg)
.tile({
size: 512,
depth: 'onepixel'
})
.toFile(fixtures.path('output.512_depth_onepixel.dzi'), function (err, info) {
if (err) throw err;
// Verify only one depth generated
assertDeepZoomTiles(directory, 512, 13, done);
});
});
});
it('Deep Zoom layout with depth of onetile', function (done) {
const directory = fixtures.path('output.256_depth_onetile.dzi_files');
rimraf(directory, function () {
sharp(fixtures.inputJpg)
.tile({
size: 256,
depth: 'onetile'
})
.toFile(fixtures.path('output.256_depth_onetile.dzi'), function (err, info) {
if (err) throw err;
// Verify only one depth generated
assertDeepZoomTiles(directory, 256, 5, done);
});
});
});
it('Zoomify layout', function (done) {
const directory = fixtures.path('output.zoomify.dzi');
rimraf(directory, function () {
@@ -275,6 +388,69 @@ describe('Tile', function () {
});
});
it('Zoomify layout with depth one', function (done) {
const directory = fixtures.path('output.zoomify.depth_one.dzi');
rimraf(directory, function () {
sharp(fixtures.inputJpg)
.tile({
size: 256,
layout: 'zoomify',
depth: 'one'
})
.toFile(directory, function (err, info) {
if (err) throw err;
assert.strictEqual('dz', info.format);
assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size);
assertZoomifyTiles(directory, 256, 1, done);
});
});
});
it('Zoomify layout with depth onetile', function (done) {
const directory = fixtures.path('output.zoomify.depth_onetile.dzi');
rimraf(directory, function () {
sharp(fixtures.inputJpg)
.tile({
size: 256,
layout: 'zoomify',
depth: 'onetile'
})
.toFile(directory, function (err, info) {
if (err) throw err;
assert.strictEqual('dz', info.format);
assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size);
assertZoomifyTiles(directory, 256, 5, done);
});
});
});
it('Zoomify layout with depth onepixel', function (done) {
const directory = fixtures.path('output.zoomify.depth_onepixel.dzi');
rimraf(directory, function () {
sharp(fixtures.inputJpg)
.tile({
size: 256,
layout: 'zoomify',
depth: 'onepixel'
})
.toFile(directory, function (err, info) {
if (err) throw err;
assert.strictEqual('dz', info.format);
assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size);
assertZoomifyTiles(directory, 256, 13, done);
});
});
});
it('Google layout', function (done) {
const directory = fixtures.path('output.google.dzi');
rimraf(directory, function () {
@@ -410,6 +586,72 @@ describe('Tile', function () {
});
});
it('Google layout with depth one', function (done) {
const directory = fixtures.path('output.google_depth_one.dzi');
rimraf(directory, function () {
sharp(fixtures.inputJpg)
.tile({
layout: 'google',
depth: 'one',
size: 256
})
.toFile(directory, function (err, info) {
if (err) throw err;
assert.strictEqual('dz', info.format);
assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size);
assertGoogleTiles(directory, 256, 1, done);
});
});
});
it('Google layout with depth onepixel', function (done) {
const directory = fixtures.path('output.google_depth_onepixel.dzi');
rimraf(directory, function () {
sharp(fixtures.inputJpg)
.tile({
layout: 'google',
depth: 'onepixel',
size: 256
})
.toFile(directory, function (err, info) {
if (err) throw err;
assert.strictEqual('dz', info.format);
assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size);
assertGoogleTiles(directory, 256, 13, done);
});
});
});
it('Google layout with depth onetile', function (done) {
const directory = fixtures.path('output.google_depth_onetile.dzi');
rimraf(directory, function () {
sharp(fixtures.inputJpg)
.tile({
layout: 'google',
depth: 'onetile',
size: 256
})
.toFile(directory, function (err, info) {
if (err) throw err;
assert.strictEqual('dz', info.format);
assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size);
assertGoogleTiles(directory, 256, 5, done);
});
});
});
it('Write to ZIP container using file extension', function (done) {
const container = fixtures.path('output.dz.container.zip');
const extractTo = fixtures.path('output.dz.container');