mirror of
https://github.com/lovell/sharp.git
synced 2026-02-05 22:26:20 +01:00
Compare commits
30 Commits
v0.33.3-rc
...
v0.33.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
19d0e272e6 | ||
|
|
16b764f1c1 | ||
|
|
1593ee3838 | ||
|
|
668b5ba8bc | ||
|
|
29336f4cc7 | ||
|
|
b5fddd7c5e | ||
|
|
da655a1859 | ||
|
|
93c615d39f | ||
|
|
f325dc3ec9 | ||
|
|
0fde71c783 | ||
|
|
9c8fbaa1cc | ||
|
|
a9e662e612 | ||
|
|
ba843002be | ||
|
|
7f3d452bc5 | ||
|
|
aa8bc19362 | ||
|
|
36e60bf040 | ||
|
|
a1309aa3b8 | ||
|
|
3e8a0fc522 | ||
|
|
397ee492d9 | ||
|
|
52b9dc0f63 | ||
|
|
a715c73fc2 | ||
|
|
579cf93030 | ||
|
|
f67228e5ea | ||
|
|
6257994746 | ||
|
|
7950fc0ea3 | ||
|
|
fc93ab3b82 | ||
|
|
0981b24f60 | ||
|
|
02fd565476 | ||
|
|
e55bb93b10 | ||
|
|
55466f122c |
16
.github/ISSUE_TEMPLATE/possible-bug.md
vendored
16
.github/ISSUE_TEMPLATE/possible-bug.md
vendored
@@ -32,6 +32,22 @@ If you are using another package which depends on a version of `sharp` that is n
|
|||||||
|
|
||||||
<!-- Please provide output of the above command here. -->
|
<!-- Please provide output of the above command here. -->
|
||||||
|
|
||||||
|
### Does this problem relate to file caching?
|
||||||
|
|
||||||
|
The default behaviour of libvips is to cache input files, which can lead to `EBUSY` or `EPERM` errors on Windows.
|
||||||
|
Use [`sharp.cache(false)`](https://sharp.pixelplumbing.com/api-utility#cache) to switch this feature off.
|
||||||
|
|
||||||
|
- [ ] Adding `sharp.cache(false)` does not fix this problem.
|
||||||
|
|
||||||
|
### Does this problem relate to images appearing to have been rotated by 90 degrees?
|
||||||
|
|
||||||
|
Images that contain EXIF Orientation metadata are not auto-oriented. By default, EXIF metadata is removed.
|
||||||
|
|
||||||
|
- To auto-orient pixel values use the parameter-less [`rotate()`](https://sharp.pixelplumbing.com/api-operation#rotate) operation.
|
||||||
|
- To retain EXIF Orientation use [`keepExif()`](https://sharp.pixelplumbing.com/api-output#keepexif).
|
||||||
|
|
||||||
|
- [ ] Using `rotate()` or `keepExif()` does not fix this problem.
|
||||||
|
|
||||||
### What are the steps to reproduce?
|
### What are the steps to reproduce?
|
||||||
|
|
||||||
<!-- Please enter steps to reproduce here. -->
|
<!-- Please enter steps to reproduce here. -->
|
||||||
|
|||||||
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@@ -131,12 +131,14 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- platform: linux-arm
|
- platform: linux-arm
|
||||||
|
distro: buster
|
||||||
run_on_arch: armv6
|
run_on_arch: armv6
|
||||||
nodejs_arch: armv6l
|
nodejs_arch: armv6l
|
||||||
nodejs_hostname: unofficial-builds.nodejs.org
|
nodejs_hostname: unofficial-builds.nodejs.org
|
||||||
nodejs_version: "18.17.0"
|
nodejs_version: "18.17.0"
|
||||||
nodejs_version_major: 18
|
nodejs_version_major: 18
|
||||||
- platform: linux-s390x
|
- platform: linux-s390x
|
||||||
|
distro: bullseye
|
||||||
run_on_arch: s390x
|
run_on_arch: s390x
|
||||||
nodejs_arch: s390x
|
nodejs_arch: s390x
|
||||||
nodejs_hostname: nodejs.org
|
nodejs_hostname: nodejs.org
|
||||||
@@ -147,7 +149,7 @@ jobs:
|
|||||||
- uses: uraimo/run-on-arch-action@v2
|
- uses: uraimo/run-on-arch-action@v2
|
||||||
with:
|
with:
|
||||||
arch: ${{ matrix.run_on_arch }}
|
arch: ${{ matrix.run_on_arch }}
|
||||||
distro: buster
|
distro: ${{ matrix.distro }}
|
||||||
env: |
|
env: |
|
||||||
prebuild_upload: "${{ startsWith(github.ref, 'refs/tags/') && secrets.GITHUB_TOKEN || '' }}"
|
prebuild_upload: "${{ startsWith(github.ref, 'refs/tags/') && secrets.GITHUB_TOKEN || '' }}"
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
4
.github/workflows/npm.yml
vendored
4
.github/workflows/npm.yml
vendored
@@ -110,7 +110,7 @@ jobs:
|
|||||||
script: |
|
script: |
|
||||||
core.setOutput('semver', context.ref.replace('refs/tags/v',''))
|
core.setOutput('semver', context.ref.replace('refs/tags/v',''))
|
||||||
- name: Create package.json
|
- name: Create package.json
|
||||||
uses: DamianReeves/write-file-action@v1.2
|
uses: DamianReeves/write-file-action@v1.3
|
||||||
with:
|
with:
|
||||||
path: package.json
|
path: package.json
|
||||||
contents: |
|
contents: |
|
||||||
@@ -121,7 +121,7 @@ jobs:
|
|||||||
"type": "module"
|
"type": "module"
|
||||||
}
|
}
|
||||||
- name: Create release.mjs
|
- name: Create release.mjs
|
||||||
uses: DamianReeves/write-file-action@v1.2
|
uses: DamianReeves/write-file-action@v1.3
|
||||||
with:
|
with:
|
||||||
path: release.mjs
|
path: release.mjs
|
||||||
contents: |
|
contents: |
|
||||||
|
|||||||
@@ -66,8 +66,6 @@ The input image will be converted to the provided colourspace at the start of th
|
|||||||
All operations will use this colourspace before converting to the output colourspace,
|
All operations will use this colourspace before converting to the output colourspace,
|
||||||
as defined by [toColourspace](#tocolourspace).
|
as defined by [toColourspace](#tocolourspace).
|
||||||
|
|
||||||
This feature is experimental and has not yet been fully-tested with all operations.
|
|
||||||
|
|
||||||
|
|
||||||
**Throws**:
|
**Throws**:
|
||||||
|
|
||||||
|
|||||||
@@ -21,18 +21,22 @@ When using a **fit** of `cover` or `contain`, the default **position** is `centr
|
|||||||
|
|
||||||
Some of these values are based on the [object-position](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position) CSS property.
|
Some of these values are based on the [object-position](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position) CSS property.
|
||||||
|
|
||||||
The experimental strategy-based approach resizes so one dimension is at its target length
|
The strategy-based approach initially resizes so one dimension is at its target length
|
||||||
then repeatedly ranks edge regions, discarding the edge with the lowest score based on the selected strategy.
|
then repeatedly ranks edge regions, discarding the edge with the lowest score based on the selected strategy.
|
||||||
- `entropy`: focus on the region with the highest [Shannon entropy](https://en.wikipedia.org/wiki/Entropy_%28information_theory%29).
|
- `entropy`: focus on the region with the highest [Shannon entropy](https://en.wikipedia.org/wiki/Entropy_%28information_theory%29).
|
||||||
- `attention`: focus on the region with the highest luminance frequency, colour saturation and presence of skin tones.
|
- `attention`: focus on the region with the highest luminance frequency, colour saturation and presence of skin tones.
|
||||||
|
|
||||||
Possible interpolation kernels are:
|
Possible downsizing kernels are:
|
||||||
- `nearest`: Use [nearest neighbour interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation).
|
- `nearest`: Use [nearest neighbour interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation).
|
||||||
|
- `linear`: Use a [triangle filter](https://en.wikipedia.org/wiki/Triangular_function).
|
||||||
- `cubic`: Use a [Catmull-Rom spline](https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline).
|
- `cubic`: Use a [Catmull-Rom spline](https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline).
|
||||||
- `mitchell`: Use a [Mitchell-Netravali spline](https://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf).
|
- `mitchell`: Use a [Mitchell-Netravali spline](https://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf).
|
||||||
- `lanczos2`: Use a [Lanczos kernel](https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel) with `a=2`.
|
- `lanczos2`: Use a [Lanczos kernel](https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel) with `a=2`.
|
||||||
- `lanczos3`: Use a Lanczos kernel with `a=3` (the default).
|
- `lanczos3`: Use a Lanczos kernel with `a=3` (the default).
|
||||||
|
|
||||||
|
When upsampling, these kernels map to `nearest`, `linear` and `cubic` interpolators.
|
||||||
|
Downsampling kernels without a matching upsampling interpolator map to `cubic`.
|
||||||
|
|
||||||
Only one resize can occur per pipeline.
|
Only one resize can occur per pipeline.
|
||||||
Previous calls to `resize` in the same pipeline will be ignored.
|
Previous calls to `resize` in the same pipeline will be ignored.
|
||||||
|
|
||||||
@@ -52,7 +56,7 @@ Previous calls to `resize` in the same pipeline will be ignored.
|
|||||||
| [options.fit] | <code>String</code> | <code>'cover'</code> | How the image should be resized/cropped to fit the target dimension(s), one of `cover`, `contain`, `fill`, `inside` or `outside`. |
|
| [options.fit] | <code>String</code> | <code>'cover'</code> | How the image should be resized/cropped to fit the target dimension(s), one of `cover`, `contain`, `fill`, `inside` or `outside`. |
|
||||||
| [options.position] | <code>String</code> | <code>'centre'</code> | A position, gravity or strategy to use when `fit` is `cover` or `contain`. |
|
| [options.position] | <code>String</code> | <code>'centre'</code> | A position, gravity or strategy to use when `fit` is `cover` or `contain`. |
|
||||||
| [options.background] | <code>String</code> \| <code>Object</code> | <code>{r: 0, g: 0, b: 0, alpha: 1}</code> | background colour when `fit` is `contain`, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to black without transparency. |
|
| [options.background] | <code>String</code> \| <code>Object</code> | <code>{r: 0, g: 0, b: 0, alpha: 1}</code> | background colour when `fit` is `contain`, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to black without transparency. |
|
||||||
| [options.kernel] | <code>String</code> | <code>'lanczos3'</code> | The kernel to use for image reduction. Use the `fastShrinkOnLoad` option to control kernel vs shrink-on-load. |
|
| [options.kernel] | <code>String</code> | <code>'lanczos3'</code> | The kernel to use for image reduction and the inferred interpolator to use for upsampling. Use the `fastShrinkOnLoad` option to control kernel vs shrink-on-load. |
|
||||||
| [options.withoutEnlargement] | <code>Boolean</code> | <code>false</code> | Do not scale up if the width *or* height are already less than the target dimensions, equivalent to GraphicsMagick's `>` geometry option. This may result in output dimensions smaller than the target dimensions. |
|
| [options.withoutEnlargement] | <code>Boolean</code> | <code>false</code> | Do not scale up if the width *or* height are already less than the target dimensions, equivalent to GraphicsMagick's `>` geometry option. This may result in output dimensions smaller than the target dimensions. |
|
||||||
| [options.withoutReduction] | <code>Boolean</code> | <code>false</code> | Do not scale down if the width *or* height are already greater than the target dimensions, equivalent to GraphicsMagick's `<` geometry option. This may still result in a crop to reach the target dimensions. |
|
| [options.withoutReduction] | <code>Boolean</code> | <code>false</code> | Do not scale down if the width *or* height are already greater than the target dimensions, equivalent to GraphicsMagick's `<` geometry option. This may still result in a crop to reach the target dimensions. |
|
||||||
| [options.fastShrinkOnLoad] | <code>Boolean</code> | <code>true</code> | Take greater advantage of the JPEG and WebP shrink-on-load feature, which can lead to a slight moiré pattern or round-down of an auto-scaled dimension. |
|
| [options.fastShrinkOnLoad] | <code>Boolean</code> | <code>true</code> | Take greater advantage of the JPEG and WebP shrink-on-load feature, which can lead to a slight moiré pattern or round-down of an auto-scaled dimension. |
|
||||||
|
|||||||
@@ -4,7 +4,37 @@
|
|||||||
|
|
||||||
Requires libvips v8.15.2
|
Requires libvips v8.15.2
|
||||||
|
|
||||||
### v0.33.3 - TBD
|
### v0.33.4 - 16th May 2024
|
||||||
|
|
||||||
|
* Remove experimental status from `pipelineColourspace`.
|
||||||
|
|
||||||
|
* Reduce default concurrency when musl thread over-subscription detected.
|
||||||
|
|
||||||
|
* TypeScript: add missing definitions for `OverlayOptions`.
|
||||||
|
[#4048](https://github.com/lovell/sharp/pull/4048)
|
||||||
|
[@ike-gg](https://github.com/ike-gg)
|
||||||
|
|
||||||
|
* Install: add advanced option to force use of a globally-installed libvips.
|
||||||
|
[#4060](https://github.com/lovell/sharp/issues/4060)
|
||||||
|
|
||||||
|
* Expose `bilinear` resizing kernel (and interpolator).
|
||||||
|
[#4061](https://github.com/lovell/sharp/issues/4061)
|
||||||
|
|
||||||
|
* Ensure `extend` operation stays sequential for multi-page TIFF (regression in 0.32.0).
|
||||||
|
[#4069](https://github.com/lovell/sharp/issues/4069)
|
||||||
|
|
||||||
|
* Tighten validation of constructor `text` integer properties.
|
||||||
|
[#4071](https://github.com/lovell/sharp/issues/4071)
|
||||||
|
|
||||||
|
* Simplify internal StaySequential logic.
|
||||||
|
[#4074](https://github.com/lovell/sharp/pull/4074)
|
||||||
|
[@kleisauke](https://github.com/kleisauke)
|
||||||
|
|
||||||
|
* Ensure negate operation occurs after profile conversion.
|
||||||
|
[#4096](https://github.com/lovell/sharp/pull/4096)
|
||||||
|
[@adriaanmeuris](https://github.com/adriaanmeuris)
|
||||||
|
|
||||||
|
### v0.33.3 - 23rd March 2024
|
||||||
|
|
||||||
* Upgrade to libvips v8.15.2 for upstream bug fixes.
|
* Upgrade to libvips v8.15.2 for upstream bug fixes.
|
||||||
|
|
||||||
|
|||||||
@@ -290,3 +290,6 @@ GitHub: https://github.com/yolopunk
|
|||||||
|
|
||||||
Name: Mert Alev
|
Name: Mert Alev
|
||||||
GitHub: https://github.com/mertalev
|
GitHub: https://github.com/mertalev
|
||||||
|
|
||||||
|
Name: Adriaan Meuris
|
||||||
|
GitHub: https://github.com/adriaanmeuris
|
||||||
|
|||||||
@@ -7,15 +7,13 @@
|
|||||||
<meta name="description" content="Resize large images in common formats to smaller, web-friendly JPEG, PNG, WebP, GIF and AVIF images of varying dimensions">
|
<meta name="description" content="Resize large images in common formats to smaller, web-friendly JPEG, PNG, WebP, GIF and AVIF images of varying dimensions">
|
||||||
<meta property="og:title" content="sharp - High performance Node.js image processing">
|
<meta property="og:title" content="sharp - High performance Node.js image processing">
|
||||||
<meta property="og:image" content="https://cdn.jsdelivr.net/gh/lovell/sharp@main/docs/image/sharp-logo-600.png">
|
<meta property="og:image" content="https://cdn.jsdelivr.net/gh/lovell/sharp@main/docs/image/sharp-logo-600.png">
|
||||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; object-src 'none'; style-src 'unsafe-inline';
|
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; connect-src 'self'; object-src 'none';
|
||||||
img-src 'unsafe-inline' data: https://cdn.jsdelivr.net/gh/lovell/ https://www.google-analytics.com;
|
style-src 'unsafe-inline';
|
||||||
connect-src 'self' https://www.google-analytics.com;
|
img-src 'unsafe-inline' data: https://cdn.jsdelivr.net/gh/lovell/;
|
||||||
script-src 'self' 'unsafe-inline' 'unsafe-eval'
|
script-src 'self' 'unsafe-inline' 'unsafe-eval' https://static.cloudflareinsights.com/beacon.min.js;">
|
||||||
https://www.google-analytics.com/analytics.js;">
|
|
||||||
<link rel="icon" type="image/svg+xml" href="https://cdn.jsdelivr.net/gh/lovell/sharp@main/docs/image/sharp-logo.svg">
|
<link rel="icon" type="image/svg+xml" href="https://cdn.jsdelivr.net/gh/lovell/sharp@main/docs/image/sharp-logo.svg">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="https://cdn.jsdelivr.net/gh/lovell/sharp@main/docs/image/sharp-logo-32.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="https://cdn.jsdelivr.net/gh/lovell/sharp@main/docs/image/sharp-logo-32.png">
|
||||||
<link rel="author" href="/humans.txt" type="text/plain">
|
<link rel="author" href="/humans.txt" type="text/plain">
|
||||||
<link rel="dns-prefetch" href="https://www.google-analytics.com">
|
|
||||||
<script type="application/ld+json">
|
<script type="application/ld+json">
|
||||||
{
|
{
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
@@ -67,7 +65,6 @@
|
|||||||
<div id="docute"></div>
|
<div id="docute"></div>
|
||||||
<script src="docute.min.js"></script>
|
<script src="docute.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
/* docute-google-analytics@1/dist/index.min.js */ !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e=e||self).docuteGoogleAnalytics=n()}(this,function(){"use strict";function e(e){var n;window.ga||((n=document.createElement("script")).async=!0,n.src="https://www.google-analytics.com/analytics.js",document.body.appendChild(n),window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)},ga.l=Number(new Date),ga("create",e,"auto"))}function n(n,t){e(t),ga("set","page",n),ga("send","pageview")}return function(e){return{name:"@google-analytics",extend:function(t){!function(e,t){"function"==typeof e?e(function(e){n(e,t)}):e.afterEach(function(e){n(e.fullPath,t)})}(t.router,e)}}}});
|
|
||||||
const docuteApiTitlePlugin = {
|
const docuteApiTitlePlugin = {
|
||||||
name: 'apiTitle',
|
name: 'apiTitle',
|
||||||
extend(api) {
|
extend(api) {
|
||||||
@@ -126,7 +123,6 @@
|
|||||||
detectSystemDarkTheme: true,
|
detectSystemDarkTheme: true,
|
||||||
footer: '<a href="https://pixelplumbing.com/" target="_blank">pixelplumbing.com<a>',
|
footer: '<a href="https://pixelplumbing.com/" target="_blank">pixelplumbing.com<a>',
|
||||||
plugins: [
|
plugins: [
|
||||||
docuteGoogleAnalytics('UA-13034748-12'),
|
|
||||||
docuteApiTitlePlugin,
|
docuteApiTitlePlugin,
|
||||||
docuteApiSearchPlugin
|
docuteApiSearchPlugin
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ Ready-compiled sharp and libvips binaries are provided for use on the most commo
|
|||||||
* macOS ARM64
|
* macOS ARM64
|
||||||
* Linux ARM (glibc >= 2.28)
|
* Linux ARM (glibc >= 2.28)
|
||||||
* Linux ARM64 (glibc >= 2.26, musl >= 1.2.2)
|
* Linux ARM64 (glibc >= 2.26, musl >= 1.2.2)
|
||||||
* Linux s390x (glibc >= 2.28)
|
* Linux s390x (glibc >= 2.31)
|
||||||
* Linux x64 (glibc >= 2.26, musl >= 1.2.2, CPU with SSE4.2)
|
* Linux x64 (glibc >= 2.26, musl >= 1.2.2, CPU with SSE4.2)
|
||||||
* Windows x64
|
* Windows x64
|
||||||
* Windows x86
|
* Windows x86
|
||||||
@@ -67,15 +67,17 @@ within the same installation tree and/or using the same lockfile.
|
|||||||
|
|
||||||
Provides limited support via `--os`, `--cpu` and `--libc` flags.
|
Provides limited support via `--os`, `--cpu` and `--libc` flags.
|
||||||
|
|
||||||
Example to support both Intel and ARM CPUs on macOS:
|
To support macOS with Intel x64 and ARM64 CPUs:
|
||||||
```sh
|
```sh
|
||||||
npm install --cpu=x64 --os=darwin sharp
|
npm install --cpu=x64 --os=darwin sharp
|
||||||
npm install --cpu=arm64 --os=darwin sharp
|
npm install --cpu=arm64 --os=darwin sharp
|
||||||
```
|
```
|
||||||
|
|
||||||
Example to support both glibc and musl-based Linux:
|
When the cross-target is Linux, the C standard library must be specified.
|
||||||
|
|
||||||
|
To support glibc (e.g. Debian) and musl (e.g. Alpine) Linux with Intel x64 CPUs:
|
||||||
```sh
|
```sh
|
||||||
npm install --cpu=x64 --os=linux sharp
|
npm install --cpu=x64 --os=linux --libc=glibc sharp
|
||||||
npm install --cpu=x64 --os=linux --libc=musl sharp
|
npm install --cpu=x64 --os=linux --libc=musl sharp
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -103,9 +105,14 @@ and on macOS when running Node.js under Rosetta.
|
|||||||
|
|
||||||
This module will be compiled from source at `npm install` time when:
|
This module will be compiled from source at `npm install` time when:
|
||||||
|
|
||||||
* a globally-installed libvips is detected (set the `SHARP_IGNORE_GLOBAL_LIBVIPS` environment variable to skip this), or
|
* a globally-installed libvips is detected, or
|
||||||
* when the `npm install --build-from-source` flag is used.
|
* when the `npm install --build-from-source` flag is used.
|
||||||
|
|
||||||
|
The logic to detect a globally-installed libvips can be skipped by setting the
|
||||||
|
`SHARP_IGNORE_GLOBAL_LIBVIPS` (never try to use it) or
|
||||||
|
`SHARP_FORCE_GLOBAL_LIBVIPS` (always try to use it, even when missing or outdated)
|
||||||
|
environment variables.
|
||||||
|
|
||||||
Building from source requires:
|
Building from source requires:
|
||||||
|
|
||||||
* C++11 compiler
|
* C++11 compiler
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -30,6 +30,7 @@ module.exports = [
|
|||||||
'current',
|
'current',
|
||||||
'date',
|
'date',
|
||||||
'default',
|
'default',
|
||||||
|
'deprecated',
|
||||||
'does',
|
'does',
|
||||||
'each',
|
'each',
|
||||||
'either',
|
'either',
|
||||||
@@ -46,6 +47,7 @@ module.exports = [
|
|||||||
'given',
|
'given',
|
||||||
'has',
|
'has',
|
||||||
'have',
|
'have',
|
||||||
|
'helps',
|
||||||
'how',
|
'how',
|
||||||
'image',
|
'image',
|
||||||
'implies',
|
'implies',
|
||||||
@@ -58,6 +60,7 @@ module.exports = [
|
|||||||
'lots',
|
'lots',
|
||||||
'make',
|
'make',
|
||||||
'may',
|
'may',
|
||||||
|
'meaning',
|
||||||
'more',
|
'more',
|
||||||
'most',
|
'most',
|
||||||
'much',
|
'much',
|
||||||
@@ -79,6 +82,7 @@ module.exports = [
|
|||||||
'pre',
|
'pre',
|
||||||
'previously',
|
'previously',
|
||||||
'produce',
|
'produce',
|
||||||
|
'proper',
|
||||||
'provide',
|
'provide',
|
||||||
'provided',
|
'provided',
|
||||||
'ready',
|
'ready',
|
||||||
@@ -116,6 +120,7 @@ module.exports = [
|
|||||||
'unless',
|
'unless',
|
||||||
'unmaintained',
|
'unmaintained',
|
||||||
'unsuitable',
|
'unsuitable',
|
||||||
|
'unsupported',
|
||||||
'until',
|
'until',
|
||||||
'use',
|
'use',
|
||||||
'used',
|
'used',
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ try {
|
|||||||
log(msg);
|
log(msg);
|
||||||
log('Attempting to build from source via node-gyp');
|
log('Attempting to build from source via node-gyp');
|
||||||
try {
|
try {
|
||||||
require('node-addon-api');
|
const addonApi = require('node-addon-api');
|
||||||
log('Found node-addon-api');
|
log(`Found node-addon-api ${addonApi.version || ''}`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log('Please add node-addon-api to your dependencies');
|
log('Please add node-addon-api to your dependencies');
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -71,8 +71,6 @@ function grayscale (grayscale) {
|
|||||||
* All operations will use this colourspace before converting to the output colourspace,
|
* All operations will use this colourspace before converting to the output colourspace,
|
||||||
* as defined by {@link #tocolourspace|toColourspace}.
|
* as defined by {@link #tocolourspace|toColourspace}.
|
||||||
*
|
*
|
||||||
* This feature is experimental and has not yet been fully-tested with all operations.
|
|
||||||
*
|
|
||||||
* @since 0.29.0
|
* @since 0.29.0
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
|
|||||||
8
lib/index.d.ts
vendored
8
lib/index.d.ts
vendored
@@ -1479,6 +1479,14 @@ declare namespace sharp {
|
|||||||
tile?: boolean | undefined;
|
tile?: boolean | undefined;
|
||||||
/** Set to true to avoid premultipling the image below. Equivalent to the --premultiplied vips option. */
|
/** Set to true to avoid premultipling the image below. Equivalent to the --premultiplied vips option. */
|
||||||
premultiplied?: boolean | undefined;
|
premultiplied?: boolean | undefined;
|
||||||
|
/** number representing the DPI for vector overlay image. (optional, default 72)*/
|
||||||
|
density?: number | undefined;
|
||||||
|
/** Set to true to read all frames/pages of an animated image. (optional, default false) */
|
||||||
|
animated?: boolean | undefined;
|
||||||
|
/** see sharp() constructor, (optional, default 'warning') */
|
||||||
|
failOn?: FailOnOptions | undefined;
|
||||||
|
/** see sharp() constructor, (optional, default 268402689) */
|
||||||
|
limitInputPixels?: number | boolean | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TileOptions {
|
interface TileOptions {
|
||||||
|
|||||||
16
lib/input.js
16
lib/input.js
@@ -296,17 +296,17 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is.defined(inputOptions.text.width)) {
|
if (is.defined(inputOptions.text.width)) {
|
||||||
if (is.number(inputOptions.text.width)) {
|
if (is.integer(inputOptions.text.width) && inputOptions.text.width > 0) {
|
||||||
inputDescriptor.textWidth = inputOptions.text.width;
|
inputDescriptor.textWidth = inputOptions.text.width;
|
||||||
} else {
|
} else {
|
||||||
throw is.invalidParameterError('text.textWidth', 'number', inputOptions.text.width);
|
throw is.invalidParameterError('text.width', 'positive integer', inputOptions.text.width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is.defined(inputOptions.text.height)) {
|
if (is.defined(inputOptions.text.height)) {
|
||||||
if (is.number(inputOptions.text.height)) {
|
if (is.integer(inputOptions.text.height) && inputOptions.text.height > 0) {
|
||||||
inputDescriptor.textHeight = inputOptions.text.height;
|
inputDescriptor.textHeight = inputOptions.text.height;
|
||||||
} else {
|
} else {
|
||||||
throw is.invalidParameterError('text.height', 'number', inputOptions.text.height);
|
throw is.invalidParameterError('text.height', 'positive integer', inputOptions.text.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is.defined(inputOptions.text.align)) {
|
if (is.defined(inputOptions.text.align)) {
|
||||||
@@ -324,10 +324,10 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is.defined(inputOptions.text.dpi)) {
|
if (is.defined(inputOptions.text.dpi)) {
|
||||||
if (is.number(inputOptions.text.dpi) && is.inRange(inputOptions.text.dpi, 1, 100000)) {
|
if (is.integer(inputOptions.text.dpi) && is.inRange(inputOptions.text.dpi, 1, 1000000)) {
|
||||||
inputDescriptor.textDpi = inputOptions.text.dpi;
|
inputDescriptor.textDpi = inputOptions.text.dpi;
|
||||||
} else {
|
} else {
|
||||||
throw is.invalidParameterError('text.dpi', 'number between 1 and 100000', inputOptions.text.dpi);
|
throw is.invalidParameterError('text.dpi', 'integer between 1 and 1000000', inputOptions.text.dpi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is.defined(inputOptions.text.rgba)) {
|
if (is.defined(inputOptions.text.rgba)) {
|
||||||
@@ -338,10 +338,10 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is.defined(inputOptions.text.spacing)) {
|
if (is.defined(inputOptions.text.spacing)) {
|
||||||
if (is.number(inputOptions.text.spacing)) {
|
if (is.integer(inputOptions.text.spacing) && is.inRange(inputOptions.text.spacing, -1000000, 1000000)) {
|
||||||
inputDescriptor.textSpacing = inputOptions.text.spacing;
|
inputDescriptor.textSpacing = inputOptions.text.spacing;
|
||||||
} else {
|
} else {
|
||||||
throw is.invalidParameterError('text.spacing', 'number', inputOptions.text.spacing);
|
throw is.invalidParameterError('text.spacing', 'integer between -1000000 and 1000000', inputOptions.text.spacing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is.defined(inputOptions.text.wrap)) {
|
if (is.defined(inputOptions.text.wrap)) {
|
||||||
|
|||||||
@@ -162,15 +162,21 @@ const pkgConfigPath = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const skipSearch = (status, reason) => {
|
||||||
|
log(`Detected ${reason}, skipping search for globally-installed libvips`);
|
||||||
|
return status;
|
||||||
|
};
|
||||||
|
|
||||||
const useGlobalLibvips = () => {
|
const useGlobalLibvips = () => {
|
||||||
if (Boolean(process.env.SHARP_IGNORE_GLOBAL_LIBVIPS) === true) {
|
if (Boolean(process.env.SHARP_IGNORE_GLOBAL_LIBVIPS) === true) {
|
||||||
log('Detected SHARP_IGNORE_GLOBAL_LIBVIPS, skipping search for globally-installed libvips');
|
return skipSearch(false, 'SHARP_IGNORE_GLOBAL_LIBVIPS');
|
||||||
return false;
|
}
|
||||||
|
if (Boolean(process.env.SHARP_FORCE_GLOBAL_LIBVIPS) === true) {
|
||||||
|
return skipSearch(true, 'SHARP_FORCE_GLOBAL_LIBVIPS');
|
||||||
}
|
}
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
if (isRosetta()) {
|
if (isRosetta()) {
|
||||||
log('Detected Rosetta, skipping search for globally-installed libvips');
|
return skipSearch(false, 'Rosetta');
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
const globalVipsVersion = globalLibvipsVersion();
|
const globalVipsVersion = globalLibvipsVersion();
|
||||||
return !!globalVipsVersion && /* istanbul ignore next */
|
return !!globalVipsVersion && /* istanbul ignore next */
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ const strategy = {
|
|||||||
*/
|
*/
|
||||||
const kernel = {
|
const kernel = {
|
||||||
nearest: 'nearest',
|
nearest: 'nearest',
|
||||||
|
linear: 'linear',
|
||||||
cubic: 'cubic',
|
cubic: 'cubic',
|
||||||
mitchell: 'mitchell',
|
mitchell: 'mitchell',
|
||||||
lanczos2: 'lanczos2',
|
lanczos2: 'lanczos2',
|
||||||
@@ -135,18 +136,22 @@ function isResizeExpected (options) {
|
|||||||
*
|
*
|
||||||
* Some of these values are based on the [object-position](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position) CSS property.
|
* Some of these values are based on the [object-position](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position) CSS property.
|
||||||
*
|
*
|
||||||
* The experimental strategy-based approach resizes so one dimension is at its target length
|
* The strategy-based approach initially resizes so one dimension is at its target length
|
||||||
* then repeatedly ranks edge regions, discarding the edge with the lowest score based on the selected strategy.
|
* then repeatedly ranks edge regions, discarding the edge with the lowest score based on the selected strategy.
|
||||||
* - `entropy`: focus on the region with the highest [Shannon entropy](https://en.wikipedia.org/wiki/Entropy_%28information_theory%29).
|
* - `entropy`: focus on the region with the highest [Shannon entropy](https://en.wikipedia.org/wiki/Entropy_%28information_theory%29).
|
||||||
* - `attention`: focus on the region with the highest luminance frequency, colour saturation and presence of skin tones.
|
* - `attention`: focus on the region with the highest luminance frequency, colour saturation and presence of skin tones.
|
||||||
*
|
*
|
||||||
* Possible interpolation kernels are:
|
* Possible downsizing kernels are:
|
||||||
* - `nearest`: Use [nearest neighbour interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation).
|
* - `nearest`: Use [nearest neighbour interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation).
|
||||||
|
* - `linear`: Use a [triangle filter](https://en.wikipedia.org/wiki/Triangular_function).
|
||||||
* - `cubic`: Use a [Catmull-Rom spline](https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline).
|
* - `cubic`: Use a [Catmull-Rom spline](https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline).
|
||||||
* - `mitchell`: Use a [Mitchell-Netravali spline](https://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf).
|
* - `mitchell`: Use a [Mitchell-Netravali spline](https://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf).
|
||||||
* - `lanczos2`: Use a [Lanczos kernel](https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel) with `a=2`.
|
* - `lanczos2`: Use a [Lanczos kernel](https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel) with `a=2`.
|
||||||
* - `lanczos3`: Use a Lanczos kernel with `a=3` (the default).
|
* - `lanczos3`: Use a Lanczos kernel with `a=3` (the default).
|
||||||
*
|
*
|
||||||
|
* When upsampling, these kernels map to `nearest`, `linear` and `cubic` interpolators.
|
||||||
|
* Downsampling kernels without a matching upsampling interpolator map to `cubic`.
|
||||||
|
*
|
||||||
* Only one resize can occur per pipeline.
|
* Only one resize can occur per pipeline.
|
||||||
* Previous calls to `resize` in the same pipeline will be ignored.
|
* Previous calls to `resize` in the same pipeline will be ignored.
|
||||||
*
|
*
|
||||||
@@ -239,7 +244,7 @@ function isResizeExpected (options) {
|
|||||||
* @param {String} [options.fit='cover'] - How the image should be resized/cropped to fit the target dimension(s), one of `cover`, `contain`, `fill`, `inside` or `outside`.
|
* @param {String} [options.fit='cover'] - How the image should be resized/cropped to fit the target dimension(s), one of `cover`, `contain`, `fill`, `inside` or `outside`.
|
||||||
* @param {String} [options.position='centre'] - A position, gravity or strategy to use when `fit` is `cover` or `contain`.
|
* @param {String} [options.position='centre'] - A position, gravity or strategy to use when `fit` is `cover` or `contain`.
|
||||||
* @param {String|Object} [options.background={r: 0, g: 0, b: 0, alpha: 1}] - background colour when `fit` is `contain`, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to black without transparency.
|
* @param {String|Object} [options.background={r: 0, g: 0, b: 0, alpha: 1}] - background colour when `fit` is `contain`, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to black without transparency.
|
||||||
* @param {String} [options.kernel='lanczos3'] - The kernel to use for image reduction. Use the `fastShrinkOnLoad` option to control kernel vs shrink-on-load.
|
* @param {String} [options.kernel='lanczos3'] - The kernel to use for image reduction and the inferred interpolator to use for upsampling. Use the `fastShrinkOnLoad` option to control kernel vs shrink-on-load.
|
||||||
* @param {Boolean} [options.withoutEnlargement=false] - Do not scale up if the width *or* height are already less than the target dimensions, equivalent to GraphicsMagick's `>` geometry option. This may result in output dimensions smaller than the target dimensions.
|
* @param {Boolean} [options.withoutEnlargement=false] - Do not scale up if the width *or* height are already less than the target dimensions, equivalent to GraphicsMagick's `>` geometry option. This may result in output dimensions smaller than the target dimensions.
|
||||||
* @param {Boolean} [options.withoutReduction=false] - Do not scale down if the width *or* height are already greater than the target dimensions, equivalent to GraphicsMagick's `<` geometry option. This may still result in a crop to reach the target dimensions.
|
* @param {Boolean} [options.withoutReduction=false] - Do not scale down if the width *or* height are already greater than the target dimensions, equivalent to GraphicsMagick's `<` geometry option. This may still result in a crop to reach the target dimensions.
|
||||||
* @param {Boolean} [options.fastShrinkOnLoad=true] - Take greater advantage of the JPEG and WebP shrink-on-load feature, which can lead to a slight moiré pattern or round-down of an auto-scaled dimension.
|
* @param {Boolean} [options.fastShrinkOnLoad=true] - Take greater advantage of the JPEG and WebP shrink-on-load feature, which can lead to a slight moiré pattern or round-down of an auto-scaled dimension.
|
||||||
|
|||||||
@@ -153,6 +153,9 @@ function concurrency (concurrency) {
|
|||||||
if (detectLibc.familySync() === detectLibc.GLIBC && !sharp._isUsingJemalloc()) {
|
if (detectLibc.familySync() === detectLibc.GLIBC && !sharp._isUsingJemalloc()) {
|
||||||
// Reduce default concurrency to 1 when using glibc memory allocator
|
// Reduce default concurrency to 1 when using glibc memory allocator
|
||||||
sharp.concurrency(1);
|
sharp.concurrency(1);
|
||||||
|
} else if (detectLibc.familySync() === detectLibc.MUSL && sharp.concurrency() === 1024) {
|
||||||
|
// Reduce default concurrency when musl thread over-subscription detected
|
||||||
|
sharp.concurrency(require('node:os').availableParallelism());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-darwin-arm64",
|
"name": "@img/sharp-darwin-arm64",
|
||||||
"version": "0.33.3-rc.0",
|
"version": "0.33.4",
|
||||||
"description": "Prebuilt sharp for use with macOS 64-bit ARM",
|
"description": "Prebuilt sharp for use with macOS 64-bit ARM",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-darwin-x64",
|
"name": "@img/sharp-darwin-x64",
|
||||||
"version": "0.33.3-rc.0",
|
"version": "0.33.4",
|
||||||
"description": "Prebuilt sharp for use with macOS x64",
|
"description": "Prebuilt sharp for use with macOS x64",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linux-arm",
|
"name": "@img/sharp-linux-arm",
|
||||||
"version": "0.33.3-rc.0",
|
"version": "0.33.4",
|
||||||
"description": "Prebuilt sharp for use with Linux (glibc) ARM (32-bit)",
|
"description": "Prebuilt sharp for use with Linux (glibc) ARM (32-bit)",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linux-arm64",
|
"name": "@img/sharp-linux-arm64",
|
||||||
"version": "0.33.3-rc.0",
|
"version": "0.33.4",
|
||||||
"description": "Prebuilt sharp for use with Linux (glibc) 64-bit ARM",
|
"description": "Prebuilt sharp for use with Linux (glibc) 64-bit ARM",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linux-s390x",
|
"name": "@img/sharp-linux-s390x",
|
||||||
"version": "0.33.3-rc.0",
|
"version": "0.33.4",
|
||||||
"description": "Prebuilt sharp for use with Linux (glibc) s390x",
|
"description": "Prebuilt sharp for use with Linux (glibc) s390x",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
"npm": ">=9.6.5",
|
"npm": ">=9.6.5",
|
||||||
"yarn": ">=3.2.0",
|
"yarn": ">=3.2.0",
|
||||||
"pnpm": ">=7.1.0",
|
"pnpm": ">=7.1.0",
|
||||||
"glibc": ">=2.28"
|
"glibc": ">=2.31"
|
||||||
},
|
},
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linux-x64",
|
"name": "@img/sharp-linux-x64",
|
||||||
"version": "0.33.3-rc.0",
|
"version": "0.33.4",
|
||||||
"description": "Prebuilt sharp for use with Linux (glibc) x64",
|
"description": "Prebuilt sharp for use with Linux (glibc) x64",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linuxmusl-arm64",
|
"name": "@img/sharp-linuxmusl-arm64",
|
||||||
"version": "0.33.3-rc.0",
|
"version": "0.33.4",
|
||||||
"description": "Prebuilt sharp for use with Linux (musl) 64-bit ARM",
|
"description": "Prebuilt sharp for use with Linux (musl) 64-bit ARM",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linuxmusl-x64",
|
"name": "@img/sharp-linuxmusl-x64",
|
||||||
"version": "0.33.3-rc.0",
|
"version": "0.33.4",
|
||||||
"description": "Prebuilt sharp for use with Linux (musl) x64",
|
"description": "Prebuilt sharp for use with Linux (musl) x64",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp",
|
"name": "@img/sharp",
|
||||||
"version": "0.33.3-rc.0",
|
"version": "0.33.4",
|
||||||
"private": "true",
|
"private": "true",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"darwin-arm64",
|
"darwin-arm64",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-wasm32",
|
"name": "@img/sharp-wasm32",
|
||||||
"version": "0.33.3-rc.0",
|
"version": "0.33.4",
|
||||||
"description": "Prebuilt sharp for use with wasm32",
|
"description": "Prebuilt sharp for use with wasm32",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
"pnpm": ">=7.1.0"
|
"pnpm": ">=7.1.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emnapi/runtime": "^1.1.0"
|
"@emnapi/runtime": "^1.1.1"
|
||||||
},
|
},
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"wasm32"
|
"wasm32"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-win32-ia32",
|
"name": "@img/sharp-win32-ia32",
|
||||||
"version": "0.33.3-rc.0",
|
"version": "0.33.4",
|
||||||
"description": "Prebuilt sharp for use with Windows x86 (32-bit)",
|
"description": "Prebuilt sharp for use with Windows x86 (32-bit)",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-win32-x64",
|
"name": "@img/sharp-win32-x64",
|
||||||
"version": "0.33.3-rc.0",
|
"version": "0.33.4",
|
||||||
"description": "Prebuilt sharp for use with Windows x64",
|
"description": "Prebuilt sharp for use with Windows x64",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
|
|||||||
38
package.json
38
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "sharp",
|
"name": "sharp",
|
||||||
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, 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.33.3-rc.0",
|
"version": "0.33.4",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
@@ -82,7 +82,7 @@
|
|||||||
"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>",
|
"Ankur Parihar <ankur.github@gmail.com>",
|
||||||
"Brahim Ait elhaj <brahima@gmail.com>",
|
"Brahim Ait elhaj <brahima@gmail.com>",
|
||||||
"Mart Jansink <m.jansink@gmail.com>",
|
"Mart Jansink <m.jansink@gmail.com>",
|
||||||
@@ -141,8 +141,8 @@
|
|||||||
"semver": "^7.6.0"
|
"semver": "^7.6.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-darwin-arm64": "0.33.3-rc.0",
|
"@img/sharp-darwin-arm64": "0.33.4",
|
||||||
"@img/sharp-darwin-x64": "0.33.3-rc.0",
|
"@img/sharp-darwin-x64": "0.33.4",
|
||||||
"@img/sharp-libvips-darwin-arm64": "1.0.2",
|
"@img/sharp-libvips-darwin-arm64": "1.0.2",
|
||||||
"@img/sharp-libvips-darwin-x64": "1.0.2",
|
"@img/sharp-libvips-darwin-x64": "1.0.2",
|
||||||
"@img/sharp-libvips-linux-arm": "1.0.2",
|
"@img/sharp-libvips-linux-arm": "1.0.2",
|
||||||
@@ -151,18 +151,18 @@
|
|||||||
"@img/sharp-libvips-linux-x64": "1.0.2",
|
"@img/sharp-libvips-linux-x64": "1.0.2",
|
||||||
"@img/sharp-libvips-linuxmusl-arm64": "1.0.2",
|
"@img/sharp-libvips-linuxmusl-arm64": "1.0.2",
|
||||||
"@img/sharp-libvips-linuxmusl-x64": "1.0.2",
|
"@img/sharp-libvips-linuxmusl-x64": "1.0.2",
|
||||||
"@img/sharp-linux-arm": "0.33.3-rc.0",
|
"@img/sharp-linux-arm": "0.33.4",
|
||||||
"@img/sharp-linux-arm64": "0.33.3-rc.0",
|
"@img/sharp-linux-arm64": "0.33.4",
|
||||||
"@img/sharp-linux-s390x": "0.33.3-rc.0",
|
"@img/sharp-linux-s390x": "0.33.4",
|
||||||
"@img/sharp-linux-x64": "0.33.3-rc.0",
|
"@img/sharp-linux-x64": "0.33.4",
|
||||||
"@img/sharp-linuxmusl-arm64": "0.33.3-rc.0",
|
"@img/sharp-linuxmusl-arm64": "0.33.4",
|
||||||
"@img/sharp-linuxmusl-x64": "0.33.3-rc.0",
|
"@img/sharp-linuxmusl-x64": "0.33.4",
|
||||||
"@img/sharp-wasm32": "0.33.3-rc.0",
|
"@img/sharp-wasm32": "0.33.4",
|
||||||
"@img/sharp-win32-ia32": "0.33.3-rc.0",
|
"@img/sharp-win32-ia32": "0.33.4",
|
||||||
"@img/sharp-win32-x64": "0.33.3-rc.0"
|
"@img/sharp-win32-x64": "0.33.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@emnapi/runtime": "^1.1.0",
|
"@emnapi/runtime": "^1.1.1",
|
||||||
"@img/sharp-libvips-dev": "1.0.2",
|
"@img/sharp-libvips-dev": "1.0.2",
|
||||||
"@img/sharp-libvips-dev-wasm32": "1.0.3",
|
"@img/sharp-libvips-dev-wasm32": "1.0.3",
|
||||||
"@img/sharp-libvips-win32-ia32": "1.0.2",
|
"@img/sharp-libvips-win32-ia32": "1.0.2",
|
||||||
@@ -170,19 +170,19 @@
|
|||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"async": "^3.2.5",
|
"async": "^3.2.5",
|
||||||
"cc": "^3.0.1",
|
"cc": "^3.0.1",
|
||||||
"emnapi": "^1.1.0",
|
"emnapi": "^1.1.1",
|
||||||
"exif-reader": "^2.0.1",
|
"exif-reader": "^2.0.1",
|
||||||
"extract-zip": "^2.0.1",
|
"extract-zip": "^2.0.1",
|
||||||
"icc": "^3.0.0",
|
"icc": "^3.0.0",
|
||||||
"jsdoc-to-markdown": "^8.0.1",
|
"jsdoc-to-markdown": "^8.0.1",
|
||||||
"license-checker": "^25.0.1",
|
"license-checker": "^25.0.1",
|
||||||
"mocha": "^10.3.0",
|
"mocha": "^10.4.0",
|
||||||
"node-addon-api": "^8.0.0",
|
"node-addon-api": "^8.0.0",
|
||||||
"nyc": "^15.1.0",
|
"nyc": "^15.1.0",
|
||||||
"prebuild": "^13.0.0",
|
"prebuild": "^13.0.1",
|
||||||
"semistandard": "^17.0.0",
|
"semistandard": "^17.0.0",
|
||||||
"tar-fs": "^3.0.5",
|
"tar-fs": "^3.0.6",
|
||||||
"tsd": "^0.30.7"
|
"tsd": "^0.31.0"
|
||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ namespace sharp {
|
|||||||
Napi::Buffer<char> buffer = input.Get("buffer").As<Napi::Buffer<char>>();
|
Napi::Buffer<char> buffer = input.Get("buffer").As<Napi::Buffer<char>>();
|
||||||
descriptor->bufferLength = buffer.Length();
|
descriptor->bufferLength = buffer.Length();
|
||||||
descriptor->buffer = buffer.Data();
|
descriptor->buffer = buffer.Data();
|
||||||
descriptor->isBuffer = TRUE;
|
descriptor->isBuffer = true;
|
||||||
}
|
}
|
||||||
descriptor->failOn = AttrAsEnum<VipsFailOn>(input, "failOn", VIPS_TYPE_FAIL_ON);
|
descriptor->failOn = AttrAsEnum<VipsFailOn>(input, "failOn", VIPS_TYPE_FAIL_ON);
|
||||||
// Density for vector-based input
|
// Density for vector-based input
|
||||||
@@ -384,7 +384,7 @@ namespace sharp {
|
|||||||
->set("access", descriptor->access)
|
->set("access", descriptor->access)
|
||||||
->set("fail_on", descriptor->failOn);
|
->set("fail_on", descriptor->failOn);
|
||||||
if (descriptor->unlimited && ImageTypeSupportsUnlimited(imageType)) {
|
if (descriptor->unlimited && ImageTypeSupportsUnlimited(imageType)) {
|
||||||
option->set("unlimited", TRUE);
|
option->set("unlimited", true);
|
||||||
}
|
}
|
||||||
if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
|
if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
|
||||||
option->set("dpi", descriptor->density);
|
option->set("dpi", descriptor->density);
|
||||||
@@ -488,7 +488,7 @@ namespace sharp {
|
|||||||
->set("access", descriptor->access)
|
->set("access", descriptor->access)
|
||||||
->set("fail_on", descriptor->failOn);
|
->set("fail_on", descriptor->failOn);
|
||||||
if (descriptor->unlimited && ImageTypeSupportsUnlimited(imageType)) {
|
if (descriptor->unlimited && ImageTypeSupportsUnlimited(imageType)) {
|
||||||
option->set("unlimited", TRUE);
|
option->set("unlimited", true);
|
||||||
}
|
}
|
||||||
if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
|
if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
|
||||||
option->set("dpi", descriptor->density);
|
option->set("dpi", descriptor->density);
|
||||||
@@ -768,7 +768,7 @@ namespace sharp {
|
|||||||
int *timeout = VIPS_NEW(im, int);
|
int *timeout = VIPS_NEW(im, int);
|
||||||
*timeout = seconds;
|
*timeout = seconds;
|
||||||
g_signal_connect(im, "eval", G_CALLBACK(VipsProgressCallBack), timeout);
|
g_signal_connect(im, "eval", G_CALLBACK(VipsProgressCallBack), timeout);
|
||||||
vips_image_set_progress(im, TRUE);
|
vips_image_set_progress(im, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -778,7 +778,7 @@ namespace sharp {
|
|||||||
*/
|
*/
|
||||||
void VipsProgressCallBack(VipsImage *im, VipsProgress *progress, int *timeout) {
|
void VipsProgressCallBack(VipsImage *im, VipsProgress *progress, int *timeout) {
|
||||||
if (*timeout > 0 && progress->run >= *timeout) {
|
if (*timeout > 0 && progress->run >= *timeout) {
|
||||||
vips_image_set_kill(im, TRUE);
|
vips_image_set_kill(im, true);
|
||||||
vips_error("timeout", "%d%% complete", progress->percent);
|
vips_error("timeout", "%d%% complete", progress->percent);
|
||||||
*timeout = 0;
|
*timeout = 0;
|
||||||
}
|
}
|
||||||
@@ -1081,9 +1081,10 @@ namespace sharp {
|
|||||||
/*
|
/*
|
||||||
Ensure decoding remains sequential.
|
Ensure decoding remains sequential.
|
||||||
*/
|
*/
|
||||||
VImage StaySequential(VImage image, VipsAccess access, bool condition) {
|
VImage StaySequential(VImage image, bool condition) {
|
||||||
if (access == VIPS_ACCESS_SEQUENTIAL && condition) {
|
if (vips_image_is_sequential(image.get_image()) && condition) {
|
||||||
return image.copy_memory();
|
image = image.copy_memory().copy();
|
||||||
|
image.remove(VIPS_META_SEQUENTIAL);
|
||||||
}
|
}
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/common.h
12
src/common.h
@@ -79,12 +79,12 @@ namespace sharp {
|
|||||||
buffer(nullptr),
|
buffer(nullptr),
|
||||||
failOn(VIPS_FAIL_ON_WARNING),
|
failOn(VIPS_FAIL_ON_WARNING),
|
||||||
limitInputPixels(0x3FFF * 0x3FFF),
|
limitInputPixels(0x3FFF * 0x3FFF),
|
||||||
unlimited(FALSE),
|
unlimited(false),
|
||||||
access(VIPS_ACCESS_RANDOM),
|
access(VIPS_ACCESS_RANDOM),
|
||||||
bufferLength(0),
|
bufferLength(0),
|
||||||
isBuffer(FALSE),
|
isBuffer(false),
|
||||||
density(72.0),
|
density(72.0),
|
||||||
ignoreIcc(FALSE),
|
ignoreIcc(false),
|
||||||
rawDepth(VIPS_FORMAT_UCHAR),
|
rawDepth(VIPS_FORMAT_UCHAR),
|
||||||
rawChannels(0),
|
rawChannels(0),
|
||||||
rawWidth(0),
|
rawWidth(0),
|
||||||
@@ -103,9 +103,9 @@ namespace sharp {
|
|||||||
textWidth(0),
|
textWidth(0),
|
||||||
textHeight(0),
|
textHeight(0),
|
||||||
textAlign(VIPS_ALIGN_LOW),
|
textAlign(VIPS_ALIGN_LOW),
|
||||||
textJustify(FALSE),
|
textJustify(false),
|
||||||
textDpi(72),
|
textDpi(72),
|
||||||
textRgba(FALSE),
|
textRgba(false),
|
||||||
textSpacing(0),
|
textSpacing(0),
|
||||||
textWrap(VIPS_TEXT_WRAP_WORD),
|
textWrap(VIPS_TEXT_WRAP_WORD),
|
||||||
textAutofitDpi(0) {}
|
textAutofitDpi(0) {}
|
||||||
@@ -386,7 +386,7 @@ namespace sharp {
|
|||||||
/*
|
/*
|
||||||
Ensure decoding remains sequential.
|
Ensure decoding remains sequential.
|
||||||
*/
|
*/
|
||||||
VImage StaySequential(VImage image, VipsAccess access, bool condition = TRUE);
|
VImage StaySequential(VImage image, bool condition = true);
|
||||||
|
|
||||||
} // namespace sharp
|
} // namespace sharp
|
||||||
|
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ namespace sharp {
|
|||||||
return image.conv(blur);
|
return image.conv(blur);
|
||||||
} else {
|
} else {
|
||||||
// Slower, accurate Gaussian blur
|
// Slower, accurate Gaussian blur
|
||||||
return StaySequential(image, VIPS_ACCESS_SEQUENTIAL).gaussblur(sigma);
|
return StaySequential(image).gaussblur(sigma);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,7 +386,7 @@ namespace sharp {
|
|||||||
pages.reserve(nPages);
|
pages.reserve(nPages);
|
||||||
|
|
||||||
// Split the image into cropped frames
|
// Split the image into cropped frames
|
||||||
image = StaySequential(image, VIPS_ACCESS_SEQUENTIAL);
|
image = StaySequential(image);
|
||||||
for (int i = 0; i < nPages; i++) {
|
for (int i = 0; i < nPages; i++) {
|
||||||
pages.push_back(
|
pages.push_back(
|
||||||
image.extract_area(left, *pageHeight * i + top, width, height));
|
image.extract_area(left, *pageHeight * i + top, width, height));
|
||||||
|
|||||||
@@ -70,8 +70,8 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
// Calculate angle of rotation
|
// Calculate angle of rotation
|
||||||
VipsAngle rotation = VIPS_ANGLE_D0;
|
VipsAngle rotation = VIPS_ANGLE_D0;
|
||||||
VipsAngle autoRotation = VIPS_ANGLE_D0;
|
VipsAngle autoRotation = VIPS_ANGLE_D0;
|
||||||
bool autoFlip = FALSE;
|
bool autoFlip = false;
|
||||||
bool autoFlop = FALSE;
|
bool autoFlop = false;
|
||||||
|
|
||||||
if (baton->useExifOrientation) {
|
if (baton->useExifOrientation) {
|
||||||
// Rotate and flip image according to Exif orientation
|
// Rotate and flip image according to Exif orientation
|
||||||
@@ -88,7 +88,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
baton->rotationAngle != 0.0);
|
baton->rotationAngle != 0.0);
|
||||||
|
|
||||||
if (shouldRotateBefore) {
|
if (shouldRotateBefore) {
|
||||||
image = sharp::StaySequential(image, access,
|
image = sharp::StaySequential(image,
|
||||||
rotation != VIPS_ANGLE_D0 ||
|
rotation != VIPS_ANGLE_D0 ||
|
||||||
autoRotation != VIPS_ANGLE_D0 ||
|
autoRotation != VIPS_ANGLE_D0 ||
|
||||||
autoFlip ||
|
autoFlip ||
|
||||||
@@ -104,17 +104,17 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
}
|
}
|
||||||
if (autoFlip) {
|
if (autoFlip) {
|
||||||
image = image.flip(VIPS_DIRECTION_VERTICAL);
|
image = image.flip(VIPS_DIRECTION_VERTICAL);
|
||||||
autoFlip = FALSE;
|
autoFlip = false;
|
||||||
} else if (baton->flip) {
|
} else if (baton->flip) {
|
||||||
image = image.flip(VIPS_DIRECTION_VERTICAL);
|
image = image.flip(VIPS_DIRECTION_VERTICAL);
|
||||||
baton->flip = FALSE;
|
baton->flip = false;
|
||||||
}
|
}
|
||||||
if (autoFlop) {
|
if (autoFlop) {
|
||||||
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
|
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
|
||||||
autoFlop = FALSE;
|
autoFlop = false;
|
||||||
} else if (baton->flop) {
|
} else if (baton->flop) {
|
||||||
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
|
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
|
||||||
baton->flop = FALSE;
|
baton->flop = false;
|
||||||
}
|
}
|
||||||
if (rotation != VIPS_ANGLE_D0) {
|
if (rotation != VIPS_ANGLE_D0) {
|
||||||
if (rotation != VIPS_ANGLE_D180) {
|
if (rotation != VIPS_ANGLE_D180) {
|
||||||
@@ -126,7 +126,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
if (baton->rotationAngle != 0.0) {
|
if (baton->rotationAngle != 0.0) {
|
||||||
MultiPageUnsupported(nPages, "Rotate");
|
MultiPageUnsupported(nPages, "Rotate");
|
||||||
std::vector<double> background;
|
std::vector<double> background;
|
||||||
std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground, FALSE);
|
std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground, false);
|
||||||
image = image.rotate(baton->rotationAngle, VImage::option()->set("background", background)).copy_memory();
|
image = image.rotate(baton->rotationAngle, VImage::option()->set("background", background)).copy_memory();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,7 +134,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
// Trim
|
// Trim
|
||||||
if (baton->trimThreshold >= 0.0) {
|
if (baton->trimThreshold >= 0.0) {
|
||||||
MultiPageUnsupported(nPages, "Trim");
|
MultiPageUnsupported(nPages, "Trim");
|
||||||
image = sharp::StaySequential(image, access);
|
image = sharp::StaySequential(image);
|
||||||
image = sharp::Trim(image, baton->trimBackground, baton->trimThreshold, baton->trimLineArt);
|
image = sharp::Trim(image, baton->trimBackground, baton->trimThreshold, baton->trimLineArt);
|
||||||
baton->trimOffsetLeft = image.xoffset();
|
baton->trimOffsetLeft = image.xoffset();
|
||||||
baton->trimOffsetTop = image.yoffset();
|
baton->trimOffsetTop = image.yoffset();
|
||||||
@@ -337,7 +337,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
// Convert to sRGB/P3 using embedded profile
|
// Convert to sRGB/P3 using embedded profile
|
||||||
try {
|
try {
|
||||||
image = image.icc_transform(processingProfile, VImage::option()
|
image = image.icc_transform(processingProfile, VImage::option()
|
||||||
->set("embedded", TRUE)
|
->set("embedded", true)
|
||||||
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
||||||
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
@@ -357,11 +357,6 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
image = sharp::Flatten(image, baton->flattenBackground);
|
image = sharp::Flatten(image, baton->flattenBackground);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Negate the colours in the image
|
|
||||||
if (baton->negate) {
|
|
||||||
image = sharp::Negate(image, baton->negateAlpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gamma encoding (darken)
|
// Gamma encoding (darken)
|
||||||
if (baton->gamma >= 1 && baton->gamma <= 3) {
|
if (baton->gamma >= 1 && baton->gamma <= 3) {
|
||||||
image = sharp::Gamma(image, 1.0 / baton->gamma);
|
image = sharp::Gamma(image, 1.0 / baton->gamma);
|
||||||
@@ -397,7 +392,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
->set("kernel", baton->kernel));
|
->set("kernel", baton->kernel));
|
||||||
}
|
}
|
||||||
|
|
||||||
image = sharp::StaySequential(image, access,
|
image = sharp::StaySequential(image,
|
||||||
autoRotation != VIPS_ANGLE_D0 ||
|
autoRotation != VIPS_ANGLE_D0 ||
|
||||||
baton->flip ||
|
baton->flip ||
|
||||||
autoFlip ||
|
autoFlip ||
|
||||||
@@ -500,7 +495,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
|
|
||||||
// Attention-based or Entropy-based crop
|
// Attention-based or Entropy-based crop
|
||||||
MultiPageUnsupported(nPages, "Resize strategy");
|
MultiPageUnsupported(nPages, "Resize strategy");
|
||||||
image = sharp::StaySequential(image, access);
|
image = sharp::StaySequential(image);
|
||||||
image = image.smartcrop(baton->width, baton->height, VImage::option()
|
image = image.smartcrop(baton->width, baton->height, VImage::option()
|
||||||
->set("interesting", baton->position == 16 ? VIPS_INTERESTING_ENTROPY : VIPS_INTERESTING_ATTENTION)
|
->set("interesting", baton->position == 16 ? VIPS_INTERESTING_ENTROPY : VIPS_INTERESTING_ATTENTION)
|
||||||
->set("premultiplied", shouldPremultiplyAlpha)
|
->set("premultiplied", shouldPremultiplyAlpha)
|
||||||
@@ -519,7 +514,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
// Rotate post-extract non-90 angle
|
// Rotate post-extract non-90 angle
|
||||||
if (!baton->rotateBeforePreExtract && baton->rotationAngle != 0.0) {
|
if (!baton->rotateBeforePreExtract && baton->rotationAngle != 0.0) {
|
||||||
MultiPageUnsupported(nPages, "Rotate");
|
MultiPageUnsupported(nPages, "Rotate");
|
||||||
image = sharp::StaySequential(image, access);
|
image = sharp::StaySequential(image);
|
||||||
std::vector<double> background;
|
std::vector<double> background;
|
||||||
std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground, shouldPremultiplyAlpha);
|
std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground, shouldPremultiplyAlpha);
|
||||||
image = image.rotate(baton->rotationAngle, VImage::option()->set("background", background));
|
image = image.rotate(baton->rotationAngle, VImage::option()->set("background", background));
|
||||||
@@ -543,7 +538,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
// Affine transform
|
// Affine transform
|
||||||
if (!baton->affineMatrix.empty()) {
|
if (!baton->affineMatrix.empty()) {
|
||||||
MultiPageUnsupported(nPages, "Affine");
|
MultiPageUnsupported(nPages, "Affine");
|
||||||
image = sharp::StaySequential(image, access);
|
image = sharp::StaySequential(image);
|
||||||
std::vector<double> background;
|
std::vector<double> background;
|
||||||
std::tie(image, background) = sharp::ApplyAlpha(image, baton->affineBackground, shouldPremultiplyAlpha);
|
std::tie(image, background) = sharp::ApplyAlpha(image, baton->affineBackground, shouldPremultiplyAlpha);
|
||||||
vips::VInterpolate interp = vips::VInterpolate::new_from_name(
|
vips::VInterpolate interp = vips::VInterpolate::new_from_name(
|
||||||
@@ -566,6 +561,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
std::vector<double> background;
|
std::vector<double> background;
|
||||||
std::tie(image, background) = sharp::ApplyAlpha(image, baton->extendBackground, shouldPremultiplyAlpha);
|
std::tie(image, background) = sharp::ApplyAlpha(image, baton->extendBackground, shouldPremultiplyAlpha);
|
||||||
|
|
||||||
|
image = sharp::StaySequential(image, nPages > 1);
|
||||||
image = nPages > 1
|
image = nPages > 1
|
||||||
? sharp::EmbedMultiPage(image,
|
? sharp::EmbedMultiPage(image,
|
||||||
baton->extendLeft, baton->extendTop, baton->width, baton->height,
|
baton->extendLeft, baton->extendTop, baton->width, baton->height,
|
||||||
@@ -574,7 +570,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
VImage::option()->set("extend", baton->extendWith)->set("background", background));
|
VImage::option()->set("extend", baton->extendWith)->set("background", background));
|
||||||
} else {
|
} else {
|
||||||
std::vector<double> ignoredBackground(1);
|
std::vector<double> ignoredBackground(1);
|
||||||
image = sharp::StaySequential(image, baton->input->access);
|
image = sharp::StaySequential(image);
|
||||||
image = nPages > 1
|
image = nPages > 1
|
||||||
? sharp::EmbedMultiPage(image,
|
? sharp::EmbedMultiPage(image,
|
||||||
baton->extendLeft, baton->extendTop, baton->width, baton->height,
|
baton->extendLeft, baton->extendTop, baton->width, baton->height,
|
||||||
@@ -670,7 +666,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
if (across != 0 || down != 0) {
|
if (across != 0 || down != 0) {
|
||||||
int left;
|
int left;
|
||||||
int top;
|
int top;
|
||||||
compositeImage = sharp::StaySequential(compositeImage, access).replicate(across, down);
|
compositeImage = sharp::StaySequential(compositeImage).replicate(across, down);
|
||||||
if (composite->hasOffset) {
|
if (composite->hasOffset) {
|
||||||
std::tie(left, top) = sharp::CalculateCrop(
|
std::tie(left, top) = sharp::CalculateCrop(
|
||||||
compositeImage.width(), compositeImage.height(), image.width(), image.height(),
|
compositeImage.width(), compositeImage.height(), image.width(), image.height(),
|
||||||
@@ -728,13 +724,13 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
|
|
||||||
// Apply normalisation - stretch luminance to cover full dynamic range
|
// Apply normalisation - stretch luminance to cover full dynamic range
|
||||||
if (baton->normalise) {
|
if (baton->normalise) {
|
||||||
image = sharp::StaySequential(image, access);
|
image = sharp::StaySequential(image);
|
||||||
image = sharp::Normalise(image, baton->normaliseLower, baton->normaliseUpper);
|
image = sharp::Normalise(image, baton->normaliseLower, baton->normaliseUpper);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply contrast limiting adaptive histogram equalization (CLAHE)
|
// Apply contrast limiting adaptive histogram equalization (CLAHE)
|
||||||
if (baton->claheWidth != 0 && baton->claheHeight != 0) {
|
if (baton->claheWidth != 0 && baton->claheHeight != 0) {
|
||||||
image = sharp::StaySequential(image, access);
|
image = sharp::StaySequential(image);
|
||||||
image = sharp::Clahe(image, baton->claheWidth, baton->claheHeight, baton->claheMaxSlope);
|
image = sharp::Clahe(image, baton->claheWidth, baton->claheHeight, baton->claheMaxSlope);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -780,7 +776,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
if ((baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) && baton->colourspacePipeline != VIPS_INTERPRETATION_CMYK &&
|
if ((baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) && baton->colourspacePipeline != VIPS_INTERPRETATION_CMYK &&
|
||||||
baton->withIccProfile.empty() && sharp::HasProfile(image)) {
|
baton->withIccProfile.empty() && sharp::HasProfile(image)) {
|
||||||
image = image.icc_transform(processingProfile, VImage::option()
|
image = image.icc_transform(processingProfile, VImage::option()
|
||||||
->set("embedded", TRUE)
|
->set("embedded", true)
|
||||||
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
||||||
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
||||||
}
|
}
|
||||||
@@ -811,7 +807,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
try {
|
try {
|
||||||
image = image.icc_transform(const_cast<char*>(baton->withIccProfile.data()), VImage::option()
|
image = image.icc_transform(const_cast<char*>(baton->withIccProfile.data()), VImage::option()
|
||||||
->set("input_profile", processingProfile)
|
->set("input_profile", processingProfile)
|
||||||
->set("embedded", TRUE)
|
->set("embedded", true)
|
||||||
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
||||||
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
@@ -820,6 +816,12 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
} else if (baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) {
|
} else if (baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) {
|
||||||
image = sharp::SetProfile(image, inputProfile);
|
image = sharp::SetProfile(image, inputProfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Negate the colours in the image
|
||||||
|
if (baton->negate) {
|
||||||
|
image = sharp::Negate(image, baton->negateAlpha);
|
||||||
|
}
|
||||||
|
|
||||||
// Override EXIF Orientation tag
|
// Override EXIF Orientation tag
|
||||||
if (baton->withMetadataOrientation != -1) {
|
if (baton->withMetadataOrientation != -1) {
|
||||||
image = sharp::SetExifOrientation(image, baton->withMetadataOrientation);
|
image = sharp::SetExifOrientation(image, baton->withMetadataOrientation);
|
||||||
@@ -1004,7 +1006,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
if (!sharp::HasAlpha(image)) {
|
if (!sharp::HasAlpha(image)) {
|
||||||
baton->tileBackground.pop_back();
|
baton->tileBackground.pop_back();
|
||||||
}
|
}
|
||||||
image = sharp::StaySequential(image, access, baton->tileAngle != 0);
|
image = sharp::StaySequential(image, baton->tileAngle != 0);
|
||||||
vips::VOption *options = BuildOptionsDZ(baton);
|
vips::VOption *options = BuildOptionsDZ(baton);
|
||||||
VipsArea *area = reinterpret_cast<VipsArea*>(image.dzsave_buffer(options));
|
VipsArea *area = reinterpret_cast<VipsArea*>(image.dzsave_buffer(options));
|
||||||
baton->bufferOut = static_cast<char*>(area->data);
|
baton->bufferOut = static_cast<char*>(area->data);
|
||||||
@@ -1206,7 +1208,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
if (!sharp::HasAlpha(image)) {
|
if (!sharp::HasAlpha(image)) {
|
||||||
baton->tileBackground.pop_back();
|
baton->tileBackground.pop_back();
|
||||||
}
|
}
|
||||||
image = sharp::StaySequential(image, access, baton->tileAngle != 0);
|
image = sharp::StaySequential(image, baton->tileAngle != 0);
|
||||||
vips::VOption *options = BuildOptionsDZ(baton);
|
vips::VOption *options = BuildOptionsDZ(baton);
|
||||||
image.dzsave(const_cast<char*>(baton->fileOut.data()), options);
|
image.dzsave(const_cast<char*>(baton->fileOut.data()), options);
|
||||||
baton->formatOut = "dz";
|
baton->formatOut = "dz";
|
||||||
@@ -1338,16 +1340,16 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
std::tuple<VipsAngle, bool, bool>
|
std::tuple<VipsAngle, bool, bool>
|
||||||
CalculateExifRotationAndFlip(int const exifOrientation) {
|
CalculateExifRotationAndFlip(int const exifOrientation) {
|
||||||
VipsAngle rotate = VIPS_ANGLE_D0;
|
VipsAngle rotate = VIPS_ANGLE_D0;
|
||||||
bool flip = FALSE;
|
bool flip = false;
|
||||||
bool flop = FALSE;
|
bool flop = false;
|
||||||
switch (exifOrientation) {
|
switch (exifOrientation) {
|
||||||
case 6: rotate = VIPS_ANGLE_D90; break;
|
case 6: rotate = VIPS_ANGLE_D90; break;
|
||||||
case 3: rotate = VIPS_ANGLE_D180; break;
|
case 3: rotate = VIPS_ANGLE_D180; break;
|
||||||
case 8: rotate = VIPS_ANGLE_D270; break;
|
case 8: rotate = VIPS_ANGLE_D270; break;
|
||||||
case 2: flop = TRUE; break; // flop 1
|
case 2: flop = true; break; // flop 1
|
||||||
case 7: flip = TRUE; rotate = VIPS_ANGLE_D90; break; // flip 6
|
case 7: flip = true; rotate = VIPS_ANGLE_D90; break; // flip 6
|
||||||
case 4: flop = TRUE; rotate = VIPS_ANGLE_D180; break; // flop 3
|
case 4: flop = true; rotate = VIPS_ANGLE_D180; break; // flop 3
|
||||||
case 5: flip = TRUE; rotate = VIPS_ANGLE_D270; break; // flip 8
|
case 5: flip = true; rotate = VIPS_ANGLE_D270; break; // flip 8
|
||||||
}
|
}
|
||||||
return std::make_tuple(rotate, flip, flop);
|
return std::make_tuple(rotate, flip, flop);
|
||||||
}
|
}
|
||||||
@@ -1395,7 +1397,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
std::string suffix;
|
std::string suffix;
|
||||||
if (baton->tileFormat == "png") {
|
if (baton->tileFormat == "png") {
|
||||||
std::vector<std::pair<std::string, std::string>> options {
|
std::vector<std::pair<std::string, std::string>> options {
|
||||||
{"interlace", baton->pngProgressive ? "TRUE" : "FALSE"},
|
{"interlace", baton->pngProgressive ? "true" : "false"},
|
||||||
{"compression", std::to_string(baton->pngCompressionLevel)},
|
{"compression", std::to_string(baton->pngCompressionLevel)},
|
||||||
{"filter", baton->pngAdaptiveFiltering ? "all" : "none"}
|
{"filter", baton->pngAdaptiveFiltering ? "all" : "none"}
|
||||||
};
|
};
|
||||||
@@ -1404,25 +1406,25 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
std::vector<std::pair<std::string, std::string>> options {
|
std::vector<std::pair<std::string, std::string>> options {
|
||||||
{"Q", std::to_string(baton->webpQuality)},
|
{"Q", std::to_string(baton->webpQuality)},
|
||||||
{"alpha_q", std::to_string(baton->webpAlphaQuality)},
|
{"alpha_q", std::to_string(baton->webpAlphaQuality)},
|
||||||
{"lossless", baton->webpLossless ? "TRUE" : "FALSE"},
|
{"lossless", baton->webpLossless ? "true" : "false"},
|
||||||
{"near_lossless", baton->webpNearLossless ? "TRUE" : "FALSE"},
|
{"near_lossless", baton->webpNearLossless ? "true" : "false"},
|
||||||
{"smart_subsample", baton->webpSmartSubsample ? "TRUE" : "FALSE"},
|
{"smart_subsample", baton->webpSmartSubsample ? "true" : "false"},
|
||||||
{"preset", vips_enum_nick(VIPS_TYPE_FOREIGN_WEBP_PRESET, baton->webpPreset)},
|
{"preset", vips_enum_nick(VIPS_TYPE_FOREIGN_WEBP_PRESET, baton->webpPreset)},
|
||||||
{"min_size", baton->webpMinSize ? "TRUE" : "FALSE"},
|
{"min_size", baton->webpMinSize ? "true" : "false"},
|
||||||
{"mixed", baton->webpMixed ? "TRUE" : "FALSE"},
|
{"mixed", baton->webpMixed ? "true" : "false"},
|
||||||
{"effort", std::to_string(baton->webpEffort)}
|
{"effort", std::to_string(baton->webpEffort)}
|
||||||
};
|
};
|
||||||
suffix = AssembleSuffixString(".webp", options);
|
suffix = AssembleSuffixString(".webp", options);
|
||||||
} else {
|
} else {
|
||||||
std::vector<std::pair<std::string, std::string>> options {
|
std::vector<std::pair<std::string, std::string>> options {
|
||||||
{"Q", std::to_string(baton->jpegQuality)},
|
{"Q", std::to_string(baton->jpegQuality)},
|
||||||
{"interlace", baton->jpegProgressive ? "TRUE" : "FALSE"},
|
{"interlace", baton->jpegProgressive ? "true" : "false"},
|
||||||
{"subsample_mode", baton->jpegChromaSubsampling == "4:4:4" ? "off" : "on"},
|
{"subsample_mode", baton->jpegChromaSubsampling == "4:4:4" ? "off" : "on"},
|
||||||
{"trellis_quant", baton->jpegTrellisQuantisation ? "TRUE" : "FALSE"},
|
{"trellis_quant", baton->jpegTrellisQuantisation ? "true" : "false"},
|
||||||
{"quant_table", std::to_string(baton->jpegQuantisationTable)},
|
{"quant_table", std::to_string(baton->jpegQuantisationTable)},
|
||||||
{"overshoot_deringing", baton->jpegOvershootDeringing ? "TRUE": "FALSE"},
|
{"overshoot_deringing", baton->jpegOvershootDeringing ? "true": "false"},
|
||||||
{"optimize_scans", baton->jpegOptimiseScans ? "TRUE": "FALSE"},
|
{"optimize_scans", baton->jpegOptimiseScans ? "true": "false"},
|
||||||
{"optimize_coding", baton->jpegOptimiseCoding ? "TRUE": "FALSE"}
|
{"optimize_coding", baton->jpegOptimiseCoding ? "true": "false"}
|
||||||
};
|
};
|
||||||
std::string extname = baton->tileLayout == VIPS_FOREIGN_DZ_LAYOUT_DZ ? ".jpeg" : ".jpg";
|
std::string extname = baton->tileLayout == VIPS_FOREIGN_DZ_LAYOUT_DZ ? ".jpeg" : ".jpg";
|
||||||
suffix = AssembleSuffixString(extname, options);
|
suffix = AssembleSuffixString(extname, options);
|
||||||
|
|||||||
BIN
test/fixtures/XCMYK 2017.icc
vendored
Normal file
BIN
test/fixtures/XCMYK 2017.icc
vendored
Normal file
Binary file not shown.
BIN
test/fixtures/expected/colourspace.cmyk-to-cmyk-negated.tif
vendored
Normal file
BIN
test/fixtures/expected/colourspace.cmyk-to-cmyk-negated.tif
vendored
Normal file
Binary file not shown.
BIN
test/fixtures/expected/negate-trans.png
vendored
BIN
test/fixtures/expected/negate-trans.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 5.3 KiB |
BIN
test/fixtures/fogra-0-100-100-0.tif
vendored
Normal file
BIN
test/fixtures/fogra-0-100-100-0.tif
vendored
Normal file
Binary file not shown.
1
test/fixtures/index.js
vendored
1
test/fixtures/index.js
vendored
@@ -114,6 +114,7 @@ module.exports = {
|
|||||||
inputTiffUncompressed: getPath('uncompressed_tiff.tiff'), // https://code.google.com/archive/p/imagetestsuite/wikis/TIFFTestSuite.wiki file: 0c84d07e1b22b76f24cccc70d8788e4a.tif
|
inputTiffUncompressed: getPath('uncompressed_tiff.tiff'), // https://code.google.com/archive/p/imagetestsuite/wikis/TIFFTestSuite.wiki file: 0c84d07e1b22b76f24cccc70d8788e4a.tif
|
||||||
inputTiff8BitDepth: getPath('8bit_depth.tiff'),
|
inputTiff8BitDepth: getPath('8bit_depth.tiff'),
|
||||||
inputTifftagPhotoshop: getPath('tifftag-photoshop.tiff'), // https://github.com/lovell/sharp/issues/1600
|
inputTifftagPhotoshop: getPath('tifftag-photoshop.tiff'), // https://github.com/lovell/sharp/issues/1600
|
||||||
|
inputTiffFogra: getPath('fogra-0-100-100-0.tif'), // https://github.com/lovell/sharp/issues/4045
|
||||||
|
|
||||||
inputJp2: getPath('relax.jp2'), // https://www.fnordware.com/j2k/relax.jp2
|
inputJp2: getPath('relax.jp2'), // https://www.fnordware.com/j2k/relax.jp2
|
||||||
inputGif: getPath('Crash_test.gif'), // http://upload.wikimedia.org/wikipedia/commons/e/e3/Crash_test.gif
|
inputGif: getPath('Crash_test.gif'), // http://upload.wikimedia.org/wikipedia/commons/e/e3/Crash_test.gif
|
||||||
|
|||||||
@@ -680,3 +680,24 @@ sharp(input)
|
|||||||
.keepIccProfile()
|
.keepIccProfile()
|
||||||
.withIccProfile('filename')
|
.withIccProfile('filename')
|
||||||
.withIccProfile('filename', { attach: false });
|
.withIccProfile('filename', { attach: false });
|
||||||
|
|
||||||
|
// Added missing types for OverlayOptions
|
||||||
|
// https://github.com/lovell/sharp/pull/4048
|
||||||
|
sharp(input).composite([
|
||||||
|
{
|
||||||
|
input: 'image.gif',
|
||||||
|
animated: true,
|
||||||
|
limitInputPixels: 536805378,
|
||||||
|
density: 144,
|
||||||
|
failOn: "warning"
|
||||||
|
}
|
||||||
|
])
|
||||||
|
sharp(input).composite([
|
||||||
|
{
|
||||||
|
input: 'image.png',
|
||||||
|
animated: false,
|
||||||
|
limitInputPixels: 178935126,
|
||||||
|
density: 72,
|
||||||
|
failOn: "truncated"
|
||||||
|
}
|
||||||
|
])
|
||||||
@@ -106,6 +106,43 @@ describe('Colour space conversion', function () {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('CMYK profile to CMYK profile conversion using perceptual intent', async () => {
|
||||||
|
const data = await sharp(fixtures.inputTiffFogra)
|
||||||
|
.resize(320, 240)
|
||||||
|
.toColourspace('cmyk')
|
||||||
|
.pipelineColourspace('cmyk')
|
||||||
|
.withIccProfile(fixtures.path('XCMYK 2017.icc'))
|
||||||
|
.raw()
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
const [c, m, y, k] = data;
|
||||||
|
assert.deepStrictEqual(
|
||||||
|
{ c, m, y, k },
|
||||||
|
{ c: 1, m: 239, y: 227, k: 5 }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('CMYK profile to CMYK profile with negate', (done) => {
|
||||||
|
sharp(fixtures.inputTiffFogra)
|
||||||
|
.resize(320, 240)
|
||||||
|
.toColourspace('cmyk')
|
||||||
|
.pipelineColourspace('cmyk')
|
||||||
|
.withIccProfile(fixtures.path('XCMYK 2017.icc'))
|
||||||
|
.negate()
|
||||||
|
.toBuffer(function (err, data, info) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual('tiff', info.format);
|
||||||
|
assert.strictEqual(320, info.width);
|
||||||
|
assert.strictEqual(240, info.height);
|
||||||
|
fixtures.assertSimilar(
|
||||||
|
fixtures.expected('colourspace.cmyk-to-cmyk-negated.tif'),
|
||||||
|
data,
|
||||||
|
{ threshold: 0 },
|
||||||
|
done
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('From sRGB with RGB16 pipeline, resize with gamma, to sRGB', function (done) {
|
it('From sRGB with RGB16 pipeline, resize with gamma, to sRGB', function (done) {
|
||||||
sharp(fixtures.inputPngGradients)
|
sharp(fixtures.inputPngGradients)
|
||||||
.pipelineColourspace('rgb16')
|
.pipelineColourspace('rgb16')
|
||||||
|
|||||||
@@ -73,20 +73,6 @@ describe('Extend', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('extend top with mirroring uses ordered read', async () => {
|
|
||||||
const data = await sharp(fixtures.inputJpg)
|
|
||||||
.extend({
|
|
||||||
extendWith: 'mirror',
|
|
||||||
top: 1
|
|
||||||
})
|
|
||||||
.png({ compressionLevel: 0 })
|
|
||||||
.toBuffer();
|
|
||||||
|
|
||||||
const { width, height } = await sharp(data).metadata();
|
|
||||||
assert.strictEqual(2725, width);
|
|
||||||
assert.strictEqual(2226, height);
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`extend sides unequally with RGBA (${extendWith})`, function (done) {
|
it(`extend sides unequally with RGBA (${extendWith})`, function (done) {
|
||||||
sharp(fixtures.inputPngWithTransparency16bit)
|
sharp(fixtures.inputPngWithTransparency16bit)
|
||||||
.resize(120)
|
.resize(120)
|
||||||
@@ -127,6 +113,39 @@ describe('Extend', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('extend top with mirroring uses ordered read', async () => {
|
||||||
|
const data = await sharp(fixtures.inputJpg)
|
||||||
|
.extend({
|
||||||
|
extendWith: 'mirror',
|
||||||
|
top: 1
|
||||||
|
})
|
||||||
|
.png({ compressionLevel: 0 })
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
const { width, height } = await sharp(data).metadata();
|
||||||
|
assert.strictEqual(2725, width);
|
||||||
|
assert.strictEqual(2226, height);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('multi-page extend uses ordered read', async () => {
|
||||||
|
const multiPageTiff = await sharp(fixtures.inputGifAnimated, { animated: true })
|
||||||
|
.resize({ width: 8, height: 48 })
|
||||||
|
.tiff()
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
const data = await sharp(multiPageTiff, { pages: -1 })
|
||||||
|
.extend({
|
||||||
|
background: 'red',
|
||||||
|
top: 1
|
||||||
|
})
|
||||||
|
.png({ compressionLevel: 0 })
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
const { width, height } = await sharp(data).metadata();
|
||||||
|
assert.strictEqual(8, width);
|
||||||
|
assert.strictEqual(1470, height);
|
||||||
|
});
|
||||||
|
|
||||||
it('missing parameter fails', function () {
|
it('missing parameter fails', function () {
|
||||||
assert.throws(function () {
|
assert.throws(function () {
|
||||||
sharp().extend();
|
sharp().extend();
|
||||||
|
|||||||
@@ -66,6 +66,14 @@ describe('libvips binaries', function () {
|
|||||||
|
|
||||||
delete process.env.SHARP_IGNORE_GLOBAL_LIBVIPS;
|
delete process.env.SHARP_IGNORE_GLOBAL_LIBVIPS;
|
||||||
});
|
});
|
||||||
|
it('useGlobalLibvips can be forced via an env var', function () {
|
||||||
|
process.env.SHARP_FORCE_GLOBAL_LIBVIPS = 1;
|
||||||
|
|
||||||
|
const useGlobalLibvips = libvips.useGlobalLibvips();
|
||||||
|
assert.strictEqual(true, useGlobalLibvips);
|
||||||
|
|
||||||
|
delete process.env.SHARP_FORCE_GLOBAL_LIBVIPS;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Build time platform detection', () => {
|
describe('Build time platform detection', () => {
|
||||||
|
|||||||
@@ -228,26 +228,34 @@ describe('Text to image', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('bad width input', function () {
|
it('invalid width', () => {
|
||||||
assert.throws(function () {
|
assert.throws(
|
||||||
sharp({
|
() => sharp({ text: { text: 'text', width: 'bad' } }),
|
||||||
text: {
|
/Expected positive integer for text\.width but received bad of type string/
|
||||||
text: 'text',
|
);
|
||||||
width: 'bad'
|
assert.throws(
|
||||||
}
|
() => sharp({ text: { text: 'text', width: 0.1 } }),
|
||||||
});
|
/Expected positive integer for text\.width but received 0.1 of type number/
|
||||||
});
|
);
|
||||||
|
assert.throws(
|
||||||
|
() => sharp({ text: { text: 'text', width: -1 } }),
|
||||||
|
/Expected positive integer for text\.width but received -1 of type number/
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('bad height input', function () {
|
it('invalid height', () => {
|
||||||
assert.throws(function () {
|
assert.throws(
|
||||||
sharp({
|
() => sharp({ text: { text: 'text', height: 'bad' } }),
|
||||||
text: {
|
/Expected positive integer for text\.height but received bad of type string/
|
||||||
text: 'text',
|
);
|
||||||
height: 'bad'
|
assert.throws(
|
||||||
}
|
() => sharp({ text: { text: 'text', height: 0.1 } }),
|
||||||
});
|
/Expected positive integer for text\.height but received 0.1 of type number/
|
||||||
});
|
);
|
||||||
|
assert.throws(
|
||||||
|
() => sharp({ text: { text: 'text', height: -1 } }),
|
||||||
|
/Expected positive integer for text\.height but received -1 of type number/
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('bad align input', function () {
|
it('bad align input', function () {
|
||||||
@@ -272,15 +280,19 @@ describe('Text to image', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('bad dpi input', function () {
|
it('invalid dpi', () => {
|
||||||
assert.throws(function () {
|
assert.throws(
|
||||||
sharp({
|
() => sharp({ text: { text: 'text', dpi: 'bad' } }),
|
||||||
text: {
|
/Expected integer between 1 and 1000000 for text\.dpi but received bad of type string/
|
||||||
text: 'text',
|
);
|
||||||
dpi: -10
|
assert.throws(
|
||||||
}
|
() => sharp({ text: { text: 'text', dpi: 0.1 } }),
|
||||||
});
|
/Expected integer between 1 and 1000000 for text\.dpi but received 0.1 of type number/
|
||||||
});
|
);
|
||||||
|
assert.throws(
|
||||||
|
() => sharp({ text: { text: 'text', dpi: -1 } }),
|
||||||
|
/Expected integer between 1 and 1000000 for text\.dpi but received -1 of type number/
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('bad rgba input', function () {
|
it('bad rgba input', function () {
|
||||||
@@ -294,15 +306,19 @@ describe('Text to image', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('bad spacing input', function () {
|
it('invalid spacing', () => {
|
||||||
assert.throws(function () {
|
assert.throws(
|
||||||
sharp({
|
() => sharp({ text: { text: 'text', spacing: 'bad' } }),
|
||||||
text: {
|
/Expected integer between -1000000 and 1000000 for text\.spacing but received bad of type string/
|
||||||
text: 'text',
|
);
|
||||||
spacing: 'number expected'
|
assert.throws(
|
||||||
}
|
() => sharp({ text: { text: 'text', spacing: 0.1 } }),
|
||||||
});
|
/Expected integer between -1000000 and 1000000 for text\.spacing but received 0.1 of type number/
|
||||||
});
|
);
|
||||||
|
assert.throws(
|
||||||
|
() => sharp({ text: { text: 'text', spacing: -1000001 } }),
|
||||||
|
/Expected integer between -1000000 and 1000000 for text\.spacing but received -1000001 of type number/
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('only height or dpi not both', function () {
|
it('only height or dpi not both', function () {
|
||||||
|
|||||||
Reference in New Issue
Block a user