mirror of
https://github.com/lovell/sharp.git
synced 2026-02-04 13:46:19 +01:00
Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eefaa99872 | ||
|
|
dbce6fab79 | ||
|
|
af0fcb37c2 | ||
|
|
c6f54e59da | ||
|
|
846563e45f | ||
|
|
9c217ab580 | ||
|
|
e7381e522e | ||
|
|
4340d60ccf | ||
|
|
7f64d464de | ||
|
|
67e927bdb6 | ||
|
|
9c7713ed54 | ||
|
|
8be6da1def | ||
|
|
95635683ac | ||
|
|
44a0ee3fd3 | ||
|
|
ccd51c8cbf | ||
|
|
bb7469b2d1 | ||
|
|
a2cac61209 | ||
|
|
5c19f6dd9b | ||
|
|
3d01775972 | ||
|
|
87562a5111 | ||
|
|
2829e17743 | ||
|
|
ffefbd2ecc | ||
|
|
bc8f983329 | ||
|
|
440936a699 | ||
|
|
0bc79cdb95 | ||
|
|
9a66e25f53 | ||
|
|
8370935ccf | ||
|
|
f908987f35 | ||
|
|
aea368a3a0 | ||
|
|
7ecbc20d3d | ||
|
|
cb0e2a91c4 | ||
|
|
739b317a6f |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,6 +3,7 @@ node_modules
|
||||
/coverage
|
||||
test/bench/node_modules
|
||||
test/fixtures/output*
|
||||
test/fixtures/vips-properties.xml
|
||||
test/leak/libvips.supp
|
||||
test/saliency/report.json
|
||||
test/saliency/Image*
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
## removeAlpha
|
||||
> removeAlpha() ⇒ <code>Sharp</code>
|
||||
|
||||
Remove alpha channel, if any. This is a no-op if the image does not have an alpha channel.
|
||||
|
||||
See also [flatten](/api-operation#flatten).
|
||||
@@ -15,6 +17,8 @@ sharp('rgba.png')
|
||||
|
||||
|
||||
## ensureAlpha
|
||||
> ensureAlpha([alpha]) ⇒ <code>Sharp</code>
|
||||
|
||||
Ensure the output image has an alpha transparency channel.
|
||||
If missing, the added alpha channel will have the specified
|
||||
transparency level, defaulting to fully-opaque (1).
|
||||
@@ -48,6 +52,8 @@ const rgba = await sharp(rgb)
|
||||
|
||||
|
||||
## extractChannel
|
||||
> extractChannel(channel) ⇒ <code>Sharp</code>
|
||||
|
||||
Extract a single channel from a multi-channel image.
|
||||
|
||||
|
||||
@@ -78,6 +84,8 @@ const [red1, red2, ...] = await sharp(input)
|
||||
|
||||
|
||||
## joinChannel
|
||||
> joinChannel(images, options) ⇒ <code>Sharp</code>
|
||||
|
||||
Join one or more channels to the image.
|
||||
The meaning of the added channels depends on the output colourspace, set with `toColourspace()`.
|
||||
By default the output image will be web-friendly sRGB, with additional channels interpreted as alpha channels.
|
||||
@@ -102,6 +110,8 @@ For raw pixel input, the `options` object should contain a `raw` attribute, whic
|
||||
|
||||
|
||||
## bandbool
|
||||
> bandbool(boolOp) ⇒ <code>Sharp</code>
|
||||
|
||||
Perform a bitwise boolean operation on all input image channels (bands) to produce a single channel output image.
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
## tint
|
||||
> tint(rgb) ⇒ <code>Sharp</code>
|
||||
|
||||
Tint the image using the provided chroma while preserving the image luminance.
|
||||
An alpha channel may be present and will be unchanged by the operation.
|
||||
|
||||
@@ -21,6 +23,8 @@ const output = await sharp(input)
|
||||
|
||||
|
||||
## greyscale
|
||||
> greyscale([greyscale]) ⇒ <code>Sharp</code>
|
||||
|
||||
Convert to 8-bit greyscale; 256 shades of grey.
|
||||
This is a linear operation. If the input image is in a non-linear colour space such as sRGB, use `gamma()` with `greyscale()` for the best results.
|
||||
By default the output image will be web-friendly sRGB and contain three (identical) color channels.
|
||||
@@ -41,6 +45,8 @@ const output = await sharp(input).greyscale().toBuffer();
|
||||
|
||||
|
||||
## grayscale
|
||||
> grayscale([grayscale]) ⇒ <code>Sharp</code>
|
||||
|
||||
Alternative spelling of `greyscale`.
|
||||
|
||||
|
||||
@@ -52,6 +58,8 @@ Alternative spelling of `greyscale`.
|
||||
|
||||
|
||||
## pipelineColourspace
|
||||
> pipelineColourspace([colourspace]) ⇒ <code>Sharp</code>
|
||||
|
||||
Set the pipeline colourspace.
|
||||
|
||||
The input image will be converted to the provided colourspace at the start of the pipeline.
|
||||
@@ -82,6 +90,8 @@ await sharp(input)
|
||||
|
||||
|
||||
## pipelineColorspace
|
||||
> pipelineColorspace([colorspace]) ⇒ <code>Sharp</code>
|
||||
|
||||
Alternative spelling of `pipelineColourspace`.
|
||||
|
||||
|
||||
@@ -97,6 +107,8 @@ Alternative spelling of `pipelineColourspace`.
|
||||
|
||||
|
||||
## toColourspace
|
||||
> toColourspace([colourspace]) ⇒ <code>Sharp</code>
|
||||
|
||||
Set the output colourspace.
|
||||
By default output image will be web-friendly sRGB, with additional channels interpreted as alpha channels.
|
||||
|
||||
@@ -120,6 +132,8 @@ await sharp(input)
|
||||
|
||||
|
||||
## toColorspace
|
||||
> toColorspace([colorspace]) ⇒ <code>Sharp</code>
|
||||
|
||||
Alternative spelling of `toColourspace`.
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
## composite
|
||||
> composite(images) ⇒ <code>Sharp</code>
|
||||
|
||||
Composite image(s) over the processed (resized, extracted etc.) image.
|
||||
|
||||
The images to composite must be the same size or smaller than the processed image.
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
## Sharp
|
||||
> Sharp
|
||||
|
||||
|
||||
**Emits**: <code>Sharp#event:info</code>, <code>Sharp#event:warning</code>
|
||||
<a name="new_Sharp_new"></a>
|
||||
|
||||
### new
|
||||
> new Sharp([input], [options])
|
||||
|
||||
Constructor factory to create an instance of `sharp`, to which further methods are chained.
|
||||
|
||||
JPEG, PNG, WebP, GIF, AVIF or TIFF format image data can be streamed out from this object.
|
||||
@@ -159,6 +163,8 @@ await sharp({
|
||||
|
||||
|
||||
## clone
|
||||
> clone() ⇒ [<code>Sharp</code>](#Sharp)
|
||||
|
||||
Take a "snapshot" of the Sharp instance, returning a new instance.
|
||||
Cloned instances inherit the input of their parent instance.
|
||||
This allows multiple output Streams and therefore multiple processing pipelines to share a single input Stream.
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
## metadata
|
||||
> metadata([callback]) ⇒ <code>Promise.<Object></code> \| <code>Sharp</code>
|
||||
|
||||
Fast access to (uncached) image metadata without decoding any compressed pixel data.
|
||||
|
||||
This is read from the header of the input image.
|
||||
@@ -22,6 +24,7 @@ A `Promise` is returned when `callback` is not provided.
|
||||
- `isProgressive`: Boolean indicating whether the image is interlaced using a progressive scan
|
||||
- `pages`: Number of pages/frames contained within the image, with support for TIFF, HEIF, PDF, animated GIF and animated WebP
|
||||
- `pageHeight`: Number of pixels high each page in a multi-page image will be.
|
||||
- `paletteBitDepth`: Bit depth of palette-based image (GIF, PNG).
|
||||
- `loop`: Number of times to loop an animated image, zero refers to a continuous loop.
|
||||
- `delay`: Delay in ms between each page in an animated image, provided as an array of integers.
|
||||
- `pagePrimary`: Number of the primary page in a HEIF image
|
||||
@@ -80,6 +83,8 @@ function getNormalSize({ width, height, orientation }) {
|
||||
|
||||
|
||||
## stats
|
||||
> stats([callback]) ⇒ <code>Promise.<Object></code>
|
||||
|
||||
Access to pixel-derived image statistics for every channel in the image.
|
||||
A `Promise` is returned when `callback` is not provided.
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
## rotate
|
||||
> rotate([angle], [options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Rotate the output image by either an explicit angle
|
||||
or auto-orient based on the EXIF `Orientation` tag.
|
||||
|
||||
@@ -11,7 +13,7 @@ the background colour can be provided with the `background` option.
|
||||
If no angle is provided, it is determined from the EXIF data.
|
||||
Mirroring is supported and may infer the use of a flip operation.
|
||||
|
||||
The use of `rotate` implies the removal of the EXIF `Orientation` tag, if any.
|
||||
The use of `rotate` without an angle will remove the EXIF `Orientation` tag, if any.
|
||||
|
||||
Only one rotation can occur per pipeline.
|
||||
Previous calls to `rotate` in the same pipeline will be ignored.
|
||||
@@ -57,11 +59,11 @@ const resizeThenRotate = await sharp(input)
|
||||
|
||||
|
||||
## flip
|
||||
> flip([flip]) ⇒ <code>Sharp</code>
|
||||
|
||||
Mirror the image vertically (up-down) about the x-axis.
|
||||
This always occurs before rotation, if any.
|
||||
|
||||
The use of `flip` implies the removal of the EXIF `Orientation` tag, if any.
|
||||
|
||||
This operation does not work correctly with multi-page images.
|
||||
|
||||
|
||||
@@ -77,11 +79,11 @@ const output = await sharp(input).flip().toBuffer();
|
||||
|
||||
|
||||
## flop
|
||||
> flop([flop]) ⇒ <code>Sharp</code>
|
||||
|
||||
Mirror the image horizontally (left-right) about the y-axis.
|
||||
This always occurs before rotation, if any.
|
||||
|
||||
The use of `flop` implies the removal of the EXIF `Orientation` tag, if any.
|
||||
|
||||
|
||||
|
||||
| Param | Type | Default |
|
||||
@@ -95,6 +97,8 @@ const output = await sharp(input).flop().toBuffer();
|
||||
|
||||
|
||||
## affine
|
||||
> affine(matrix, [options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Perform an affine transform on an image. This operation will always occur after resizing, extraction and rotation, if any.
|
||||
|
||||
You must provide an array of length 4 or a 2x2 affine transformation matrix.
|
||||
@@ -146,6 +150,8 @@ inputStream
|
||||
|
||||
|
||||
## sharpen
|
||||
> sharpen([options], [flat], [jagged]) ⇒ <code>Sharp</code>
|
||||
|
||||
Sharpen the image.
|
||||
|
||||
When used without parameters, performs a fast, mild sharpen of the output image.
|
||||
@@ -197,6 +203,8 @@ const data = await sharp(input)
|
||||
|
||||
|
||||
## median
|
||||
> median([size]) ⇒ <code>Sharp</code>
|
||||
|
||||
Apply median filter.
|
||||
When used without parameters the default window is 3x3.
|
||||
|
||||
@@ -221,6 +229,8 @@ const output = await sharp(input).median(5).toBuffer();
|
||||
|
||||
|
||||
## blur
|
||||
> blur([sigma]) ⇒ <code>Sharp</code>
|
||||
|
||||
Blur the image.
|
||||
|
||||
When used without parameters, performs a fast 3x3 box blur (equivalent to a box linear filter).
|
||||
@@ -252,6 +262,8 @@ const gaussianBlurred = await sharp(input)
|
||||
|
||||
|
||||
## flatten
|
||||
> flatten([options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Merge alpha transparency channel, if any, with a background, then remove the alpha channel.
|
||||
|
||||
See also [removeAlpha](/api-channel#removealpha).
|
||||
@@ -272,6 +284,8 @@ await sharp(rgbaInput)
|
||||
|
||||
|
||||
## unflatten
|
||||
> unflatten()
|
||||
|
||||
Ensure the image has an alpha channel
|
||||
with all white pixel values made fully transparent.
|
||||
|
||||
@@ -297,6 +311,8 @@ await sharp(rgbInput)
|
||||
|
||||
|
||||
## gamma
|
||||
> gamma([gamma], [gammaOut]) ⇒ <code>Sharp</code>
|
||||
|
||||
Apply a gamma correction by reducing the encoding (darken) pre-resize at a factor of `1/gamma`
|
||||
then increasing the encoding (brighten) post-resize at a factor of `gamma`.
|
||||
This can improve the perceived brightness of a resized image in non-linear colour spaces.
|
||||
@@ -319,6 +335,8 @@ Supply a second argument to use a different output gamma value, otherwise the fi
|
||||
|
||||
|
||||
## negate
|
||||
> negate([options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Produce the "negative" of the image.
|
||||
|
||||
|
||||
@@ -343,6 +361,8 @@ const output = await sharp(input)
|
||||
|
||||
|
||||
## normalise
|
||||
> normalise([options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Enhance output image contrast by stretching its luminance to cover a full dynamic range.
|
||||
|
||||
Uses a histogram-based approach, taking a default range of 1% to 99% to reduce sensitivity to noise at the extremes.
|
||||
@@ -373,6 +393,8 @@ const output = await sharp(input)
|
||||
|
||||
|
||||
## normalize
|
||||
> normalize([options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Alternative spelling of normalise.
|
||||
|
||||
|
||||
@@ -392,6 +414,8 @@ const output = await sharp(input)
|
||||
|
||||
|
||||
## clahe
|
||||
> clahe(options) ⇒ <code>Sharp</code>
|
||||
|
||||
Perform contrast limiting adaptive histogram equalization
|
||||
[CLAHE](https://en.wikipedia.org/wiki/Adaptive_histogram_equalization#Contrast_Limited_AHE).
|
||||
|
||||
@@ -423,6 +447,8 @@ const output = await sharp(input)
|
||||
|
||||
|
||||
## convolve
|
||||
> convolve(kernel) ⇒ <code>Sharp</code>
|
||||
|
||||
Convolve the image with the specified kernel.
|
||||
|
||||
|
||||
@@ -457,6 +483,8 @@ sharp(input)
|
||||
|
||||
|
||||
## threshold
|
||||
> threshold([threshold], [options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Any pixel value greater than or equal to the threshold value will be set to 255, otherwise it will be set to 0.
|
||||
|
||||
|
||||
@@ -475,6 +503,8 @@ Any pixel value greater than or equal to the threshold value will be set to 255,
|
||||
|
||||
|
||||
## boolean
|
||||
> boolean(operand, operator, [options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Perform a bitwise boolean operation with operand image.
|
||||
|
||||
This operation creates an output image where each pixel is the result of
|
||||
@@ -499,6 +529,8 @@ the selected bitwise boolean `operation` between the corresponding pixels of the
|
||||
|
||||
|
||||
## linear
|
||||
> linear([a], [b]) ⇒ <code>Sharp</code>
|
||||
|
||||
Apply the linear formula `a` * input + `b` to the image to adjust image levels.
|
||||
|
||||
When a single number is provided, it will be used for all image channels.
|
||||
@@ -533,6 +565,8 @@ await sharp(rgbInput)
|
||||
|
||||
|
||||
## recomb
|
||||
> recomb(inputMatrix) ⇒ <code>Sharp</code>
|
||||
|
||||
Recombine the image with the specified matrix.
|
||||
|
||||
|
||||
@@ -563,6 +597,8 @@ sharp(input)
|
||||
|
||||
|
||||
## modulate
|
||||
> modulate([options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Transforms the image using brightness, saturation, hue rotation, and lightness.
|
||||
Brightness and lightness both operate on luminance, with the difference being that
|
||||
brightness is multiplicative whereas lightness is additive.
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
## toFile
|
||||
> toFile(fileOut, [callback]) ⇒ <code>Promise.<Object></code>
|
||||
|
||||
Write output image data to a file.
|
||||
|
||||
If an explicit output format is not selected, it will be inferred from the extension,
|
||||
@@ -39,6 +41,8 @@ sharp(input)
|
||||
|
||||
|
||||
## toBuffer
|
||||
> toBuffer([options], [callback]) ⇒ <code>Promise.<Buffer></code>
|
||||
|
||||
Write output to a Buffer.
|
||||
JPEG, PNG, WebP, AVIF, TIFF, GIF and raw pixel data output are supported.
|
||||
|
||||
@@ -108,9 +112,11 @@ await sharp(pixelArray, { raw: { width, height, channels } })
|
||||
|
||||
|
||||
## withMetadata
|
||||
> withMetadata([options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Include all metadata (EXIF, XMP, IPTC) from the input image in the output image.
|
||||
This will also convert to and add a web-friendly sRGB ICC profile unless a custom
|
||||
output profile is provided.
|
||||
This will also convert to and add a web-friendly sRGB ICC profile if appropriate,
|
||||
unless a custom output profile is provided.
|
||||
|
||||
The default behaviour, when `withMetadata` is not used, is to convert to the device-independent
|
||||
sRGB colour space and strip all metadata, including the removal of any ICC profile.
|
||||
@@ -167,6 +173,8 @@ const data = await sharp(input)
|
||||
|
||||
|
||||
## toFormat
|
||||
> toFormat(format, options) ⇒ <code>Sharp</code>
|
||||
|
||||
Force output to a given format.
|
||||
|
||||
|
||||
@@ -190,6 +198,8 @@ const data = await sharp(input)
|
||||
|
||||
|
||||
## jpeg
|
||||
> jpeg([options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Use these JPEG options for output image.
|
||||
|
||||
|
||||
@@ -235,6 +245,8 @@ const data = await sharp(input)
|
||||
|
||||
|
||||
## png
|
||||
> png([options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Use these PNG options for output image.
|
||||
|
||||
By default, PNG output is full colour at 8 or 16 bits per pixel.
|
||||
@@ -278,6 +290,8 @@ const data = await sharp(input)
|
||||
|
||||
|
||||
## webp
|
||||
> webp([options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Use these WebP options for output image.
|
||||
|
||||
|
||||
@@ -319,6 +333,8 @@ const outputWebp = await sharp(inputWebp, { animated: true })
|
||||
|
||||
|
||||
## gif
|
||||
> gif([options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Use these GIF options for the output image.
|
||||
|
||||
The first entry in the palette is reserved for transparency.
|
||||
@@ -378,6 +394,8 @@ await sharp('in.gif', { animated: true })
|
||||
|
||||
|
||||
## jp2
|
||||
> jp2([options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Use these JP2 options for output image.
|
||||
|
||||
Requires libvips compiled with support for OpenJPEG.
|
||||
@@ -420,6 +438,8 @@ const data = await sharp(input)
|
||||
|
||||
|
||||
## tiff
|
||||
> tiff([options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Use these TIFF options for output image.
|
||||
|
||||
The `density` can be set in pixels/inch via [withMetadata](#withmetadata)
|
||||
@@ -461,6 +481,8 @@ sharp('input.svg')
|
||||
|
||||
|
||||
## avif
|
||||
> avif([options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Use these AVIF options for output image.
|
||||
|
||||
Whilst it is possible to create AVIF images smaller than 16x16 pixels,
|
||||
@@ -498,6 +520,8 @@ const data = await sharp(input)
|
||||
|
||||
|
||||
## heif
|
||||
> heif([options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Use these HEIF options for output image.
|
||||
|
||||
Support for patent-encumbered HEIC images using `hevc` compression requires the use of a
|
||||
@@ -528,6 +552,8 @@ const data = await sharp(input)
|
||||
|
||||
|
||||
## jxl
|
||||
> jxl([options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Use these JPEG-XL (JXL) options for output image.
|
||||
|
||||
This feature is experimental, please do not use in production systems.
|
||||
@@ -557,6 +583,8 @@ Image metadata (EXIF, XMP) is unsupported.
|
||||
|
||||
|
||||
## raw
|
||||
> raw([options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Force output to be raw, uncompressed pixel data.
|
||||
Pixel ordering is left-to-right, top-to-bottom, without padding.
|
||||
Channel ordering will be RGB or RGBA for non-greyscale colourspaces.
|
||||
@@ -592,6 +620,8 @@ const data = await sharp('input.png')
|
||||
|
||||
|
||||
## tile
|
||||
> tile([options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Use tile-based deep zoom (image pyramid) output.
|
||||
|
||||
Set the format and options for tile images via the `toFormat`, `jpeg`, `png` or `webp` functions.
|
||||
@@ -653,6 +683,8 @@ readableStream
|
||||
|
||||
|
||||
## timeout
|
||||
> timeout(options) ⇒ <code>Sharp</code>
|
||||
|
||||
Set a timeout for processing, in seconds.
|
||||
Use a value of zero to continue processing indefinitely, the default behaviour.
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
## resize
|
||||
> resize([width], [height], [options]) ⇒ <code>Sharp</code>
|
||||
|
||||
Resize image to `width`, `height` or `width x height`.
|
||||
|
||||
When both a `width` and `height` are provided, the possible methods by which the image should **fit** these are:
|
||||
@@ -10,7 +12,7 @@ When both a `width` and `height` are provided, the possible methods by which the
|
||||
|
||||
Some of these values are based on the [object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) CSS property.
|
||||
|
||||
<img alt="Examples of various values for the fit property when resizing" width="100%" style="aspect-ratio: 998/243" src="https://cdn.jsdelivr.net/gh/lovell/sharp@main/docs/image/api-resize-fit.png">
|
||||
<img alt="Examples of various values for the fit property when resizing" width="100%" style="aspect-ratio: 998/243" src="https://cdn.jsdelivr.net/gh/lovell/sharp@main/docs/image/api-resize-fit.svg">
|
||||
|
||||
When using a **fit** of `cover` or `contain`, the default **position** is `centre`. Other options are:
|
||||
- `sharp.position`: `top`, `right top`, `right`, `right bottom`, `bottom`, `left bottom`, `left`, `left top`.
|
||||
@@ -146,6 +148,8 @@ const scaleByHalf = await sharp(input)
|
||||
|
||||
|
||||
## extend
|
||||
> extend(extend) ⇒ <code>Sharp</code>
|
||||
|
||||
Extend / pad / extrude one or more edges of the image with either
|
||||
the provided background colour or pixels derived from the image.
|
||||
This operation will always occur after resizing and extraction, if any.
|
||||
@@ -204,6 +208,8 @@ sharp(input)
|
||||
|
||||
|
||||
## extract
|
||||
> extract(options) ⇒ <code>Sharp</code>
|
||||
|
||||
Extract/crop a region of the image.
|
||||
|
||||
- Use `extract` before `resize` for pre-resize extraction.
|
||||
@@ -245,6 +251,8 @@ sharp(input)
|
||||
|
||||
|
||||
## trim
|
||||
> trim(trim) ⇒ <code>Sharp</code>
|
||||
|
||||
Trim pixels from all edges that contain values similar to the given background colour, which defaults to that of the top-left pixel.
|
||||
|
||||
Images with an alpha channel will use the combined bounding box of alpha and non-alpha channels.
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
## versions
|
||||
> versions
|
||||
|
||||
An Object containing the version numbers of sharp, libvips and its dependencies.
|
||||
|
||||
|
||||
@@ -9,6 +11,8 @@ console.log(sharp.versions);
|
||||
|
||||
|
||||
## interpolators
|
||||
> interpolators : <code>enum</code>
|
||||
|
||||
An Object containing the available interpolators and their proper values
|
||||
|
||||
|
||||
@@ -27,6 +31,8 @@ An Object containing the available interpolators and their proper values
|
||||
|
||||
|
||||
## format
|
||||
> format ⇒ <code>Object</code>
|
||||
|
||||
An Object containing nested boolean values representing the available input and output formats/methods.
|
||||
|
||||
|
||||
@@ -37,6 +43,8 @@ console.log(sharp.format);
|
||||
|
||||
|
||||
## vendor
|
||||
> vendor
|
||||
|
||||
An Object containing the platform and architecture
|
||||
of the current and installed vendored binaries.
|
||||
|
||||
@@ -48,6 +56,8 @@ console.log(sharp.vendor);
|
||||
|
||||
|
||||
## queue
|
||||
> queue
|
||||
|
||||
An EventEmitter that emits a `change` event when a task is either:
|
||||
- queued, waiting for _libuv_ to provide a worker thread
|
||||
- complete
|
||||
@@ -62,6 +72,8 @@ sharp.queue.on('change', function(queueLength) {
|
||||
|
||||
|
||||
## cache
|
||||
> cache([options]) ⇒ <code>Object</code>
|
||||
|
||||
Gets or, when options are provided, sets the limits of _libvips'_ operation cache.
|
||||
Existing entries in the cache will be trimmed after any change in limits.
|
||||
This method always returns cache statistics,
|
||||
@@ -89,6 +101,8 @@ sharp.cache(false);
|
||||
|
||||
|
||||
## concurrency
|
||||
> concurrency([concurrency]) ⇒ <code>number</code>
|
||||
|
||||
Gets or, when a concurrency is provided, sets
|
||||
the maximum number of threads _libvips_ should use to process _each image_.
|
||||
These are from a thread pool managed by glib,
|
||||
@@ -132,6 +146,8 @@ sharp.concurrency(0); // 4
|
||||
|
||||
|
||||
## counters
|
||||
> counters() ⇒ <code>Object</code>
|
||||
|
||||
Provides access to internal task counters.
|
||||
- queue is the number of tasks this module has queued waiting for _libuv_ to provide a worker thread from its pool.
|
||||
- process is the number of resize tasks currently being processed.
|
||||
@@ -144,6 +160,8 @@ const counters = sharp.counters(); // { queue: 2, process: 4 }
|
||||
|
||||
|
||||
## simd
|
||||
> simd([simd]) ⇒ <code>boolean</code>
|
||||
|
||||
Get and set use of SIMD vector unit instructions.
|
||||
Requires libvips to have been compiled with liborc support.
|
||||
|
||||
@@ -165,4 +183,63 @@ const simd = sharp.simd();
|
||||
```js
|
||||
const simd = sharp.simd(false);
|
||||
// prevent libvips from using liborc at runtime
|
||||
```
|
||||
|
||||
|
||||
## block
|
||||
> block(options)
|
||||
|
||||
Block libvips operations at runtime.
|
||||
|
||||
This is in addition to the `VIPS_BLOCK_UNTRUSTED` environment variable,
|
||||
which when set will block all "untrusted" operations.
|
||||
|
||||
|
||||
**Since**: 0.32.4
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| options | <code>Object</code> | |
|
||||
| options.operation | <code>Array.<string></code> | List of libvips low-level operation names to block. |
|
||||
|
||||
**Example** *(Block all TIFF input.)*
|
||||
```js
|
||||
sharp.block({
|
||||
operation: ['VipsForeignLoadTiff']
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## unblock
|
||||
> unblock(options)
|
||||
|
||||
Unblock libvips operations at runtime.
|
||||
|
||||
This is useful for defining a list of allowed operations.
|
||||
|
||||
|
||||
**Since**: 0.32.4
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| options | <code>Object</code> | |
|
||||
| options.operation | <code>Array.<string></code> | List of libvips low-level operation names to unblock. |
|
||||
|
||||
**Example** *(Block all input except WebP from the filesystem.)*
|
||||
```js
|
||||
sharp.block({
|
||||
operation: ['VipsForeignLoad']
|
||||
});
|
||||
sharp.unblock({
|
||||
operation: ['VipsForeignLoadWebpFile']
|
||||
});
|
||||
```
|
||||
**Example** *(Block all input except JPEG and PNG from a Buffer or Stream.)*
|
||||
```js
|
||||
sharp.block({
|
||||
operation: ['VipsForeignLoad']
|
||||
});
|
||||
sharp.unblock({
|
||||
operation: ['VipsForeignLoadJpegBuffer', 'VipsForeignLoadPngBuffer']
|
||||
});
|
||||
```
|
||||
@@ -29,7 +29,7 @@ const jsdoc2md = require('jsdoc-to-markdown');
|
||||
});
|
||||
|
||||
const cleanMarkdown = markdown
|
||||
.replace(/(## [A-Za-z0-9]+)[^\n]*/g, '$1') // simplify headings to match those of documentationjs, ensures existing URLs work
|
||||
.replace(/(## )([A-Za-z0-9]+)([^\n]*)/g, '$1$2\n> $2$3\n') // simplify headings to match those of documentationjs, ensures existing URLs work
|
||||
.replace(/<a name="[A-Za-z0-9+]+"><\/a>/g, '') // remove anchors, let docute add these (at markdown to HTML render time)
|
||||
.replace(/\*\*Kind\*\*: global[^\n]+/g, '') // remove all "global" Kind labels (requires JSDoc refactoring)
|
||||
.trim();
|
||||
|
||||
@@ -2,7 +2,55 @@
|
||||
|
||||
## v0.32 - *flow*
|
||||
|
||||
Requires libvips v8.14.2
|
||||
Requires libvips v8.14.5
|
||||
|
||||
### v0.32.6 - 18th September 2023
|
||||
|
||||
* Upgrade to libvips v8.14.5 for upstream bug fixes.
|
||||
|
||||
* Ensure composite tile images are fully decoded (regression in 0.32.0).
|
||||
[#3767](https://github.com/lovell/sharp/issues/3767)
|
||||
|
||||
* Ensure `withMetadata` can add ICC profiles to RGB16 output.
|
||||
[#3773](https://github.com/lovell/sharp/issues/3773)
|
||||
|
||||
* Ensure `withMetadata` does not reduce 16-bit images to 8-bit (regression in 0.32.5).
|
||||
[#3773](https://github.com/lovell/sharp/issues/3773)
|
||||
|
||||
* TypeScript: Add definitions for block and unblock.
|
||||
[#3799](https://github.com/lovell/sharp/pull/3799)
|
||||
[@ldrick](https://github.com/ldrick)
|
||||
|
||||
### v0.32.5 - 15th August 2023
|
||||
|
||||
* Upgrade to libvips v8.14.4 for upstream bug fixes.
|
||||
|
||||
* TypeScript: Add missing `WebpPresetEnum` to definitions.
|
||||
[#3748](https://github.com/lovell/sharp/pull/3748)
|
||||
[@pilotso11](https://github.com/pilotso11)
|
||||
|
||||
* Ensure compilation using musl v1.2.4.
|
||||
[#3755](https://github.com/lovell/sharp/pull/3755)
|
||||
[@kleisauke](https://github.com/kleisauke)
|
||||
|
||||
* Ensure resize with a `fit` of `inside` respects 90/270 degree rotation.
|
||||
[#3756](https://github.com/lovell/sharp/issues/3756)
|
||||
|
||||
* TypeScript: Ensure `minSize` property of `WebpOptions` is boolean.
|
||||
[#3758](https://github.com/lovell/sharp/pull/3758)
|
||||
[@sho-xizz](https://github.com/sho-xizz)
|
||||
|
||||
* Ensure `withMetadata` adds default sRGB profile.
|
||||
[#3761](https://github.com/lovell/sharp/issues/3761)
|
||||
|
||||
### v0.32.4 - 21st July 2023
|
||||
|
||||
* Upgrade to libvips v8.14.3 for upstream bug fixes.
|
||||
|
||||
* Expose ability to (un)block low-level libvips operations by name.
|
||||
|
||||
* Prebuilt binaries: restore support for tile-based output.
|
||||
[#3581](https://github.com/lovell/sharp/issues/3581)
|
||||
|
||||
### v0.32.3 - 14th July 2023
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB |
61
docs/image/api-resize-fit.svg
Normal file
61
docs/image/api-resize-fit.svg
Normal file
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="998" height="243" viewBox="0 0 998 243">
|
||||
<defs>
|
||||
<g id="placeholder">
|
||||
<rect width="180" height="128" fill="#64bed8"/>
|
||||
<circle cx="61.1" cy="36.8" r="19.3" fill="#ffefa9"/>
|
||||
<circle cx="61.1" cy="36.8" r="18.1" fill="#fdda42"/>
|
||||
<path d="m67.2 34.7 15.2 46L90 57.9l30.4 38 7.8-15.2 7.5 15.4H44z" fill="#6a696f"/>
|
||||
<path d="m82.4 80.7-15.2-46-.3 69h22.9z" fill="#474749"/>
|
||||
<path d="m90.1 58 12.2 15 18.2 23-13.9.1z" fill="#474749"/>
|
||||
<path d="M135.8 96H131l-2.8-15.3z" fill="#474749"/>
|
||||
<path d="M35.2 96h107.1c0 1.7-1.4 3.2-3.2 3.2H38.4a3.2 3.2 0 0 1-3.2-3.2z" fill="#b9c861"/>
|
||||
<path d="m67.2 34.7-.1 31-6.2-3-5.3 2.7z" fill="#fff"/>
|
||||
<path d="m67.2 34.7 7.6 23-7.7 8z" fill="#b3b1b4"/>
|
||||
<rect width="30.8" height="7.7" x="71.1" y="27.2" rx="2.8" ry="4.1" fill="#fff"/>
|
||||
<rect width="30.8" height="7.7" x="82.2" y="34.8" rx="2.8" ry="4.1" fill="#fff"/>
|
||||
<rect width="30.8" height="7.7" x="36.2" y="19.6" rx="2.8" ry="4.1" fill="#fff"/>
|
||||
<path d="m89.6 72.8-7.2 7.9L90 57.9l10 23z" fill="#fff"/>
|
||||
<path d="m90.1 58 10 23 2.2-8z" fill="#b3b1b4"/>
|
||||
<path d="M131.2 85.2 137 68l9 17.2-8 6z" fill="#8da128"/>
|
||||
<rect width="109.4" height="6.8" x="33.9" y="99.1" rx="13.2" ry="11.4" fill="#22b0d6"/>
|
||||
<path d="m137 68-5.8 17.2 6.8 6.1.3-13.7z" fill="#727d2e"/>
|
||||
<rect width="83.3" height="6.8" x="50.8" y="103.6" rx="10" ry="11.4" fill="#22b0d6"/>
|
||||
<rect width=".7" height="18.4" x="138" y="77.6" fill="#585657"/>
|
||||
<rect width=".5" height="5.2" x="2" y="-161.3" fill="#585657" transform="rotate(120)"/>
|
||||
<rect width=".5" height="5.3" x="5.5" y="-163.3" fill="#585657" transform="rotate(120)"/>
|
||||
<rect width=".5" height="4.8" x="-142.4" y="77.7" fill="#585657" transform="rotate(240)"/>
|
||||
<rect width=".5" height="5.1" x="-146" y="75.6" fill="#585657" transform="rotate(240)"/>
|
||||
</g>
|
||||
<pattern id="img" height="100%" width="100%" viewBox="0 0 180 128">
|
||||
<use xlink:href="#placeholder"/>
|
||||
</pattern>
|
||||
<pattern id="img-fill" width="100%" height="100%" viewBox="0 0 180 128" preserveAspectRatio="none">
|
||||
<use xlink:href="#placeholder"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect x="0" y="0" width="998" height="243" fill="#ddd"/>
|
||||
<g id="cover">
|
||||
<rect x="22" y="28" width="180" height="132" fill="url(#img)"/>
|
||||
<rect x="48" y="30" width="128" height="128" fill="none" stroke="#000" stroke-width="4"/>
|
||||
<text x="112" y="85%" dominant-baseline="middle" text-anchor="middle" font-family="sans" font-size="32" font-weight="bold">cover</text>
|
||||
</g>
|
||||
<g id="contain">
|
||||
<rect x="240" y="30" width="128" height="128" fill="url(#img)" stroke="#000" stroke-width="4"/>
|
||||
<text x="304" y="85%" dominant-baseline="middle" text-anchor="middle" font-family="sans" font-size="32" font-weight="bold" fill="#555">contain</text>
|
||||
</g>
|
||||
<g id="fill">
|
||||
<rect x="432" y="30" width="128" height="128" fill="url(#img-fill)" stroke="#000" stroke-width="4"/>
|
||||
<text x="496" y="85%" dominant-baseline="middle" text-anchor="middle" font-family="sans" font-size="32" font-weight="bold">fill</text>
|
||||
</g>
|
||||
<g id="inside">
|
||||
<rect x="624" y="48" width="128" height="92" fill="url(#img)" stroke="#000" stroke-width="4"/>
|
||||
<rect x="624" y="30" width="128" height="128" fill="none" stroke="#000" stroke-width="4" stroke-dasharray="12 4" stroke-dashoffset="6"/>
|
||||
<text x="688" y="85%" dominant-baseline="middle" text-anchor="middle" font-family="sans" font-size="32" font-weight="bold" fill="#555">inside</text>
|
||||
</g>
|
||||
<g id="outside">
|
||||
<rect x="792" y="30" width="176" height="128" fill="url(#img)" stroke="#000" stroke-width="4"/>
|
||||
<rect x="816" y="30" width="128" height="128" fill="none" stroke="#000" stroke-width="4" stroke-dasharray="12 4" stroke-dashoffset="-2"/>
|
||||
<text x="880" y="85%" dominant-baseline="middle" text-anchor="middle" font-family="sans" font-size="32" font-weight="bold">outside</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
File diff suppressed because one or more lines are too long
@@ -40,7 +40,7 @@ for (const match of matches) {
|
||||
].forEach((section) => {
|
||||
const contents = fs.readFileSync(path.join(__dirname, '..', `api-${section}.md`), 'utf8');
|
||||
const matches = contents.matchAll(
|
||||
/## (?<title>[A-Za-z]+)\n(?<firstparagraph>.+?)\n\n.+?(?<parameters>\| Param .+?\n\n)?\*\*Example/gs
|
||||
/## (?<title>[A-Za-z]+)\n[^\n]+\n(?<firstparagraph>.+?)\n\n.+?(?<parameters>\| Param .+?\n\n)?\*\*Example/gs
|
||||
);
|
||||
for (const match of matches) {
|
||||
const { title, firstparagraph, parameters } = match.groups;
|
||||
|
||||
59
lib/index.d.ts
vendored
59
lib/index.d.ts
vendored
@@ -139,6 +139,52 @@ declare namespace sharp {
|
||||
*/
|
||||
function simd(enable?: boolean): boolean;
|
||||
|
||||
/**
|
||||
* Block libvips operations at runtime.
|
||||
*
|
||||
* This is in addition to the `VIPS_BLOCK_UNTRUSTED` environment variable,
|
||||
* which when set will block all "untrusted" operations.
|
||||
*
|
||||
* @since 0.32.4
|
||||
*
|
||||
* @example <caption>Block all TIFF input.</caption>
|
||||
* sharp.block({
|
||||
* operation: ['VipsForeignLoadTiff']
|
||||
* });
|
||||
*
|
||||
* @param {Object} options
|
||||
* @param {Array<string>} options.operation - List of libvips low-level operation names to block.
|
||||
*/
|
||||
function block(options: { operation: string[] }): void;
|
||||
|
||||
/**
|
||||
* Unblock libvips operations at runtime.
|
||||
*
|
||||
* This is useful for defining a list of allowed operations.
|
||||
*
|
||||
* @since 0.32.4
|
||||
*
|
||||
* @example <caption>Block all input except WebP from the filesystem.</caption>
|
||||
* sharp.block({
|
||||
* operation: ['VipsForeignLoad']
|
||||
* });
|
||||
* sharp.unblock({
|
||||
* operation: ['VipsForeignLoadWebpFile']
|
||||
* });
|
||||
*
|
||||
* @example <caption>Block all input except JPEG and PNG from a Buffer or Stream.</caption>
|
||||
* sharp.block({
|
||||
* operation: ['VipsForeignLoad']
|
||||
* });
|
||||
* sharp.unblock({
|
||||
* operation: ['VipsForeignLoadJpegBuffer', 'VipsForeignLoadPngBuffer']
|
||||
* });
|
||||
*
|
||||
* @param {Object} options
|
||||
* @param {Array<string>} options.operation - List of libvips low-level operation names to unblock.
|
||||
*/
|
||||
function unblock(options: { operation: string[] }): void;
|
||||
|
||||
//#endregion
|
||||
|
||||
const gravity: GravityEnum;
|
||||
@@ -1124,9 +1170,11 @@ declare namespace sharp {
|
||||
/** Level of CPU effort to reduce file size, integer 0-6 (optional, default 4) */
|
||||
effort?: number | undefined;
|
||||
/** Prevent use of animation key frames to minimise file size (slow) (optional, default false) */
|
||||
minSize?: number;
|
||||
minSize?: boolean;
|
||||
/** Allow mixture of lossy and lossless animation frames (slow) (optional, default false) */
|
||||
mixed?: boolean;
|
||||
/** Preset options: one of default, photo, picture, drawing, icon, text (optional, default 'default') */
|
||||
preset?: keyof PresetEnum | undefined;
|
||||
}
|
||||
|
||||
interface AvifOptions extends OutputOptions {
|
||||
@@ -1476,6 +1524,15 @@ declare namespace sharp {
|
||||
lanczos3: 'lanczos3';
|
||||
}
|
||||
|
||||
interface PresetEnum {
|
||||
default: 'default';
|
||||
picture: 'picture';
|
||||
photo: 'photo';
|
||||
drawing: 'drawing';
|
||||
icon: 'icon';
|
||||
text: 'text';
|
||||
}
|
||||
|
||||
interface BoolEnum {
|
||||
and: 'and';
|
||||
or: 'or';
|
||||
|
||||
@@ -432,6 +432,7 @@ function _isStreamInput () {
|
||||
* - `isProgressive`: Boolean indicating whether the image is interlaced using a progressive scan
|
||||
* - `pages`: Number of pages/frames contained within the image, with support for TIFF, HEIF, PDF, animated GIF and animated WebP
|
||||
* - `pageHeight`: Number of pixels high each page in a multi-page image will be.
|
||||
* - `paletteBitDepth`: Bit depth of palette-based image (GIF, PNG).
|
||||
* - `loop`: Number of times to loop an animated image, zero refers to a continuous loop.
|
||||
* - `delay`: Delay in ms between each page in an animated image, provided as an array of integers.
|
||||
* - `pagePrimary`: Number of the primary page in a HEIF image
|
||||
|
||||
@@ -19,7 +19,7 @@ const is = require('./is');
|
||||
* If no angle is provided, it is determined from the EXIF data.
|
||||
* Mirroring is supported and may infer the use of a flip operation.
|
||||
*
|
||||
* The use of `rotate` implies the removal of the EXIF `Orientation` tag, if any.
|
||||
* The use of `rotate` without an angle will remove the EXIF `Orientation` tag, if any.
|
||||
*
|
||||
* Only one rotation can occur per pipeline.
|
||||
* Previous calls to `rotate` in the same pipeline will be ignored.
|
||||
@@ -83,8 +83,6 @@ function rotate (angle, options) {
|
||||
* Mirror the image vertically (up-down) about the x-axis.
|
||||
* This always occurs before rotation, if any.
|
||||
*
|
||||
* The use of `flip` implies the removal of the EXIF `Orientation` tag, if any.
|
||||
*
|
||||
* This operation does not work correctly with multi-page images.
|
||||
*
|
||||
* @example
|
||||
@@ -102,8 +100,6 @@ function flip (flip) {
|
||||
* Mirror the image horizontally (left-right) about the y-axis.
|
||||
* This always occurs before rotation, if any.
|
||||
*
|
||||
* The use of `flop` implies the removal of the EXIF `Orientation` tag, if any.
|
||||
*
|
||||
* @example
|
||||
* const output = await sharp(input).flop().toBuffer();
|
||||
*
|
||||
|
||||
@@ -162,8 +162,8 @@ function toBuffer (options, callback) {
|
||||
|
||||
/**
|
||||
* Include all metadata (EXIF, XMP, IPTC) from the input image in the output image.
|
||||
* This will also convert to and add a web-friendly sRGB ICC profile unless a custom
|
||||
* output profile is provided.
|
||||
* This will also convert to and add a web-friendly sRGB ICC profile if appropriate,
|
||||
* unless a custom output profile is provided.
|
||||
*
|
||||
* The default behaviour, when `withMetadata` is not used, is to convert to the device-independent
|
||||
* sRGB colour space and strip all metadata, including the removal of any ICC profile.
|
||||
@@ -1046,6 +1046,7 @@ function jxl (options) {
|
||||
*
|
||||
* @param {Object} [options] - output options
|
||||
* @param {string} [options.depth='uchar'] - bit depth, one of: char, uchar (default), short, ushort, int, uint, float, complex, double, dpcomplex
|
||||
* @returns {Sharp}
|
||||
* @throws {Error} Invalid options
|
||||
*/
|
||||
function raw (options) {
|
||||
|
||||
@@ -126,7 +126,7 @@ function isResizeExpected (options) {
|
||||
*
|
||||
* Some of these values are based on the [object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) CSS property.
|
||||
*
|
||||
* <img alt="Examples of various values for the fit property when resizing" width="100%" style="aspect-ratio: 998/243" src="https://cdn.jsdelivr.net/gh/lovell/sharp@main/docs/image/api-resize-fit.png">
|
||||
* <img alt="Examples of various values for the fit property when resizing" width="100%" style="aspect-ratio: 998/243" src="https://cdn.jsdelivr.net/gh/lovell/sharp@main/docs/image/api-resize-fit.svg">
|
||||
*
|
||||
* When using a **fit** of `cover` or `contain`, the default **position** is `centre`. Other options are:
|
||||
* - `sharp.position`: `top`, `right top`, `right`, `right bottom`, `bottom`, `left bottom`, `left`, `left top`.
|
||||
|
||||
@@ -202,6 +202,72 @@ function simd (simd) {
|
||||
}
|
||||
simd(true);
|
||||
|
||||
/**
|
||||
* Block libvips operations at runtime.
|
||||
*
|
||||
* This is in addition to the `VIPS_BLOCK_UNTRUSTED` environment variable,
|
||||
* which when set will block all "untrusted" operations.
|
||||
*
|
||||
* @since 0.32.4
|
||||
*
|
||||
* @example <caption>Block all TIFF input.</caption>
|
||||
* sharp.block({
|
||||
* operation: ['VipsForeignLoadTiff']
|
||||
* });
|
||||
*
|
||||
* @param {Object} options
|
||||
* @param {Array<string>} options.operation - List of libvips low-level operation names to block.
|
||||
*/
|
||||
function block (options) {
|
||||
if (is.object(options)) {
|
||||
if (Array.isArray(options.operation) && options.operation.every(is.string)) {
|
||||
sharp.block(options.operation, true);
|
||||
} else {
|
||||
throw is.invalidParameterError('operation', 'Array<string>', options.operation);
|
||||
}
|
||||
} else {
|
||||
throw is.invalidParameterError('options', 'object', options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unblock libvips operations at runtime.
|
||||
*
|
||||
* This is useful for defining a list of allowed operations.
|
||||
*
|
||||
* @since 0.32.4
|
||||
*
|
||||
* @example <caption>Block all input except WebP from the filesystem.</caption>
|
||||
* sharp.block({
|
||||
* operation: ['VipsForeignLoad']
|
||||
* });
|
||||
* sharp.unblock({
|
||||
* operation: ['VipsForeignLoadWebpFile']
|
||||
* });
|
||||
*
|
||||
* @example <caption>Block all input except JPEG and PNG from a Buffer or Stream.</caption>
|
||||
* sharp.block({
|
||||
* operation: ['VipsForeignLoad']
|
||||
* });
|
||||
* sharp.unblock({
|
||||
* operation: ['VipsForeignLoadJpegBuffer', 'VipsForeignLoadPngBuffer']
|
||||
* });
|
||||
*
|
||||
* @param {Object} options
|
||||
* @param {Array<string>} options.operation - List of libvips low-level operation names to unblock.
|
||||
*/
|
||||
function unblock (options) {
|
||||
if (is.object(options)) {
|
||||
if (Array.isArray(options.operation) && options.operation.every(is.string)) {
|
||||
sharp.block(options.operation, false);
|
||||
} else {
|
||||
throw is.invalidParameterError('operation', 'Array<string>', options.operation);
|
||||
}
|
||||
} else {
|
||||
throw is.invalidParameterError('options', 'object', options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decorate the Sharp class with utility-related functions.
|
||||
* @private
|
||||
@@ -216,4 +282,6 @@ module.exports = function (Sharp) {
|
||||
Sharp.versions = versions;
|
||||
Sharp.vendor = vendor;
|
||||
Sharp.queue = queue;
|
||||
Sharp.block = block;
|
||||
Sharp.unblock = unblock;
|
||||
};
|
||||
|
||||
32
package.json
32
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "sharp",
|
||||
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, GIF, AVIF and TIFF images",
|
||||
"version": "0.32.3",
|
||||
"version": "0.32.6",
|
||||
"author": "Lovell Fuller <npm@lovell.info>",
|
||||
"homepage": "https://github.com/lovell/sharp",
|
||||
"contributors": [
|
||||
@@ -133,7 +133,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"color": "^4.2.3",
|
||||
"detect-libc": "^2.0.1",
|
||||
"detect-libc": "^2.0.2",
|
||||
"node-addon-api": "^6.1.0",
|
||||
"prebuild-install": "^7.1.1",
|
||||
"semver": "^7.5.4",
|
||||
@@ -153,25 +153,25 @@
|
||||
"mocha": "^10.2.0",
|
||||
"mock-fs": "^5.2.0",
|
||||
"nyc": "^15.1.0",
|
||||
"prebuild": "lovell/prebuild#add-nodejs-20-drop-nodejs-10-and-12",
|
||||
"prebuild": "^12.0.0",
|
||||
"semistandard": "^16.0.1",
|
||||
"tsd": "^0.28.1"
|
||||
"tsd": "^0.29.0"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"config": {
|
||||
"libvips": "8.14.2",
|
||||
"libvips": "8.14.5",
|
||||
"integrity": {
|
||||
"darwin-arm64v8": "sha512-eUuxg6H0tXgX4z2lsaGtZ4cbPAm7yoFgkvPDd4csxoiVt+QUB25pEJwiXw7oB53VlBFIp3O8lbydSFS5zH8MQQ==",
|
||||
"darwin-x64": "sha512-cMT4v76IgzSR0VoXqLk/yftRyzMEZ+SBVMLzXCgqP/lmnYisrpmHHNqrWnoZbUUBXbPXLn6KMultYOJHe/c9ZQ==",
|
||||
"linux-arm64v8": "sha512-OcDJ/ly80pxwaKnw0W91sSvZczPtWsjmzrY/+6NMiQZT84LkmeaRuwErbHhorKDxnl7iZuNn9Uj5V25Xmj+LDQ==",
|
||||
"linux-armv6": "sha512-hk2ohSOYTJEtVQxEQFyQ+tuayKpYqx6NiXa7AE+8MF+yscxt+g+mLJ7TjDqtmb4ttFGH4IVfsEfU2YXIqWqkpg==",
|
||||
"linux-armv7": "sha512-/5Ci2Cd+yLZmTaEt9lVJ89elxX3RMJpps0ESjj43X40yrwka51QfXeg1QV38uNzZpCDIZkrbXZK0lyKldjpLuA==",
|
||||
"linux-x64": "sha512-wjCKmWfBb0uz1UB7rPDLvO0s+VWuoAY/Vv/YGCRFEQUkdSLQUgHExrOMMbOM3FleuYfQqznDYCXXphkl7X44+w==",
|
||||
"linuxmusl-arm64v8": "sha512-QtD2n90yi+rLE65C0gksFUU5uMUFPICI/pS3A0bgthpIcoCejAOYs3ZjVWpZbHQuV/lWahIUYO78MB9CzY860A==",
|
||||
"linuxmusl-x64": "sha512-TokQ/ETCJAsPYuxIMOPYDp25rlcwtpmIMtRUR9PB75TmZEJe7abRfCEInIPYeD8F/HxxnJSLiEdlbn1z1Jfzng==",
|
||||
"win32-arm64v8": "sha512-IIuj4EAgLqEVAoOuYH79C61a7TcJXlU/RBwk+5JsGWc2mr4J/Ar5J01e6XBvU4Lu3eqcU+3GPaACZEa1511buA==",
|
||||
"win32-ia32": "sha512-CsZi7lrReX3B6tmYgOGJ0IiAfcN5APDC6l+3gdosxfTfwpLLO+jXaSmyNwIGeMqrdgckG/gwwc+IrUZmkmjJ/A==",
|
||||
"win32-x64": "sha512-J7znmNKUK4ZKo6SnSnEtzT1xRAwvkGXxIx9/QihAadu1TFdS06yNhcENmwC4973+KZBlAdVpWbZ8sLrEoWkdCA=="
|
||||
"darwin-arm64v8": "sha512-1QZzICfCJd4wAO0P6qmYI5e5VFMt9iCE4QgefI8VMMbdSzjIXA9L/ARN6pkMQPZ3h20Y9RtJ2W1skgCsvCIccw==",
|
||||
"darwin-x64": "sha512-sMIKMYXsdU9FlIfztj6Kt/SfHlhlDpP0Ups7ftVFqwjaszmYmpI9y/d/q3mLb4jrzuSiSUEislSWCwBnW7MPTw==",
|
||||
"linux-arm64v8": "sha512-CD8owELzkDumaom+O3jJ8fKamILAQdj+//KK/VNcHK3sngUcFpdjx36C8okwbux9sml/T7GTB/gzpvReDrAejQ==",
|
||||
"linux-armv6": "sha512-wk6IPHatDFVWKJy7lI1TJezHGHPQut1wF2bwx256KlZwXUQU3fcVcMpV1zxXjgLFewHq2+uhyMkoSGBPahWzlA==",
|
||||
"linux-armv7": "sha512-HEZC9KYtkmBK5rUR2MqBhrVarnQVZ/TwLUeLkKq0XuoM2pc/eXI6N0Fh5NGEFwdXI2XE8g1ySf+OYS6DDi+xCQ==",
|
||||
"linux-x64": "sha512-SlFWrITSW5XVUkaFPQOySAaSGXnhkGJCj8X2wGYYta9hk5piZldQyMp4zwy0z6UeRu1qKTKtZvmq28W3Gnh9xA==",
|
||||
"linuxmusl-arm64v8": "sha512-ga9iX7WUva3sG/VsKkOD318InLlCfPIztvzCZKZ2/+izQXRbQi8VoXWMHgEN4KHACv45FTl7mJ/8CRqUzhS8wQ==",
|
||||
"linuxmusl-x64": "sha512-yeaHnpfee1hrZLok2l4eFceHzlfq8gN3QOu0R4Mh8iMK5O5vAUu97bdtxeZZeJJvHw8tfh2/msGi0qysxKN8bw==",
|
||||
"win32-arm64v8": "sha512-kR91hy9w1+GEXK56hLh51+hBCBo7T+ijM4Slkmvb/2PsYZySq5H7s61n99iDYl6kTJP2y9sW5Xcvm3uuXDaDgg==",
|
||||
"win32-ia32": "sha512-HrnofEbzHNpHJ0vVnjsTj5yfgVdcqdWshXuwFO2zc8xlEjA83BvXZ0lVj9MxPxkxJ2ta+/UlLr+CFzc5bOceMw==",
|
||||
"win32-x64": "sha512-BwKckinJZ0Fu/EcunqiLPwOLEBWp4xf8GV7nvmVuKKz5f6B+GxoA2k9aa2wueqv4r4RJVgV/aWXZWFKOIjre/Q=="
|
||||
},
|
||||
"runtime": "napi",
|
||||
"target": 7
|
||||
|
||||
@@ -964,12 +964,7 @@ namespace sharp {
|
||||
}
|
||||
|
||||
std::pair<double, double> ResolveShrink(int width, int height, int targetWidth, int targetHeight,
|
||||
Canvas canvas, bool swap, bool withoutEnlargement, bool withoutReduction) {
|
||||
if (swap && canvas != Canvas::IGNORE_ASPECT) {
|
||||
// Swap input width and height when requested.
|
||||
std::swap(width, height);
|
||||
}
|
||||
|
||||
Canvas canvas, bool withoutEnlargement, bool withoutReduction) {
|
||||
double hshrink = 1.0;
|
||||
double vshrink = 1.0;
|
||||
|
||||
|
||||
11
src/common.h
11
src/common.h
@@ -15,8 +15,8 @@
|
||||
|
||||
#if (VIPS_MAJOR_VERSION < 8) || \
|
||||
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 14) || \
|
||||
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 14 && VIPS_MICRO_VERSION < 2)
|
||||
#error "libvips version 8.14.2+ is required - please see https://sharp.pixelplumbing.com/install"
|
||||
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 14 && VIPS_MICRO_VERSION < 5)
|
||||
#error "libvips version 8.14.5+ is required - please see https://sharp.pixelplumbing.com/install"
|
||||
#endif
|
||||
|
||||
#if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)))
|
||||
@@ -362,13 +362,10 @@ namespace sharp {
|
||||
VImage EnsureAlpha(VImage image, double const value);
|
||||
|
||||
/*
|
||||
Calculate the shrink factor, taking into account auto-rotate, the canvas
|
||||
mode, and so on. The hshrink/vshrink are the amount to shrink the input
|
||||
image axes by in order for the output axes (ie. after rotation) to match
|
||||
the required thumbnail width/height and canvas mode.
|
||||
Calculate the horizontal and vertical shrink factors, taking the canvas mode into account.
|
||||
*/
|
||||
std::pair<double, double> ResolveShrink(int width, int height, int targetWidth, int targetHeight,
|
||||
Canvas canvas, bool swap, bool withoutEnlargement, bool withoutReduction);
|
||||
Canvas canvas, bool withoutEnlargement, bool withoutReduction);
|
||||
|
||||
/*
|
||||
Ensure decoding remains sequential.
|
||||
|
||||
@@ -20,18 +20,15 @@
|
||||
#include "operations.h"
|
||||
#include "pipeline.h"
|
||||
|
||||
#if defined(WIN32)
|
||||
#ifdef _WIN32
|
||||
#define STAT64_STRUCT __stat64
|
||||
#define STAT64_FUNCTION _stat64
|
||||
#elif defined(__APPLE__)
|
||||
#define STAT64_STRUCT stat
|
||||
#define STAT64_FUNCTION stat
|
||||
#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
|
||||
#define STAT64_STRUCT stat
|
||||
#define STAT64_FUNCTION stat
|
||||
#else
|
||||
#elif defined(_LARGEFILE64_SOURCE)
|
||||
#define STAT64_STRUCT stat64
|
||||
#define STAT64_FUNCTION stat64
|
||||
#else
|
||||
#define STAT64_STRUCT stat
|
||||
#define STAT64_FUNCTION stat
|
||||
#endif
|
||||
|
||||
class PipelineWorker : public Napi::AsyncWorker {
|
||||
@@ -160,15 +157,18 @@ class PipelineWorker : public Napi::AsyncWorker {
|
||||
int targetResizeWidth = baton->width;
|
||||
int targetResizeHeight = baton->height;
|
||||
|
||||
// Swap input output width and height when rotating by 90 or 270 degrees
|
||||
bool swap = !baton->rotateBeforePreExtract &&
|
||||
(rotation == VIPS_ANGLE_D90 || rotation == VIPS_ANGLE_D270 ||
|
||||
autoRotation == VIPS_ANGLE_D90 || autoRotation == VIPS_ANGLE_D270);
|
||||
// When auto-rotating by 90 or 270 degrees, swap the target width and
|
||||
// height to ensure the behavior aligns with how it would have been if
|
||||
// the rotation had taken place *before* resizing.
|
||||
if (!baton->rotateBeforePreExtract &&
|
||||
(autoRotation == VIPS_ANGLE_D90 || autoRotation == VIPS_ANGLE_D270)) {
|
||||
std::swap(targetResizeWidth, targetResizeHeight);
|
||||
}
|
||||
|
||||
// Shrink to pageHeight, so we work for multi-page images
|
||||
std::tie(hshrink, vshrink) = sharp::ResolveShrink(
|
||||
inputWidth, pageHeight, targetResizeWidth, targetResizeHeight,
|
||||
baton->canvas, swap, baton->withoutEnlargement, baton->withoutReduction);
|
||||
baton->canvas, baton->withoutEnlargement, baton->withoutReduction);
|
||||
|
||||
// The jpeg preload shrink.
|
||||
int jpegShrinkOnLoad = 1;
|
||||
@@ -302,7 +302,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
||||
// Shrink to pageHeight, so we work for multi-page images
|
||||
std::tie(hshrink, vshrink) = sharp::ResolveShrink(
|
||||
inputWidth, pageHeight, targetResizeWidth, targetResizeHeight,
|
||||
baton->canvas, swap, baton->withoutEnlargement, baton->withoutReduction);
|
||||
baton->canvas, baton->withoutEnlargement, baton->withoutReduction);
|
||||
|
||||
int targetHeight = static_cast<int>(std::rint(static_cast<double>(pageHeight) / vshrink));
|
||||
int targetPageHeight = targetHeight;
|
||||
@@ -326,7 +326,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
||||
try {
|
||||
image = image.icc_transform(processingProfile, VImage::option()
|
||||
->set("embedded", TRUE)
|
||||
->set("depth", image.interpretation() == VIPS_INTERPRETATION_RGB16 ? 16 : 8)
|
||||
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
||||
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
||||
} catch(...) {
|
||||
sharp::VipsWarningCallback(nullptr, G_LOG_LEVEL_WARNING, "Invalid embedded profile", nullptr);
|
||||
@@ -653,7 +653,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
||||
if (across != 0 || down != 0) {
|
||||
int left;
|
||||
int top;
|
||||
compositeImage = compositeImage.replicate(across, down);
|
||||
compositeImage = sharp::StaySequential(compositeImage, access).replicate(across, down);
|
||||
if (composite->hasOffset) {
|
||||
std::tie(left, top) = sharp::CalculateCrop(
|
||||
compositeImage.width(), compositeImage.height(), image.width(), image.height(),
|
||||
@@ -763,6 +763,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
||||
if (baton->withMetadata && sharp::HasProfile(image) && baton->withMetadataIcc.empty()) {
|
||||
image = image.icc_transform("srgb", VImage::option()
|
||||
->set("embedded", TRUE)
|
||||
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
||||
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
||||
}
|
||||
}
|
||||
@@ -788,12 +789,13 @@ class PipelineWorker : public Napi::AsyncWorker {
|
||||
}
|
||||
|
||||
// Apply output ICC profile
|
||||
if (!baton->withMetadataIcc.empty()) {
|
||||
if (baton->withMetadata) {
|
||||
image = image.icc_transform(
|
||||
const_cast<char*>(baton->withMetadataIcc.data()),
|
||||
baton->withMetadataIcc.empty() ? "srgb" : const_cast<char*>(baton->withMetadataIcc.data()),
|
||||
VImage::option()
|
||||
->set("input_profile", processingProfile)
|
||||
->set("embedded", TRUE)
|
||||
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
||||
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
||||
}
|
||||
// Override EXIF Orientation tag
|
||||
|
||||
@@ -31,6 +31,7 @@ Napi::Object init(Napi::Env env, Napi::Object exports) {
|
||||
exports.Set("simd", Napi::Function::New(env, simd));
|
||||
exports.Set("libvipsVersion", Napi::Function::New(env, libvipsVersion));
|
||||
exports.Set("format", Napi::Function::New(env, format));
|
||||
exports.Set("block", Napi::Function::New(env, block));
|
||||
exports.Set("_maxColourDistance", Napi::Function::New(env, _maxColourDistance));
|
||||
exports.Set("_isUsingJemalloc", Napi::Function::New(env, _isUsingJemalloc));
|
||||
exports.Set("stats", Napi::Function::New(env, stats));
|
||||
|
||||
@@ -164,6 +164,17 @@ Napi::Value format(const Napi::CallbackInfo& info) {
|
||||
return format;
|
||||
}
|
||||
|
||||
/*
|
||||
(Un)block libvips operations at runtime.
|
||||
*/
|
||||
void block(const Napi::CallbackInfo& info) {
|
||||
Napi::Array ops = info[size_t(0)].As<Napi::Array>();
|
||||
bool const state = info[size_t(1)].As<Napi::Boolean>().Value();
|
||||
for (unsigned int i = 0; i < ops.Length(); i++) {
|
||||
vips_operation_block_set(ops.Get(i).As<Napi::String>().Utf8Value().c_str(), state);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Synchronous, internal-only method used by some of the functional tests.
|
||||
Calculates the maximum colour distance using the DE2000 algorithm
|
||||
|
||||
@@ -12,6 +12,7 @@ Napi::Value counters(const Napi::CallbackInfo& info);
|
||||
Napi::Value simd(const Napi::CallbackInfo& info);
|
||||
Napi::Value libvipsVersion(const Napi::CallbackInfo& info);
|
||||
Napi::Value format(const Napi::CallbackInfo& info);
|
||||
void block(const Napi::CallbackInfo& info);
|
||||
Napi::Value _maxColourDistance(const Napi::CallbackInfo& info);
|
||||
Napi::Value _isUsingJemalloc(const Napi::CallbackInfo& info);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ ARG BRANCH=main
|
||||
RUN apt-get -y update && apt-get install -y build-essential curl git
|
||||
|
||||
# Install latest Node.js LTS
|
||||
RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash -
|
||||
RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash -
|
||||
RUN apt-get install -y nodejs
|
||||
|
||||
# Install benchmark dependencies
|
||||
@@ -23,4 +23,9 @@ RUN cat /etc/os-release | grep VERSION=
|
||||
RUN node -v
|
||||
|
||||
WORKDIR /tmp/sharp/test/bench
|
||||
|
||||
# Workaround for: https://github.com/emscripten-core/emscripten/pull/16917
|
||||
# This could be removed once Squoosh is an optional dependency.
|
||||
ENV NODE_OPTIONS="--no-experimental-fetch"
|
||||
|
||||
CMD [ "node", "perf" ]
|
||||
|
||||
@@ -9,15 +9,15 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@squoosh/cli": "0.7.3",
|
||||
"@squoosh/lib": "0.4.0",
|
||||
"@squoosh/lib": "0.5.3",
|
||||
"async": "3.2.4",
|
||||
"benchmark": "2.1.4",
|
||||
"gm": "1.25.0",
|
||||
"imagemagick": "0.1.3",
|
||||
"jimp": "0.22.7"
|
||||
"jimp": "0.22.10"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@tensorflow/tfjs-node": "4.2.0",
|
||||
"@tensorflow/tfjs-node": "4.9.0",
|
||||
"mapnik": "4.5.9"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -109,7 +109,7 @@ async.series({
|
||||
jpegSuite.add('squoosh-lib-buffer-buffer', {
|
||||
defer: true,
|
||||
fn: function (deferred) {
|
||||
const pool = new squoosh.ImagePool();
|
||||
const pool = new squoosh.ImagePool(os.cpus().length);
|
||||
const image = pool.ingestImage(inputJpgBuffer);
|
||||
image.decoded
|
||||
.then(function () {
|
||||
@@ -652,7 +652,7 @@ async.series({
|
||||
throw err;
|
||||
} else {
|
||||
image
|
||||
.resize(width, heightPng)
|
||||
.resize(width, heightPng, jimp.RESIZE_BICUBIC)
|
||||
.deflateLevel(6)
|
||||
.filterType(0)
|
||||
.getBuffer(jimp.MIME_PNG, function (err) {
|
||||
@@ -673,7 +673,7 @@ async.series({
|
||||
throw err;
|
||||
} else {
|
||||
image
|
||||
.resize(width, heightPng)
|
||||
.resize(width, heightPng, jimp.RESIZE_BICUBIC)
|
||||
.deflateLevel(6)
|
||||
.filterType(0)
|
||||
.write(outputPng, function (err) {
|
||||
@@ -707,7 +707,7 @@ async.series({
|
||||
pngSuite.add('squoosh-lib-buffer-buffer', {
|
||||
defer: true,
|
||||
fn: function (deferred) {
|
||||
const pool = new squoosh.ImagePool();
|
||||
const pool = new squoosh.ImagePool(os.cpus().length);
|
||||
const image = pool.ingestImage(inputPngBuffer);
|
||||
image.decoded
|
||||
.then(function () {
|
||||
|
||||
@@ -524,7 +524,7 @@ sharp('input.tiff').jxl({ lossless: true }).toFile('out.jxl');
|
||||
sharp('input.tiff').jxl({ effort: 7 }).toFile('out.jxl');
|
||||
|
||||
// Support `minSize` and `mixed` webp options
|
||||
sharp('input.tiff').webp({ minSize: 1000, mixed: true }).toFile('out.gif');
|
||||
sharp('input.tiff').webp({ minSize: true, mixed: true }).toFile('out.gif');
|
||||
|
||||
// 'failOn' input param
|
||||
sharp('input.tiff', { failOn: 'none' });
|
||||
@@ -651,3 +651,13 @@ sharp(input).composite([
|
||||
unlimited: true,
|
||||
}
|
||||
]);
|
||||
|
||||
// Support for webp preset in types
|
||||
// https://github.com/lovell/sharp/issues/3747
|
||||
sharp('input.tiff').webp({ preset: 'photo' }).toFile('out.webp');
|
||||
sharp('input.tiff').webp({ preset: 'picture' }).toFile('out.webp');
|
||||
sharp('input.tiff').webp({ preset: 'icon' }).toFile('out.webp');
|
||||
sharp('input.tiff').webp({ preset: 'drawing' }).toFile('out.webp');
|
||||
sharp('input.tiff').webp({ preset: 'text' }).toFile('out.webp');
|
||||
sharp('input.tiff').webp({ preset: 'default' }).toFile('out.webp');
|
||||
|
||||
|
||||
@@ -472,4 +472,28 @@ describe('composite', () => {
|
||||
assert.strictEqual(b, 19);
|
||||
assert.strictEqual(a, 128);
|
||||
});
|
||||
|
||||
it('Ensure tiled overlay is fully decoded', async () => {
|
||||
const tile = await sharp({
|
||||
create: {
|
||||
width: 8, height: 513, channels: 3, background: 'red'
|
||||
}
|
||||
})
|
||||
.png({ compressionLevel: 0 })
|
||||
.toBuffer();
|
||||
|
||||
const { info } = await sharp({
|
||||
create: {
|
||||
width: 8, height: 514, channels: 3, background: 'green'
|
||||
}
|
||||
})
|
||||
.composite([{
|
||||
input: tile,
|
||||
tile: true
|
||||
}])
|
||||
.toBuffer({ resolveWithObject: true });
|
||||
|
||||
assert.strictEqual(info.width, 8);
|
||||
assert.strictEqual(info.height, 514);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -781,6 +781,55 @@ describe('Image metadata', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('withMetadata adds default sRGB profile', async () => {
|
||||
const data = await sharp(fixtures.inputJpg)
|
||||
.resize(32, 24)
|
||||
.withMetadata()
|
||||
.toBuffer();
|
||||
|
||||
const metadata = await sharp(data).metadata();
|
||||
const { colorSpace, deviceClass, intent } = icc.parse(metadata.icc);
|
||||
assert.strictEqual(colorSpace, 'RGB');
|
||||
assert.strictEqual(deviceClass, 'Monitor');
|
||||
assert.strictEqual(intent, 'Perceptual');
|
||||
});
|
||||
|
||||
it('withMetadata adds default sRGB profile to RGB16', async () => {
|
||||
const data = await sharp({
|
||||
create: {
|
||||
width: 8, height: 8, channels: 4, background: 'orange'
|
||||
}
|
||||
})
|
||||
.toColorspace('rgb16')
|
||||
.png()
|
||||
.withMetadata()
|
||||
.toBuffer();
|
||||
|
||||
const metadata = await sharp(data).metadata();
|
||||
assert.strictEqual(metadata.depth, 'ushort');
|
||||
|
||||
const { description } = icc.parse(metadata.icc);
|
||||
assert.strictEqual(description, 'sRGB');
|
||||
});
|
||||
|
||||
it('withMetadata adds P3 profile to 16-bit PNG', async () => {
|
||||
const data = await sharp({
|
||||
create: {
|
||||
width: 8, height: 8, channels: 4, background: 'orange'
|
||||
}
|
||||
})
|
||||
.toColorspace('rgb16')
|
||||
.png()
|
||||
.withMetadata({ icc: 'p3' })
|
||||
.toBuffer();
|
||||
|
||||
const metadata = await sharp(data).metadata();
|
||||
assert.strictEqual(metadata.depth, 'ushort');
|
||||
|
||||
const { description } = icc.parse(metadata.icc);
|
||||
assert.strictEqual(description, 'sP3C');
|
||||
});
|
||||
|
||||
it('File input with corrupt header fails gracefully', function (done) {
|
||||
sharp(fixtures.inputJpgWithCorruptHeader)
|
||||
.metadata(function (err) {
|
||||
|
||||
@@ -192,6 +192,23 @@ describe('Rotation', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('Auto-rotate by 270 degrees, rectangular output ignoring aspect ratio', function (done) {
|
||||
sharp(fixtures.inputJpgWithLandscapeExif8)
|
||||
.resize(320, 240, { fit: sharp.fit.fill })
|
||||
.rotate()
|
||||
.toBuffer(function (err, data, info) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(240, info.height);
|
||||
sharp(data).metadata(function (err, metadata) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(320, metadata.width);
|
||||
assert.strictEqual(240, metadata.height);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Rotate by 30 degrees, rectangular output ignoring aspect ratio', function (done) {
|
||||
sharp(fixtures.inputJpg)
|
||||
.resize(320, 240, { fit: sharp.fit.fill })
|
||||
@@ -489,4 +506,28 @@ describe('Rotation', function () {
|
||||
.timeout({ seconds: 5 })
|
||||
.toBuffer()
|
||||
);
|
||||
|
||||
it('Rotate 90 then resize with inside fit', async () => {
|
||||
const data = await sharp({ create: { width: 16, height: 8, channels: 3, background: 'red' } })
|
||||
.rotate(90)
|
||||
.resize({ width: 6, fit: 'inside' })
|
||||
.png({ compressionLevel: 0 })
|
||||
.toBuffer();
|
||||
|
||||
const { width, height } = await sharp(data).metadata();
|
||||
assert.strictEqual(width, 6);
|
||||
assert.strictEqual(height, 12);
|
||||
});
|
||||
|
||||
it('Resize with inside fit then rotate 90', async () => {
|
||||
const data = await sharp({ create: { width: 16, height: 8, channels: 3, background: 'red' } })
|
||||
.resize({ width: 6, fit: 'inside' })
|
||||
.rotate(90)
|
||||
.png({ compressionLevel: 0 })
|
||||
.toBuffer();
|
||||
|
||||
const { width, height } = await sharp(data).metadata();
|
||||
assert.strictEqual(width, 3);
|
||||
assert.strictEqual(height, 6);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -928,7 +928,7 @@ describe('Tile', function () {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(true, stat.isFile());
|
||||
assert.strictEqual(true, stat.size > 0);
|
||||
extractZip(container, { dir: path.dirname(extractTo) })
|
||||
extractZip(container, { dir: extractTo })
|
||||
.then(() => {
|
||||
assertDeepZoomTiles(directory, 256, 13, done);
|
||||
})
|
||||
@@ -959,7 +959,7 @@ describe('Tile', function () {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(true, stat.isFile());
|
||||
assert.strictEqual(true, stat.size > 0);
|
||||
extractZip(container, { dir: path.dirname(extractTo) })
|
||||
extractZip(container, { dir: extractTo })
|
||||
.then(() => {
|
||||
assertDeepZoomTiles(directory, 256, 13, done);
|
||||
})
|
||||
@@ -988,7 +988,7 @@ describe('Tile', function () {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(true, stat.isFile());
|
||||
assert.strictEqual(true, stat.size > 0);
|
||||
extractZip(container, { dir: path.dirname(extractTo) })
|
||||
extractZip(container, { dir: extractTo })
|
||||
.then(() => {
|
||||
assertDeepZoomTiles(directory, 256, 13, done);
|
||||
})
|
||||
|
||||
@@ -153,4 +153,41 @@ describe('Utilities', function () {
|
||||
assert.strictEqual(true, Array.isArray(sharp.vendor.installed));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Block', () => {
|
||||
it('Can block a named operation', () => {
|
||||
sharp.block({ operation: ['test'] });
|
||||
});
|
||||
it('Can unblock a named operation', () => {
|
||||
sharp.unblock({ operation: ['test'] });
|
||||
});
|
||||
it('Invalid block operation throws', () => {
|
||||
assert.throws(() => sharp.block(1),
|
||||
/Expected object for options but received 1 of type number/
|
||||
);
|
||||
assert.throws(() => sharp.block({}),
|
||||
/Expected Array<string> for operation but received undefined of type undefined/
|
||||
);
|
||||
assert.throws(() => sharp.block({ operation: 'fail' }),
|
||||
/Expected Array<string> for operation but received fail of type string/
|
||||
);
|
||||
assert.throws(() => sharp.block({ operation: ['maybe', false] }),
|
||||
/Expected Array<string> for operation but received maybe,false of type object/
|
||||
);
|
||||
});
|
||||
it('Invalid unblock operation throws', () => {
|
||||
assert.throws(() => sharp.unblock(1),
|
||||
/Expected object for options but received 1 of type number/
|
||||
);
|
||||
assert.throws(() => sharp.unblock({}),
|
||||
/Expected Array<string> for operation but received undefined of type undefined/
|
||||
);
|
||||
assert.throws(() => sharp.unblock({ operation: 'fail' }),
|
||||
/Expected Array<string> for operation but received fail of type string/
|
||||
);
|
||||
assert.throws(() => sharp.unblock({ operation: ['maybe', false] }),
|
||||
/Expected Array<string> for operation but received maybe,false of type object/
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user