Compare commits

...

13 Commits

Author SHA1 Message Date
Lovell Fuller
db654de385 Release v0.30.5 2022-05-23 12:19:02 +01:00
Lovell Fuller
a6aeef612b Install: pass PKG_CONFIG_PATH via env rather than substitution 2022-05-23 12:12:19 +01:00
Lovell Fuller
7bf6cbd669 Docs: correct links to libvips documentation 2022-05-22 12:14:24 +01:00
Lovell Fuller
04c31b35a7 Install: warn about filesystem owner running npm v8+ as root 2022-05-15 19:43:45 +01:00
Lovell Fuller
ee9cdb6598 Bump deps 2022-05-15 17:20:33 +01:00
Lovell Fuller
8960eb8309 Docs: changelog entry for #3218 2022-05-15 17:12:51 +01:00
jakob0fischl
54d9dc46f5 Fix rotate-then-extract for EXIF orientation 2 (#3218) 2022-05-15 12:26:57 +01:00
Joona Heinikoski
51b4a7c564 Add support for --libc flag to improve cross-platform install (#3160)
This deprecates the libc-as-suffix approach of --platform=linuxmusl
2022-04-28 11:24:45 +01:00
Lovell Fuller
5b03579e5c Docs: more details about concurrency, parallelism, threads 2022-04-25 14:40:55 +01:00
Lovell Fuller
58c2af3251 Docs: improve output format info for toBuffer 2022-04-25 11:41:06 +01:00
Lovell Fuller
ee948ac6fa Docs: changelog and credit for #3196 2022-04-25 11:33:05 +01:00
Ankur Parihar
66a3ce5e55 Allow installation of prebuilt libvips binary from filesystem (#3196) 2022-04-24 18:47:57 +01:00
David Humphrey
75e5afcd42 Docs: fix typo in gif example (#3201) 2022-04-22 16:09:28 +01:00
21 changed files with 283 additions and 128 deletions

View File

@@ -16,7 +16,7 @@ If a [similar request](https://github.com/lovell/sharp/labels/enhancement) exist
it's probably fastest to add a comment to it about your requirement. it's probably fastest to add a comment to it about your requirement.
Implementation is usually straightforward if libvips Implementation is usually straightforward if libvips
[already supports](https://libvips.github.io/libvips/API/current/func-list.html) [already supports](https://www.libvips.org/API/current/func-list.html)
the feature you need. the feature you need.
## Submit a Pull Request to fix a bug ## Submit a Pull Request to fix a bug

View File

@@ -14,7 +14,7 @@ The `blend` option can be one of `clear`, `source`, `over`, `in`, `out`, `atop`,
`hard-light`, `soft-light`, `difference`, `exclusion`. `hard-light`, `soft-light`, `difference`, `exclusion`.
More information about blend modes can be found at More information about blend modes can be found at
[https://libvips.github.io/libvips/API/current/libvips-conversion.html#VipsBlendMode][1] [https://www.libvips.org/API/current/libvips-conversion.html#VipsBlendMode][1]
and [https://www.cairographics.org/operators/][2] and [https://www.cairographics.org/operators/][2]
### Parameters ### Parameters
@@ -89,7 +89,7 @@ Returns **Sharp**
* **since**: 0.22.0 * **since**: 0.22.0
[1]: https://libvips.github.io/libvips/API/current/libvips-conversion.html#VipsBlendMode [1]: https://www.libvips.org/API/current/libvips-conversion.html#VipsBlendMode
[2]: https://www.cairographics.org/operators/ [2]: https://www.cairographics.org/operators/

View File

@@ -131,9 +131,9 @@ const stats = await sharp(part).stats();
Returns **[Promise][5]<[Object][6]>** Returns **[Promise][5]<[Object][6]>**
[1]: https://libvips.github.io/libvips/API/current/VipsImage.html#VipsInterpretation [1]: https://www.libvips.org/API/current/VipsImage.html#VipsInterpretation
[2]: https://libvips.github.io/libvips/API/current/VipsImage.html#VipsBandFormat [2]: https://www.libvips.org/API/current/VipsImage.html#VipsBandFormat
[3]: https://www.npmjs.com/package/icc [3]: https://www.npmjs.com/package/icc

View File

@@ -46,6 +46,8 @@ Returns **[Promise][5]<[Object][6]>** when no callback is provided
Write output to a Buffer. Write output to a Buffer.
JPEG, PNG, WebP, AVIF, TIFF, GIF and raw pixel data output are supported. JPEG, PNG, WebP, AVIF, TIFF, GIF and raw pixel data output are supported.
Use [toFormat][7] or one of the format-specific functions such as [jpeg][8], [png][9] etc. to set the output format.
If no explicit format is set, the output format will match the input image, except SVG input which becomes PNG output. If no explicit format is set, the output format will match the input image, except SVG input which becomes PNG output.
By default all metadata will be removed, which includes EXIF-based orientation. By default all metadata will be removed, which includes EXIF-based orientation.
@@ -66,7 +68,7 @@ A `Promise` is returned when `callback` is not provided.
* `options` **[Object][6]?** * `options` **[Object][6]?**
* `options.resolveWithObject` **[boolean][7]?** Resolve the Promise with an Object containing `data` and `info` properties instead of resolving only with `data`. * `options.resolveWithObject` **[boolean][10]?** Resolve the Promise with an Object containing `data` and `info` properties instead of resolving only with `data`.
* `callback` **[Function][3]?** * `callback` **[Function][3]?**
### Examples ### Examples
@@ -85,6 +87,7 @@ sharp(input)
```javascript ```javascript
sharp(input) sharp(input)
.png()
.toBuffer({ resolveWithObject: true }) .toBuffer({ resolveWithObject: true })
.then(({ data, info }) => { ... }) .then(({ data, info }) => { ... })
.catch(err => { ... }); .catch(err => { ... });
@@ -107,7 +110,7 @@ await sharp(pixelArray, { raw: { width, height, channels } })
.toFile('my-changed-image.jpg'); .toFile('my-changed-image.jpg');
``` ```
Returns **[Promise][5]<[Buffer][8]>** when no callback is provided Returns **[Promise][5]<[Buffer][11]>** when no callback is provided
## withMetadata ## withMetadata
@@ -124,10 +127,10 @@ EXIF metadata is unsupported for TIFF output.
* `options` **[Object][6]?** * `options` **[Object][6]?**
* `options.orientation` **[number][9]?** value between 1 and 8, used to update the EXIF `Orientation` tag. * `options.orientation` **[number][12]?** value between 1 and 8, used to update the EXIF `Orientation` tag.
* `options.icc` **[string][2]?** filesystem path to output ICC profile, defaults to sRGB. * `options.icc` **[string][2]?** filesystem path to output ICC profile, defaults to sRGB.
* `options.exif` **[Object][6]<[Object][6]>** Object keyed by IFD0, IFD1 etc. of key/value string pairs to write as EXIF data. (optional, default `{}`) * `options.exif` **[Object][6]<[Object][6]>** Object keyed by IFD0, IFD1 etc. of key/value string pairs to write as EXIF data. (optional, default `{}`)
* `options.density` **[number][9]?** Number of pixels per inch (DPI). * `options.density` **[number][12]?** Number of pixels per inch (DPI).
### Examples ### Examples
@@ -192,19 +195,19 @@ Use these JPEG options for output image.
* `options` **[Object][6]?** output options * `options` **[Object][6]?** output options
* `options.quality` **[number][9]** quality, integer 1-100 (optional, default `80`) * `options.quality` **[number][12]** quality, integer 1-100 (optional, default `80`)
* `options.progressive` **[boolean][7]** use progressive (interlace) scan (optional, default `false`) * `options.progressive` **[boolean][10]** use progressive (interlace) scan (optional, default `false`)
* `options.chromaSubsampling` **[string][2]** set to '4:4:4' to prevent chroma subsampling otherwise defaults to '4:2:0' chroma subsampling (optional, default `'4:2:0'`) * `options.chromaSubsampling` **[string][2]** set to '4:4:4' to prevent chroma subsampling otherwise defaults to '4:2:0' chroma subsampling (optional, default `'4:2:0'`)
* `options.optimiseCoding` **[boolean][7]** optimise Huffman coding tables (optional, default `true`) * `options.optimiseCoding` **[boolean][10]** optimise Huffman coding tables (optional, default `true`)
* `options.optimizeCoding` **[boolean][7]** alternative spelling of optimiseCoding (optional, default `true`) * `options.optimizeCoding` **[boolean][10]** alternative spelling of optimiseCoding (optional, default `true`)
* `options.mozjpeg` **[boolean][7]** use mozjpeg defaults, equivalent to `{ trellisQuantisation: true, overshootDeringing: true, optimiseScans: true, quantisationTable: 3 }` (optional, default `false`) * `options.mozjpeg` **[boolean][10]** use mozjpeg defaults, equivalent to `{ trellisQuantisation: true, overshootDeringing: true, optimiseScans: true, quantisationTable: 3 }` (optional, default `false`)
* `options.trellisQuantisation` **[boolean][7]** apply trellis quantisation (optional, default `false`) * `options.trellisQuantisation` **[boolean][10]** apply trellis quantisation (optional, default `false`)
* `options.overshootDeringing` **[boolean][7]** apply overshoot deringing (optional, default `false`) * `options.overshootDeringing` **[boolean][10]** apply overshoot deringing (optional, default `false`)
* `options.optimiseScans` **[boolean][7]** optimise progressive scans, forces progressive (optional, default `false`) * `options.optimiseScans` **[boolean][10]** optimise progressive scans, forces progressive (optional, default `false`)
* `options.optimizeScans` **[boolean][7]** alternative spelling of optimiseScans (optional, default `false`) * `options.optimizeScans` **[boolean][10]** alternative spelling of optimiseScans (optional, default `false`)
* `options.quantisationTable` **[number][9]** quantization table to use, integer 0-8 (optional, default `0`) * `options.quantisationTable` **[number][12]** quantization table to use, integer 0-8 (optional, default `0`)
* `options.quantizationTable` **[number][9]** alternative spelling of quantisationTable (optional, default `0`) * `options.quantizationTable` **[number][12]** alternative spelling of quantisationTable (optional, default `0`)
* `options.force` **[boolean][7]** force JPEG output, otherwise attempt to use input format (optional, default `true`) * `options.force` **[boolean][10]** force JPEG output, otherwise attempt to use input format (optional, default `true`)
### Examples ### Examples
@@ -241,16 +244,16 @@ Set `palette` to `true` for slower, indexed PNG output.
* `options` **[Object][6]?** * `options` **[Object][6]?**
* `options.progressive` **[boolean][7]** use progressive (interlace) scan (optional, default `false`) * `options.progressive` **[boolean][10]** use progressive (interlace) scan (optional, default `false`)
* `options.compressionLevel` **[number][9]** zlib compression level, 0 (fastest, largest) to 9 (slowest, smallest) (optional, default `6`) * `options.compressionLevel` **[number][12]** zlib compression level, 0 (fastest, largest) to 9 (slowest, smallest) (optional, default `6`)
* `options.adaptiveFiltering` **[boolean][7]** use adaptive row filtering (optional, default `false`) * `options.adaptiveFiltering` **[boolean][10]** use adaptive row filtering (optional, default `false`)
* `options.palette` **[boolean][7]** quantise to a palette-based image with alpha transparency support (optional, default `false`) * `options.palette` **[boolean][10]** quantise to a palette-based image with alpha transparency support (optional, default `false`)
* `options.quality` **[number][9]** use the lowest number of colours needed to achieve given quality, sets `palette` to `true` (optional, default `100`) * `options.quality` **[number][12]** use the lowest number of colours needed to achieve given quality, sets `palette` to `true` (optional, default `100`)
* `options.effort` **[number][9]** CPU effort, between 1 (fastest) and 10 (slowest), sets `palette` to `true` (optional, default `7`) * `options.effort` **[number][12]** CPU effort, between 1 (fastest) and 10 (slowest), sets `palette` to `true` (optional, default `7`)
* `options.colours` **[number][9]** maximum number of palette entries, sets `palette` to `true` (optional, default `256`) * `options.colours` **[number][12]** maximum number of palette entries, sets `palette` to `true` (optional, default `256`)
* `options.colors` **[number][9]** alternative spelling of `options.colours`, sets `palette` to `true` (optional, default `256`) * `options.colors` **[number][12]** alternative spelling of `options.colours`, sets `palette` to `true` (optional, default `256`)
* `options.dither` **[number][9]** level of Floyd-Steinberg error diffusion, sets `palette` to `true` (optional, default `1.0`) * `options.dither` **[number][12]** level of Floyd-Steinberg error diffusion, sets `palette` to `true` (optional, default `1.0`)
* `options.force` **[boolean][7]** force PNG output, otherwise attempt to use input format (optional, default `true`) * `options.force` **[boolean][10]** force PNG output, otherwise attempt to use input format (optional, default `true`)
### Examples ### Examples
@@ -280,15 +283,15 @@ Use these WebP options for output image.
* `options` **[Object][6]?** output options * `options` **[Object][6]?** output options
* `options.quality` **[number][9]** quality, integer 1-100 (optional, default `80`) * `options.quality` **[number][12]** quality, integer 1-100 (optional, default `80`)
* `options.alphaQuality` **[number][9]** quality of alpha layer, integer 0-100 (optional, default `100`) * `options.alphaQuality` **[number][12]** quality of alpha layer, integer 0-100 (optional, default `100`)
* `options.lossless` **[boolean][7]** use lossless compression mode (optional, default `false`) * `options.lossless` **[boolean][10]** use lossless compression mode (optional, default `false`)
* `options.nearLossless` **[boolean][7]** use near_lossless compression mode (optional, default `false`) * `options.nearLossless` **[boolean][10]** use near_lossless compression mode (optional, default `false`)
* `options.smartSubsample` **[boolean][7]** use high quality chroma subsampling (optional, default `false`) * `options.smartSubsample` **[boolean][10]** use high quality chroma subsampling (optional, default `false`)
* `options.effort` **[number][9]** CPU effort, between 0 (fastest) and 6 (slowest) (optional, default `4`) * `options.effort` **[number][12]** CPU effort, between 0 (fastest) and 6 (slowest) (optional, default `4`)
* `options.loop` **[number][9]** number of animation iterations, use 0 for infinite animation (optional, default `0`) * `options.loop` **[number][12]** number of animation iterations, use 0 for infinite animation (optional, default `0`)
* `options.delay` **([number][9] | [Array][10]<[number][9]>)?** delay(s) between animation frames (in milliseconds) * `options.delay` **([number][12] | [Array][13]<[number][12]>)?** delay(s) between animation frames (in milliseconds)
* `options.force` **[boolean][7]** force WebP output, otherwise attempt to use input format (optional, default `true`) * `options.force` **[boolean][10]** force WebP output, otherwise attempt to use input format (optional, default `true`)
### Examples ### Examples
@@ -320,13 +323,13 @@ The first entry in the palette is reserved for transparency.
* `options` **[Object][6]?** output options * `options` **[Object][6]?** output options
* `options.colours` **[number][9]** maximum number of palette entries, including transparency, between 2 and 256 (optional, default `256`) * `options.colours` **[number][12]** maximum number of palette entries, including transparency, between 2 and 256 (optional, default `256`)
* `options.colors` **[number][9]** alternative spelling of `options.colours` (optional, default `256`) * `options.colors` **[number][12]** alternative spelling of `options.colours` (optional, default `256`)
* `options.effort` **[number][9]** CPU effort, between 1 (fastest) and 10 (slowest) (optional, default `7`) * `options.effort` **[number][12]** CPU effort, between 1 (fastest) and 10 (slowest) (optional, default `7`)
* `options.dither` **[number][9]** level of Floyd-Steinberg error diffusion, between 0 (least) and 1 (most) (optional, default `1.0`) * `options.dither` **[number][12]** level of Floyd-Steinberg error diffusion, between 0 (least) and 1 (most) (optional, default `1.0`)
* `options.loop` **[number][9]** number of animation iterations, use 0 for infinite animation (optional, default `0`) * `options.loop` **[number][12]** number of animation iterations, use 0 for infinite animation (optional, default `0`)
* `options.delay` **([number][9] | [Array][10]<[number][9]>)?** delay(s) between animation frames (in milliseconds) * `options.delay` **([number][12] | [Array][13]<[number][12]>)?** delay(s) between animation frames (in milliseconds)
* `options.force` **[boolean][7]** force GIF output, otherwise attempt to use input format (optional, default `true`) * `options.force` **[boolean][10]** force GIF output, otherwise attempt to use input format (optional, default `true`)
### Examples ### Examples
@@ -334,7 +337,7 @@ The first entry in the palette is reserved for transparency.
// Convert PNG to GIF // Convert PNG to GIF
await sharp(pngBuffer) await sharp(pngBuffer)
.gif() .gif()
.toBuffer()); .toBuffer();
``` ```
```javascript ```javascript
@@ -365,16 +368,16 @@ Use these JP2 options for output image.
Requires libvips compiled with support for OpenJPEG. Requires libvips compiled with support for OpenJPEG.
The prebuilt binaries do not include this - see The prebuilt binaries do not include this - see
[installing a custom libvips][11]. [installing a custom libvips][14].
### Parameters ### Parameters
* `options` **[Object][6]?** output options * `options` **[Object][6]?** output options
* `options.quality` **[number][9]** quality, integer 1-100 (optional, default `80`) * `options.quality` **[number][12]** quality, integer 1-100 (optional, default `80`)
* `options.lossless` **[boolean][7]** use lossless compression mode (optional, default `false`) * `options.lossless` **[boolean][10]** use lossless compression mode (optional, default `false`)
* `options.tileWidth` **[number][9]** horizontal tile size (optional, default `512`) * `options.tileWidth` **[number][12]** horizontal tile size (optional, default `512`)
* `options.tileHeight` **[number][9]** vertical tile size (optional, default `512`) * `options.tileHeight` **[number][12]** vertical tile size (optional, default `512`)
* `options.chromaSubsampling` **[string][2]** set to '4:2:0' to use chroma subsampling (optional, default `'4:4:4'`) * `options.chromaSubsampling` **[string][2]** set to '4:2:0' to use chroma subsampling (optional, default `'4:4:4'`)
### Examples ### Examples
@@ -414,18 +417,18 @@ The `density` can be set in pixels/inch via [withMetadata][1] instead of providi
* `options` **[Object][6]?** output options * `options` **[Object][6]?** output options
* `options.quality` **[number][9]** quality, integer 1-100 (optional, default `80`) * `options.quality` **[number][12]** quality, integer 1-100 (optional, default `80`)
* `options.force` **[boolean][7]** force TIFF output, otherwise attempt to use input format (optional, default `true`) * `options.force` **[boolean][10]** force TIFF output, otherwise attempt to use input format (optional, default `true`)
* `options.compression` **[string][2]** compression options: lzw, deflate, jpeg, ccittfax4 (optional, default `'jpeg'`) * `options.compression` **[string][2]** compression options: lzw, deflate, jpeg, ccittfax4 (optional, default `'jpeg'`)
* `options.predictor` **[string][2]** compression predictor options: none, horizontal, float (optional, default `'horizontal'`) * `options.predictor` **[string][2]** compression predictor options: none, horizontal, float (optional, default `'horizontal'`)
* `options.pyramid` **[boolean][7]** write an image pyramid (optional, default `false`) * `options.pyramid` **[boolean][10]** write an image pyramid (optional, default `false`)
* `options.tile` **[boolean][7]** write a tiled tiff (optional, default `false`) * `options.tile` **[boolean][10]** write a tiled tiff (optional, default `false`)
* `options.tileWidth` **[number][9]** horizontal tile size (optional, default `256`) * `options.tileWidth` **[number][12]** horizontal tile size (optional, default `256`)
* `options.tileHeight` **[number][9]** vertical tile size (optional, default `256`) * `options.tileHeight` **[number][12]** vertical tile size (optional, default `256`)
* `options.xres` **[number][9]** horizontal resolution in pixels/mm (optional, default `1.0`) * `options.xres` **[number][12]** horizontal resolution in pixels/mm (optional, default `1.0`)
* `options.yres` **[number][9]** vertical resolution in pixels/mm (optional, default `1.0`) * `options.yres` **[number][12]** vertical resolution in pixels/mm (optional, default `1.0`)
* `options.resolutionUnit` **[string][2]** resolution unit options: inch, cm (optional, default `'inch'`) * `options.resolutionUnit` **[string][2]** resolution unit options: inch, cm (optional, default `'inch'`)
* `options.bitdepth` **[number][9]** reduce bitdepth to 1, 2 or 4 bit (optional, default `8`) * `options.bitdepth` **[number][12]** reduce bitdepth to 1, 2 or 4 bit (optional, default `8`)
### Examples ### Examples
@@ -457,9 +460,9 @@ AVIF image sequences are not supported.
* `options` **[Object][6]?** output options * `options` **[Object][6]?** output options
* `options.quality` **[number][9]** quality, integer 1-100 (optional, default `50`) * `options.quality` **[number][12]** quality, integer 1-100 (optional, default `50`)
* `options.lossless` **[boolean][7]** use lossless compression (optional, default `false`) * `options.lossless` **[boolean][10]** use lossless compression (optional, default `false`)
* `options.effort` **[number][9]** CPU effort, between 0 (fastest) and 9 (slowest) (optional, default `4`) * `options.effort` **[number][12]** CPU effort, between 0 (fastest) and 9 (slowest) (optional, default `4`)
* `options.chromaSubsampling` **[string][2]** set to '4:2:0' to use chroma subsampling (optional, default `'4:4:4'`) * `options.chromaSubsampling` **[string][2]** set to '4:2:0' to use chroma subsampling (optional, default `'4:4:4'`)
<!----> <!---->
@@ -483,10 +486,10 @@ globally-installed libvips compiled with support for libheif, libde265 and x265.
* `options` **[Object][6]?** output options * `options` **[Object][6]?** output options
* `options.quality` **[number][9]** quality, integer 1-100 (optional, default `50`) * `options.quality` **[number][12]** quality, integer 1-100 (optional, default `50`)
* `options.compression` **[string][2]** compression format: av1, hevc (optional, default `'av1'`) * `options.compression` **[string][2]** compression format: av1, hevc (optional, default `'av1'`)
* `options.lossless` **[boolean][7]** use lossless compression (optional, default `false`) * `options.lossless` **[boolean][10]** use lossless compression (optional, default `false`)
* `options.effort` **[number][9]** CPU effort, between 0 (fastest) and 9 (slowest) (optional, default `4`) * `options.effort` **[number][12]** CPU effort, between 0 (fastest) and 9 (slowest) (optional, default `4`)
* `options.chromaSubsampling` **[string][2]** set to '4:2:0' to use chroma subsampling (optional, default `'4:4:4'`) * `options.chromaSubsampling` **[string][2]** set to '4:2:0' to use chroma subsampling (optional, default `'4:4:4'`)
<!----> <!---->
@@ -542,16 +545,16 @@ Use a `.zip` or `.szi` file extension with `toFile` to write to a compressed arc
* `options` **[Object][6]?** * `options` **[Object][6]?**
* `options.size` **[number][9]** tile size in pixels, a value between 1 and 8192. (optional, default `256`) * `options.size` **[number][12]** tile size in pixels, a value between 1 and 8192. (optional, default `256`)
* `options.overlap` **[number][9]** tile overlap in pixels, a value between 0 and 8192. (optional, default `0`) * `options.overlap` **[number][12]** tile overlap in pixels, a value between 0 and 8192. (optional, default `0`)
* `options.angle` **[number][9]** tile angle of rotation, must be a multiple of 90. (optional, default `0`) * `options.angle` **[number][12]** tile angle of rotation, must be a multiple of 90. (optional, default `0`)
* `options.background` **([string][2] | [Object][6])** background colour, parsed by the [color][12] module, defaults to white without transparency. (optional, default `{r:255,g:255,b:255,alpha:1}`) * `options.background` **([string][2] | [Object][6])** background colour, parsed by the [color][15] module, defaults to white without transparency. (optional, default `{r:255,g:255,b:255,alpha:1}`)
* `options.depth` **[string][2]?** how deep to make the pyramid, possible values are `onepixel`, `onetile` or `one`, default based on layout. * `options.depth` **[string][2]?** how deep to make the pyramid, possible values are `onepixel`, `onetile` or `one`, default based on layout.
* `options.skipBlanks` **[number][9]** threshold to skip tile generation, a value 0 - 255 for 8-bit images or 0 - 65535 for 16-bit images (optional, default `-1`) * `options.skipBlanks` **[number][12]** threshold to skip tile generation, a value 0 - 255 for 8-bit images or 0 - 65535 for 16-bit images (optional, default `-1`)
* `options.container` **[string][2]** tile container, with value `fs` (filesystem) or `zip` (compressed file). (optional, default `'fs'`) * `options.container` **[string][2]** tile container, with value `fs` (filesystem) or `zip` (compressed file). (optional, default `'fs'`)
* `options.layout` **[string][2]** filesystem layout, possible values are `dz`, `iiif`, `iiif3`, `zoomify` or `google`. (optional, default `'dz'`) * `options.layout` **[string][2]** filesystem layout, possible values are `dz`, `iiif`, `iiif3`, `zoomify` or `google`. (optional, default `'dz'`)
* `options.centre` **[boolean][7]** centre image in tile. (optional, default `false`) * `options.centre` **[boolean][10]** centre image in tile. (optional, default `false`)
* `options.center` **[boolean][7]** alternative spelling of centre. (optional, default `false`) * `options.center` **[boolean][10]** alternative spelling of centre. (optional, default `false`)
* `options.id` **[string][2]** when `layout` is `iiif`/`iiif3`, sets the `@id`/`id` attribute of `info.json` (optional, default `'https://example.com/iiif'`) * `options.id` **[string][2]** when `layout` is `iiif`/`iiif3`, sets the `@id`/`id` attribute of `info.json` (optional, default `'https://example.com/iiif'`)
### Examples ### Examples
@@ -584,7 +587,7 @@ Time spent waiting for a libuv thread to become available is not included.
* `options` **[Object][6]** * `options` **[Object][6]**
* `options.seconds` **[number][9]** Number of seconds after which processing will be stopped * `options.seconds` **[number][12]** Number of seconds after which processing will be stopped
Returns **Sharp** Returns **Sharp**
@@ -604,14 +607,20 @@ Returns **Sharp**
[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object [6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean [7]: #toformat
[8]: https://nodejs.org/api/buffer.html [8]: #jpeg
[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number [9]: #png
[10]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array [10]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[11]: https://sharp.pixelplumbing.com/install#custom-libvips [11]: https://nodejs.org/api/buffer.html
[12]: https://www.npmjs.org/package/color [12]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[13]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
[14]: https://sharp.pixelplumbing.com/install#custom-libvips
[15]: https://www.npmjs.org/package/color

View File

@@ -95,7 +95,11 @@ Returns **[Object][1]**
## concurrency ## concurrency
Gets or, when a concurrency is provided, sets Gets or, when a concurrency is provided, sets
the number of threads *libvips'* should create to process each image. the maximum number of threads *libvips* should use to process *each image*.
These are from a thread pool managed by glib,
which helps avoid the overhead of creating new threads.
This method always returns the current concurrency.
The default value is the number of CPU cores, The default value is the number of CPU cores,
except when using glibc-based Linux without jemalloc, except when using glibc-based Linux without jemalloc,
@@ -103,10 +107,19 @@ where the default is `1` to help reduce memory fragmentation.
A value of `0` will reset this to the number of CPU cores. A value of `0` will reset this to the number of CPU cores.
The maximum number of images that can be processed in parallel Some image format libraries spawn additional threads,
is limited by libuv's `UV_THREADPOOL_SIZE` environment variable. e.g. libaom manages its own 4 threads when encoding AVIF images,
and these are independent of the value set here.
This method always returns the current concurrency. The maximum number of images that sharp can process in parallel
is controlled by libuv's `UV_THREADPOOL_SIZE` environment variable,
which defaults to 4.
[https://nodejs.org/api/cli.html#uv_threadpool_sizesize][12]
For example, by default, a machine with 8 CPU cores will process
4 images in parallel and use up to 8 threads per image,
so there will be up to 32 concurrent threads.
### Parameters ### Parameters
@@ -199,3 +212,5 @@ Returns **[boolean][10]**
[10]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean [10]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[11]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number [11]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[12]: https://nodejs.org/api/cli.html#uv_threadpool_sizesize

View File

@@ -4,6 +4,19 @@
Requires libvips v8.12.2 Requires libvips v8.12.2
### v0.30.5 - 23rd May 2022
* Install: pass `PKG_CONFIG_PATH` via env rather than substitution.
[@dwisiswant0](https://github.com/dwisiswant0)
* Allow installation of prebuilt libvips binaries from filesystem.
[#3196](https://github.com/lovell/sharp/pull/3196)
[@ankurparihar](https://github.com/ankurparihar)
* Fix rotate-then-extract for EXIF orientation 2.
[#3218](https://github.com/lovell/sharp/pull/3218)
[@jakob0fischl](https://github.com/jakob0fischl)
### v0.30.4 - 18th April 2022 ### v0.30.4 - 18th April 2022
* Increase control over sensitivity to invalid images via `failOn`, deprecate `failOnError` (equivalent to `failOn: 'warning'`). * Increase control over sensitivity to invalid images via `failOn`, deprecate `failOnError` (equivalent to `failOn: 'warning'`).

View File

@@ -242,3 +242,6 @@ GitHub: https://github.com/codepage949
Name: Chris Hranj Name: Chris Hranj
GitHub: https://github.com/Brodan GitHub: https://github.com/Brodan
Name: Ankur Parihar
GitHub: https://github.com/ankurparihar

View File

@@ -74,20 +74,28 @@ The target platform and/or architecture can be manually selected using the follo
npm install --platform=... --arch=... --arm-version=... sharp npm install --platform=... --arch=... --arm-version=... sharp
``` ```
* `--platform`: one of `linux`, `linuxmusl`, `darwin` or `win32`. * `--platform`: one of `linux`, `darwin` or `win32`.
* `--arch`: one of `x64`, `ia32`, `arm` or `arm64`. * `--arch`: one of `x64`, `ia32`, `arm` or `arm64`.
* `--arm-version`: one of `6`, `7` or `8` (`arm` defaults to `6`, `arm64` defaults to `8`). * `--arm-version`: one of `6`, `7` or `8` (`arm` defaults to `6`, `arm64` defaults to `8`).
* `--libc`: one of `glibc` or `musl`. This option only works with platform `linux`, defaults to `glibc`
* `--sharp-install-force`: skip version compatibility and Subresource Integrity checks. * `--sharp-install-force`: skip version compatibility and Subresource Integrity checks.
These values can also be set via environment variables, These values can also be set via environment variables,
`npm_config_platform`, `npm_config_arch`, `npm_config_arm_version` `npm_config_platform`, `npm_config_arch`, `npm_config_arm_version`, `npm_config_libc`
and `SHARP_INSTALL_FORCE` respectively. and `SHARP_INSTALL_FORCE` respectively.
For example, if the target machine has a 64-bit ARM CPU and is running Alpine Linux, For example, if the target machine has a 64-bit ARM CPU and is running Alpine Linux,
use the following flags: use the following flags:
```sh ```sh
npm install --arch=arm64 --platform=linuxmusl sharp npm install --arch=arm64 --platform=linux --libc=musl sharp
```
If the current machine is Alpine Linux and the target machine is Debian Linux on x64 cpu,
use the following flags:
```sh
npm install --arch=x64 --platform=linux --libc=glibc sharp
``` ```
## Custom libvips ## Custom libvips
@@ -96,8 +104,8 @@ To use a custom, globally-installed version of libvips instead of the provided b
make sure it is at least the version listed under `config.libvips` in the `package.json` file make sure it is at least the version listed under `config.libvips` in the `package.json` file
and that it can be located using `pkg-config --modversion vips-cpp`. and that it can be located using `pkg-config --modversion vips-cpp`.
For help compiling libvips from source, please see For help compiling libvips and its dependencies, please see
[https://libvips.github.io/libvips/install.html#building-libvips-from-a-source-tarball](https://libvips.github.io/libvips/install.html#building-libvips-from-a-source-tarball). [building libvips from source](https://www.libvips.org/install.html#building-libvips-from-source).
The use of a globally-installed libvips is unsupported on Windows. The use of a globally-installed libvips is unsupported on Windows.
@@ -118,6 +126,8 @@ Building from source requires:
This is an advanced approach that most people will not require. This is an advanced approach that most people will not require.
### Prebuilt sharp binaries
To install the prebuilt sharp binaries from a custom URL, To install the prebuilt sharp binaries from a custom URL,
set the `sharp_binary_host` npm config option set the `sharp_binary_host` npm config option
or the `npm_config_sharp_binary_host` environment variable. or the `npm_config_sharp_binary_host` environment variable.
@@ -126,10 +136,16 @@ To install the prebuilt sharp binaries from a directory on the local filesystem,
set the `sharp_local_prebuilds` npm config option set the `sharp_local_prebuilds` npm config option
or the `npm_config_sharp_local_prebuilds` environment variable. or the `npm_config_sharp_local_prebuilds` environment variable.
### Prebuilt libvips binaries
To install the prebuilt libvips binaries from a custom URL, To install the prebuilt libvips binaries from a custom URL,
set the `sharp_libvips_binary_host` npm config option set the `sharp_libvips_binary_host` npm config option
or the `npm_config_sharp_libvips_binary_host` environment variable. or the `npm_config_sharp_libvips_binary_host` environment variable.
To install the prebuilt libvips binaries from a directory on the local filesystem,
set the `sharp_libvips_local_prebuilds` npm config option
or the `npm_config_sharp_libvips_local_prebuilds` environment variable.
The version subpath and file name are appended to these. The version subpath and file name are appended to these.
For example, if `sharp_libvips_binary_host` is set to `https://hostname/path` For example, if `sharp_libvips_binary_host` is set to `https://hostname/path`
and the libvips version is `1.2.3` then the resultant URL will be and the libvips version is `1.2.3` then the resultant URL will be
@@ -207,7 +223,8 @@ run the following additional command after `npm install`:
```sh ```sh
npm install npm install
SHARP_IGNORE_GLOBAL_LIBVIPS=1 npm install --arch=x64 --platform=linux sharp rm -rf node_modules/sharp
SHARP_IGNORE_GLOBAL_LIBVIPS=1 npm install --arch=x64 --platform=linux --libc=glibc sharp
``` ```
To get the best performance select the largest memory available. To get the best performance select the largest memory available.

File diff suppressed because one or more lines are too long

View File

@@ -35,6 +35,7 @@ const hasSharpPrebuild = [
]; ];
const { minimumLibvipsVersion, minimumLibvipsVersionLabelled } = libvips; const { minimumLibvipsVersion, minimumLibvipsVersionLabelled } = libvips;
const localLibvipsDir = process.env.npm_config_sharp_libvips_local_prebuilds || '';
const distHost = process.env.npm_config_sharp_libvips_binary_host || 'https://github.com/lovell/sharp-libvips/releases/download'; const distHost = process.env.npm_config_sharp_libvips_binary_host || 'https://github.com/lovell/sharp-libvips/releases/download';
const distBaseUrl = process.env.npm_config_sharp_dist_base_url || process.env.SHARP_DIST_BASE_URL || `${distHost}/v${minimumLibvipsVersionLabelled}/`; const distBaseUrl = process.env.npm_config_sharp_dist_base_url || process.env.SHARP_DIST_BASE_URL || `${distHost}/v${minimumLibvipsVersionLabelled}/`;
const installationForced = !!(process.env.npm_config_sharp_install_force || process.env.SHARP_INSTALL_FORCE); const installationForced = !!(process.env.npm_config_sharp_install_force || process.env.SHARP_INSTALL_FORCE);
@@ -42,7 +43,9 @@ const installationForced = !!(process.env.npm_config_sharp_install_force || proc
const fail = function (err) { const fail = function (err) {
libvips.log(err); libvips.log(err);
if (err.code === 'EACCES') { if (err.code === 'EACCES') {
libvips.log('Are you trying to install as a root or sudo user? Try again with the --unsafe-perm flag'); libvips.log('Are you trying to install as a root or sudo user?');
libvips.log('- For npm <= v6, try again with the "--unsafe-perm" flag');
libvips.log('- For npm >= v8, the user must own the directory "npm install" is run in');
} }
libvips.log('Please see https://sharp.pixelplumbing.com/install for required dependencies'); libvips.log('Please see https://sharp.pixelplumbing.com/install for required dependencies');
process.exit(1); process.exit(1);
@@ -156,6 +159,11 @@ try {
if (fs.existsSync(tarPathCache)) { if (fs.existsSync(tarPathCache)) {
libvips.log(`Using cached ${tarPathCache}`); libvips.log(`Using cached ${tarPathCache}`);
extractTarball(tarPathCache, platformAndArch); extractTarball(tarPathCache, platformAndArch);
} else if (localLibvipsDir) {
// If localLibvipsDir is given try to use binaries from local directory
const tarPathLocal = path.join(path.resolve(localLibvipsDir), `v${minimumLibvipsVersionLabelled}`, tarFilename);
libvips.log(`Using local libvips from ${tarPathLocal}`);
extractTarball(tarPathLocal, platformAndArch);
} else { } else {
const url = distBaseUrl + tarFilename; const url = distBaseUrl + tarFilename;
libvips.log(`Downloading ${url}`); libvips.log(`Downloading ${url}`);

View File

@@ -50,7 +50,7 @@ const blend = {
* `hard-light`, `soft-light`, `difference`, `exclusion`. * `hard-light`, `soft-light`, `difference`, `exclusion`.
* *
* More information about blend modes can be found at * More information about blend modes can be found at
* https://libvips.github.io/libvips/API/current/libvips-conversion.html#VipsBlendMode * https://www.libvips.org/API/current/libvips-conversion.html#VipsBlendMode
* and https://www.cairographics.org/operators/ * and https://www.cairographics.org/operators/
* *
* @since 0.22.0 * @since 0.22.0

View File

@@ -309,9 +309,9 @@ function _isStreamInput () {
* - `size`: Total size of image in bytes, for Stream and Buffer input only * - `size`: Total size of image in bytes, for Stream and Buffer input only
* - `width`: Number of pixels wide (EXIF orientation is not taken into consideration, see example below) * - `width`: Number of pixels wide (EXIF orientation is not taken into consideration, see example below)
* - `height`: Number of pixels high (EXIF orientation is not taken into consideration, see example below) * - `height`: Number of pixels high (EXIF orientation is not taken into consideration, see example below)
* - `space`: Name of colour space interpretation e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://libvips.github.io/libvips/API/current/VipsImage.html#VipsInterpretation) * - `space`: Name of colour space interpretation e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://www.libvips.org/API/current/VipsImage.html#VipsInterpretation)
* - `channels`: Number of bands e.g. `3` for sRGB, `4` for CMYK * - `channels`: Number of bands e.g. `3` for sRGB, `4` for CMYK
* - `depth`: Name of pixel depth format e.g. `uchar`, `char`, `ushort`, `float` [...](https://libvips.github.io/libvips/API/current/VipsImage.html#VipsBandFormat) * - `depth`: Name of pixel depth format e.g. `uchar`, `char`, `ushort`, `float` [...](https://www.libvips.org/API/current/VipsImage.html#VipsBandFormat)
* - `density`: Number of pixels per inch (DPI), if present * - `density`: Number of pixels per inch (DPI), if present
* - `chromaSubsampling`: String containing JPEG chroma subsampling, `4:2:0` or `4:4:4` for RGB, `4:2:0:4` or `4:4:4:4` for CMYK * - `chromaSubsampling`: String containing JPEG chroma subsampling, `4:2:0` or `4:4:4` for RGB, `4:2:0:4` or `4:4:4:4` for CMYK
* - `isProgressive`: Boolean indicating whether the image is interlaced using a progressive scan * - `isProgressive`: Boolean indicating whether the image is interlaced using a progressive scan

View File

@@ -65,7 +65,12 @@ const isRosetta = function () {
const globalLibvipsVersion = function () { const globalLibvipsVersion = function () {
if (process.platform !== 'win32') { if (process.platform !== 'win32') {
const globalLibvipsVersion = spawnSync(`PKG_CONFIG_PATH="${pkgConfigPath()}" pkg-config --modversion vips-cpp`, spawnSyncOptions).stdout; const globalLibvipsVersion = spawnSync('pkg-config --modversion vips-cpp', {
...spawnSyncOptions,
env: {
PKG_CONFIG_PATH: pkgConfigPath()
}
}).stdout;
/* istanbul ignore next */ /* istanbul ignore next */
return (globalLibvipsVersion || '').trim(); return (globalLibvipsVersion || '').trim();
} else { } else {
@@ -85,7 +90,10 @@ const removeVendoredLibvips = function () {
const pkgConfigPath = function () { const pkgConfigPath = function () {
if (process.platform !== 'win32') { if (process.platform !== 'win32') {
const brewPkgConfigPath = spawnSync('which brew >/dev/null 2>&1 && eval $(brew --env) && echo $PKG_CONFIG_LIBDIR', spawnSyncOptions).stdout || ''; const brewPkgConfigPath = spawnSync(
'which brew >/dev/null 2>&1 && brew environment --plain | grep PKG_CONFIG_LIBDIR | cut -d" " -f2',
spawnSyncOptions
).stdout || '';
return [ return [
brewPkgConfigPath.trim(), brewPkgConfigPath.trim(),
env.PKG_CONFIG_PATH, env.PKG_CONFIG_PATH,

View File

@@ -82,6 +82,8 @@ function toFile (fileOut, callback) {
* Write output to a Buffer. * Write output to a Buffer.
* JPEG, PNG, WebP, AVIF, TIFF, GIF and raw pixel data output are supported. * JPEG, PNG, WebP, AVIF, TIFF, GIF and raw pixel data output are supported.
* *
* Use {@link toFormat} or one of the format-specific functions such as {@link jpeg}, {@link png} etc. to set the output format.
*
* If no explicit format is set, the output format will match the input image, except SVG input which becomes PNG output. * If no explicit format is set, the output format will match the input image, except SVG input which becomes PNG output.
* *
* By default all metadata will be removed, which includes EXIF-based orientation. * By default all metadata will be removed, which includes EXIF-based orientation.
@@ -108,6 +110,7 @@ function toFile (fileOut, callback) {
* *
* @example * @example
* sharp(input) * sharp(input)
* .png()
* .toBuffer({ resolveWithObject: true }) * .toBuffer({ resolveWithObject: true })
* .then(({ data, info }) => { ... }) * .then(({ data, info }) => { ... })
* .catch(err => { ... }); * .catch(err => { ... });
@@ -516,7 +519,7 @@ function webp (options) {
* // Convert PNG to GIF * // Convert PNG to GIF
* await sharp(pngBuffer) * await sharp(pngBuffer)
* .gif() * .gif()
* .toBuffer()); * .toBuffer();
* *
* @example * @example
* // Convert animated WebP to animated GIF * // Convert animated WebP to animated GIF

View File

@@ -7,10 +7,12 @@ const env = process.env;
module.exports = function () { module.exports = function () {
const arch = env.npm_config_arch || process.arch; const arch = env.npm_config_arch || process.arch;
const platform = env.npm_config_platform || process.platform; const platform = env.npm_config_platform || process.platform;
/* istanbul ignore next */ const libc = process.env.npm_config_libc ||
const libc = (platform === 'linux' && detectLibc.isNonGlibcLinuxSync()) ? detectLibc.familySync() : ''; /* istanbul ignore next */
(detectLibc.isNonGlibcLinuxSync() ? detectLibc.familySync() : '');
const libcId = platform !== 'linux' || libc === detectLibc.GLIBC ? '' : libc;
const platformId = [`${platform}${libc}`]; const platformId = [`${platform}${libcId}`];
if (arch === 'arm') { if (arch === 'arm') {
const fallback = process.versions.electron ? '7' : '6'; const fallback = process.versions.electron ? '7' : '6';

View File

@@ -13,7 +13,7 @@ try {
} else { } else {
const [platform, arch] = platformAndArch.split('-'); const [platform, arch] = platformAndArch.split('-');
help.push( help.push(
'- Install with the --verbose flag and look for errors: "npm install --ignore-scripts=false --verbose sharp"', '- Install with verbose logging and look for errors: "npm install --ignore-scripts=false --foreground-scripts --verbose sharp"',
`- Install for the current ${platformAndArch} runtime: "npm install --platform=${platform} --arch=${arch} sharp"` `- Install for the current ${platformAndArch} runtime: "npm install --platform=${platform} --arch=${arch} sharp"`
); );
} }

View File

@@ -103,7 +103,11 @@ cache(true);
/** /**
* Gets or, when a concurrency is provided, sets * Gets or, when a concurrency is provided, sets
* the number of threads _libvips'_ should create to process each image. * the maximum number of threads _libvips_ should use to process _each image_.
* These are from a thread pool managed by glib,
* which helps avoid the overhead of creating new threads.
*
* This method always returns the current concurrency.
* *
* The default value is the number of CPU cores, * The default value is the number of CPU cores,
* except when using glibc-based Linux without jemalloc, * except when using glibc-based Linux without jemalloc,
@@ -111,10 +115,19 @@ cache(true);
* *
* A value of `0` will reset this to the number of CPU cores. * A value of `0` will reset this to the number of CPU cores.
* *
* The maximum number of images that can be processed in parallel * Some image format libraries spawn additional threads,
* is limited by libuv's `UV_THREADPOOL_SIZE` environment variable. * e.g. libaom manages its own 4 threads when encoding AVIF images,
* and these are independent of the value set here.
* *
* This method always returns the current concurrency. * The maximum number of images that sharp can process in parallel
* is controlled by libuv's `UV_THREADPOOL_SIZE` environment variable,
* which defaults to 4.
*
* https://nodejs.org/api/cli.html#uv_threadpool_sizesize
*
* For example, by default, a machine with 8 CPU cores will process
* 4 images in parallel and use up to 8 threads per image,
* so there will be up to 32 concurrent threads.
* *
* @example * @example
* const threads = sharp.concurrency(); // 4 * const threads = sharp.concurrency(); // 4

View File

@@ -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.30.4", "version": "0.30.5",
"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": [
@@ -82,7 +82,8 @@
"Joris Dugué <zaruike10@gmail.com>", "Joris Dugué <zaruike10@gmail.com>",
"Chris Banks <christopher.bradley.banks@gmail.com>", "Chris Banks <christopher.bradley.banks@gmail.com>",
"Ompal Singh <ompal.hitm09@gmail.com>", "Ompal Singh <ompal.hitm09@gmail.com>",
"Brodan <christopher.hranj@gmail.com" "Brodan <christopher.hranj@gmail.com",
"Ankur Parihar <ankur.github@gmail.com>"
], ],
"scripts": { "scripts": {
"install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node install/can-compile && node-gyp rebuild && node install/dll-copy)", "install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node install/can-compile && node-gyp rebuild && node install/dll-copy)",
@@ -129,8 +130,8 @@
"dependencies": { "dependencies": {
"color": "^4.2.3", "color": "^4.2.3",
"detect-libc": "^2.0.1", "detect-libc": "^2.0.1",
"node-addon-api": "^4.3.0", "node-addon-api": "^5.0.0",
"prebuild-install": "^7.0.1", "prebuild-install": "^7.1.0",
"semver": "^7.3.7", "semver": "^7.3.7",
"simple-get": "^4.0.1", "simple-get": "^4.0.1",
"tar-fs": "^2.1.1", "tar-fs": "^2.1.1",
@@ -144,7 +145,7 @@
"exif-reader": "^1.0.3", "exif-reader": "^1.0.3",
"icc": "^2.0.0", "icc": "^2.0.0",
"license-checker": "^25.0.1", "license-checker": "^25.0.1",
"mocha": "^9.2.2", "mocha": "^10.0.0",
"mock-fs": "^5.1.2", "mock-fs": "^5.1.2",
"nyc": "^15.1.0", "nyc": "^15.1.0",
"prebuild": "^11.0.3", "prebuild": "^11.0.3",

View File

@@ -95,16 +95,18 @@ class PipelineWorker : public Napi::AsyncWorker {
if (baton->rotateBeforePreExtract) { if (baton->rotateBeforePreExtract) {
if (rotation != VIPS_ANGLE_D0) { if (rotation != VIPS_ANGLE_D0) {
image = image.rot(rotation); image = image.rot(rotation);
if (flip) { }
image = image.flip(VIPS_DIRECTION_VERTICAL); if (flip) {
flip = FALSE; image = image.flip(VIPS_DIRECTION_VERTICAL);
} }
if (flop) { if (flop) {
image = image.flip(VIPS_DIRECTION_HORIZONTAL); image = image.flip(VIPS_DIRECTION_HORIZONTAL);
flop = FALSE; }
} if (rotation != VIPS_ANGLE_D0 || flip || flop) {
image = sharp::RemoveExifOrientation(image); image = sharp::RemoveExifOrientation(image);
} }
flop = FALSE;
flip = FALSE;
if (baton->rotationAngle != 0.0) { if (baton->rotationAngle != 0.0) {
MultiPageUnsupported(nPages, "Rotate"); MultiPageUnsupported(nPages, "Rotate");
std::vector<double> background; std::vector<double> background;

View File

@@ -168,14 +168,51 @@ describe('Partial image extraction', function () {
}); });
}); });
it('Rotate with EXIF mirroring then extract', function (done) { describe('Apply exif orientation and mirroring then extract', () => {
sharp(fixtures.inputJpgWithLandscapeExif7) [
.rotate() {
.extract({ left: 0, top: 208, width: 60, height: 40 }) name: 'EXIF-1',
.toBuffer(function (err, data) { image: fixtures.inputJpgWithLandscapeExif1
if (err) throw err; },
fixtures.assertSimilar(fixtures.expected('rotate-mirror-extract.jpg'), data, done); {
name: 'EXIF-2',
image: fixtures.inputJpgWithLandscapeExif2
},
{
name: 'EXIF-3',
image: fixtures.inputJpgWithLandscapeExif3
},
{
name: 'EXIF-4',
image: fixtures.inputJpgWithLandscapeExif4
},
{
name: 'EXIF-5',
image: fixtures.inputJpgWithLandscapeExif5
},
{
name: 'EXIF-6',
image: fixtures.inputJpgWithLandscapeExif6
},
{
name: 'EXIF-7',
image: fixtures.inputJpgWithLandscapeExif7
},
{
name: 'EXIF-8',
image: fixtures.inputJpgWithLandscapeExif8
}
].forEach(({ name, image }) => {
it(name, function (done) {
sharp(image)
.rotate()
.extract({ left: 0, top: 208, width: 60, height: 40 })
.toBuffer(function (err, data) {
if (err) throw err;
fixtures.assertSimilar(fixtures.expected('rotate-mirror-extract.jpg'), data, done);
});
}); });
});
}); });
describe('Invalid parameters', function () { describe('Invalid parameters', function () {

View File

@@ -61,4 +61,28 @@ describe('Platform-detection', function () {
delete process.env.npm_config_arch; delete process.env.npm_config_arch;
delete process.versions.electron; delete process.versions.electron;
}); });
it('Can override libc if platform is linux', function () {
process.env.npm_config_platform = 'linux';
process.env.npm_config_libc = 'test';
assert.strictEqual('linuxtest', platform().split('-')[0]);
delete process.env.npm_config_platform;
delete process.env.npm_config_libc;
});
it('Handles libc value "glibc" as default linux', function () {
process.env.npm_config_platform = 'linux';
process.env.npm_config_libc = 'glibc';
assert.strictEqual('linux', platform().split('-')[0]);
delete process.env.npm_config_platform;
delete process.env.npm_config_libc;
});
it('Discards libc value on non-linux platform', function () {
process.env.npm_config_platform = 'win32';
process.env.npm_config_libc = 'gnuwin32';
assert.strictEqual('win32', platform().split('-')[0]);
delete process.env.npm_config_platform;
delete process.env.npm_config_libc;
});
}); });