mirror of
https://github.com/lovell/sharp.git
synced 2026-02-04 21:56:18 +01:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a0e1c39785 | ||
|
|
85b26dab68 | ||
|
|
66f7cef253 | ||
|
|
863174f201 | ||
|
|
bcd865cc96 |
@@ -1,5 +1,5 @@
|
|||||||
freebsd_instance:
|
freebsd_instance:
|
||||||
image_family: freebsd-14-0-snap
|
image_family: freebsd-13-2
|
||||||
|
|
||||||
task:
|
task:
|
||||||
name: FreeBSD
|
name: FreeBSD
|
||||||
@@ -9,7 +9,7 @@ task:
|
|||||||
prerequisites_script:
|
prerequisites_script:
|
||||||
- pkg update -f
|
- pkg update -f
|
||||||
- pkg upgrade -y
|
- pkg upgrade -y
|
||||||
- pkg install -y devel/pkgconf graphics/vips www/node16 www/npm
|
- pkg install -y devel/git devel/pkgconf graphics/vips www/node20 www/npm
|
||||||
install_script:
|
install_script:
|
||||||
- npm install --build-from-source --unsafe-perm
|
- npm install --build-from-source --unsafe-perm
|
||||||
test_script:
|
test_script:
|
||||||
|
|||||||
@@ -42,14 +42,14 @@ and https://www.cairographics.org/operators/
|
|||||||
| [images[].input.text.align] | <code>string</code> | <code>"'left'"</code> | text alignment (`'left'`, `'centre'`, `'center'`, `'right'`). |
|
| [images[].input.text.align] | <code>string</code> | <code>"'left'"</code> | text alignment (`'left'`, `'centre'`, `'center'`, `'right'`). |
|
||||||
| [images[].input.text.justify] | <code>boolean</code> | <code>false</code> | set this to true to apply justification to the text. |
|
| [images[].input.text.justify] | <code>boolean</code> | <code>false</code> | set this to true to apply justification to the text. |
|
||||||
| [images[].input.text.dpi] | <code>number</code> | <code>72</code> | the resolution (size) at which to render the text. Does not take effect if `height` is specified. |
|
| [images[].input.text.dpi] | <code>number</code> | <code>72</code> | the resolution (size) at which to render the text. Does not take effect if `height` is specified. |
|
||||||
| [images[].input.text.rgba] | <code>boolean</code> | <code>false</code> | set this to true to enable RGBA output. This is useful for colour emoji rendering, or support for pango markup features like `<span foreground="red">Red!</span>`. |
|
| [images[].input.text.rgba] | <code>boolean</code> | <code>false</code> | set this to true to enable RGBA output. This is useful for colour emoji rendering, or support for Pango markup features like `<span foreground="red">Red!</span>`. |
|
||||||
| [images[].input.text.spacing] | <code>number</code> | <code>0</code> | text line height in points. Will use the font line height if none is specified. |
|
| [images[].input.text.spacing] | <code>number</code> | <code>0</code> | text line height in points. Will use the font line height if none is specified. |
|
||||||
| [images[].blend] | <code>String</code> | <code>'over'</code> | how to blend this image with the image below. |
|
| [images[].blend] | <code>String</code> | <code>'over'</code> | how to blend this image with the image below. |
|
||||||
| [images[].gravity] | <code>String</code> | <code>'centre'</code> | gravity at which to place the overlay. |
|
| [images[].gravity] | <code>String</code> | <code>'centre'</code> | gravity at which to place the overlay. |
|
||||||
| [images[].top] | <code>Number</code> | | the pixel offset from the top edge. |
|
| [images[].top] | <code>Number</code> | | the pixel offset from the top edge. |
|
||||||
| [images[].left] | <code>Number</code> | | the pixel offset from the left edge. |
|
| [images[].left] | <code>Number</code> | | the pixel offset from the left edge. |
|
||||||
| [images[].tile] | <code>Boolean</code> | <code>false</code> | set to true to repeat the overlay image across the entire image with the given `gravity`. |
|
| [images[].tile] | <code>Boolean</code> | <code>false</code> | set to true to repeat the overlay image across the entire image with the given `gravity`. |
|
||||||
| [images[].premultiplied] | <code>Boolean</code> | <code>false</code> | set to true to avoid premultipling the image below. Equivalent to the `--premultiplied` vips option. |
|
| [images[].premultiplied] | <code>Boolean</code> | <code>false</code> | set to true to avoid premultiplying the image below. Equivalent to the `--premultiplied` vips option. |
|
||||||
| [images[].density] | <code>Number</code> | <code>72</code> | number representing the DPI for vector overlay image. |
|
| [images[].density] | <code>Number</code> | <code>72</code> | number representing the DPI for vector overlay image. |
|
||||||
| [images[].raw] | <code>Object</code> | | describes overlay when using raw pixel data. |
|
| [images[].raw] | <code>Object</code> | | describes overlay when using raw pixel data. |
|
||||||
| [images[].raw.width] | <code>Number</code> | | |
|
| [images[].raw.width] | <code>Number</code> | | |
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ Implements the [stream.Duplex](http://nodejs.org/api/stream.html#stream_class_st
|
|||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| [input] | <code>Buffer</code> \| <code>ArrayBuffer</code> \| <code>Uint8Array</code> \| <code>Uint8ClampedArray</code> \| <code>Int8Array</code> \| <code>Uint16Array</code> \| <code>Int16Array</code> \| <code>Uint32Array</code> \| <code>Int32Array</code> \| <code>Float32Array</code> \| <code>Float64Array</code> \| <code>string</code> | | if present, can be a Buffer / ArrayBuffer / Uint8Array / Uint8ClampedArray containing JPEG, PNG, WebP, AVIF, GIF, SVG or TIFF image data, or a TypedArray containing raw pixel image data, or a String containing the filesystem path to an JPEG, PNG, WebP, AVIF, GIF, SVG or TIFF image file. JPEG, PNG, WebP, AVIF, GIF, SVG, TIFF or raw pixel image data can be streamed into the object when not present. |
|
| [input] | <code>Buffer</code> \| <code>ArrayBuffer</code> \| <code>Uint8Array</code> \| <code>Uint8ClampedArray</code> \| <code>Int8Array</code> \| <code>Uint16Array</code> \| <code>Int16Array</code> \| <code>Uint32Array</code> \| <code>Int32Array</code> \| <code>Float32Array</code> \| <code>Float64Array</code> \| <code>string</code> | | if present, can be a Buffer / ArrayBuffer / Uint8Array / Uint8ClampedArray containing JPEG, PNG, WebP, AVIF, GIF, SVG or TIFF image data, or a TypedArray containing raw pixel image data, or a String containing the filesystem path to an JPEG, PNG, WebP, AVIF, GIF, SVG or TIFF image file. JPEG, PNG, WebP, AVIF, GIF, SVG, TIFF or raw pixel image data can be streamed into the object when not present. |
|
||||||
| [options] | <code>Object</code> | | if present, is an Object with optional attributes. |
|
| [options] | <code>Object</code> | | if present, is an Object with optional attributes. |
|
||||||
| [options.failOn] | <code>string</code> | <code>"'warning'"</code> | when to abort processing of invalid pixel data, one of (in order of sensitivity): 'none' (least), 'truncated', 'error' or 'warning' (most), highers level imply lower levels, invalid metadata will always abort. |
|
| [options.failOn] | <code>string</code> | <code>"'warning'"</code> | when to abort processing of invalid pixel data, one of (in order of sensitivity): 'none' (least), 'truncated', 'error' or 'warning' (most), higher levels imply lower levels, invalid metadata will always abort. |
|
||||||
| [options.limitInputPixels] | <code>number</code> \| <code>boolean</code> | <code>268402689</code> | Do not process input images where the number of pixels (width x height) exceeds this limit. Assumes image dimensions contained in the input metadata can be trusted. An integral Number of pixels, zero or false to remove limit, true to use default limit of 268402689 (0x3FFF x 0x3FFF). |
|
| [options.limitInputPixels] | <code>number</code> \| <code>boolean</code> | <code>268402689</code> | Do not process input images where the number of pixels (width x height) exceeds this limit. Assumes image dimensions contained in the input metadata can be trusted. An integral Number of pixels, zero or false to remove limit, true to use default limit of 268402689 (0x3FFF x 0x3FFF). |
|
||||||
| [options.unlimited] | <code>boolean</code> | <code>false</code> | Set this to `true` to remove safety features that help prevent memory exhaustion (JPEG, PNG, SVG, HEIF). |
|
| [options.unlimited] | <code>boolean</code> | <code>false</code> | Set this to `true` to remove safety features that help prevent memory exhaustion (JPEG, PNG, SVG, HEIF). |
|
||||||
| [options.sequentialRead] | <code>boolean</code> | <code>true</code> | Set this to `false` to use random access rather than sequential read. Some operations will do this automatically. |
|
| [options.sequentialRead] | <code>boolean</code> | <code>true</code> | Set this to `false` to use random access rather than sequential read. Some operations will do this automatically. |
|
||||||
@@ -84,7 +84,7 @@ readableStream.pipe(transformer).pipe(writableStream);
|
|||||||
```
|
```
|
||||||
**Example**
|
**Example**
|
||||||
```js
|
```js
|
||||||
// Create a blank 300x200 PNG image of semi-transluent red pixels
|
// Create a blank 300x200 PNG image of semi-translucent red pixels
|
||||||
sharp({
|
sharp({
|
||||||
create: {
|
create: {
|
||||||
width: 300,
|
width: 300,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ Rotate the output image by either an explicit angle
|
|||||||
or auto-orient based on the EXIF `Orientation` tag.
|
or auto-orient based on the EXIF `Orientation` tag.
|
||||||
|
|
||||||
If an angle is provided, it is converted to a valid positive degree rotation.
|
If an angle is provided, it is converted to a valid positive degree rotation.
|
||||||
For example, `-450` will produce a 270deg rotation.
|
For example, `-450` will produce a 270 degree rotation.
|
||||||
|
|
||||||
When rotating by an angle other than a multiple of 90,
|
When rotating by an angle other than a multiple of 90,
|
||||||
the background colour can be provided with the `background` option.
|
the background colour can be provided with the `background` option.
|
||||||
@@ -533,7 +533,7 @@ await sharp(rgbInput)
|
|||||||
|
|
||||||
|
|
||||||
## recomb
|
## recomb
|
||||||
Recomb the image with the specified matrix.
|
Recombine the image with the specified matrix.
|
||||||
|
|
||||||
|
|
||||||
**Throws**:
|
**Throws**:
|
||||||
@@ -556,7 +556,7 @@ sharp(input)
|
|||||||
])
|
])
|
||||||
.raw()
|
.raw()
|
||||||
.toBuffer(function(err, data, info) {
|
.toBuffer(function(err, data, info) {
|
||||||
// data contains the raw pixel data after applying the recomb
|
// data contains the raw pixel data after applying the matrix
|
||||||
// With this example input, a sepia filter has been applied
|
// With this example input, a sepia filter has been applied
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
@@ -607,7 +607,7 @@ const output = await sharp(input)
|
|||||||
```
|
```
|
||||||
**Example**
|
**Example**
|
||||||
```js
|
```js
|
||||||
// decreate brightness and saturation while also hue-rotating by 90 degrees
|
// decrease brightness and saturation while also hue-rotating by 90 degrees
|
||||||
const output = await sharp(input)
|
const output = await sharp(input)
|
||||||
.modulate({
|
.modulate({
|
||||||
brightness: 0.5,
|
brightness: 0.5,
|
||||||
|
|||||||
@@ -294,6 +294,7 @@ Use these WebP options for output image.
|
|||||||
| [options.lossless] | <code>boolean</code> | <code>false</code> | use lossless compression mode |
|
| [options.lossless] | <code>boolean</code> | <code>false</code> | use lossless compression mode |
|
||||||
| [options.nearLossless] | <code>boolean</code> | <code>false</code> | use near_lossless compression mode |
|
| [options.nearLossless] | <code>boolean</code> | <code>false</code> | use near_lossless compression mode |
|
||||||
| [options.smartSubsample] | <code>boolean</code> | <code>false</code> | use high quality chroma subsampling |
|
| [options.smartSubsample] | <code>boolean</code> | <code>false</code> | use high quality chroma subsampling |
|
||||||
|
| [options.preset] | <code>string</code> | <code>"'default'"</code> | named preset for preprocessing/filtering, one of: default, photo, picture, drawing, icon, text |
|
||||||
| [options.effort] | <code>number</code> | <code>4</code> | CPU effort, between 0 (fastest) and 6 (slowest) |
|
| [options.effort] | <code>number</code> | <code>4</code> | CPU effort, between 0 (fastest) and 6 (slowest) |
|
||||||
| [options.loop] | <code>number</code> | <code>0</code> | number of animation iterations, use 0 for infinite animation |
|
| [options.loop] | <code>number</code> | <code>0</code> | number of animation iterations, use 0 for infinite animation |
|
||||||
| [options.delay] | <code>number</code> \| <code>Array.<number></code> | | delay(s) between animation frames (in milliseconds) |
|
| [options.delay] | <code>number</code> \| <code>Array.<number></code> | | delay(s) between animation frames (in milliseconds) |
|
||||||
|
|||||||
@@ -4,6 +4,14 @@
|
|||||||
|
|
||||||
Requires libvips v8.14.2
|
Requires libvips v8.14.2
|
||||||
|
|
||||||
|
### v0.32.3 - 14th July 2023
|
||||||
|
|
||||||
|
* Expose `preset` option for WebP output.
|
||||||
|
[#3639](https://github.com/lovell/sharp/issues/3639)
|
||||||
|
|
||||||
|
* Ensure decoding remains sequential for all operations (regression in 0.32.2).
|
||||||
|
[#3725](https://github.com/lovell/sharp/issues/3725)
|
||||||
|
|
||||||
### v0.32.2 - 11th July 2023
|
### v0.32.2 - 11th July 2023
|
||||||
|
|
||||||
* Limit HEIF output dimensions to 16384x16384, matches libvips.
|
* Limit HEIF output dimensions to 16384x16384, matches libvips.
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -108,14 +108,14 @@ const blend = {
|
|||||||
* @param {string} [images[].input.text.align='left'] - text alignment (`'left'`, `'centre'`, `'center'`, `'right'`).
|
* @param {string} [images[].input.text.align='left'] - text alignment (`'left'`, `'centre'`, `'center'`, `'right'`).
|
||||||
* @param {boolean} [images[].input.text.justify=false] - set this to true to apply justification to the text.
|
* @param {boolean} [images[].input.text.justify=false] - set this to true to apply justification to the text.
|
||||||
* @param {number} [images[].input.text.dpi=72] - the resolution (size) at which to render the text. Does not take effect if `height` is specified.
|
* @param {number} [images[].input.text.dpi=72] - the resolution (size) at which to render the text. Does not take effect if `height` is specified.
|
||||||
* @param {boolean} [images[].input.text.rgba=false] - set this to true to enable RGBA output. This is useful for colour emoji rendering, or support for pango markup features like `<span foreground="red">Red!</span>`.
|
* @param {boolean} [images[].input.text.rgba=false] - set this to true to enable RGBA output. This is useful for colour emoji rendering, or support for Pango markup features like `<span foreground="red">Red!</span>`.
|
||||||
* @param {number} [images[].input.text.spacing=0] - text line height in points. Will use the font line height if none is specified.
|
* @param {number} [images[].input.text.spacing=0] - text line height in points. Will use the font line height if none is specified.
|
||||||
* @param {String} [images[].blend='over'] - how to blend this image with the image below.
|
* @param {String} [images[].blend='over'] - how to blend this image with the image below.
|
||||||
* @param {String} [images[].gravity='centre'] - gravity at which to place the overlay.
|
* @param {String} [images[].gravity='centre'] - gravity at which to place the overlay.
|
||||||
* @param {Number} [images[].top] - the pixel offset from the top edge.
|
* @param {Number} [images[].top] - the pixel offset from the top edge.
|
||||||
* @param {Number} [images[].left] - the pixel offset from the left edge.
|
* @param {Number} [images[].left] - the pixel offset from the left edge.
|
||||||
* @param {Boolean} [images[].tile=false] - set to true to repeat the overlay image across the entire image with the given `gravity`.
|
* @param {Boolean} [images[].tile=false] - set to true to repeat the overlay image across the entire image with the given `gravity`.
|
||||||
* @param {Boolean} [images[].premultiplied=false] - set to true to avoid premultipling the image below. Equivalent to the `--premultiplied` vips option.
|
* @param {Boolean} [images[].premultiplied=false] - set to true to avoid premultiplying the image below. Equivalent to the `--premultiplied` vips option.
|
||||||
* @param {Number} [images[].density=72] - number representing the DPI for vector overlay image.
|
* @param {Number} [images[].density=72] - number representing the DPI for vector overlay image.
|
||||||
* @param {Object} [images[].raw] - describes overlay when using raw pixel data.
|
* @param {Object} [images[].raw] - describes overlay when using raw pixel data.
|
||||||
* @param {Number} [images[].raw.width]
|
* @param {Number} [images[].raw.width]
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ const debuglog = util.debuglog('sharp');
|
|||||||
* readableStream.pipe(transformer).pipe(writableStream);
|
* readableStream.pipe(transformer).pipe(writableStream);
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* // Create a blank 300x200 PNG image of semi-transluent red pixels
|
* // Create a blank 300x200 PNG image of semi-translucent red pixels
|
||||||
* sharp({
|
* sharp({
|
||||||
* create: {
|
* create: {
|
||||||
* width: 300,
|
* width: 300,
|
||||||
@@ -122,7 +122,7 @@ const debuglog = util.debuglog('sharp');
|
|||||||
* a String containing the filesystem path to an JPEG, PNG, WebP, AVIF, GIF, SVG or TIFF image file.
|
* a String containing the filesystem path to an JPEG, PNG, WebP, AVIF, GIF, SVG or TIFF image file.
|
||||||
* JPEG, PNG, WebP, AVIF, GIF, SVG, TIFF or raw pixel image data can be streamed into the object when not present.
|
* JPEG, PNG, WebP, AVIF, GIF, SVG, TIFF or raw pixel image data can be streamed into the object when not present.
|
||||||
* @param {Object} [options] - if present, is an Object with optional attributes.
|
* @param {Object} [options] - if present, is an Object with optional attributes.
|
||||||
* @param {string} [options.failOn='warning'] - when to abort processing of invalid pixel data, one of (in order of sensitivity): 'none' (least), 'truncated', 'error' or 'warning' (most), highers level imply lower levels, invalid metadata will always abort.
|
* @param {string} [options.failOn='warning'] - when to abort processing of invalid pixel data, one of (in order of sensitivity): 'none' (least), 'truncated', 'error' or 'warning' (most), higher levels imply lower levels, invalid metadata will always abort.
|
||||||
* @param {number|boolean} [options.limitInputPixels=268402689] - Do not process input images where the number of pixels
|
* @param {number|boolean} [options.limitInputPixels=268402689] - Do not process input images where the number of pixels
|
||||||
* (width x height) exceeds this limit. Assumes image dimensions contained in the input metadata can be trusted.
|
* (width x height) exceeds this limit. Assumes image dimensions contained in the input metadata can be trusted.
|
||||||
* An integral Number of pixels, zero or false to remove limit, true to use default limit of 268402689 (0x3FFF x 0x3FFF).
|
* An integral Number of pixels, zero or false to remove limit, true to use default limit of 268402689 (0x3FFF x 0x3FFF).
|
||||||
@@ -291,6 +291,7 @@ const Sharp = function (input, options) {
|
|||||||
webpLossless: false,
|
webpLossless: false,
|
||||||
webpNearLossless: false,
|
webpNearLossless: false,
|
||||||
webpSmartSubsample: false,
|
webpSmartSubsample: false,
|
||||||
|
webpPreset: 'default',
|
||||||
webpEffort: 4,
|
webpEffort: 4,
|
||||||
webpMinSize: false,
|
webpMinSize: false,
|
||||||
webpMixed: false,
|
webpMixed: false,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const is = require('./is');
|
|||||||
* or auto-orient based on the EXIF `Orientation` tag.
|
* or auto-orient based on the EXIF `Orientation` tag.
|
||||||
*
|
*
|
||||||
* If an angle is provided, it is converted to a valid positive degree rotation.
|
* If an angle is provided, it is converted to a valid positive degree rotation.
|
||||||
* For example, `-450` will produce a 270deg rotation.
|
* For example, `-450` will produce a 270 degree rotation.
|
||||||
*
|
*
|
||||||
* When rotating by an angle other than a multiple of 90,
|
* When rotating by an angle other than a multiple of 90,
|
||||||
* the background colour can be provided with the `background` option.
|
* the background colour can be provided with the `background` option.
|
||||||
@@ -772,7 +772,7 @@ function linear (a, b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recomb the image with the specified matrix.
|
* Recombine the image with the specified matrix.
|
||||||
*
|
*
|
||||||
* @since 0.21.1
|
* @since 0.21.1
|
||||||
*
|
*
|
||||||
@@ -785,7 +785,7 @@ function linear (a, b) {
|
|||||||
* ])
|
* ])
|
||||||
* .raw()
|
* .raw()
|
||||||
* .toBuffer(function(err, data, info) {
|
* .toBuffer(function(err, data, info) {
|
||||||
* // data contains the raw pixel data after applying the recomb
|
* // data contains the raw pixel data after applying the matrix
|
||||||
* // With this example input, a sepia filter has been applied
|
* // With this example input, a sepia filter has been applied
|
||||||
* });
|
* });
|
||||||
*
|
*
|
||||||
@@ -842,7 +842,7 @@ function recomb (inputMatrix) {
|
|||||||
* .toBuffer();
|
* .toBuffer();
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* // decreate brightness and saturation while also hue-rotating by 90 degrees
|
* // decrease brightness and saturation while also hue-rotating by 90 degrees
|
||||||
* const output = await sharp(input)
|
* const output = await sharp(input)
|
||||||
* .modulate({
|
* .modulate({
|
||||||
* brightness: 0.5,
|
* brightness: 0.5,
|
||||||
|
|||||||
@@ -483,6 +483,7 @@ function png (options) {
|
|||||||
* @param {boolean} [options.lossless=false] - use lossless compression mode
|
* @param {boolean} [options.lossless=false] - use lossless compression mode
|
||||||
* @param {boolean} [options.nearLossless=false] - use near_lossless compression mode
|
* @param {boolean} [options.nearLossless=false] - use near_lossless compression mode
|
||||||
* @param {boolean} [options.smartSubsample=false] - use high quality chroma subsampling
|
* @param {boolean} [options.smartSubsample=false] - use high quality chroma subsampling
|
||||||
|
* @param {string} [options.preset='default'] - named preset for preprocessing/filtering, one of: default, photo, picture, drawing, icon, text
|
||||||
* @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 6 (slowest)
|
* @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 6 (slowest)
|
||||||
* @param {number} [options.loop=0] - number of animation iterations, use 0 for infinite animation
|
* @param {number} [options.loop=0] - number of animation iterations, use 0 for infinite animation
|
||||||
* @param {number|number[]} [options.delay] - delay(s) between animation frames (in milliseconds)
|
* @param {number|number[]} [options.delay] - delay(s) between animation frames (in milliseconds)
|
||||||
@@ -517,6 +518,13 @@ function webp (options) {
|
|||||||
if (is.defined(options.smartSubsample)) {
|
if (is.defined(options.smartSubsample)) {
|
||||||
this._setBooleanOption('webpSmartSubsample', options.smartSubsample);
|
this._setBooleanOption('webpSmartSubsample', options.smartSubsample);
|
||||||
}
|
}
|
||||||
|
if (is.defined(options.preset)) {
|
||||||
|
if (is.string(options.preset) && is.inArray(options.preset, ['default', 'photo', 'picture', 'drawing', 'icon', 'text'])) {
|
||||||
|
this.options.webpPreset = options.preset;
|
||||||
|
} else {
|
||||||
|
throw is.invalidParameterError('preset', 'one of: default, photo, picture, drawing, icon, text', options.preset);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (is.defined(options.effort)) {
|
if (is.defined(options.effort)) {
|
||||||
if (is.integer(options.effort) && is.inRange(options.effort, 0, 6)) {
|
if (is.integer(options.effort) && is.inRange(options.effort, 0, 6)) {
|
||||||
this.options.webpEffort = options.effort;
|
this.options.webpEffort = options.effort;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "sharp",
|
"name": "sharp",
|
||||||
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, GIF, AVIF and TIFF images",
|
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, GIF, AVIF and TIFF images",
|
||||||
"version": "0.32.2",
|
"version": "0.32.3",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://github.com/lovell/sharp",
|
"homepage": "https://github.com/lovell/sharp",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
|
|||||||
@@ -1035,4 +1035,13 @@ namespace sharp {
|
|||||||
return std::make_pair(hshrink, vshrink);
|
return std::make_pair(hshrink, vshrink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Ensure decoding remains sequential.
|
||||||
|
*/
|
||||||
|
VImage StaySequential(VImage image, VipsAccess access, bool condition) {
|
||||||
|
if (access == VIPS_ACCESS_SEQUENTIAL && condition) {
|
||||||
|
return image.copy_memory();
|
||||||
|
}
|
||||||
|
return image;
|
||||||
|
}
|
||||||
} // namespace sharp
|
} // namespace sharp
|
||||||
|
|||||||
@@ -370,6 +370,11 @@ namespace sharp {
|
|||||||
std::pair<double, double> ResolveShrink(int width, int height, int targetWidth, int targetHeight,
|
std::pair<double, double> ResolveShrink(int width, int height, int targetWidth, int targetHeight,
|
||||||
Canvas canvas, bool swap, bool withoutEnlargement, bool withoutReduction);
|
Canvas canvas, bool swap, bool withoutEnlargement, bool withoutReduction);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Ensure decoding remains sequential.
|
||||||
|
*/
|
||||||
|
VImage StaySequential(VImage image, VipsAccess access, bool condition = TRUE);
|
||||||
|
|
||||||
} // namespace sharp
|
} // namespace sharp
|
||||||
|
|
||||||
#endif // SRC_COMMON_H_
|
#endif // SRC_COMMON_H_
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
vips::VImage image;
|
vips::VImage image;
|
||||||
sharp::ImageType inputImageType;
|
sharp::ImageType inputImageType;
|
||||||
std::tie(image, inputImageType) = sharp::OpenInput(baton->input);
|
std::tie(image, inputImageType) = sharp::OpenInput(baton->input);
|
||||||
|
VipsAccess access = baton->input->access;
|
||||||
image = sharp::EnsureColourspace(image, baton->colourspaceInput);
|
image = sharp::EnsureColourspace(image, baton->colourspaceInput);
|
||||||
|
|
||||||
int nPages = baton->input->pages;
|
int nPages = baton->input->pages;
|
||||||
@@ -79,9 +80,6 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
// Rotate and flip image according to Exif orientation
|
// Rotate and flip image according to Exif orientation
|
||||||
std::tie(autoRotation, autoFlip, autoFlop) = CalculateExifRotationAndFlip(sharp::ExifOrientation(image));
|
std::tie(autoRotation, autoFlip, autoFlop) = CalculateExifRotationAndFlip(sharp::ExifOrientation(image));
|
||||||
image = sharp::RemoveExifOrientation(image);
|
image = sharp::RemoveExifOrientation(image);
|
||||||
if (baton->input->access == VIPS_ACCESS_SEQUENTIAL && (autoRotation != VIPS_ANGLE_D0 || autoFlip)) {
|
|
||||||
image = image.copy_memory();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
rotation = CalculateAngleRotation(baton->angle);
|
rotation = CalculateAngleRotation(baton->angle);
|
||||||
}
|
}
|
||||||
@@ -93,6 +91,13 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
baton->rotationAngle != 0.0);
|
baton->rotationAngle != 0.0);
|
||||||
|
|
||||||
if (shouldRotateBefore) {
|
if (shouldRotateBefore) {
|
||||||
|
image = sharp::StaySequential(image, access,
|
||||||
|
rotation != VIPS_ANGLE_D0 ||
|
||||||
|
autoRotation != VIPS_ANGLE_D0 ||
|
||||||
|
autoFlip ||
|
||||||
|
baton->flip ||
|
||||||
|
baton->rotationAngle != 0.0);
|
||||||
|
|
||||||
if (autoRotation != VIPS_ANGLE_D0) {
|
if (autoRotation != VIPS_ANGLE_D0) {
|
||||||
image = image.rot(autoRotation);
|
image = image.rot(autoRotation);
|
||||||
autoRotation = VIPS_ANGLE_D0;
|
autoRotation = VIPS_ANGLE_D0;
|
||||||
@@ -126,6 +131,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
// Trim
|
// Trim
|
||||||
if (baton->trimThreshold > 0.0) {
|
if (baton->trimThreshold > 0.0) {
|
||||||
MultiPageUnsupported(nPages, "Trim");
|
MultiPageUnsupported(nPages, "Trim");
|
||||||
|
image = sharp::StaySequential(image, access);
|
||||||
image = sharp::Trim(image, baton->trimBackground, baton->trimThreshold);
|
image = sharp::Trim(image, baton->trimBackground, baton->trimThreshold);
|
||||||
baton->trimOffsetLeft = image.xoffset();
|
baton->trimOffsetLeft = image.xoffset();
|
||||||
baton->trimOffsetTop = image.yoffset();
|
baton->trimOffsetTop = image.yoffset();
|
||||||
@@ -212,7 +218,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
// pdfload* and svgload*
|
// pdfload* and svgload*
|
||||||
if (jpegShrinkOnLoad > 1) {
|
if (jpegShrinkOnLoad > 1) {
|
||||||
vips::VOption *option = VImage::option()
|
vips::VOption *option = VImage::option()
|
||||||
->set("access", baton->input->access)
|
->set("access", access)
|
||||||
->set("shrink", jpegShrinkOnLoad)
|
->set("shrink", jpegShrinkOnLoad)
|
||||||
->set("unlimited", baton->input->unlimited)
|
->set("unlimited", baton->input->unlimited)
|
||||||
->set("fail_on", baton->input->failOn);
|
->set("fail_on", baton->input->failOn);
|
||||||
@@ -227,7 +233,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
}
|
}
|
||||||
} else if (scale != 1.0) {
|
} else if (scale != 1.0) {
|
||||||
vips::VOption *option = VImage::option()
|
vips::VOption *option = VImage::option()
|
||||||
->set("access", baton->input->access)
|
->set("access", access)
|
||||||
->set("scale", scale)
|
->set("scale", scale)
|
||||||
->set("fail_on", baton->input->failOn);
|
->set("fail_on", baton->input->failOn);
|
||||||
if (inputImageType == sharp::ImageType::WEBP) {
|
if (inputImageType == sharp::ImageType::WEBP) {
|
||||||
@@ -379,6 +385,11 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
->set("kernel", baton->kernel));
|
->set("kernel", baton->kernel));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
image = sharp::StaySequential(image, access,
|
||||||
|
autoRotation != VIPS_ANGLE_D0 ||
|
||||||
|
baton->flip ||
|
||||||
|
autoFlip ||
|
||||||
|
rotation != VIPS_ANGLE_D0);
|
||||||
// Auto-rotate post-extract
|
// Auto-rotate post-extract
|
||||||
if (autoRotation != VIPS_ANGLE_D0) {
|
if (autoRotation != VIPS_ANGLE_D0) {
|
||||||
image = image.rot(autoRotation);
|
image = image.rot(autoRotation);
|
||||||
@@ -402,7 +413,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
sharp::ImageType joinImageType = sharp::ImageType::UNKNOWN;
|
sharp::ImageType joinImageType = sharp::ImageType::UNKNOWN;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < baton->joinChannelIn.size(); i++) {
|
for (unsigned int i = 0; i < baton->joinChannelIn.size(); i++) {
|
||||||
baton->joinChannelIn[i]->access = baton->input->access;
|
baton->joinChannelIn[i]->access = access;
|
||||||
std::tie(joinImage, joinImageType) = sharp::OpenInput(baton->joinChannelIn[i]);
|
std::tie(joinImage, joinImageType) = sharp::OpenInput(baton->joinChannelIn[i]);
|
||||||
joinImage = sharp::EnsureColourspace(joinImage, baton->colourspaceInput);
|
joinImage = sharp::EnsureColourspace(joinImage, baton->colourspaceInput);
|
||||||
image = image.bandjoin(joinImage);
|
image = image.bandjoin(joinImage);
|
||||||
@@ -471,10 +482,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
|
|
||||||
// Attention-based or Entropy-based crop
|
// Attention-based or Entropy-based crop
|
||||||
MultiPageUnsupported(nPages, "Resize strategy");
|
MultiPageUnsupported(nPages, "Resize strategy");
|
||||||
image = image.tilecache(VImage::option()
|
image = sharp::StaySequential(image, access);
|
||||||
->set("access", VIPS_ACCESS_RANDOM)
|
|
||||||
->set("threaded", TRUE));
|
|
||||||
|
|
||||||
image = image.smartcrop(baton->width, baton->height, VImage::option()
|
image = image.smartcrop(baton->width, baton->height, VImage::option()
|
||||||
->set("interesting", baton->position == 16 ? VIPS_INTERESTING_ENTROPY : VIPS_INTERESTING_ATTENTION)
|
->set("interesting", baton->position == 16 ? VIPS_INTERESTING_ENTROPY : VIPS_INTERESTING_ATTENTION)
|
||||||
#if (VIPS_MAJOR_VERSION >= 8 && VIPS_MINOR_VERSION >= 15)
|
#if (VIPS_MAJOR_VERSION >= 8 && VIPS_MINOR_VERSION >= 15)
|
||||||
@@ -495,6 +503,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
// Rotate post-extract non-90 angle
|
// Rotate post-extract non-90 angle
|
||||||
if (!baton->rotateBeforePreExtract && baton->rotationAngle != 0.0) {
|
if (!baton->rotateBeforePreExtract && baton->rotationAngle != 0.0) {
|
||||||
MultiPageUnsupported(nPages, "Rotate");
|
MultiPageUnsupported(nPages, "Rotate");
|
||||||
|
image = sharp::StaySequential(image, access);
|
||||||
std::vector<double> background;
|
std::vector<double> background;
|
||||||
std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground, shouldPremultiplyAlpha);
|
std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground, shouldPremultiplyAlpha);
|
||||||
image = image.rotate(baton->rotationAngle, VImage::option()->set("background", background));
|
image = image.rotate(baton->rotationAngle, VImage::option()->set("background", background));
|
||||||
@@ -518,6 +527,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
// Affine transform
|
// Affine transform
|
||||||
if (!baton->affineMatrix.empty()) {
|
if (!baton->affineMatrix.empty()) {
|
||||||
MultiPageUnsupported(nPages, "Affine");
|
MultiPageUnsupported(nPages, "Affine");
|
||||||
|
image = sharp::StaySequential(image, access);
|
||||||
std::vector<double> background;
|
std::vector<double> background;
|
||||||
std::tie(image, background) = sharp::ApplyAlpha(image, baton->affineBackground, shouldPremultiplyAlpha);
|
std::tie(image, background) = sharp::ApplyAlpha(image, baton->affineBackground, shouldPremultiplyAlpha);
|
||||||
vips::VInterpolate interp = vips::VInterpolate::new_from_name(
|
vips::VInterpolate interp = vips::VInterpolate::new_from_name(
|
||||||
@@ -614,7 +624,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
for (Composite *composite : baton->composite) {
|
for (Composite *composite : baton->composite) {
|
||||||
VImage compositeImage;
|
VImage compositeImage;
|
||||||
sharp::ImageType compositeImageType = sharp::ImageType::UNKNOWN;
|
sharp::ImageType compositeImageType = sharp::ImageType::UNKNOWN;
|
||||||
composite->input->access = baton->input->access;
|
composite->input->access = access;
|
||||||
std::tie(compositeImage, compositeImageType) = sharp::OpenInput(composite->input);
|
std::tie(compositeImage, compositeImageType) = sharp::OpenInput(composite->input);
|
||||||
compositeImage = sharp::EnsureColourspace(compositeImage, baton->colourspaceInput);
|
compositeImage = sharp::EnsureColourspace(compositeImage, baton->colourspaceInput);
|
||||||
// Verify within current dimensions
|
// Verify within current dimensions
|
||||||
@@ -701,11 +711,13 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
|
|
||||||
// Apply normalisation - stretch luminance to cover full dynamic range
|
// Apply normalisation - stretch luminance to cover full dynamic range
|
||||||
if (baton->normalise) {
|
if (baton->normalise) {
|
||||||
|
image = sharp::StaySequential(image, access);
|
||||||
image = sharp::Normalise(image, baton->normaliseLower, baton->normaliseUpper);
|
image = sharp::Normalise(image, baton->normaliseLower, baton->normaliseUpper);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply contrast limiting adaptive histogram equalization (CLAHE)
|
// Apply contrast limiting adaptive histogram equalization (CLAHE)
|
||||||
if (baton->claheWidth != 0 && baton->claheHeight != 0) {
|
if (baton->claheWidth != 0 && baton->claheHeight != 0) {
|
||||||
|
image = sharp::StaySequential(image, access);
|
||||||
image = sharp::Clahe(image, baton->claheWidth, baton->claheHeight, baton->claheMaxSlope);
|
image = sharp::Clahe(image, baton->claheWidth, baton->claheHeight, baton->claheMaxSlope);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -713,7 +725,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
if (baton->boolean != nullptr) {
|
if (baton->boolean != nullptr) {
|
||||||
VImage booleanImage;
|
VImage booleanImage;
|
||||||
sharp::ImageType booleanImageType = sharp::ImageType::UNKNOWN;
|
sharp::ImageType booleanImageType = sharp::ImageType::UNKNOWN;
|
||||||
baton->boolean->access = baton->input->access;
|
baton->boolean->access = access;
|
||||||
std::tie(booleanImage, booleanImageType) = sharp::OpenInput(baton->boolean);
|
std::tie(booleanImage, booleanImageType) = sharp::OpenInput(baton->boolean);
|
||||||
booleanImage = sharp::EnsureColourspace(booleanImage, baton->colourspaceInput);
|
booleanImage = sharp::EnsureColourspace(booleanImage, baton->colourspaceInput);
|
||||||
image = sharp::Boolean(image, booleanImage, baton->booleanOp);
|
image = sharp::Boolean(image, booleanImage, baton->booleanOp);
|
||||||
@@ -882,6 +894,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
->set("lossless", baton->webpLossless)
|
->set("lossless", baton->webpLossless)
|
||||||
->set("near_lossless", baton->webpNearLossless)
|
->set("near_lossless", baton->webpNearLossless)
|
||||||
->set("smart_subsample", baton->webpSmartSubsample)
|
->set("smart_subsample", baton->webpSmartSubsample)
|
||||||
|
->set("preset", baton->webpPreset)
|
||||||
->set("effort", baton->webpEffort)
|
->set("effort", baton->webpEffort)
|
||||||
->set("min_size", baton->webpMinSize)
|
->set("min_size", baton->webpMinSize)
|
||||||
->set("mixed", baton->webpMixed)
|
->set("mixed", baton->webpMixed)
|
||||||
@@ -963,6 +976,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
if (!sharp::HasAlpha(image)) {
|
if (!sharp::HasAlpha(image)) {
|
||||||
baton->tileBackground.pop_back();
|
baton->tileBackground.pop_back();
|
||||||
}
|
}
|
||||||
|
image = sharp::StaySequential(image, access, baton->tileAngle != 0);
|
||||||
vips::VOption *options = BuildOptionsDZ(baton);
|
vips::VOption *options = BuildOptionsDZ(baton);
|
||||||
VipsArea *area = reinterpret_cast<VipsArea*>(image.dzsave_buffer(options));
|
VipsArea *area = reinterpret_cast<VipsArea*>(image.dzsave_buffer(options));
|
||||||
baton->bufferOut = static_cast<char*>(area->data);
|
baton->bufferOut = static_cast<char*>(area->data);
|
||||||
@@ -1086,6 +1100,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
->set("lossless", baton->webpLossless)
|
->set("lossless", baton->webpLossless)
|
||||||
->set("near_lossless", baton->webpNearLossless)
|
->set("near_lossless", baton->webpNearLossless)
|
||||||
->set("smart_subsample", baton->webpSmartSubsample)
|
->set("smart_subsample", baton->webpSmartSubsample)
|
||||||
|
->set("preset", baton->webpPreset)
|
||||||
->set("effort", baton->webpEffort)
|
->set("effort", baton->webpEffort)
|
||||||
->set("min_size", baton->webpMinSize)
|
->set("min_size", baton->webpMinSize)
|
||||||
->set("mixed", baton->webpMixed)
|
->set("mixed", baton->webpMixed)
|
||||||
@@ -1162,6 +1177,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
if (!sharp::HasAlpha(image)) {
|
if (!sharp::HasAlpha(image)) {
|
||||||
baton->tileBackground.pop_back();
|
baton->tileBackground.pop_back();
|
||||||
}
|
}
|
||||||
|
image = sharp::StaySequential(image, access, baton->tileAngle != 0);
|
||||||
vips::VOption *options = BuildOptionsDZ(baton);
|
vips::VOption *options = BuildOptionsDZ(baton);
|
||||||
image.dzsave(const_cast<char*>(baton->fileOut.data()), options);
|
image.dzsave(const_cast<char*>(baton->fileOut.data()), options);
|
||||||
baton->formatOut = "dz";
|
baton->formatOut = "dz";
|
||||||
@@ -1363,6 +1379,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
{"lossless", baton->webpLossless ? "TRUE" : "FALSE"},
|
{"lossless", baton->webpLossless ? "TRUE" : "FALSE"},
|
||||||
{"near_lossless", baton->webpNearLossless ? "TRUE" : "FALSE"},
|
{"near_lossless", baton->webpNearLossless ? "TRUE" : "FALSE"},
|
||||||
{"smart_subsample", baton->webpSmartSubsample ? "TRUE" : "FALSE"},
|
{"smart_subsample", baton->webpSmartSubsample ? "TRUE" : "FALSE"},
|
||||||
|
{"preset", vips_enum_nick(VIPS_TYPE_FOREIGN_WEBP_PRESET, baton->webpPreset)},
|
||||||
{"min_size", baton->webpMinSize ? "TRUE" : "FALSE"},
|
{"min_size", baton->webpMinSize ? "TRUE" : "FALSE"},
|
||||||
{"mixed", baton->webpMixed ? "TRUE" : "FALSE"},
|
{"mixed", baton->webpMixed ? "TRUE" : "FALSE"},
|
||||||
{"effort", std::to_string(baton->webpEffort)}
|
{"effort", std::to_string(baton->webpEffort)}
|
||||||
@@ -1615,6 +1632,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|||||||
baton->webpLossless = sharp::AttrAsBool(options, "webpLossless");
|
baton->webpLossless = sharp::AttrAsBool(options, "webpLossless");
|
||||||
baton->webpNearLossless = sharp::AttrAsBool(options, "webpNearLossless");
|
baton->webpNearLossless = sharp::AttrAsBool(options, "webpNearLossless");
|
||||||
baton->webpSmartSubsample = sharp::AttrAsBool(options, "webpSmartSubsample");
|
baton->webpSmartSubsample = sharp::AttrAsBool(options, "webpSmartSubsample");
|
||||||
|
baton->webpPreset = sharp::AttrAsEnum<VipsForeignWebpPreset>(options, "webpPreset", VIPS_TYPE_FOREIGN_WEBP_PRESET);
|
||||||
baton->webpEffort = sharp::AttrAsUint32(options, "webpEffort");
|
baton->webpEffort = sharp::AttrAsUint32(options, "webpEffort");
|
||||||
baton->webpMinSize = sharp::AttrAsBool(options, "webpMinSize");
|
baton->webpMinSize = sharp::AttrAsBool(options, "webpMinSize");
|
||||||
baton->webpMixed = sharp::AttrAsBool(options, "webpMixed");
|
baton->webpMixed = sharp::AttrAsBool(options, "webpMixed");
|
||||||
@@ -1674,23 +1692,6 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|||||||
baton->tileId = sharp::AttrAsStr(options, "tileId");
|
baton->tileId = sharp::AttrAsStr(options, "tileId");
|
||||||
baton->tileBasename = sharp::AttrAsStr(options, "tileBasename");
|
baton->tileBasename = sharp::AttrAsStr(options, "tileBasename");
|
||||||
|
|
||||||
// Force random access for certain operations
|
|
||||||
if (baton->input->access == VIPS_ACCESS_SEQUENTIAL) {
|
|
||||||
if (
|
|
||||||
baton->trimThreshold > 0.0 ||
|
|
||||||
baton->normalise ||
|
|
||||||
baton->position == 16 || baton->position == 17 ||
|
|
||||||
baton->angle != 0 ||
|
|
||||||
baton->rotationAngle != 0.0 ||
|
|
||||||
baton->tileAngle != 0 ||
|
|
||||||
baton->flip ||
|
|
||||||
baton->claheWidth != 0 ||
|
|
||||||
!baton->affineMatrix.empty()
|
|
||||||
) {
|
|
||||||
baton->input->access = VIPS_ACCESS_RANDOM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function to notify of libvips warnings
|
// Function to notify of libvips warnings
|
||||||
Napi::Function debuglog = options.Get("debuglog").As<Napi::Function>();
|
Napi::Function debuglog = options.Get("debuglog").As<Napi::Function>();
|
||||||
|
|
||||||
|
|||||||
@@ -153,6 +153,7 @@ struct PipelineBaton {
|
|||||||
bool webpNearLossless;
|
bool webpNearLossless;
|
||||||
bool webpLossless;
|
bool webpLossless;
|
||||||
bool webpSmartSubsample;
|
bool webpSmartSubsample;
|
||||||
|
VipsForeignWebpPreset webpPreset;
|
||||||
int webpEffort;
|
int webpEffort;
|
||||||
bool webpMinSize;
|
bool webpMinSize;
|
||||||
bool webpMixed;
|
bool webpMixed;
|
||||||
@@ -318,6 +319,7 @@ struct PipelineBaton {
|
|||||||
webpNearLossless(false),
|
webpNearLossless(false),
|
||||||
webpLossless(false),
|
webpLossless(false),
|
||||||
webpSmartSubsample(false),
|
webpSmartSubsample(false),
|
||||||
|
webpPreset(VIPS_FOREIGN_WEBP_PRESET_DEFAULT),
|
||||||
webpEffort(4),
|
webpEffort(4),
|
||||||
webpMinSize(false),
|
webpMinSize(false),
|
||||||
webpMixed(false),
|
webpMixed(false),
|
||||||
|
|||||||
@@ -102,6 +102,29 @@ describe('WebP', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should produce a different file size with specific preset', () =>
|
||||||
|
sharp(fixtures.inputJpg)
|
||||||
|
.resize(320, 240)
|
||||||
|
.webp({ preset: 'default' })
|
||||||
|
.toBuffer()
|
||||||
|
.then(presetDefault =>
|
||||||
|
sharp(fixtures.inputJpg)
|
||||||
|
.resize(320, 240)
|
||||||
|
.webp({ preset: 'picture' })
|
||||||
|
.toBuffer()
|
||||||
|
.then(presetPicture => {
|
||||||
|
assert.notStrictEqual(presetDefault.length, presetPicture.length);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
it('invalid preset throws', () => {
|
||||||
|
assert.throws(
|
||||||
|
() => sharp().webp({ preset: 'fail' }),
|
||||||
|
/Expected one of: default, photo, picture, drawing, icon, text for preset but received fail of type string/
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should produce a smaller file size with increased effort', () =>
|
it('should produce a smaller file size with increased effort', () =>
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
|
|||||||
Reference in New Issue
Block a user