mirror of
https://github.com/lovell/sharp.git
synced 2026-02-05 06:06:18 +01:00
Compare commits
90 Commits
v0.33.0-rc
...
v0.33.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55466f122c | ||
|
|
ede8217ab3 | ||
|
|
2689fb4e65 | ||
|
|
eaf31a59e5 | ||
|
|
aa1bbcb5c1 | ||
|
|
3c26080c39 | ||
|
|
dc07fd4e9c | ||
|
|
7bc74feb11 | ||
|
|
c5f318ed4d | ||
|
|
8fbb1cd154 | ||
|
|
88aee8a887 | ||
|
|
0f77b18078 | ||
|
|
3eeaee71c0 | ||
|
|
045d54e2e6 | ||
|
|
75fedf1b75 | ||
|
|
debdacb726 | ||
|
|
1c8ae67ed2 | ||
|
|
0eb57698ec | ||
|
|
bc95531f2d | ||
|
|
60f4048d6c | ||
|
|
fb70fbb09f | ||
|
|
fc439bedf1 | ||
|
|
26d0b7147d | ||
|
|
af6aa8a690 | ||
|
|
bd4f1abba2 | ||
|
|
d2656a3679 | ||
|
|
a3b45ceccc | ||
|
|
0dcc7d50a8 | ||
|
|
bcb22af034 | ||
|
|
d04dc62666 | ||
|
|
c30d355f97 | ||
|
|
49cb148b38 | ||
|
|
3bc31a8b20 | ||
|
|
c28523e70e | ||
|
|
278f393f74 | ||
|
|
cbf68c1395 | ||
|
|
45e8071599 | ||
|
|
b96389d975 | ||
|
|
a77ac6ae25 | ||
|
|
9bcf399b4c | ||
|
|
4aacee8055 | ||
|
|
0b18aeff62 | ||
|
|
bed1c2ac18 | ||
|
|
8cd832656b | ||
|
|
0499f59e71 | ||
|
|
1fa59bf9b3 | ||
|
|
db40ee6912 | ||
|
|
02b98b8e1b | ||
|
|
31fef216e4 | ||
|
|
77ab5d7a51 | ||
|
|
cd5cf7ce2d | ||
|
|
39cb9d9a6c | ||
|
|
4919bc5134 | ||
|
|
a4e64eb01f | ||
|
|
328b18df88 | ||
|
|
5e7bf32e5e | ||
|
|
04403f4e5f | ||
|
|
420e0822b4 | ||
|
|
f7a3ea6415 | ||
|
|
f28e79ef4f | ||
|
|
5cd787bf85 | ||
|
|
021d637fd6 | ||
|
|
2e14096af7 | ||
|
|
fe2b298a2f | ||
|
|
c9e3996007 | ||
|
|
3a0c375692 | ||
|
|
c5eaeb2ddb | ||
|
|
19fa4cd1d3 | ||
|
|
0adf7ef16f | ||
|
|
8f7fb96a44 | ||
|
|
9e3b021b1a | ||
|
|
25164d4cef | ||
|
|
516b1ec332 | ||
|
|
95ba045a69 | ||
|
|
6e02f9288e | ||
|
|
a584ae093e | ||
|
|
1592f96b7b | ||
|
|
004fff975f | ||
|
|
4d049ee8f5 | ||
|
|
c80e92fa16 | ||
|
|
545e09fad2 | ||
|
|
133dc56ff4 | ||
|
|
9c877d93fa | ||
|
|
7ad86fed03 | ||
|
|
31cf07f0ba | ||
|
|
4ffb48711a | ||
|
|
3da96a86e6 | ||
|
|
45ed9ea9bf | ||
|
|
61057f25bc | ||
|
|
68ef72cb61 |
@@ -24,7 +24,7 @@ jobs:
|
|||||||
linux-arm64-glibc-node-18:
|
linux-arm64-glibc-node-18:
|
||||||
resource_class: arm.medium
|
resource_class: arm.medium
|
||||||
machine:
|
machine:
|
||||||
image: ubuntu-2004:current
|
image: ubuntu-2204:current
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- run: |
|
- run: |
|
||||||
@@ -46,7 +46,7 @@ jobs:
|
|||||||
linux-arm64-glibc-node-20:
|
linux-arm64-glibc-node-20:
|
||||||
resource_class: arm.medium
|
resource_class: arm.medium
|
||||||
machine:
|
machine:
|
||||||
image: ubuntu-2004:current
|
image: ubuntu-2204:current
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- run: |
|
- run: |
|
||||||
@@ -69,7 +69,7 @@ jobs:
|
|||||||
linux-arm64-musl-node-18:
|
linux-arm64-musl-node-18:
|
||||||
resource_class: arm.medium
|
resource_class: arm.medium
|
||||||
machine:
|
machine:
|
||||||
image: ubuntu-2004:current
|
image: ubuntu-2204:current
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- run: |
|
- run: |
|
||||||
@@ -87,7 +87,7 @@ jobs:
|
|||||||
linux-arm64-musl-node-20:
|
linux-arm64-musl-node-20:
|
||||||
resource_class: arm.medium
|
resource_class: arm.medium
|
||||||
machine:
|
machine:
|
||||||
image: ubuntu-2004:current
|
image: ubuntu-2204:current
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- run: |
|
- run: |
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
freebsd_instance:
|
freebsd_instance:
|
||||||
image_family: freebsd-13-2
|
image_family: freebsd-14-0-snap
|
||||||
|
|
||||||
task:
|
task:
|
||||||
name: FreeBSD
|
name: FreeBSD
|
||||||
@@ -10,7 +10,8 @@ task:
|
|||||||
- pkg update -f
|
- pkg update -f
|
||||||
- pkg upgrade -y
|
- pkg upgrade -y
|
||||||
- pkg install -y devel/git devel/pkgconf graphics/vips www/node20 www/npm
|
- pkg install -y devel/git devel/pkgconf graphics/vips www/node20 www/npm
|
||||||
|
- pkg-config --modversion vips-cpp
|
||||||
install_script:
|
install_script:
|
||||||
- npm install --build-from-source
|
- npm install --build-from-source
|
||||||
test_script:
|
test_script:
|
||||||
- npm test
|
- npx mocha --no-config --spec=test/unit/io.js --timeout=30000
|
||||||
|
|||||||
2
.github/CONTRIBUTING.md
vendored
2
.github/CONTRIBUTING.md
vendored
@@ -63,7 +63,7 @@ By way of example, the `background()` method present in v0.20.0 was deprecated i
|
|||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
The public API is documented with [JSDoc](http://usejsdoc.org/) annotated comments.
|
The public API is documented with [JSDoc](https://jsdoc.app/) annotated comments.
|
||||||
|
|
||||||
These can be converted to Markdown by running:
|
These can be converted to Markdown by running:
|
||||||
```sh
|
```sh
|
||||||
|
|||||||
33
.github/ISSUE_TEMPLATE/installation.md
vendored
33
.github/ISSUE_TEMPLATE/installation.md
vendored
@@ -11,7 +11,10 @@ labels: installation
|
|||||||
|
|
||||||
<!-- Please place an [x] in the box to confirm. -->
|
<!-- Please place an [x] in the box to confirm. -->
|
||||||
|
|
||||||
- [ ] I have read the [documentation relating to installation](https://sharp.pixelplumbing.com/install).
|
- [ ] I have read and understood all of the [documentation relating to installation](https://sharp.pixelplumbing.com/install).
|
||||||
|
- [ ] I have searched for known bugs relating to this problem in my choice of package manager.
|
||||||
|
|
||||||
|
You must confirm both of these before continuing.
|
||||||
|
|
||||||
### Are you using the latest version of sharp?
|
### Are you using the latest version of sharp?
|
||||||
|
|
||||||
@@ -21,27 +24,37 @@ labels: installation
|
|||||||
|
|
||||||
If you cannot confirm this, please upgrade to the latest version and try again before opening an issue.
|
If you cannot confirm this, please upgrade to the latest version and try again before opening an issue.
|
||||||
|
|
||||||
If you are using another package which depends on a version of `sharp` that is not the latest, please open an issue against that package instead.
|
If you are using another package which depends on a version of `sharp` that is not the latest,
|
||||||
|
please open an issue against that package instead.
|
||||||
|
|
||||||
### Are you using a supported runtime?
|
### Are you using a supported runtime?
|
||||||
|
|
||||||
<!-- Please place an [x] in the relevant box to confirm. -->
|
<!-- Please place an [x] in the relevant box to confirm. -->
|
||||||
|
|
||||||
- [ ] I am using Node.js 18 with a version >= 18.17.0
|
- [ ] I am using Node.js with a version that satisfies `^18.17.0 || ^20.3.0 || >=21.0.0`
|
||||||
- [ ] I am using Node.js 20 with a version >= 20.3.0
|
- [ ] I am using Deno
|
||||||
- [ ] I am using Node.js 21 or later
|
- [ ] I am using Bun
|
||||||
|
|
||||||
If you cannot confirm any of these, please upgrade to the latest version and try again before opening an issue.
|
If you cannot confirm any of these,
|
||||||
|
please upgrade to the latest version
|
||||||
|
and try again before opening an issue.
|
||||||
|
|
||||||
### Are you using a supported package manager?
|
### Are you using a supported package manager and installing optional dependencies?
|
||||||
|
|
||||||
<!-- Please place an [x] in the relevant box to confirm. -->
|
<!-- Please place an [x] in the relevant box to confirm. -->
|
||||||
|
|
||||||
- [ ] I am using npm >= 9.6.5
|
- [ ] I am using npm >= 9.6.5 with `--include=optional`
|
||||||
- [ ] I am using yarn >= 3.2.0
|
- [ ] I am using yarn >= 3.2.0
|
||||||
- [ ] I am using pnpm >= 7.1.0
|
- [ ] I am using pnpm >= 7.1.0 with `--no-optional=false`
|
||||||
|
- [ ] I am using Deno
|
||||||
|
- [ ] I am using Bun
|
||||||
|
|
||||||
If you cannot confirm any of these, please upgrade to the latest version and try again before opening an issue.
|
If you cannot confirm any of these, please upgrade to the latest version of your chosen package manager
|
||||||
|
and ensure you are allowing the installation of optional or multi-platform dependencies before opening an issue.
|
||||||
|
|
||||||
|
### What is the complete error message, including the full stack trace?
|
||||||
|
|
||||||
|
<!-- Please provide the error message and stack trace here. -->
|
||||||
|
|
||||||
### What is the complete output of running `npm install --verbose --foreground-scripts sharp` in an empty directory?
|
### What is the complete output of running `npm install --verbose --foreground-scripts sharp` in an empty directory?
|
||||||
|
|
||||||
|
|||||||
93
.github/workflows/ci.yml
vendored
93
.github/workflows/ci.yml
vendored
@@ -16,12 +16,14 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
- os: ubuntu-22.04
|
- os: ubuntu-22.04
|
||||||
container: rockylinux:8
|
container: rockylinux:8
|
||||||
|
nodejs_arch: x64
|
||||||
nodejs_version: "^18.17.0"
|
nodejs_version: "^18.17.0"
|
||||||
nodejs_version_major: 18
|
nodejs_version_major: 18
|
||||||
platform: linux-x64
|
platform: linux-x64
|
||||||
prebuild: true
|
prebuild: true
|
||||||
- os: ubuntu-22.04
|
- os: ubuntu-22.04
|
||||||
container: rockylinux:8
|
container: rockylinux:8
|
||||||
|
nodejs_arch: x64
|
||||||
nodejs_version: "^20.3.0"
|
nodejs_version: "^20.3.0"
|
||||||
nodejs_version_major: 20
|
nodejs_version_major: 20
|
||||||
platform: linux-x64
|
platform: linux-x64
|
||||||
@@ -45,9 +47,20 @@ jobs:
|
|||||||
nodejs_version: "^20.3.0"
|
nodejs_version: "^20.3.0"
|
||||||
nodejs_version_major: 20
|
nodejs_version_major: 20
|
||||||
platform: darwin-x64
|
platform: darwin-x64
|
||||||
|
- os: macos-14
|
||||||
|
nodejs_arch: arm64
|
||||||
|
nodejs_version: "^18.17.0"
|
||||||
|
nodejs_version_major: 18
|
||||||
|
platform: darwin-arm64
|
||||||
|
prebuild: true
|
||||||
|
- os: macos-14
|
||||||
|
nodejs_arch: arm64
|
||||||
|
nodejs_version: "^20.3.0"
|
||||||
|
nodejs_version_major: 20
|
||||||
|
platform: darwin-arm64
|
||||||
- os: windows-2019
|
- os: windows-2019
|
||||||
nodejs_arch: x86
|
nodejs_arch: x86
|
||||||
nodejs_version: "^18.17.0"
|
nodejs_version: "18.18.2" # pinned to avoid 18.19.0 and npm 10
|
||||||
nodejs_version_major: 18
|
nodejs_version_major: 18
|
||||||
platform: win32-ia32
|
platform: win32-ia32
|
||||||
prebuild: true
|
prebuild: true
|
||||||
@@ -68,19 +81,9 @@ jobs:
|
|||||||
nodejs_version_major: 20
|
nodejs_version_major: 20
|
||||||
platform: win32-x64
|
platform: win32-x64
|
||||||
steps:
|
steps:
|
||||||
- name: Dependencies (Linux glibc)
|
|
||||||
if: contains(matrix.container, 'centos')
|
|
||||||
run: |
|
|
||||||
yum install -y https://rpm.nodesource.com/pub_${{ matrix.nodejs_version_major }}.x/nodistro/repo/nodesource-release-nodistro-1.noarch.rpm
|
|
||||||
yum install -y https://packages.endpointdev.com/rhel/7/os/x86_64/endpoint-repo.x86_64.rpm
|
|
||||||
yum install -y centos-release-scl
|
|
||||||
yum install -y devtoolset-11-gcc-c++ make git python3 nodejs fontconfig google-noto-sans-fonts
|
|
||||||
echo "/opt/rh/devtoolset-11/root/usr/bin" >> $GITHUB_PATH
|
|
||||||
- name: Dependencies (Rocky Linux glibc)
|
- name: Dependencies (Rocky Linux glibc)
|
||||||
if: contains(matrix.container, 'rockylinux')
|
if: contains(matrix.container, 'rockylinux')
|
||||||
run: |
|
run: |
|
||||||
dnf install -y https://rpm.nodesource.com/pub_${{ matrix.nodejs_version_major }}.x/nodistro/repo/nodesource-release-nodistro-1.noarch.rpm
|
|
||||||
dnf install -y --setopt=nodesource-nodejs.module_hotfixes=1 nodejs
|
|
||||||
dnf install -y gcc-toolset-11-gcc-c++ make git python3 fontconfig google-noto-sans-fonts
|
dnf install -y gcc-toolset-11-gcc-c++ make git python3 fontconfig google-noto-sans-fonts
|
||||||
echo "/opt/rh/gcc-toolset-11/root/usr/bin" >> $GITHUB_PATH
|
echo "/opt/rh/gcc-toolset-11/root/usr/bin" >> $GITHUB_PATH
|
||||||
- name: Dependencies (Linux musl)
|
- name: Dependencies (Linux musl)
|
||||||
@@ -88,12 +91,12 @@ jobs:
|
|||||||
run: apk add build-base git python3 font-noto --update-cache
|
run: apk add build-base git python3 font-noto --update-cache
|
||||||
- name: Dependencies (Python 3.11 - macOS, Windows)
|
- name: Dependencies (Python 3.11 - macOS, Windows)
|
||||||
if: contains(matrix.os, 'macos') || contains(matrix.os, 'windows')
|
if: contains(matrix.os, 'macos') || contains(matrix.os, 'windows')
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: '3.11'
|
python-version: "3.12"
|
||||||
- name: Dependencies (Node.js - macOS, Windows)
|
- name: Dependencies (Node.js)
|
||||||
if: contains(matrix.os, 'macos') || contains(matrix.os, 'windows')
|
if: "!contains(matrix.platform, 'linuxmusl')"
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.nodejs_version }}
|
node-version: ${{ matrix.nodejs_version }}
|
||||||
architecture: ${{ matrix.nodejs_arch }}
|
architecture: ${{ matrix.nodejs_arch }}
|
||||||
@@ -166,18 +169,25 @@ jobs:
|
|||||||
contents: write
|
contents: write
|
||||||
name: wasm32 - prebuild
|
name: wasm32 - prebuild
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
container: "emscripten/emsdk:3.1.48"
|
container: "emscripten/emsdk:3.1.56"
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Dependencies
|
- name: Dependencies
|
||||||
run: apt-get update && apt-get install -y pkg-config
|
run: apt-get update && apt-get install -y pkg-config
|
||||||
- name: Dependencies (Node.js)
|
- name: Dependencies (Node.js)
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: "20"
|
node-version: "20"
|
||||||
- name: Install
|
- name: Install
|
||||||
run: emmake npm install --build-from-source
|
run: emmake npm install --build-from-source
|
||||||
|
- name: Verify emscripten versions match
|
||||||
|
run: |
|
||||||
|
EMSCRIPTEN_VERSION_LIBVIPS=$(node -p "require('@img/sharp-libvips-dev-wasm32/versions').emscripten")
|
||||||
|
EMSCRIPTEN_VERSION_SHARP=$(emcc -dumpversion)
|
||||||
|
echo "libvips built with emscripten $EMSCRIPTEN_VERSION_LIBVIPS"
|
||||||
|
echo "sharp built with emscripten $EMSCRIPTEN_VERSION_SHARP"
|
||||||
|
test "$EMSCRIPTEN_VERSION_LIBVIPS" = "$EMSCRIPTEN_VERSION_SHARP"
|
||||||
- name: Test
|
- name: Test
|
||||||
run: emmake npm test
|
run: emmake npm test
|
||||||
- name: Test packaging
|
- name: Test packaging
|
||||||
@@ -185,7 +195,7 @@ jobs:
|
|||||||
emmake npm run package-from-local-build
|
emmake npm run package-from-local-build
|
||||||
npm pkg set "optionalDependencies.@img/sharp-wasm32=file:./npm/wasm32"
|
npm pkg set "optionalDependencies.@img/sharp-wasm32=file:./npm/wasm32"
|
||||||
npm run clean
|
npm run clean
|
||||||
rm -r node_modules/@img/sharp-linux-x64
|
rm -rf node_modules/@img/sharp-linux-x64
|
||||||
npm install --cpu=wasm32
|
npm install --cpu=wasm32
|
||||||
npm test
|
npm test
|
||||||
- name: Prebuild
|
- name: Prebuild
|
||||||
@@ -194,48 +204,3 @@ jobs:
|
|||||||
npm_config_nodedir: emscripten
|
npm_config_nodedir: emscripten
|
||||||
prebuild_upload: ${{ secrets.GITHUB_TOKEN }}
|
prebuild_upload: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: cd src && ln -s ../package.json && emmake npx prebuild --platform=emscripten --arch=wasm32 --strip=0
|
run: cd src && ln -s ../package.json && emmake npx prebuild --platform=emscripten --arch=wasm32 --strip=0
|
||||||
macstadium-runner:
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
name: ${{ matrix.platform }} - Node.js ${{ matrix.nodejs_version_major }} ${{ matrix.prebuild && '- prebuild' }}
|
|
||||||
runs-on: macos-m1
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- nodejs_arch: x64
|
|
||||||
nodejs_version: "^18.17.0"
|
|
||||||
nodejs_version_major: 18
|
|
||||||
platform: darwin-x64
|
|
||||||
- nodejs_arch: arm64
|
|
||||||
nodejs_version: "^18.17.0"
|
|
||||||
nodejs_version_major: 18
|
|
||||||
platform: darwin-arm64
|
|
||||||
prebuild: true
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: /usr/bin/arch -arch arm64e /bin/bash -l {0}
|
|
||||||
steps:
|
|
||||||
- name: Dependencies (Node.js)
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: ${{ matrix.nodejs_version }}
|
|
||||||
architecture: ${{ matrix.nodejs_arch }}
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Install
|
|
||||||
run: npm install --build-from-source
|
|
||||||
- name: Test
|
|
||||||
run: npm test
|
|
||||||
- name: Test packaging
|
|
||||||
run: |
|
|
||||||
npm run package-from-local-build
|
|
||||||
npm pkg set "optionalDependencies.@img/sharp-${{ matrix.platform }}=file:./npm/${{ matrix.platform }}"
|
|
||||||
npm run clean
|
|
||||||
npm install --ignore-scripts
|
|
||||||
npm test
|
|
||||||
- name: Prebuild
|
|
||||||
if: matrix.prebuild && startsWith(github.ref, 'refs/tags/')
|
|
||||||
env:
|
|
||||||
prebuild_upload: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: cd src && ln -s ../package.json && npx prebuild
|
|
||||||
|
|||||||
36
.github/workflows/npm.yml
vendored
36
.github/workflows/npm.yml
vendored
@@ -27,6 +27,10 @@ jobs:
|
|||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
runtime: node
|
runtime: node
|
||||||
package-manager: yarn
|
package-manager: yarn
|
||||||
|
- name: linux-x64-node-yarn-pnp
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
runtime: node
|
||||||
|
package-manager: yarn-pnp
|
||||||
- name: linux-x64-deno
|
- name: linux-x64-deno
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
runtime: deno
|
runtime: deno
|
||||||
@@ -46,6 +50,10 @@ jobs:
|
|||||||
runs-on: macos-11
|
runs-on: macos-11
|
||||||
runtime: node
|
runtime: node
|
||||||
package-manager: yarn
|
package-manager: yarn
|
||||||
|
- name: darwin-x64-node-yarn-pnp
|
||||||
|
runs-on: macos-11
|
||||||
|
runtime: node
|
||||||
|
package-manager: yarn-pnp
|
||||||
- name: darwin-x64-deno
|
- name: darwin-x64-deno
|
||||||
runs-on: macos-11
|
runs-on: macos-11
|
||||||
runtime: deno
|
runtime: deno
|
||||||
@@ -65,6 +73,10 @@ jobs:
|
|||||||
runs-on: windows-2019
|
runs-on: windows-2019
|
||||||
runtime: node
|
runtime: node
|
||||||
package-manager: yarn
|
package-manager: yarn
|
||||||
|
- name: win32-x64-node-yarn-pnp
|
||||||
|
runs-on: windows-2019
|
||||||
|
runtime: node
|
||||||
|
package-manager: yarn-pnp
|
||||||
- name: win32-x64-deno
|
- name: win32-x64-deno
|
||||||
runs-on: windows-2019
|
runs-on: windows-2019
|
||||||
runtime: deno
|
runtime: deno
|
||||||
@@ -72,7 +84,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
if: ${{ matrix.runtime == 'node' }}
|
if: ${{ matrix.runtime == 'node' }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
- name: Install pnpm
|
- name: Install pnpm
|
||||||
@@ -105,7 +117,8 @@ jobs:
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"sharp": "${{ steps.version.outputs.semver }}"
|
"sharp": "${{ steps.version.outputs.semver }}"
|
||||||
}
|
},
|
||||||
|
"type": "module"
|
||||||
}
|
}
|
||||||
- name: Create release.mjs
|
- name: Create release.mjs
|
||||||
uses: DamianReeves/write-file-action@v1.2
|
uses: DamianReeves/write-file-action@v1.2
|
||||||
@@ -114,22 +127,22 @@ jobs:
|
|||||||
contents: |
|
contents: |
|
||||||
import { deepStrictEqual } from 'node:assert';
|
import { deepStrictEqual } from 'node:assert';
|
||||||
import sharp from 'sharp';
|
import sharp from 'sharp';
|
||||||
deepStrictEqual(['.jpg', '.jpeg', '.jpe'], sharp.format.jpeg.input.fileSuffix);
|
deepStrictEqual(['.jpg', '.jpeg', '.jpe', '.jfif'], sharp.format.jpeg.input.fileSuffix);
|
||||||
|
|
||||||
- name: Run with Node.js + npm
|
- name: Run with Node.js + npm
|
||||||
if: ${{ matrix.runtime == 'node' && matrix.package-manager == 'npm' }}
|
if: ${{ matrix.package-manager == 'npm' }}
|
||||||
run: |
|
run: |
|
||||||
npm install --ignore-scripts
|
npm install --ignore-scripts
|
||||||
node release.mjs
|
node release.mjs
|
||||||
|
|
||||||
- name: Run with Node.js + pnpm
|
- name: Run with Node.js + pnpm
|
||||||
if: ${{ matrix.runtime == 'node' && matrix.package-manager == 'pnpm' }}
|
if: ${{ matrix.package-manager == 'pnpm' }}
|
||||||
run: |
|
run: |
|
||||||
pnpm install --ignore-scripts
|
pnpm install --ignore-scripts
|
||||||
node release.mjs
|
node release.mjs
|
||||||
|
|
||||||
- name: Run with Node.js + yarn
|
- name: Run with Node.js + yarn
|
||||||
if: ${{ matrix.runtime == 'node' && matrix.package-manager == 'yarn' }}
|
if: ${{ matrix.package-manager == 'yarn' }}
|
||||||
run: |
|
run: |
|
||||||
corepack enable
|
corepack enable
|
||||||
yarn set version stable
|
yarn set version stable
|
||||||
@@ -139,6 +152,17 @@ jobs:
|
|||||||
yarn install
|
yarn install
|
||||||
node release.mjs
|
node release.mjs
|
||||||
|
|
||||||
|
- name: Run with Node.js + yarn pnp
|
||||||
|
if: ${{ matrix.package-manager == 'yarn-pnp' }}
|
||||||
|
run: |
|
||||||
|
corepack enable
|
||||||
|
yarn set version stable
|
||||||
|
yarn config set enableImmutableInstalls false
|
||||||
|
yarn config set enableScripts false
|
||||||
|
yarn config set nodeLinker pnp
|
||||||
|
yarn install
|
||||||
|
yarn node release.mjs
|
||||||
|
|
||||||
- name: Run with Deno
|
- name: Run with Deno
|
||||||
if: ${{ matrix.runtime == 'deno' }}
|
if: ${{ matrix.runtime == 'deno' }}
|
||||||
run: deno run --allow-read --allow-ffi release.mjs
|
run: deno run --allow-read --allow-ffi release.mjs
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ smaller, web-friendly JPEG, PNG, WebP, GIF and AVIF images of varying dimensions
|
|||||||
|
|
||||||
It can be used with all JavaScript runtimes
|
It can be used with all JavaScript runtimes
|
||||||
that provide support for Node-API v9, including
|
that provide support for Node-API v9, including
|
||||||
Node.js >= 18.17.0, Deno and Bun.
|
Node.js (^18.17.0 or >= 20.3.0), Deno and Bun.
|
||||||
|
|
||||||
Resizing an image is typically 4x-5x faster than using the
|
Resizing an image is typically 4x-5x faster than using the
|
||||||
quickest ImageMagick and GraphicsMagick settings
|
quickest ImageMagick and GraphicsMagick settings
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ Non-critical problems encountered during processing are emitted as `warning` eve
|
|||||||
|
|
||||||
Implements the [stream.Duplex](http://nodejs.org/api/stream.html#stream_class_stream_duplex) class.
|
Implements the [stream.Duplex](http://nodejs.org/api/stream.html#stream_class_stream_duplex) class.
|
||||||
|
|
||||||
|
When loading more than one page/frame of an animated image,
|
||||||
|
these are combined as a vertically-stacked "toilet roll" image
|
||||||
|
where the overall height is the `pageHeight` multiplied by the number of `pages`.
|
||||||
|
|
||||||
**Throws**:
|
**Throws**:
|
||||||
|
|
||||||
- <code>Error</code> Invalid parameters
|
- <code>Error</code> Invalid parameters
|
||||||
@@ -62,7 +66,7 @@ Implements the [stream.Duplex](http://nodejs.org/api/stream.html#stream_class_st
|
|||||||
| [options.text.dpi] | <code>number</code> | <code>72</code> | the resolution (size) at which to render the text. Does not take effect if `height` is specified. |
|
| [options.text.dpi] | <code>number</code> | <code>72</code> | the resolution (size) at which to render the text. Does not take effect if `height` is specified. |
|
||||||
| [options.text.rgba] | <code>boolean</code> | <code>false</code> | set this to true to enable RGBA output. This is useful for colour emoji rendering, or support for pango markup features like `<span foreground="red">Red!</span>`. |
|
| [options.text.rgba] | <code>boolean</code> | <code>false</code> | set this to true to enable RGBA output. This is useful for colour emoji rendering, or support for pango markup features like `<span foreground="red">Red!</span>`. |
|
||||||
| [options.text.spacing] | <code>number</code> | <code>0</code> | text line height in points. Will use the font line height if none is specified. |
|
| [options.text.spacing] | <code>number</code> | <code>0</code> | text line height in points. Will use the font line height if none is specified. |
|
||||||
| [options.text.wrap] | <code>string</code> | <code>"'word'"</code> | word wrapping style when width is provided, one of: 'word', 'char', 'charWord' (prefer char, fallback to word) or 'none'. |
|
| [options.text.wrap] | <code>string</code> | <code>"'word'"</code> | word wrapping style when width is provided, one of: 'word', 'char', 'word-char' (prefer word, fallback to char) or 'none'. |
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
```js
|
```js
|
||||||
@@ -75,14 +79,16 @@ sharp('input.jpg')
|
|||||||
```
|
```
|
||||||
**Example**
|
**Example**
|
||||||
```js
|
```js
|
||||||
// Read image data from readableStream,
|
// Read image data from remote URL,
|
||||||
// resize to 300 pixels wide,
|
// resize to 300 pixels wide,
|
||||||
// emit an 'info' event with calculated dimensions
|
// emit an 'info' event with calculated dimensions
|
||||||
// and finally write image data to writableStream
|
// and finally write image data to writableStream
|
||||||
var transformer = sharp()
|
const { body } = fetch('https://...');
|
||||||
|
const readableStream = Readable.fromWeb(body);
|
||||||
|
const transformer = sharp()
|
||||||
.resize(300)
|
.resize(300)
|
||||||
.on('info', function(info) {
|
.on('info', ({ height }) => {
|
||||||
console.log('Image height is ' + info.height);
|
console.log(`Image height is ${height}`);
|
||||||
});
|
});
|
||||||
readableStream.pipe(transformer).pipe(writableStream);
|
readableStream.pipe(transformer).pipe(writableStream);
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ The use of `rotate` without an angle will remove the EXIF `Orientation` tag, if
|
|||||||
Only one rotation can occur per pipeline.
|
Only one rotation can occur per pipeline.
|
||||||
Previous calls to `rotate` in the same pipeline will be ignored.
|
Previous calls to `rotate` in the same pipeline will be ignored.
|
||||||
|
|
||||||
|
Multi-page images can only be rotated by 180 degrees.
|
||||||
|
|
||||||
Method order is important when rotating, resizing and/or extracting regions,
|
Method order is important when rotating, resizing and/or extracting regions,
|
||||||
for example `.rotate(x).extract(y)` will produce a different result to `.extract(y).rotate(x)`.
|
for example `.rotate(x).extract(y)` will produce a different result to `.extract(y).rotate(x)`.
|
||||||
|
|
||||||
|
|||||||
@@ -367,10 +367,14 @@ const data = await sharp(input)
|
|||||||
|
|
||||||
Use these PNG options for output image.
|
Use these PNG options for output image.
|
||||||
|
|
||||||
By default, PNG output is full colour at 8 or 16 bits per pixel.
|
By default, PNG output is full colour at 8 bits per pixel.
|
||||||
|
|
||||||
Indexed PNG input at 1, 2 or 4 bits per pixel is converted to 8 bits per pixel.
|
Indexed PNG input at 1, 2 or 4 bits per pixel is converted to 8 bits per pixel.
|
||||||
Set `palette` to `true` for slower, indexed PNG output.
|
Set `palette` to `true` for slower, indexed PNG output.
|
||||||
|
|
||||||
|
For 16 bits per pixel output, convert to `rgb16` via
|
||||||
|
[toColourspace](/api-colour#tocolourspace).
|
||||||
|
|
||||||
|
|
||||||
**Throws**:
|
**Throws**:
|
||||||
|
|
||||||
@@ -405,6 +409,14 @@ const data = await sharp(input)
|
|||||||
.png({ palette: true })
|
.png({ palette: true })
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
```
|
```
|
||||||
|
**Example**
|
||||||
|
```js
|
||||||
|
// Output 16 bits per pixel RGB(A)
|
||||||
|
const data = await sharp(input)
|
||||||
|
.toColourspace('rgb16')
|
||||||
|
.png()
|
||||||
|
.toBuffer();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## webp
|
## webp
|
||||||
@@ -605,6 +617,7 @@ sharp('input.svg')
|
|||||||
Use these AVIF options for output image.
|
Use these AVIF options for output image.
|
||||||
|
|
||||||
AVIF image sequences are not supported.
|
AVIF image sequences are not supported.
|
||||||
|
Prebuilt binaries support a bitdepth of 8 only.
|
||||||
|
|
||||||
|
|
||||||
**Throws**:
|
**Throws**:
|
||||||
@@ -620,6 +633,7 @@ AVIF image sequences are not supported.
|
|||||||
| [options.lossless] | <code>boolean</code> | <code>false</code> | use lossless compression |
|
| [options.lossless] | <code>boolean</code> | <code>false</code> | use lossless compression |
|
||||||
| [options.effort] | <code>number</code> | <code>4</code> | CPU effort, between 0 (fastest) and 9 (slowest) |
|
| [options.effort] | <code>number</code> | <code>4</code> | CPU effort, between 0 (fastest) and 9 (slowest) |
|
||||||
| [options.chromaSubsampling] | <code>string</code> | <code>"'4:4:4'"</code> | set to '4:2:0' to use chroma subsampling |
|
| [options.chromaSubsampling] | <code>string</code> | <code>"'4:4:4'"</code> | set to '4:2:0' to use chroma subsampling |
|
||||||
|
| [options.bitdepth] | <code>number</code> | <code>8</code> | set bitdepth to 8, 10 or 12 bit |
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
```js
|
```js
|
||||||
@@ -658,6 +672,7 @@ globally-installed libvips compiled with support for libheif, libde265 and x265.
|
|||||||
| [options.lossless] | <code>boolean</code> | <code>false</code> | use lossless compression |
|
| [options.lossless] | <code>boolean</code> | <code>false</code> | use lossless compression |
|
||||||
| [options.effort] | <code>number</code> | <code>4</code> | CPU effort, between 0 (fastest) and 9 (slowest) |
|
| [options.effort] | <code>number</code> | <code>4</code> | CPU effort, between 0 (fastest) and 9 (slowest) |
|
||||||
| [options.chromaSubsampling] | <code>string</code> | <code>"'4:4:4'"</code> | set to '4:2:0' to use chroma subsampling |
|
| [options.chromaSubsampling] | <code>string</code> | <code>"'4:4:4'"</code> | set to '4:2:0' to use chroma subsampling |
|
||||||
|
| [options.bitdepth] | <code>number</code> | <code>8</code> | set bitdepth to 8, 10 or 12 bit |
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
```js
|
```js
|
||||||
@@ -763,7 +778,7 @@ The prebuilt binaries do not include this - see
|
|||||||
| [options.angle] | <code>number</code> | <code>0</code> | tile angle of rotation, must be a multiple of 90. |
|
| [options.angle] | <code>number</code> | <code>0</code> | tile angle of rotation, must be a multiple of 90. |
|
||||||
| [options.background] | <code>string</code> \| <code>Object</code> | <code>"{r: 255, g: 255, b: 255, alpha: 1}"</code> | background colour, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to white without transparency. |
|
| [options.background] | <code>string</code> \| <code>Object</code> | <code>"{r: 255, g: 255, b: 255, alpha: 1}"</code> | background colour, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to white without transparency. |
|
||||||
| [options.depth] | <code>string</code> | | how deep to make the pyramid, possible values are `onepixel`, `onetile` or `one`, default based on layout. |
|
| [options.depth] | <code>string</code> | | how deep to make the pyramid, possible values are `onepixel`, `onetile` or `one`, default based on layout. |
|
||||||
| [options.skipBlanks] | <code>number</code> | <code>-1</code> | threshold to skip tile generation, a value 0 - 255 for 8-bit images or 0 - 65535 for 16-bit images |
|
| [options.skipBlanks] | <code>number</code> | <code>-1</code> | Threshold to skip tile generation. Range is 0-255 for 8-bit images, 0-65535 for 16-bit images. Default is 5 for `google` layout, -1 (no skip) otherwise. |
|
||||||
| [options.container] | <code>string</code> | <code>"'fs'"</code> | tile container, with value `fs` (filesystem) or `zip` (compressed file). |
|
| [options.container] | <code>string</code> | <code>"'fs'"</code> | tile container, with value `fs` (filesystem) or `zip` (compressed file). |
|
||||||
| [options.layout] | <code>string</code> | <code>"'dz'"</code> | filesystem layout, possible values are `dz`, `iiif`, `iiif3`, `zoomify` or `google`. |
|
| [options.layout] | <code>string</code> | <code>"'dz'"</code> | filesystem layout, possible values are `dz`, `iiif`, `iiif3`, `zoomify` or `google`. |
|
||||||
| [options.centre] | <code>boolean</code> | <code>false</code> | centre image in tile. |
|
| [options.centre] | <code>boolean</code> | <code>false</code> | centre image in tile. |
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ const counters = sharp.counters(); // { queue: 2, process: 4 }
|
|||||||
> simd([simd]) ⇒ <code>boolean</code>
|
> simd([simd]) ⇒ <code>boolean</code>
|
||||||
|
|
||||||
Get and set use of SIMD vector unit instructions.
|
Get and set use of SIMD vector unit instructions.
|
||||||
Requires libvips to have been compiled with liborc support.
|
Requires libvips to have been compiled with highway support.
|
||||||
|
|
||||||
Improves the performance of `resize`, `blur` and `sharpen` operations
|
Improves the performance of `resize`, `blur` and `sharpen` operations
|
||||||
by taking advantage of the SIMD vector unit of the CPU, e.g. Intel SSE and ARM NEON.
|
by taking advantage of the SIMD vector unit of the CPU, e.g. Intel SSE and ARM NEON.
|
||||||
@@ -165,12 +165,12 @@ by taking advantage of the SIMD vector unit of the CPU, e.g. Intel SSE and ARM N
|
|||||||
**Example**
|
**Example**
|
||||||
```js
|
```js
|
||||||
const simd = sharp.simd();
|
const simd = sharp.simd();
|
||||||
// simd is `true` if the runtime use of liborc is currently enabled
|
// simd is `true` if the runtime use of highway is currently enabled
|
||||||
```
|
```
|
||||||
**Example**
|
**Example**
|
||||||
```js
|
```js
|
||||||
const simd = sharp.simd(false);
|
const simd = sharp.simd(false);
|
||||||
// prevent libvips from using liborc at runtime
|
// prevent libvips from using highway at runtime
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,56 @@
|
|||||||
|
|
||||||
## v0.33 - *gauge*
|
## v0.33 - *gauge*
|
||||||
|
|
||||||
Requires libvips v8.15.0
|
Requires libvips v8.15.2
|
||||||
|
|
||||||
### v0.33.0 - TBD
|
### v0.33.3 - 23rd March 2024
|
||||||
|
|
||||||
* Drop support for Node.js 14 and 16, now requires Node.js >= 18.17.0
|
* Upgrade to libvips v8.15.2 for upstream bug fixes.
|
||||||
|
|
||||||
|
* Ensure `keepIccProfile` retains P3 and CMYK input profiles.
|
||||||
|
[#3906](https://github.com/lovell/sharp/issues/3906)
|
||||||
|
[#4008](https://github.com/lovell/sharp/issues/4008)
|
||||||
|
|
||||||
|
* Ensure `text.wrap` property can accept `word-char` as value.
|
||||||
|
[#4028](https://github.com/lovell/sharp/pull/4028)
|
||||||
|
[@yolopunk](https://github.com/yolopunk)
|
||||||
|
|
||||||
|
* Ensure `clone` takes a deep copy of existing options.
|
||||||
|
[#4029](https://github.com/lovell/sharp/issues/4029)
|
||||||
|
|
||||||
|
* Add `bitdepth` option to `heif` output (prebuilt binaries support 8-bit only).
|
||||||
|
[#4036](https://github.com/lovell/sharp/pull/4036)
|
||||||
|
[@mertalev](https://github.com/mertalev)
|
||||||
|
|
||||||
|
### v0.33.2 - 12th January 2024
|
||||||
|
|
||||||
|
* Upgrade to libvips v8.15.1 for upstream bug fixes.
|
||||||
|
|
||||||
|
* TypeScript: add definition for `keepMetadata`.
|
||||||
|
[#3914](https://github.com/lovell/sharp/pull/3914)
|
||||||
|
[@abhi0498](https://github.com/abhi0498)
|
||||||
|
|
||||||
|
* Ensure `extend` operation stays sequential when copying (regression in 0.32.0).
|
||||||
|
[#3928](https://github.com/lovell/sharp/issues/3928)
|
||||||
|
|
||||||
|
* Improve error handling for unsupported multi-page rotation.
|
||||||
|
[#3940](https://github.com/lovell/sharp/issues/3940)
|
||||||
|
|
||||||
|
### v0.33.1 - 17th December 2023
|
||||||
|
|
||||||
|
* Add support for Yarn Plug'n'Play filesystem layout.
|
||||||
|
[#3888](https://github.com/lovell/sharp/issues/3888)
|
||||||
|
|
||||||
|
* Emit warning when attempting to use invalid ICC profiles.
|
||||||
|
[#3895](https://github.com/lovell/sharp/issues/3895)
|
||||||
|
|
||||||
|
* Ensure `VIPS_NOVECTOR` environment variable is respected.
|
||||||
|
[#3897](https://github.com/lovell/sharp/pull/3897)
|
||||||
|
[@icetee](https://github.com/icetee)
|
||||||
|
|
||||||
|
### v0.33.0 - 29th November 2023
|
||||||
|
|
||||||
|
* Drop support for Node.js 14 and 16, now requires Node.js ^18.17.0 or >= 20.3.0
|
||||||
|
|
||||||
* Prebuilt binaries distributed via npm registry and installed via package manager.
|
* Prebuilt binaries distributed via npm registry and installed via package manager.
|
||||||
|
|
||||||
|
|||||||
@@ -281,3 +281,12 @@ GitHub: https://github.com/dnsbty
|
|||||||
|
|
||||||
Name: Ingvar Stepanyan
|
Name: Ingvar Stepanyan
|
||||||
GitHub: https://github.com/RReverser
|
GitHub: https://github.com/RReverser
|
||||||
|
|
||||||
|
Name: Tamás András Horváth
|
||||||
|
GitHub: https://github.com/icetee
|
||||||
|
|
||||||
|
Name: Aaron Che
|
||||||
|
GitHub: https://github.com/yolopunk
|
||||||
|
|
||||||
|
Name: Mert Alev
|
||||||
|
GitHub: https://github.com/mertalev
|
||||||
|
|||||||
117
docs/install.md
117
docs/install.md
@@ -2,6 +2,12 @@
|
|||||||
|
|
||||||
Works with your choice of JavaScript package manager.
|
Works with your choice of JavaScript package manager.
|
||||||
|
|
||||||
|
> ⚠️ **Please ensure your package manager is configured to install optional dependencies**
|
||||||
|
|
||||||
|
If a package manager lockfile must support multiple platforms,
|
||||||
|
please see the [cross-platform](#cross-platform) section
|
||||||
|
to help decide which package manager is appropriate.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npm install sharp
|
npm install sharp
|
||||||
```
|
```
|
||||||
@@ -11,7 +17,12 @@ pnpm add sharp
|
|||||||
```
|
```
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
yarn add sharp # v3 recommended, Plug'n'Play unsupported
|
yarn add sharp
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# yarn v1 (maintenance mode)
|
||||||
|
yarn add sharp --ignore-engines
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
@@ -24,7 +35,7 @@ deno run --allow-ffi ...
|
|||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
* Node-API v9 compatible runtime e.g. Node.js >= 18.17.0
|
* Node-API v9 compatible runtime e.g. Node.js ^18.17.0 or >=20.3.0.
|
||||||
|
|
||||||
## Prebuilt binaries
|
## Prebuilt binaries
|
||||||
|
|
||||||
@@ -42,6 +53,40 @@ Ready-compiled sharp and libvips binaries are provided for use on the most commo
|
|||||||
This provides support for the
|
This provides support for the
|
||||||
JPEG, PNG, WebP, AVIF (limited to 8-bit depth), TIFF, GIF and SVG (input) image formats.
|
JPEG, PNG, WebP, AVIF (limited to 8-bit depth), TIFF, GIF and SVG (input) image formats.
|
||||||
|
|
||||||
|
## Cross-platform
|
||||||
|
|
||||||
|
At install time, package managers will automatically select prebuilt binaries
|
||||||
|
for the current OS platform and CPU architecture, where available.
|
||||||
|
|
||||||
|
Some package managers support multiple platforms and architectures
|
||||||
|
within the same installation tree and/or using the same lockfile.
|
||||||
|
|
||||||
|
### npm v10+
|
||||||
|
|
||||||
|
> ⚠️ **npm `package-lock.json` files can cause installation problems due to [npm bug #4828](https://github.com/npm/cli/issues/4828)**
|
||||||
|
|
||||||
|
Provides limited support via `--os`, `--cpu` and `--libc` flags.
|
||||||
|
|
||||||
|
Example to support both Intel and ARM CPUs on macOS:
|
||||||
|
```sh
|
||||||
|
npm install --cpu=x64 --os=darwin sharp
|
||||||
|
npm install --cpu=arm64 --os=darwin sharp
|
||||||
|
```
|
||||||
|
|
||||||
|
Example to support both glibc and musl-based Linux:
|
||||||
|
```sh
|
||||||
|
npm install --cpu=x64 --os=linux sharp
|
||||||
|
npm install --cpu=x64 --os=linux --libc=musl sharp
|
||||||
|
```
|
||||||
|
|
||||||
|
### yarn v3+
|
||||||
|
|
||||||
|
Use the [supportedArchitectures](https://yarnpkg.com/configuration/yarnrc#supportedArchitectures) configuration.
|
||||||
|
|
||||||
|
### pnpm v8+
|
||||||
|
|
||||||
|
Use the [supportedArchitectures](https://pnpm.io/package_json#pnpmsupportedarchitectures) configuration.
|
||||||
|
|
||||||
## Custom libvips
|
## Custom libvips
|
||||||
|
|
||||||
To use a custom, globally-installed version of libvips instead of the provided binaries,
|
To use a custom, globally-installed version of libvips instead of the provided binaries,
|
||||||
@@ -64,8 +109,8 @@ This module will be compiled from source at `npm install` time when:
|
|||||||
Building from source requires:
|
Building from source requires:
|
||||||
|
|
||||||
* C++11 compiler
|
* C++11 compiler
|
||||||
* [node-addon-api](https://www.npmjs.com/package/node-addon-api)
|
* [node-addon-api](https://www.npmjs.com/package/node-addon-api) version 7+
|
||||||
* [node-gyp](https://github.com/nodejs/node-gyp#installation) and its dependencies
|
* [node-gyp](https://github.com/nodejs/node-gyp#installation) version 9+ and its dependencies
|
||||||
|
|
||||||
There is an install-time check for these dependencies.
|
There is an install-time check for these dependencies.
|
||||||
If `node-addon-api` or `node-gyp` cannot be found, try adding them via:
|
If `node-addon-api` or `node-gyp` cannot be found, try adding them via:
|
||||||
@@ -83,6 +128,10 @@ can be used to configure the target environment.
|
|||||||
Experimental support is provided for runtime environments that provide
|
Experimental support is provided for runtime environments that provide
|
||||||
multi-threaded Wasm via Workers.
|
multi-threaded Wasm via Workers.
|
||||||
|
|
||||||
|
Use in web browsers is unsupported.
|
||||||
|
|
||||||
|
Native text rendering is unsupported.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npm install --cpu=wasm32 sharp
|
npm install --cpu=wasm32 sharp
|
||||||
```
|
```
|
||||||
@@ -124,25 +173,11 @@ must include binaries for either the linux-x64 or linux-arm64 platforms
|
|||||||
depending on the chosen architecture.
|
depending on the chosen architecture.
|
||||||
|
|
||||||
When building your deployment package on a machine that differs from the target architecture,
|
When building your deployment package on a machine that differs from the target architecture,
|
||||||
you will need to install either `@img/sharp-linux-x64` or `@img/sharp-linux-arm64` package.
|
see the [cross-platform](#cross-platform) section to help decide which package manager is appropriate
|
||||||
|
and how to configure it.
|
||||||
|
|
||||||
```sh
|
Some package managers use symbolic links
|
||||||
npm install --os=linux --cpu=x64 sharp
|
but AWS Lambda does not support these within deployment packages.
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install --os=linux --cpu=arm64 sharp
|
|
||||||
```
|
|
||||||
|
|
||||||
When using npm 9 or earlier, this can be achieved using the following:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install --force @img/sharp-linux-x64
|
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install --force @img/sharp-linux-arm64
|
|
||||||
```
|
|
||||||
|
|
||||||
To get the best performance select the largest memory available.
|
To get the best performance select the largest memory available.
|
||||||
A 1536 MB function provides ~12x more CPU time than a 128 MB function.
|
A 1536 MB function provides ~12x more CPU time than a 128 MB function.
|
||||||
@@ -196,6 +231,44 @@ custom:
|
|||||||
- npm install --os=linux --cpu=x64 sharp
|
- npm install --os=linux --cpu=x64 sharp
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### electron
|
||||||
|
|
||||||
|
Ensure `sharp` is unpacked from the ASAR archive file using the
|
||||||
|
[asarUnpack](https://www.electron.build/configuration/configuration.html)
|
||||||
|
option.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"asar": true,
|
||||||
|
"asarUnpack": [
|
||||||
|
"**/node_modules/sharp/**/*",
|
||||||
|
"**/node_modules/@img/**/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### vite
|
||||||
|
|
||||||
|
Ensure `sharp` is excluded from bundling via the
|
||||||
|
[build.rollupOptions](https://vitejs.dev/config/build-options.html)
|
||||||
|
configuration.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
build: {
|
||||||
|
rollupOptions: {
|
||||||
|
external: [
|
||||||
|
"sharp"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
## TypeScript
|
## TypeScript
|
||||||
|
|
||||||
TypeScript definitions are published as part of
|
TypeScript definitions are published as part of
|
||||||
|
|||||||
@@ -9,26 +9,26 @@ The I/O limits of the relevant (de)compression library will generally determine
|
|||||||
|
|
||||||
## Contenders
|
## Contenders
|
||||||
|
|
||||||
* [jimp](https://www.npmjs.com/package/jimp) v0.22.7 - Image processing in pure JavaScript.
|
* [jimp](https://www.npmjs.com/package/jimp) v0.22.10 - Image processing in pure JavaScript.
|
||||||
* [imagemagick](https://www.npmjs.com/package/imagemagick) v0.1.3 - Supports filesystem only and "*has been unmaintained for a long time*".
|
* [imagemagick](https://www.npmjs.com/package/imagemagick) v0.1.3 - Supports filesystem only and "*has been unmaintained for a long time*".
|
||||||
* [gm](https://www.npmjs.com/package/gm) v1.25.0 - Fully featured wrapper around GraphicsMagick's `gm` command line utility.
|
* [gm](https://www.npmjs.com/package/gm) v1.25.0 - Fully featured wrapper around GraphicsMagick's `gm` command line utility.
|
||||||
* [@squoosh/lib](https://www.npmjs.com/package/@squoosh/lib) v0.4.0 - Image libraries transpiled to WebAssembly, includes GPLv3 code, but "*Project no longer maintained*".
|
* [@squoosh/lib](https://www.npmjs.com/package/@squoosh/lib) v0.5.3 - Image libraries transpiled to WebAssembly, includes GPLv3 code, but "*Project no longer maintained*".
|
||||||
* [@squoosh/cli](https://www.npmjs.com/package/@squoosh/cli) v0.7.3 - Command line wrapper around `@squoosh/lib`, avoids GPLv3 by spawning process, but "*Project no longer maintained*".
|
* [@squoosh/cli](https://www.npmjs.com/package/@squoosh/cli) v0.7.3 - Command line wrapper around `@squoosh/lib`, avoids GPLv3 by spawning process, but "*Project no longer maintained*".
|
||||||
* sharp v0.32.0 / libvips v8.14.2 - Caching within libvips disabled to ensure a fair comparison.
|
* sharp v0.33.0 / libvips v8.15.0 - Caching within libvips disabled to ensure a fair comparison.
|
||||||
|
|
||||||
## Environment
|
## Environment
|
||||||
|
|
||||||
### AMD64
|
### AMD64
|
||||||
|
|
||||||
* AWS EC2 us-east-2 [c6a.xlarge](https://aws.amazon.com/ec2/instance-types/c6a/) (4x AMD EPYC 7R13)
|
* AWS EC2 us-east-2 [c7a.xlarge](https://aws.amazon.com/ec2/instance-types/c7a/) (4x AMD EPYC 9R14)
|
||||||
* Ubuntu 22.04 20230303 (ami-0122295b0eb922138)
|
* Ubuntu 23.10 [13f233a16be2](https://hub.docker.com/layers/library/ubuntu/23.10/images/sha256-13f233a16be210b57907b98b0d927ceff7571df390701e14fe1f3901b2c4a4d7)
|
||||||
* Node.js 16.19.1
|
* Node.js 20.10.0
|
||||||
|
|
||||||
### ARM64
|
### ARM64
|
||||||
|
|
||||||
* AWS EC2 us-east-2 [c7g.xlarge](https://aws.amazon.com/ec2/instance-types/c7g/) (4x ARM Graviton3)
|
* AWS EC2 us-east-2 [c7g.xlarge](https://aws.amazon.com/ec2/instance-types/c7g/) (4x ARM Graviton3)
|
||||||
* Ubuntu 22.04 20230303 (ami-0af198159897e7a29)
|
* Ubuntu 23.10 [7708743264cb](https://hub.docker.com/layers/library/ubuntu/23.10/images/sha256-7708743264cbb7f6cf7fc13e915faece45a6cdda455748bc55e58e8de3d27b63)
|
||||||
* Node.js 16.19.1
|
* Node.js 20.10.0
|
||||||
|
|
||||||
## Task: JPEG
|
## Task: JPEG
|
||||||
|
|
||||||
@@ -43,28 +43,28 @@ Note: jimp does not support Lanczos 3, bicubic resampling used instead.
|
|||||||
| Module | Input | Output | Ops/sec | Speed-up |
|
| Module | Input | Output | Ops/sec | Speed-up |
|
||||||
| :----------------- | :----- | :----- | ------: | -------: |
|
| :----------------- | :----- | :----- | ------: | -------: |
|
||||||
| jimp | buffer | buffer | 0.84 | 1.0 |
|
| jimp | buffer | buffer | 0.84 | 1.0 |
|
||||||
| squoosh-cli | file | file | 1.07 | 1.3 |
|
| squoosh-cli | file | file | 1.54 | 1.8 |
|
||||||
| squoosh-lib | buffer | buffer | 1.82 | 2.2 |
|
| squoosh-lib | buffer | buffer | 2.24 | 2.7 |
|
||||||
| gm | buffer | buffer | 8.41 | 10.0 |
|
| imagemagick | file | file | 11.75 | 14.0 |
|
||||||
| gm | file | file | 8.45 | 10.0 |
|
| gm | buffer | buffer | 12.66 | 15.1 |
|
||||||
| imagemagick | file | file | 8.77 | 10.4 |
|
| gm | file | file | 12.72 | 15.1 |
|
||||||
| sharp | stream | stream | 36.36 | 43.3 |
|
| sharp | stream | stream | 48.31 | 57.5 |
|
||||||
| sharp | file | file | 38.67 | 46.0 |
|
| sharp | file | file | 51.42 | 61.2 |
|
||||||
| sharp | buffer | buffer | 39.44 | 47.0 |
|
| sharp | buffer | buffer | 52.41 | 62.4 |
|
||||||
|
|
||||||
#### Results: JPEG (ARM64)
|
#### Results: JPEG (ARM64)
|
||||||
|
|
||||||
| Module | Input | Output | Ops/sec | Speed-up |
|
| Module | Input | Output | Ops/sec | Speed-up |
|
||||||
| :----------------- | :----- | :----- | ------: | -------: |
|
| :----------------- | :----- | :----- | ------: | -------: |
|
||||||
| jimp | buffer | buffer | 1.02 | 1.0 |
|
| jimp | buffer | buffer | 0.88 | 1.0 |
|
||||||
| squoosh-cli | file | file | 1.11 | 1.1 |
|
| squoosh-cli | file | file | 1.18 | 1.3 |
|
||||||
| squoosh-lib | buffer | buffer | 2.08 | 2.0 |
|
| squoosh-lib | buffer | buffer | 1.99 | 2.3 |
|
||||||
| gm | buffer | buffer | 8.80 | 8.6 |
|
| gm | buffer | buffer | 6.06 | 6.9 |
|
||||||
| gm | file | file | 10.05 | 9.9 |
|
| gm | file | file | 10.81 | 12.3 |
|
||||||
| imagemagick | file | file | 10.28 | 10.1 |
|
| imagemagick | file | file | 10.95 | 12.4 |
|
||||||
| sharp | stream | stream | 26.87 | 26.3 |
|
| sharp | stream | stream | 33.15 | 37.7 |
|
||||||
| sharp | file | file | 27.88 | 27.3 |
|
| sharp | file | file | 34.99 | 39.8 |
|
||||||
| sharp | buffer | buffer | 28.40 | 27.8 |
|
| sharp | buffer | buffer | 36.05 | 41.0 |
|
||||||
|
|
||||||
## Task: PNG
|
## Task: PNG
|
||||||
|
|
||||||
@@ -80,25 +80,25 @@ Note: jimp does not support premultiply/unpremultiply.
|
|||||||
|
|
||||||
| Module | Input | Output | Ops/sec | Speed-up |
|
| Module | Input | Output | Ops/sec | Speed-up |
|
||||||
| :----------------- | :----- | :----- | ------: | -------: |
|
| :----------------- | :----- | :----- | ------: | -------: |
|
||||||
| squoosh-cli | file | file | 0.40 | 1.0 |
|
| squoosh-cli | file | file | 0.34 | 1.0 |
|
||||||
| squoosh-lib | buffer | buffer | 0.47 | 1.2 |
|
| squoosh-lib | buffer | buffer | 0.51 | 1.5 |
|
||||||
| gm | file | file | 6.47 | 16.2 |
|
| jimp | buffer | buffer | 3.59 | 10.6 |
|
||||||
| jimp | buffer | buffer | 6.60 | 16.5 |
|
| gm | file | file | 8.54 | 25.1 |
|
||||||
| imagemagick | file | file | 7.08 | 17.7 |
|
| imagemagick | file | file | 9.23 | 27.1 |
|
||||||
| sharp | file | file | 17.80 | 44.5 |
|
| sharp | file | file | 25.43 | 74.8 |
|
||||||
| sharp | buffer | buffer | 18.02 | 45.0 |
|
| sharp | buffer | buffer | 25.70 | 75.6 |
|
||||||
|
|
||||||
### Results: PNG (ARM64)
|
### Results: PNG (ARM64)
|
||||||
|
|
||||||
| Module | Input | Output | Ops/sec | Speed-up |
|
| Module | Input | Output | Ops/sec | Speed-up |
|
||||||
| :----------------- | :----- | :----- | ------: | -------: |
|
| :----------------- | :----- | :----- | ------: | -------: |
|
||||||
| squoosh-cli | file | file | 0.40 | 1.0 |
|
| squoosh-cli | file | file | 0.33 | 1.0 |
|
||||||
| squoosh-lib | buffer | buffer | 0.48 | 1.2 |
|
| squoosh-lib | buffer | buffer | 0.46 | 1.4 |
|
||||||
| gm | file | file | 7.20 | 18.0 |
|
| jimp | buffer | buffer | 3.51 | 10.6 |
|
||||||
| jimp | buffer | buffer | 7.62 | 19.1 |
|
| gm | file | file | 7.47 | 22.6 |
|
||||||
| imagemagick | file | file | 7.96 | 19.9 |
|
| imagemagick | file | file | 8.06 | 24.4 |
|
||||||
| sharp | file | file | 12.97 | 32.4 |
|
| sharp | file | file | 17.31 | 52.5 |
|
||||||
| sharp | buffer | buffer | 13.12 | 32.8 |
|
| sharp | buffer | buffer | 17.66 | 53.5 |
|
||||||
|
|
||||||
## Running the benchmark test
|
## Running the benchmark test
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -3,34 +3,39 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { useGlobalLibvips, globalLibvipsVersion, log, spawnRebuild } = require('../lib/libvips');
|
try {
|
||||||
|
const { useGlobalLibvips, globalLibvipsVersion, log, spawnRebuild } = require('../lib/libvips');
|
||||||
|
|
||||||
const buildFromSource = (msg) => {
|
const buildFromSource = (msg) => {
|
||||||
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');
|
require('node-addon-api');
|
||||||
log('Found node-addon-api');
|
log('Found node-addon-api');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log('Please add node-addon-api to your dependencies');
|
log('Please add node-addon-api to your dependencies');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const gyp = require('node-gyp');
|
const gyp = require('node-gyp');
|
||||||
log(`Found node-gyp version ${gyp().version}`);
|
log(`Found node-gyp version ${gyp().version}`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log('Please add node-gyp to your dependencies');
|
log('Please add node-gyp to your dependencies');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log('See https://sharp.pixelplumbing.com/install#building-from-source');
|
log('See https://sharp.pixelplumbing.com/install#building-from-source');
|
||||||
const status = spawnRebuild();
|
const status = spawnRebuild();
|
||||||
if (status !== 0) {
|
if (status !== 0) {
|
||||||
process.exit(status);
|
process.exit(status);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (useGlobalLibvips()) {
|
if (useGlobalLibvips()) {
|
||||||
buildFromSource(`Detected globally-installed libvips v${globalLibvipsVersion()}`);
|
buildFromSource(`Detected globally-installed libvips v${globalLibvipsVersion()}`);
|
||||||
} else if (process.env.npm_config_build_from_source) {
|
} else if (process.env.npm_config_build_from_source) {
|
||||||
buildFromSource('Detected --build-from-source flag');
|
buildFromSource('Detected --build-from-source flag');
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
const summary = err.message.split(/\n/).slice(0, 1);
|
||||||
|
console.log(`sharp: skipping install check: ${summary}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ function pipelineColourspace (colourspace) {
|
|||||||
if (!is.string(colourspace)) {
|
if (!is.string(colourspace)) {
|
||||||
throw is.invalidParameterError('colourspace', 'string', colourspace);
|
throw is.invalidParameterError('colourspace', 'string', colourspace);
|
||||||
}
|
}
|
||||||
this.options.colourspaceInput = colourspace;
|
this.options.colourspacePipeline = colourspace;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ const debuglog = util.debuglog('sharp');
|
|||||||
*
|
*
|
||||||
* Implements the [stream.Duplex](http://nodejs.org/api/stream.html#stream_class_stream_duplex) class.
|
* Implements the [stream.Duplex](http://nodejs.org/api/stream.html#stream_class_stream_duplex) class.
|
||||||
*
|
*
|
||||||
|
* When loading more than one page/frame of an animated image,
|
||||||
|
* these are combined as a vertically-stacked "toilet roll" image
|
||||||
|
* where the overall height is the `pageHeight` multiplied by the number of `pages`.
|
||||||
|
*
|
||||||
* @constructs Sharp
|
* @constructs Sharp
|
||||||
*
|
*
|
||||||
* @emits Sharp#info
|
* @emits Sharp#info
|
||||||
@@ -36,14 +40,16 @@ const debuglog = util.debuglog('sharp');
|
|||||||
* });
|
* });
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* // Read image data from readableStream,
|
* // Read image data from remote URL,
|
||||||
* // resize to 300 pixels wide,
|
* // resize to 300 pixels wide,
|
||||||
* // emit an 'info' event with calculated dimensions
|
* // emit an 'info' event with calculated dimensions
|
||||||
* // and finally write image data to writableStream
|
* // and finally write image data to writableStream
|
||||||
* var transformer = sharp()
|
* const { body } = fetch('https://...');
|
||||||
|
* const readableStream = Readable.fromWeb(body);
|
||||||
|
* const transformer = sharp()
|
||||||
* .resize(300)
|
* .resize(300)
|
||||||
* .on('info', function(info) {
|
* .on('info', ({ height }) => {
|
||||||
* console.log('Image height is ' + info.height);
|
* console.log(`Image height is ${height}`);
|
||||||
* });
|
* });
|
||||||
* readableStream.pipe(transformer).pipe(writableStream);
|
* readableStream.pipe(transformer).pipe(writableStream);
|
||||||
*
|
*
|
||||||
@@ -160,7 +166,7 @@ const debuglog = util.debuglog('sharp');
|
|||||||
* @param {number} [options.text.dpi=72] - the resolution (size) at which to render the text. Does not take effect if `height` is specified.
|
* @param {number} [options.text.dpi=72] - the resolution (size) at which to render the text. Does not take effect if `height` is specified.
|
||||||
* @param {boolean} [options.text.rgba=false] - set this to true to enable RGBA output. This is useful for colour emoji rendering, or support for pango markup features like `<span foreground="red">Red!</span>`.
|
* @param {boolean} [options.text.rgba=false] - set this to true to enable RGBA output. This is useful for colour emoji rendering, or support for pango markup features like `<span foreground="red">Red!</span>`.
|
||||||
* @param {number} [options.text.spacing=0] - text line height in points. Will use the font line height if none is specified.
|
* @param {number} [options.text.spacing=0] - text line height in points. Will use the font line height if none is specified.
|
||||||
* @param {string} [options.text.wrap='word'] - word wrapping style when width is provided, one of: 'word', 'char', 'charWord' (prefer char, fallback to word) or 'none'.
|
* @param {string} [options.text.wrap='word'] - word wrapping style when width is provided, one of: 'word', 'char', 'word-char' (prefer word, fallback to char) or 'none'.
|
||||||
* @returns {Sharp}
|
* @returns {Sharp}
|
||||||
* @throws {Error} Invalid parameters
|
* @throws {Error} Invalid parameters
|
||||||
*/
|
*/
|
||||||
@@ -251,7 +257,7 @@ const Sharp = function (input, options) {
|
|||||||
removeAlpha: false,
|
removeAlpha: false,
|
||||||
ensureAlpha: -1,
|
ensureAlpha: -1,
|
||||||
colourspace: 'srgb',
|
colourspace: 'srgb',
|
||||||
colourspaceInput: 'last',
|
colourspacePipeline: 'last',
|
||||||
composite: [],
|
composite: [],
|
||||||
// output
|
// output
|
||||||
fileOut: '',
|
fileOut: '',
|
||||||
@@ -319,6 +325,7 @@ const Sharp = function (input, options) {
|
|||||||
heifCompression: 'av1',
|
heifCompression: 'av1',
|
||||||
heifEffort: 4,
|
heifEffort: 4,
|
||||||
heifChromaSubsampling: '4:4:4',
|
heifChromaSubsampling: '4:4:4',
|
||||||
|
heifBitdepth: 8,
|
||||||
jxlDistance: 1,
|
jxlDistance: 1,
|
||||||
jxlDecodingTier: 0,
|
jxlDecodingTier: 0,
|
||||||
jxlEffort: 7,
|
jxlEffort: 7,
|
||||||
@@ -419,13 +426,16 @@ Object.setPrototypeOf(Sharp, stream.Duplex);
|
|||||||
function clone () {
|
function clone () {
|
||||||
// Clone existing options
|
// Clone existing options
|
||||||
const clone = this.constructor.call();
|
const clone = this.constructor.call();
|
||||||
clone.options = Object.assign({}, this.options);
|
const { debuglog, queueListener, ...options } = this.options;
|
||||||
|
clone.options = structuredClone(options);
|
||||||
|
clone.options.debuglog = debuglog;
|
||||||
|
clone.options.queueListener = queueListener;
|
||||||
// Pass 'finish' event to clone for Stream-based input
|
// Pass 'finish' event to clone for Stream-based input
|
||||||
if (this._isStreamInput()) {
|
if (this._isStreamInput()) {
|
||||||
this.on('finish', () => {
|
this.on('finish', () => {
|
||||||
// Clone inherits input data
|
// Clone inherits input data
|
||||||
this._flattenBufferIn();
|
this._flattenBufferIn();
|
||||||
clone.options.bufferIn = this.options.bufferIn;
|
clone.options.input.buffer = this.options.input.buffer;
|
||||||
clone.emit('finish');
|
clone.emit('finish');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
16
lib/index.d.ts
vendored
16
lib/index.d.ts
vendored
@@ -126,7 +126,7 @@ declare namespace sharp {
|
|||||||
function counters(): SharpCounters;
|
function counters(): SharpCounters;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get and set use of SIMD vector unit instructions. Requires libvips to have been compiled with liborc support.
|
* Get and set use of SIMD vector unit instructions. Requires libvips to have been compiled with highway support.
|
||||||
* Improves the performance of resize, blur and sharpen operations by taking advantage of the SIMD vector unit of the CPU, e.g. Intel SSE and ARM NEON.
|
* Improves the performance of resize, blur and sharpen operations by taking advantage of the SIMD vector unit of the CPU, e.g. Intel SSE and ARM NEON.
|
||||||
* @param enable enable or disable use of SIMD vector unit instructions
|
* @param enable enable or disable use of SIMD vector unit instructions
|
||||||
* @returns true if usage of SIMD vector unit instructions is enabled
|
* @returns true if usage of SIMD vector unit instructions is enabled
|
||||||
@@ -341,6 +341,12 @@ declare namespace sharp {
|
|||||||
*/
|
*/
|
||||||
metadata(): Promise<Metadata>;
|
metadata(): Promise<Metadata>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep all metadata (EXIF, ICC, XMP, IPTC) from the input image in the output image.
|
||||||
|
* @returns A sharp instance that can be used to chain operations
|
||||||
|
*/
|
||||||
|
keepMetadata(): Sharp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access to pixel-derived image statistics for every channel in the image.
|
* Access to pixel-derived image statistics for every channel in the image.
|
||||||
* @returns A sharp instance that can be used to chain operations
|
* @returns A sharp instance that can be used to chain operations
|
||||||
@@ -1011,7 +1017,7 @@ declare namespace sharp {
|
|||||||
rgba?: boolean;
|
rgba?: boolean;
|
||||||
/** Text line height in points. Will use the font line height if none is specified. (optional, default `0`) */
|
/** Text line height in points. Will use the font line height if none is specified. (optional, default `0`) */
|
||||||
spacing?: number;
|
spacing?: number;
|
||||||
/** Word wrapping style when width is provided, one of: 'word', 'char', 'charWord' (prefer char, fallback to word) or 'none' */
|
/** Word wrapping style when width is provided, one of: 'word', 'char', 'word-char' (prefer word, fallback to char) or 'none' */
|
||||||
wrap?: TextWrap;
|
wrap?: TextWrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1238,6 +1244,8 @@ declare namespace sharp {
|
|||||||
effort?: number | undefined;
|
effort?: number | undefined;
|
||||||
/** set to '4:2:0' to use chroma subsampling, requires libvips v8.11.0 (optional, default '4:4:4') */
|
/** set to '4:2:0' to use chroma subsampling, requires libvips v8.11.0 (optional, default '4:4:4') */
|
||||||
chromaSubsampling?: string | undefined;
|
chromaSubsampling?: string | undefined;
|
||||||
|
/** Set bitdepth to 8, 10 or 12 bit (optional, default 8) */
|
||||||
|
bitdepth?: 8 | 10 | 12 | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface HeifOptions extends OutputOptions {
|
interface HeifOptions extends OutputOptions {
|
||||||
@@ -1251,6 +1259,8 @@ declare namespace sharp {
|
|||||||
effort?: number | undefined;
|
effort?: number | undefined;
|
||||||
/** set to '4:2:0' to use chroma subsampling (optional, default '4:4:4') */
|
/** set to '4:2:0' to use chroma subsampling (optional, default '4:4:4') */
|
||||||
chromaSubsampling?: string | undefined;
|
chromaSubsampling?: string | undefined;
|
||||||
|
/** Set bitdepth to 8, 10 or 12 bit (optional, default 8) */
|
||||||
|
bitdepth?: 8 | 10 | 12 | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GifOptions extends OutputOptions, AnimationOptions {
|
interface GifOptions extends OutputOptions, AnimationOptions {
|
||||||
@@ -1607,7 +1617,7 @@ declare namespace sharp {
|
|||||||
|
|
||||||
type TextAlign = 'left' | 'centre' | 'center' | 'right';
|
type TextAlign = 'left' | 'centre' | 'center' | 'right';
|
||||||
|
|
||||||
type TextWrap = 'word' | 'char' | 'charWord' | 'none';
|
type TextWrap = 'word' | 'char' | 'word-char' | 'none';
|
||||||
|
|
||||||
type TileContainer = 'fs' | 'zip';
|
type TileContainer = 'fs' | 'zip';
|
||||||
|
|
||||||
|
|||||||
@@ -345,10 +345,10 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is.defined(inputOptions.text.wrap)) {
|
if (is.defined(inputOptions.text.wrap)) {
|
||||||
if (is.string(inputOptions.text.wrap) && is.inArray(inputOptions.text.wrap, ['word', 'char', 'wordChar', 'none'])) {
|
if (is.string(inputOptions.text.wrap) && is.inArray(inputOptions.text.wrap, ['word', 'char', 'word-char', 'none'])) {
|
||||||
inputDescriptor.textWrap = inputOptions.text.wrap;
|
inputDescriptor.textWrap = inputOptions.text.wrap;
|
||||||
} else {
|
} else {
|
||||||
throw is.invalidParameterError('text.wrap', 'one of: word, char, wordChar, none', inputOptions.text.wrap);
|
throw is.invalidParameterError('text.wrap', 'one of: word, char, word-char, none', inputOptions.text.wrap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete inputDescriptor.buffer;
|
delete inputDescriptor.buffer;
|
||||||
|
|||||||
@@ -4,11 +4,13 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { spawnSync } = require('node:child_process');
|
const { spawnSync } = require('node:child_process');
|
||||||
|
const { createHash } = require('node:crypto');
|
||||||
const semverCoerce = require('semver/functions/coerce');
|
const semverCoerce = require('semver/functions/coerce');
|
||||||
const semverGreaterThanOrEqualTo = require('semver/functions/gte');
|
const semverGreaterThanOrEqualTo = require('semver/functions/gte');
|
||||||
|
const semverSatisfies = require('semver/functions/satisfies');
|
||||||
const detectLibc = require('detect-libc');
|
const detectLibc = require('detect-libc');
|
||||||
|
|
||||||
const { engines } = require('../package.json');
|
const { engines, optionalDependencies } = require('../package.json');
|
||||||
|
|
||||||
const minimumLibvipsVersionLabelled = process.env.npm_package_config_libvips || /* istanbul ignore next */
|
const minimumLibvipsVersionLabelled = process.env.npm_package_config_libvips || /* istanbul ignore next */
|
||||||
engines.libvips;
|
engines.libvips;
|
||||||
@@ -82,6 +84,15 @@ const buildSharpLibvipsLibDir = () => {
|
|||||||
return '';
|
return '';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isUnsupportedNodeRuntime = () => {
|
||||||
|
/* istanbul ignore next */
|
||||||
|
if (process.release?.name === 'node' && process.versions) {
|
||||||
|
if (!semverSatisfies(process.versions.node, engines.node)) {
|
||||||
|
return { found: process.versions.node, expected: engines.node };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
const isEmscripten = () => {
|
const isEmscripten = () => {
|
||||||
const { CC } = process.env;
|
const { CC } = process.env;
|
||||||
@@ -97,6 +108,17 @@ const isRosetta = () => {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const sha512 = (s) => createHash('sha512').update(s).digest('hex');
|
||||||
|
|
||||||
|
const yarnLocator = () => {
|
||||||
|
try {
|
||||||
|
const identHash = sha512(`imgsharp-libvips-${buildPlatformArch()}`);
|
||||||
|
const npmVersion = semverCoerce(optionalDependencies[`@img/sharp-libvips-${buildPlatformArch()}`]).version;
|
||||||
|
return sha512(`${identHash}npm:${npmVersion}`).slice(0, 10);
|
||||||
|
} catch {}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
const spawnRebuild = () =>
|
const spawnRebuild = () =>
|
||||||
spawnSync(`node-gyp rebuild --directory=src ${isEmscripten() ? '--nodedir=emscripten' : ''}`, {
|
spawnSync(`node-gyp rebuild --directory=src ${isEmscripten() ? '--nodedir=emscripten' : ''}`, {
|
||||||
@@ -162,8 +184,10 @@ module.exports = {
|
|||||||
buildSharpLibvipsIncludeDir,
|
buildSharpLibvipsIncludeDir,
|
||||||
buildSharpLibvipsCPlusPlusDir,
|
buildSharpLibvipsCPlusPlusDir,
|
||||||
buildSharpLibvipsLibDir,
|
buildSharpLibvipsLibDir,
|
||||||
|
isUnsupportedNodeRuntime,
|
||||||
runtimePlatformArch,
|
runtimePlatformArch,
|
||||||
log,
|
log,
|
||||||
|
yarnLocator,
|
||||||
spawnRebuild,
|
spawnRebuild,
|
||||||
globalLibvipsVersion,
|
globalLibvipsVersion,
|
||||||
pkgConfigPath,
|
pkgConfigPath,
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ const is = require('./is');
|
|||||||
* Only one rotation can occur per pipeline.
|
* Only one rotation can occur per pipeline.
|
||||||
* Previous calls to `rotate` in the same pipeline will be ignored.
|
* Previous calls to `rotate` in the same pipeline will be ignored.
|
||||||
*
|
*
|
||||||
|
* Multi-page images can only be rotated by 180 degrees.
|
||||||
|
*
|
||||||
* Method order is important when rotating, resizing and/or extracting regions,
|
* Method order is important when rotating, resizing and/or extracting regions,
|
||||||
* for example `.rotate(x).extract(y)` will produce a different result to `.extract(y).rotate(x)`.
|
* for example `.rotate(x).extract(y)` will produce a different result to `.extract(y).rotate(x)`.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -504,10 +504,14 @@ function jpeg (options) {
|
|||||||
/**
|
/**
|
||||||
* Use these PNG options for output image.
|
* Use these PNG options for output image.
|
||||||
*
|
*
|
||||||
* By default, PNG output is full colour at 8 or 16 bits per pixel.
|
* By default, PNG output is full colour at 8 bits per pixel.
|
||||||
|
*
|
||||||
* Indexed PNG input at 1, 2 or 4 bits per pixel is converted to 8 bits per pixel.
|
* Indexed PNG input at 1, 2 or 4 bits per pixel is converted to 8 bits per pixel.
|
||||||
* Set `palette` to `true` for slower, indexed PNG output.
|
* Set `palette` to `true` for slower, indexed PNG output.
|
||||||
*
|
*
|
||||||
|
* For 16 bits per pixel output, convert to `rgb16` via
|
||||||
|
* {@link /api-colour#tocolourspace|toColourspace}.
|
||||||
|
*
|
||||||
* @example
|
* @example
|
||||||
* // Convert any input to full colour PNG output
|
* // Convert any input to full colour PNG output
|
||||||
* const data = await sharp(input)
|
* const data = await sharp(input)
|
||||||
@@ -520,6 +524,13 @@ function jpeg (options) {
|
|||||||
* .png({ palette: true })
|
* .png({ palette: true })
|
||||||
* .toBuffer();
|
* .toBuffer();
|
||||||
*
|
*
|
||||||
|
* @example
|
||||||
|
* // Output 16 bits per pixel RGB(A)
|
||||||
|
* const data = await sharp(input)
|
||||||
|
* .toColourspace('rgb16')
|
||||||
|
* .png()
|
||||||
|
* .toBuffer();
|
||||||
|
*
|
||||||
* @param {Object} [options]
|
* @param {Object} [options]
|
||||||
* @param {boolean} [options.progressive=false] - use progressive (interlace) scan
|
* @param {boolean} [options.progressive=false] - use progressive (interlace) scan
|
||||||
* @param {number} [options.compressionLevel=6] - zlib compression level, 0 (fastest, largest) to 9 (slowest, smallest)
|
* @param {number} [options.compressionLevel=6] - zlib compression level, 0 (fastest, largest) to 9 (slowest, smallest)
|
||||||
@@ -1000,6 +1011,7 @@ function tiff (options) {
|
|||||||
* Use these AVIF options for output image.
|
* Use these AVIF options for output image.
|
||||||
*
|
*
|
||||||
* AVIF image sequences are not supported.
|
* AVIF image sequences are not supported.
|
||||||
|
* Prebuilt binaries support a bitdepth of 8 only.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* const data = await sharp(input)
|
* const data = await sharp(input)
|
||||||
@@ -1018,6 +1030,7 @@ function tiff (options) {
|
|||||||
* @param {boolean} [options.lossless=false] - use lossless compression
|
* @param {boolean} [options.lossless=false] - use lossless compression
|
||||||
* @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 9 (slowest)
|
* @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 9 (slowest)
|
||||||
* @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
|
* @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
|
||||||
|
* @param {number} [options.bitdepth=8] - set bitdepth to 8, 10 or 12 bit
|
||||||
* @returns {Sharp}
|
* @returns {Sharp}
|
||||||
* @throws {Error} Invalid options
|
* @throws {Error} Invalid options
|
||||||
*/
|
*/
|
||||||
@@ -1044,6 +1057,7 @@ function avif (options) {
|
|||||||
* @param {boolean} [options.lossless=false] - use lossless compression
|
* @param {boolean} [options.lossless=false] - use lossless compression
|
||||||
* @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 9 (slowest)
|
* @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 9 (slowest)
|
||||||
* @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
|
* @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
|
||||||
|
* @param {number} [options.bitdepth=8] - set bitdepth to 8, 10 or 12 bit
|
||||||
* @returns {Sharp}
|
* @returns {Sharp}
|
||||||
* @throws {Error} Invalid options
|
* @throws {Error} Invalid options
|
||||||
*/
|
*/
|
||||||
@@ -1082,6 +1096,16 @@ function heif (options) {
|
|||||||
throw is.invalidParameterError('chromaSubsampling', 'one of: 4:2:0, 4:4:4', options.chromaSubsampling);
|
throw is.invalidParameterError('chromaSubsampling', 'one of: 4:2:0, 4:4:4', options.chromaSubsampling);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (is.defined(options.bitdepth)) {
|
||||||
|
if (is.integer(options.bitdepth) && is.inArray(options.bitdepth, [8, 10, 12])) {
|
||||||
|
if (options.bitdepth !== 8 && this.constructor.versions.heif) {
|
||||||
|
throw is.invalidParameterError('bitdepth when using prebuilt binaries', 8, options.bitdepth);
|
||||||
|
}
|
||||||
|
this.options.heifBitdepth = options.bitdepth;
|
||||||
|
} else {
|
||||||
|
throw is.invalidParameterError('bitdepth', '8, 10 or 12', options.bitdepth);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw is.invalidParameterError('options', 'Object', options);
|
throw is.invalidParameterError('options', 'Object', options);
|
||||||
}
|
}
|
||||||
@@ -1233,7 +1257,7 @@ function raw (options) {
|
|||||||
* @param {number} [options.angle=0] tile angle of rotation, must be a multiple of 90.
|
* @param {number} [options.angle=0] tile angle of rotation, must be a multiple of 90.
|
||||||
* @param {string|Object} [options.background={r: 255, g: 255, b: 255, alpha: 1}] - background colour, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to white without transparency.
|
* @param {string|Object} [options.background={r: 255, g: 255, b: 255, alpha: 1}] - background colour, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to white without transparency.
|
||||||
* @param {string} [options.depth] how deep to make the pyramid, possible values are `onepixel`, `onetile` or `one`, default based on layout.
|
* @param {string} [options.depth] how deep to make the pyramid, possible values are `onepixel`, `onetile` or `one`, default based on layout.
|
||||||
* @param {number} [options.skipBlanks=-1] threshold to skip tile generation, a value 0 - 255 for 8-bit images or 0 - 65535 for 16-bit images
|
* @param {number} [options.skipBlanks=-1] Threshold to skip tile generation. Range is 0-255 for 8-bit images, 0-65535 for 16-bit images. Default is 5 for `google` layout, -1 (no skip) otherwise.
|
||||||
* @param {string} [options.container='fs'] tile container, with value `fs` (filesystem) or `zip` (compressed file).
|
* @param {string} [options.container='fs'] tile container, with value `fs` (filesystem) or `zip` (compressed file).
|
||||||
* @param {string} [options.layout='dz'] filesystem layout, possible values are `dz`, `iiif`, `iiif3`, `zoomify` or `google`.
|
* @param {string} [options.layout='dz'] filesystem layout, possible values are `dz`, `iiif`, `iiif3`, `zoomify` or `google`.
|
||||||
* @param {boolean} [options.centre=false] centre image in tile.
|
* @param {boolean} [options.centre=false] centre image in tile.
|
||||||
|
|||||||
73
lib/sharp.js
73
lib/sharp.js
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
const { familySync, versionSync } = require('detect-libc');
|
const { familySync, versionSync } = require('detect-libc');
|
||||||
|
|
||||||
const { runtimePlatformArch, prebuiltPlatforms, minimumLibvipsVersion } = require('./libvips');
|
const { runtimePlatformArch, isUnsupportedNodeRuntime, prebuiltPlatforms, minimumLibvipsVersion } = require('./libvips');
|
||||||
const runtimePlatform = runtimePlatformArch();
|
const runtimePlatform = runtimePlatformArch();
|
||||||
|
|
||||||
const paths = [
|
const paths = [
|
||||||
@@ -44,43 +44,72 @@ if (sharp) {
|
|||||||
const messages = errors.map(err => err.message).join(' ');
|
const messages = errors.map(err => err.message).join(' ');
|
||||||
help.push('Possible solutions:');
|
help.push('Possible solutions:');
|
||||||
// Common error messages
|
// Common error messages
|
||||||
if (prebuiltPlatforms.includes(runtimePlatform)) {
|
if (isUnsupportedNodeRuntime()) {
|
||||||
|
const { found, expected } = isUnsupportedNodeRuntime();
|
||||||
|
help.push(
|
||||||
|
'- Please upgrade Node.js:',
|
||||||
|
` Found ${found}`,
|
||||||
|
` Requires ${expected}`
|
||||||
|
);
|
||||||
|
} else if (prebuiltPlatforms.includes(runtimePlatform)) {
|
||||||
const [os, cpu] = runtimePlatform.split('-');
|
const [os, cpu] = runtimePlatform.split('-');
|
||||||
help.push('- Add platform-specific dependencies:');
|
const libc = os.endsWith('musl') ? ' --libc=musl' : '';
|
||||||
help.push(` npm install --os=${os} --cpu=${cpu} sharp`);
|
help.push(
|
||||||
help.push(' or');
|
'- Ensure optional dependencies can be installed:',
|
||||||
help.push(` npm install --force @img/sharp-${runtimePlatform}`);
|
' npm install --include=optional sharp',
|
||||||
|
' yarn add sharp --ignore-engines',
|
||||||
|
'- Ensure your package manager supports multi-platform installation:',
|
||||||
|
' See https://sharp.pixelplumbing.com/install#cross-platform',
|
||||||
|
'- Add platform-specific dependencies:',
|
||||||
|
` npm install --os=${os.replace('musl', '')}${libc} --cpu=${cpu} sharp`
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
help.push(`- Manually install libvips >= ${minimumLibvipsVersion}`);
|
help.push(
|
||||||
help.push('- Add experimental WebAssembly-based dependencies:');
|
`- Manually install libvips >= ${minimumLibvipsVersion}`,
|
||||||
help.push(' npm install --cpu=wasm32 sharp');
|
'- Add experimental WebAssembly-based dependencies:',
|
||||||
|
' npm install --cpu=wasm32 sharp',
|
||||||
|
' npm install @img/sharp-wasm32'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (isLinux && /symbol not found/i.test(messages)) {
|
if (isLinux && /(symbol not found|CXXABI_)/i.test(messages)) {
|
||||||
try {
|
try {
|
||||||
const { engines } = require(`@img/sharp-libvips-${runtimePlatform}/package`);
|
const { engines } = require(`@img/sharp-libvips-${runtimePlatform}/package`);
|
||||||
const libcFound = `${familySync()} ${versionSync()}`;
|
const libcFound = `${familySync()} ${versionSync()}`;
|
||||||
const libcRequires = `${engines.musl ? 'musl' : 'glibc'} ${engines.musl || engines.glibc}`;
|
const libcRequires = `${engines.musl ? 'musl' : 'glibc'} ${engines.musl || engines.glibc}`;
|
||||||
help.push('- Update your OS:');
|
help.push(
|
||||||
help.push(` Found ${libcFound}`);
|
'- Update your OS:',
|
||||||
help.push(` Requires ${libcRequires}`);
|
` Found ${libcFound}`,
|
||||||
|
` Requires ${libcRequires}`
|
||||||
|
);
|
||||||
} catch (errEngines) {}
|
} catch (errEngines) {}
|
||||||
}
|
}
|
||||||
|
if (isLinux && /\/snap\/core[0-9]{2}/.test(messages)) {
|
||||||
|
help.push(
|
||||||
|
'- Remove the Node.js Snap, which does not support native modules',
|
||||||
|
' snap remove node'
|
||||||
|
);
|
||||||
|
}
|
||||||
if (isMacOs && /Incompatible library version/.test(messages)) {
|
if (isMacOs && /Incompatible library version/.test(messages)) {
|
||||||
help.push('- Update Homebrew:');
|
help.push(
|
||||||
help.push(' brew update && brew upgrade vips');
|
'- Update Homebrew:',
|
||||||
|
' brew update && brew upgrade vips'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (errors.some(err => err.code === 'ERR_DLOPEN_DISABLED')) {
|
if (errors.some(err => err.code === 'ERR_DLOPEN_DISABLED')) {
|
||||||
help.push('- Run Node.js without using the --no-addons flag');
|
help.push('- Run Node.js without using the --no-addons flag');
|
||||||
}
|
}
|
||||||
if (process.versions.pnp) {
|
|
||||||
help.push('- Use a supported yarn linker, either pnpm or node-modules:');
|
|
||||||
help.push(' yarn config set nodeLinker node-modules');
|
|
||||||
}
|
|
||||||
// Link to installation docs
|
// Link to installation docs
|
||||||
if (isWindows && /The specified procedure could not be found/.test(messages)) {
|
if (isWindows && /The specified procedure could not be found/.test(messages)) {
|
||||||
help.push('- Using the canvas package on Windows? See https://sharp.pixelplumbing.com/install#canvas-and-windows');
|
help.push(
|
||||||
} else {
|
'- Using the canvas package on Windows?',
|
||||||
help.push('- Consult the installation documentation: https://sharp.pixelplumbing.com/install');
|
' See https://sharp.pixelplumbing.com/install#canvas-and-windows',
|
||||||
|
'- Check for outdated versions of sharp in the dependency tree:',
|
||||||
|
' npm ls sharp'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
help.push(
|
||||||
|
'- Consult the installation documentation:',
|
||||||
|
' See https://sharp.pixelplumbing.com/install'
|
||||||
|
);
|
||||||
throw new Error(help.join('\n'));
|
throw new Error(help.join('\n'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,17 +183,17 @@ function counters () {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get and set use of SIMD vector unit instructions.
|
* Get and set use of SIMD vector unit instructions.
|
||||||
* Requires libvips to have been compiled with liborc support.
|
* Requires libvips to have been compiled with highway support.
|
||||||
*
|
*
|
||||||
* Improves the performance of `resize`, `blur` and `sharpen` operations
|
* Improves the performance of `resize`, `blur` and `sharpen` operations
|
||||||
* by taking advantage of the SIMD vector unit of the CPU, e.g. Intel SSE and ARM NEON.
|
* by taking advantage of the SIMD vector unit of the CPU, e.g. Intel SSE and ARM NEON.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* const simd = sharp.simd();
|
* const simd = sharp.simd();
|
||||||
* // simd is `true` if the runtime use of liborc is currently enabled
|
* // simd is `true` if the runtime use of highway is currently enabled
|
||||||
* @example
|
* @example
|
||||||
* const simd = sharp.simd(false);
|
* const simd = sharp.simd(false);
|
||||||
* // prevent libvips from using liborc at runtime
|
* // prevent libvips from using highway at runtime
|
||||||
*
|
*
|
||||||
* @param {boolean} [simd=true]
|
* @param {boolean} [simd=true]
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
@@ -201,7 +201,6 @@ function counters () {
|
|||||||
function simd (simd) {
|
function simd (simd) {
|
||||||
return sharp.simd(is.bool(simd) ? simd : null);
|
return sharp.simd(is.bool(simd) ? simd : null);
|
||||||
}
|
}
|
||||||
simd(true);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Block libvips operations at runtime.
|
* Block libvips operations at runtime.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-darwin-arm64",
|
"name": "@img/sharp-darwin-arm64",
|
||||||
"version": "0.33.0-rc.1",
|
"version": "0.33.3",
|
||||||
"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",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-darwin-arm64": "1.0.0"
|
"@img/sharp-libvips-darwin-arm64": "1.0.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"lib"
|
"lib"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-darwin-x64",
|
"name": "@img/sharp-darwin-x64",
|
||||||
"version": "0.33.0-rc.1",
|
"version": "0.33.3",
|
||||||
"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",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-darwin-x64": "1.0.0"
|
"@img/sharp-libvips-darwin-x64": "1.0.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"lib"
|
"lib"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linux-arm",
|
"name": "@img/sharp-linux-arm",
|
||||||
"version": "0.33.0-rc.1",
|
"version": "0.33.3",
|
||||||
"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",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-linux-arm": "1.0.0"
|
"@img/sharp-libvips-linux-arm": "1.0.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"lib"
|
"lib"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linux-arm64",
|
"name": "@img/sharp-linux-arm64",
|
||||||
"version": "0.33.0-rc.1",
|
"version": "0.33.3",
|
||||||
"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",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-linux-arm64": "1.0.0"
|
"@img/sharp-libvips-linux-arm64": "1.0.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"lib"
|
"lib"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linux-s390x",
|
"name": "@img/sharp-linux-s390x",
|
||||||
"version": "0.33.0-rc.1",
|
"version": "0.33.3",
|
||||||
"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",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-linux-s390x": "1.0.0"
|
"@img/sharp-libvips-linux-s390x": "1.0.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"lib"
|
"lib"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linux-x64",
|
"name": "@img/sharp-linux-x64",
|
||||||
"version": "0.33.0-rc.1",
|
"version": "0.33.3",
|
||||||
"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",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-linux-x64": "1.0.0"
|
"@img/sharp-libvips-linux-x64": "1.0.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"lib"
|
"lib"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linuxmusl-arm64",
|
"name": "@img/sharp-linuxmusl-arm64",
|
||||||
"version": "0.33.0-rc.1",
|
"version": "0.33.3",
|
||||||
"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",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-linuxmusl-arm64": "1.0.0"
|
"@img/sharp-libvips-linuxmusl-arm64": "1.0.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"lib"
|
"lib"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linuxmusl-x64",
|
"name": "@img/sharp-linuxmusl-x64",
|
||||||
"version": "0.33.0-rc.1",
|
"version": "0.33.3",
|
||||||
"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",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-linuxmusl-x64": "1.0.0"
|
"@img/sharp-libvips-linuxmusl-x64": "1.0.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"lib"
|
"lib"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp",
|
"name": "@img/sharp",
|
||||||
"version": "0.33.0-rc.1",
|
"version": "0.33.3",
|
||||||
"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.0-rc.1",
|
"version": "0.33.3",
|
||||||
"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": "^0.44.0"
|
"@emnapi/runtime": "^1.1.0"
|
||||||
},
|
},
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"wasm32"
|
"wasm32"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-win32-ia32",
|
"name": "@img/sharp-win32-ia32",
|
||||||
"version": "0.33.0-rc.1",
|
"version": "0.33.3",
|
||||||
"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.0-rc.1",
|
"version": "0.33.3",
|
||||||
"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",
|
||||||
|
|||||||
74
package.json
74
package.json
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"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.0-rc.1",
|
"version": "0.33.3",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://github.com/lovell/sharp",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
"Pierre Inglebert <pierre.inglebert@gmail.com>",
|
"Pierre Inglebert <pierre.inglebert@gmail.com>",
|
||||||
"Jonathan Ong <jonathanrichardong@gmail.com>",
|
"Jonathan Ong <jonathanrichardong@gmail.com>",
|
||||||
@@ -137,57 +137,57 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"color": "^4.2.3",
|
"color": "^4.2.3",
|
||||||
"detect-libc": "^2.0.2",
|
"detect-libc": "^2.0.3",
|
||||||
"semver": "^7.5.4"
|
"semver": "^7.6.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-darwin-arm64": "0.33.0-rc.1",
|
"@img/sharp-darwin-arm64": "0.33.3",
|
||||||
"@img/sharp-darwin-x64": "0.33.0-rc.1",
|
"@img/sharp-darwin-x64": "0.33.3",
|
||||||
"@img/sharp-libvips-darwin-arm64": "1.0.0",
|
"@img/sharp-libvips-darwin-arm64": "1.0.2",
|
||||||
"@img/sharp-libvips-darwin-x64": "1.0.0",
|
"@img/sharp-libvips-darwin-x64": "1.0.2",
|
||||||
"@img/sharp-libvips-linux-arm": "1.0.0",
|
"@img/sharp-libvips-linux-arm": "1.0.2",
|
||||||
"@img/sharp-libvips-linux-arm64": "1.0.0",
|
"@img/sharp-libvips-linux-arm64": "1.0.2",
|
||||||
"@img/sharp-libvips-linux-s390x": "1.0.0",
|
"@img/sharp-libvips-linux-s390x": "1.0.2",
|
||||||
"@img/sharp-libvips-linux-x64": "1.0.0",
|
"@img/sharp-libvips-linux-x64": "1.0.2",
|
||||||
"@img/sharp-libvips-linuxmusl-arm64": "1.0.0",
|
"@img/sharp-libvips-linuxmusl-arm64": "1.0.2",
|
||||||
"@img/sharp-libvips-linuxmusl-x64": "1.0.0",
|
"@img/sharp-libvips-linuxmusl-x64": "1.0.2",
|
||||||
"@img/sharp-linux-arm": "0.33.0-rc.1",
|
"@img/sharp-linux-arm": "0.33.3",
|
||||||
"@img/sharp-linux-arm64": "0.33.0-rc.1",
|
"@img/sharp-linux-arm64": "0.33.3",
|
||||||
"@img/sharp-linux-s390x": "0.33.0-rc.1",
|
"@img/sharp-linux-s390x": "0.33.3",
|
||||||
"@img/sharp-linux-x64": "0.33.0-rc.1",
|
"@img/sharp-linux-x64": "0.33.3",
|
||||||
"@img/sharp-linuxmusl-arm64": "0.33.0-rc.1",
|
"@img/sharp-linuxmusl-arm64": "0.33.3",
|
||||||
"@img/sharp-linuxmusl-x64": "0.33.0-rc.1",
|
"@img/sharp-linuxmusl-x64": "0.33.3",
|
||||||
"@img/sharp-wasm32": "0.33.0-rc.1",
|
"@img/sharp-wasm32": "0.33.3",
|
||||||
"@img/sharp-win32-ia32": "0.33.0-rc.1",
|
"@img/sharp-win32-ia32": "0.33.3",
|
||||||
"@img/sharp-win32-x64": "0.33.0-rc.1"
|
"@img/sharp-win32-x64": "0.33.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@emnapi/runtime": "^0.44.0",
|
"@emnapi/runtime": "^1.1.0",
|
||||||
"@img/sharp-libvips-dev": "1.0.0",
|
"@img/sharp-libvips-dev": "1.0.2",
|
||||||
"@img/sharp-libvips-dev-wasm32": "1.0.0",
|
"@img/sharp-libvips-dev-wasm32": "1.0.3",
|
||||||
"@img/sharp-libvips-win32-ia32": "1.0.0",
|
"@img/sharp-libvips-win32-ia32": "1.0.2",
|
||||||
"@img/sharp-libvips-win32-x64": "1.0.0",
|
"@img/sharp-libvips-win32-x64": "1.0.2",
|
||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"async": "^3.2.5",
|
"async": "^3.2.5",
|
||||||
"cc": "^3.0.1",
|
"cc": "^3.0.1",
|
||||||
"emnapi": "^0.44.0",
|
"emnapi": "^1.1.0",
|
||||||
"exif-reader": "^2.0.0",
|
"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.0",
|
"jsdoc-to-markdown": "^8.0.1",
|
||||||
"license-checker": "^25.0.1",
|
"license-checker": "^25.0.1",
|
||||||
"mocha": "^10.2.0",
|
"mocha": "^10.3.0",
|
||||||
"node-addon-api": "^7.0.0",
|
"node-addon-api": "^8.0.0",
|
||||||
"nyc": "^15.1.0",
|
"nyc": "^15.1.0",
|
||||||
"prebuild": "^12.1.0",
|
"prebuild": "^13.0.0",
|
||||||
"semistandard": "^17.0.0",
|
"semistandard": "^17.0.0",
|
||||||
"tar-fs": "^3.0.4",
|
"tar-fs": "^3.0.5",
|
||||||
"tsd": "^0.29.0"
|
"tsd": "^0.30.7"
|
||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0",
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0",
|
||||||
"libvips": ">=8.15.0"
|
"libvips": ">=8.15.2"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
'vips_version': '<!(node -p "require(\'../lib/libvips\').minimumLibvipsVersion")',
|
'vips_version': '<!(node -p "require(\'../lib/libvips\').minimumLibvipsVersion")',
|
||||||
'platform_and_arch': '<!(node -p "require(\'../lib/libvips\').buildPlatformArch()")',
|
'platform_and_arch': '<!(node -p "require(\'../lib/libvips\').buildPlatformArch()")',
|
||||||
'sharp_libvips_version': '<!(node -p "require(\'../package.json\').optionalDependencies[\'@img/sharp-libvips-<(platform_and_arch)\']")',
|
'sharp_libvips_version': '<!(node -p "require(\'../package.json\').optionalDependencies[\'@img/sharp-libvips-<(platform_and_arch)\']")',
|
||||||
|
'sharp_libvips_yarn_locator': '<!(node -p "require(\'../lib/libvips\').yarnLocator()")',
|
||||||
'sharp_libvips_include_dir': '<!(node -p "require(\'../lib/libvips\').buildSharpLibvipsIncludeDir()")',
|
'sharp_libvips_include_dir': '<!(node -p "require(\'../lib/libvips\').buildSharpLibvipsIncludeDir()")',
|
||||||
'sharp_libvips_cplusplus_dir': '<!(node -p "require(\'../lib/libvips\').buildSharpLibvipsCPlusPlusDir()")',
|
'sharp_libvips_cplusplus_dir': '<!(node -p "require(\'../lib/libvips\').buildSharpLibvipsCPlusPlusDir()")',
|
||||||
'sharp_libvips_lib_dir': '<!(node -p "require(\'../lib/libvips\').buildSharpLibvipsLibDir()")'
|
'sharp_libvips_lib_dir': '<!(node -p "require(\'../lib/libvips\').buildSharpLibvipsLibDir()")'
|
||||||
@@ -157,7 +158,8 @@
|
|||||||
'-Wl,-rpath,\'@loader_path/../../sharp-libvips-<(platform_and_arch)/lib\'',
|
'-Wl,-rpath,\'@loader_path/../../sharp-libvips-<(platform_and_arch)/lib\'',
|
||||||
'-Wl,-rpath,\'@loader_path/../../../sharp-libvips-<(platform_and_arch)/<(sharp_libvips_version)/lib\'',
|
'-Wl,-rpath,\'@loader_path/../../../sharp-libvips-<(platform_and_arch)/<(sharp_libvips_version)/lib\'',
|
||||||
'-Wl,-rpath,\'@loader_path/../../node_modules/@img/sharp-libvips-<(platform_and_arch)/lib\'',
|
'-Wl,-rpath,\'@loader_path/../../node_modules/@img/sharp-libvips-<(platform_and_arch)/lib\'',
|
||||||
'-Wl,-rpath,\'@loader_path/../../../node_modules/@img/sharp-libvips-<(platform_and_arch)/lib\''
|
'-Wl,-rpath,\'@loader_path/../../../node_modules/@img/sharp-libvips-<(platform_and_arch)/lib\'',
|
||||||
|
'-Wl,-rpath,\'@loader_path/../../../../../@img-sharp-libvips-<(platform_and_arch)-npm-<(sharp_libvips_version)-<(sharp_libvips_yarn_locator)/node_modules/@img/sharp-libvips-<(platform_and_arch)/lib\''
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
@@ -176,7 +178,8 @@
|
|||||||
'-Wl,-rpath=\'$$ORIGIN/../../sharp-libvips-<(platform_and_arch)/lib\'',
|
'-Wl,-rpath=\'$$ORIGIN/../../sharp-libvips-<(platform_and_arch)/lib\'',
|
||||||
'-Wl,-rpath=\'$$ORIGIN/../../../sharp-libvips-<(platform_and_arch)/<(sharp_libvips_version)/lib\'',
|
'-Wl,-rpath=\'$$ORIGIN/../../../sharp-libvips-<(platform_and_arch)/<(sharp_libvips_version)/lib\'',
|
||||||
'-Wl,-rpath=\'$$ORIGIN/../../node_modules/@img/sharp-libvips-<(platform_and_arch)/lib\'',
|
'-Wl,-rpath=\'$$ORIGIN/../../node_modules/@img/sharp-libvips-<(platform_and_arch)/lib\'',
|
||||||
'-Wl,-rpath=\'$$ORIGIN/../../../node_modules/@img/sharp-libvips-<(platform_and_arch)/lib\''
|
'-Wl,-rpath=\'$$ORIGIN/../../../node_modules/@img/sharp-libvips-<(platform_and_arch)/lib\'',
|
||||||
|
'-Wl,-rpath,\'$$ORIGIN/../../../../../@img-sharp-libvips-<(platform_and_arch)-npm-<(sharp_libvips_version)-<(sharp_libvips_yarn_locator)/node_modules/@img/sharp-libvips-<(platform_and_arch)/lib\''
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
#if (VIPS_MAJOR_VERSION < 8) || \
|
#if (VIPS_MAJOR_VERSION < 8) || \
|
||||||
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 15) || \
|
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 15) || \
|
||||||
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 15 && VIPS_MICRO_VERSION < 0)
|
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 15 && VIPS_MICRO_VERSION < 2)
|
||||||
#error "libvips version 8.15.0+ is required - please see https://sharp.pixelplumbing.com/install"
|
#error "libvips version 8.15.2+ is required - please see https://sharp.pixelplumbing.com/install"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)))
|
#if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)))
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
sharp::ImageType inputImageType;
|
sharp::ImageType inputImageType;
|
||||||
std::tie(image, inputImageType) = sharp::OpenInput(baton->input);
|
std::tie(image, inputImageType) = sharp::OpenInput(baton->input);
|
||||||
VipsAccess access = baton->input->access;
|
VipsAccess access = baton->input->access;
|
||||||
image = sharp::EnsureColourspace(image, baton->colourspaceInput);
|
image = sharp::EnsureColourspace(image, baton->colourspacePipeline);
|
||||||
|
|
||||||
int nPages = baton->input->pages;
|
int nPages = baton->input->pages;
|
||||||
if (nPages == -1) {
|
if (nPages == -1) {
|
||||||
@@ -96,6 +96,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
baton->rotationAngle != 0.0);
|
baton->rotationAngle != 0.0);
|
||||||
|
|
||||||
if (autoRotation != VIPS_ANGLE_D0) {
|
if (autoRotation != VIPS_ANGLE_D0) {
|
||||||
|
if (autoRotation != VIPS_ANGLE_D180) {
|
||||||
|
MultiPageUnsupported(nPages, "Rotate");
|
||||||
|
}
|
||||||
image = image.rot(autoRotation);
|
image = image.rot(autoRotation);
|
||||||
autoRotation = VIPS_ANGLE_D0;
|
autoRotation = VIPS_ANGLE_D0;
|
||||||
}
|
}
|
||||||
@@ -114,6 +117,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
baton->flop = FALSE;
|
baton->flop = FALSE;
|
||||||
}
|
}
|
||||||
if (rotation != VIPS_ANGLE_D0) {
|
if (rotation != VIPS_ANGLE_D0) {
|
||||||
|
if (rotation != VIPS_ANGLE_D180) {
|
||||||
|
MultiPageUnsupported(nPages, "Rotate");
|
||||||
|
}
|
||||||
image = image.rot(rotation);
|
image = image.rot(rotation);
|
||||||
rotation = VIPS_ANGLE_D0;
|
rotation = VIPS_ANGLE_D0;
|
||||||
}
|
}
|
||||||
@@ -183,7 +189,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
// - input colourspace is not specified;
|
// - input colourspace is not specified;
|
||||||
bool const shouldPreShrink = (targetResizeWidth > 0 || targetResizeHeight > 0) &&
|
bool const shouldPreShrink = (targetResizeWidth > 0 || targetResizeHeight > 0) &&
|
||||||
baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimThreshold < 0.0 &&
|
baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimThreshold < 0.0 &&
|
||||||
baton->colourspaceInput == VIPS_INTERPRETATION_LAST && !shouldRotateBefore;
|
baton->colourspacePipeline == VIPS_INTERPRETATION_LAST && !shouldRotateBefore;
|
||||||
|
|
||||||
if (shouldPreShrink) {
|
if (shouldPreShrink) {
|
||||||
// The common part of the shrink: the bit by which both axes must be shrunk
|
// The common part of the shrink: the bit by which both axes must be shrunk
|
||||||
@@ -325,6 +331,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
sharp::HasProfile(image) &&
|
sharp::HasProfile(image) &&
|
||||||
image.interpretation() != VIPS_INTERPRETATION_LABS &&
|
image.interpretation() != VIPS_INTERPRETATION_LABS &&
|
||||||
image.interpretation() != VIPS_INTERPRETATION_GREY16 &&
|
image.interpretation() != VIPS_INTERPRETATION_GREY16 &&
|
||||||
|
baton->colourspacePipeline != VIPS_INTERPRETATION_CMYK &&
|
||||||
!baton->input->ignoreIcc
|
!baton->input->ignoreIcc
|
||||||
) {
|
) {
|
||||||
// Convert to sRGB/P3 using embedded profile
|
// Convert to sRGB/P3 using embedded profile
|
||||||
@@ -338,7 +345,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
}
|
}
|
||||||
} else if (
|
} else if (
|
||||||
image.interpretation() == VIPS_INTERPRETATION_CMYK &&
|
image.interpretation() == VIPS_INTERPRETATION_CMYK &&
|
||||||
baton->colourspaceInput != VIPS_INTERPRETATION_CMYK
|
baton->colourspacePipeline != VIPS_INTERPRETATION_CMYK
|
||||||
) {
|
) {
|
||||||
image = image.icc_transform(processingProfile, VImage::option()
|
image = image.icc_transform(processingProfile, VImage::option()
|
||||||
->set("input_profile", "cmyk")
|
->set("input_profile", "cmyk")
|
||||||
@@ -397,6 +404,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
rotation != VIPS_ANGLE_D0);
|
rotation != VIPS_ANGLE_D0);
|
||||||
// Auto-rotate post-extract
|
// Auto-rotate post-extract
|
||||||
if (autoRotation != VIPS_ANGLE_D0) {
|
if (autoRotation != VIPS_ANGLE_D0) {
|
||||||
|
if (autoRotation != VIPS_ANGLE_D180) {
|
||||||
|
MultiPageUnsupported(nPages, "Rotate");
|
||||||
|
}
|
||||||
image = image.rot(autoRotation);
|
image = image.rot(autoRotation);
|
||||||
}
|
}
|
||||||
// Mirror vertically (up-down) about the x-axis
|
// Mirror vertically (up-down) about the x-axis
|
||||||
@@ -409,6 +419,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
}
|
}
|
||||||
// Rotate post-extract 90-angle
|
// Rotate post-extract 90-angle
|
||||||
if (rotation != VIPS_ANGLE_D0) {
|
if (rotation != VIPS_ANGLE_D0) {
|
||||||
|
if (rotation != VIPS_ANGLE_D180) {
|
||||||
|
MultiPageUnsupported(nPages, "Rotate");
|
||||||
|
}
|
||||||
image = image.rot(rotation);
|
image = image.rot(rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,7 +433,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
for (unsigned int i = 0; i < baton->joinChannelIn.size(); i++) {
|
for (unsigned int i = 0; i < baton->joinChannelIn.size(); i++) {
|
||||||
baton->joinChannelIn[i]->access = access;
|
baton->joinChannelIn[i]->access = access;
|
||||||
std::tie(joinImage, joinImageType) = sharp::OpenInput(baton->joinChannelIn[i]);
|
std::tie(joinImage, joinImageType) = sharp::OpenInput(baton->joinChannelIn[i]);
|
||||||
joinImage = sharp::EnsureColourspace(joinImage, baton->colourspaceInput);
|
joinImage = sharp::EnsureColourspace(joinImage, baton->colourspacePipeline);
|
||||||
image = image.bandjoin(joinImage);
|
image = image.bandjoin(joinImage);
|
||||||
}
|
}
|
||||||
image = image.copy(VImage::option()->set("interpretation", baton->colourspace));
|
image = image.copy(VImage::option()->set("interpretation", baton->colourspace));
|
||||||
@@ -561,6 +574,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 = 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,
|
||||||
@@ -629,7 +643,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
sharp::ImageType compositeImageType = sharp::ImageType::UNKNOWN;
|
sharp::ImageType compositeImageType = sharp::ImageType::UNKNOWN;
|
||||||
composite->input->access = access;
|
composite->input->access = access;
|
||||||
std::tie(compositeImage, compositeImageType) = sharp::OpenInput(composite->input);
|
std::tie(compositeImage, compositeImageType) = sharp::OpenInput(composite->input);
|
||||||
compositeImage = sharp::EnsureColourspace(compositeImage, baton->colourspaceInput);
|
compositeImage = sharp::EnsureColourspace(compositeImage, baton->colourspacePipeline);
|
||||||
// Verify within current dimensions
|
// Verify within current dimensions
|
||||||
if (compositeImage.width() > image.width() || compositeImage.height() > image.height()) {
|
if (compositeImage.width() > image.width() || compositeImage.height() > image.height()) {
|
||||||
throw vips::VError("Image to composite must have same dimensions or smaller");
|
throw vips::VError("Image to composite must have same dimensions or smaller");
|
||||||
@@ -730,7 +744,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
sharp::ImageType booleanImageType = sharp::ImageType::UNKNOWN;
|
sharp::ImageType booleanImageType = sharp::ImageType::UNKNOWN;
|
||||||
baton->boolean->access = access;
|
baton->boolean->access = access;
|
||||||
std::tie(booleanImage, booleanImageType) = sharp::OpenInput(baton->boolean);
|
std::tie(booleanImage, booleanImageType) = sharp::OpenInput(baton->boolean);
|
||||||
booleanImage = sharp::EnsureColourspace(booleanImage, baton->colourspaceInput);
|
booleanImage = sharp::EnsureColourspace(booleanImage, baton->colourspacePipeline);
|
||||||
image = sharp::Boolean(image, booleanImage, baton->booleanOp);
|
image = sharp::Boolean(image, booleanImage, baton->booleanOp);
|
||||||
image = sharp::RemoveGifPalette(image);
|
image = sharp::RemoveGifPalette(image);
|
||||||
}
|
}
|
||||||
@@ -763,9 +777,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
// Convert colourspace, pass the current known interpretation so libvips doesn't have to guess
|
// Convert colourspace, pass the current known interpretation so libvips doesn't have to guess
|
||||||
image = image.colourspace(baton->colourspace, VImage::option()->set("source_space", image.interpretation()));
|
image = image.colourspace(baton->colourspace, VImage::option()->set("source_space", image.interpretation()));
|
||||||
// Transform colours from embedded profile to output profile
|
// Transform colours from embedded profile to output profile
|
||||||
if ((baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) &&
|
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("srgb", 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));
|
||||||
@@ -794,11 +808,15 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
|
|
||||||
// Apply output ICC profile
|
// Apply output ICC profile
|
||||||
if (!baton->withIccProfile.empty()) {
|
if (!baton->withIccProfile.empty()) {
|
||||||
image = image.icc_transform(const_cast<char*>(baton->withIccProfile.data()), VImage::option()
|
try {
|
||||||
->set("input_profile", processingProfile)
|
image = image.icc_transform(const_cast<char*>(baton->withIccProfile.data()), VImage::option()
|
||||||
->set("embedded", TRUE)
|
->set("input_profile", processingProfile)
|
||||||
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
->set("embedded", TRUE)
|
||||||
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
||||||
|
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
||||||
|
} catch(...) {
|
||||||
|
sharp::VipsWarningCallback(nullptr, G_LOG_LEVEL_WARNING, "Invalid profile", nullptr);
|
||||||
|
}
|
||||||
} 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);
|
||||||
}
|
}
|
||||||
@@ -971,7 +989,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
->set("Q", baton->heifQuality)
|
->set("Q", baton->heifQuality)
|
||||||
->set("compression", baton->heifCompression)
|
->set("compression", baton->heifCompression)
|
||||||
->set("effort", baton->heifEffort)
|
->set("effort", baton->heifEffort)
|
||||||
->set("bitdepth", 8)
|
->set("bitdepth", baton->heifBitdepth)
|
||||||
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
||||||
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
||||||
->set("lossless", baton->heifLossless)));
|
->set("lossless", baton->heifLossless)));
|
||||||
@@ -1164,7 +1182,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
->set("Q", baton->heifQuality)
|
->set("Q", baton->heifQuality)
|
||||||
->set("compression", baton->heifCompression)
|
->set("compression", baton->heifCompression)
|
||||||
->set("effort", baton->heifEffort)
|
->set("effort", baton->heifEffort)
|
||||||
->set("bitdepth", 8)
|
->set("bitdepth", baton->heifBitdepth)
|
||||||
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
||||||
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
||||||
->set("lossless", baton->heifLossless));
|
->set("lossless", baton->heifLossless));
|
||||||
@@ -1590,10 +1608,10 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|||||||
baton->recombMatrix[i] = sharp::AttrAsDouble(recombMatrix, i);
|
baton->recombMatrix[i] = sharp::AttrAsDouble(recombMatrix, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
baton->colourspaceInput = sharp::AttrAsEnum<VipsInterpretation>(
|
baton->colourspacePipeline = sharp::AttrAsEnum<VipsInterpretation>(
|
||||||
options, "colourspaceInput", VIPS_TYPE_INTERPRETATION);
|
options, "colourspacePipeline", VIPS_TYPE_INTERPRETATION);
|
||||||
if (baton->colourspaceInput == VIPS_INTERPRETATION_ERROR) {
|
if (baton->colourspacePipeline == VIPS_INTERPRETATION_ERROR) {
|
||||||
baton->colourspaceInput = VIPS_INTERPRETATION_LAST;
|
baton->colourspacePipeline = VIPS_INTERPRETATION_LAST;
|
||||||
}
|
}
|
||||||
baton->colourspace = sharp::AttrAsEnum<VipsInterpretation>(options, "colourspace", VIPS_TYPE_INTERPRETATION);
|
baton->colourspace = sharp::AttrAsEnum<VipsInterpretation>(options, "colourspace", VIPS_TYPE_INTERPRETATION);
|
||||||
if (baton->colourspace == VIPS_INTERPRETATION_ERROR) {
|
if (baton->colourspace == VIPS_INTERPRETATION_ERROR) {
|
||||||
@@ -1678,6 +1696,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|||||||
options, "heifCompression", VIPS_TYPE_FOREIGN_HEIF_COMPRESSION);
|
options, "heifCompression", VIPS_TYPE_FOREIGN_HEIF_COMPRESSION);
|
||||||
baton->heifEffort = sharp::AttrAsUint32(options, "heifEffort");
|
baton->heifEffort = sharp::AttrAsUint32(options, "heifEffort");
|
||||||
baton->heifChromaSubsampling = sharp::AttrAsStr(options, "heifChromaSubsampling");
|
baton->heifChromaSubsampling = sharp::AttrAsStr(options, "heifChromaSubsampling");
|
||||||
|
baton->heifBitdepth = sharp::AttrAsUint32(options, "heifBitdepth");
|
||||||
baton->jxlDistance = sharp::AttrAsDouble(options, "jxlDistance");
|
baton->jxlDistance = sharp::AttrAsDouble(options, "jxlDistance");
|
||||||
baton->jxlDecodingTier = sharp::AttrAsUint32(options, "jxlDecodingTier");
|
baton->jxlDecodingTier = sharp::AttrAsUint32(options, "jxlDecodingTier");
|
||||||
baton->jxlEffort = sharp::AttrAsUint32(options, "jxlEffort");
|
baton->jxlEffort = sharp::AttrAsUint32(options, "jxlEffort");
|
||||||
|
|||||||
@@ -181,6 +181,7 @@ struct PipelineBaton {
|
|||||||
int heifEffort;
|
int heifEffort;
|
||||||
std::string heifChromaSubsampling;
|
std::string heifChromaSubsampling;
|
||||||
bool heifLossless;
|
bool heifLossless;
|
||||||
|
int heifBitdepth;
|
||||||
double jxlDistance;
|
double jxlDistance;
|
||||||
int jxlDecodingTier;
|
int jxlDecodingTier;
|
||||||
int jxlEffort;
|
int jxlEffort;
|
||||||
@@ -205,7 +206,7 @@ struct PipelineBaton {
|
|||||||
int extractChannel;
|
int extractChannel;
|
||||||
bool removeAlpha;
|
bool removeAlpha;
|
||||||
double ensureAlpha;
|
double ensureAlpha;
|
||||||
VipsInterpretation colourspaceInput;
|
VipsInterpretation colourspacePipeline;
|
||||||
VipsInterpretation colourspace;
|
VipsInterpretation colourspace;
|
||||||
std::vector<int> delay;
|
std::vector<int> delay;
|
||||||
int loop;
|
int loop;
|
||||||
@@ -349,6 +350,7 @@ struct PipelineBaton {
|
|||||||
heifEffort(4),
|
heifEffort(4),
|
||||||
heifChromaSubsampling("4:4:4"),
|
heifChromaSubsampling("4:4:4"),
|
||||||
heifLossless(false),
|
heifLossless(false),
|
||||||
|
heifBitdepth(8),
|
||||||
jxlDistance(1.0),
|
jxlDistance(1.0),
|
||||||
jxlDecodingTier(0),
|
jxlDecodingTier(0),
|
||||||
jxlEffort(7),
|
jxlEffort(7),
|
||||||
@@ -369,7 +371,7 @@ struct PipelineBaton {
|
|||||||
extractChannel(-1),
|
extractChannel(-1),
|
||||||
removeAlpha(false),
|
removeAlpha(false),
|
||||||
ensureAlpha(-1.0),
|
ensureAlpha(-1.0),
|
||||||
colourspaceInput(VIPS_INTERPRETATION_LAST),
|
colourspacePipeline(VIPS_INTERPRETATION_LAST),
|
||||||
colourspace(VIPS_INTERPRETATION_LAST),
|
colourspace(VIPS_INTERPRETATION_LAST),
|
||||||
loop(-1),
|
loop(-1),
|
||||||
tileSize(256),
|
tileSize(256),
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
FROM ubuntu:22.04
|
FROM ubuntu:23.10
|
||||||
ARG BRANCH=main
|
ARG BRANCH=main
|
||||||
|
|
||||||
# Install basic dependencies
|
# Install basic dependencies
|
||||||
RUN apt-get -y update && apt-get install -y build-essential curl git
|
RUN apt-get -y update && apt-get install -y build-essential curl git ca-certificates gnupg
|
||||||
|
|
||||||
# Install latest Node.js LTS
|
# Install latest Node.js LTS
|
||||||
RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash -
|
RUN mkdir -p /etc/apt/keyrings
|
||||||
RUN apt-get install -y nodejs
|
RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
|
||||||
|
RUN echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list
|
||||||
|
RUN apt-get -y update && apt-get install -y nodejs
|
||||||
|
|
||||||
# Install benchmark dependencies
|
# Install benchmark dependencies
|
||||||
RUN apt-get install -y imagemagick libmagick++-dev graphicsmagick
|
RUN apt-get install -y imagemagick libmagick++-dev graphicsmagick
|
||||||
|
|||||||
@@ -10,14 +10,14 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@squoosh/cli": "0.7.3",
|
"@squoosh/cli": "0.7.3",
|
||||||
"@squoosh/lib": "0.5.3",
|
"@squoosh/lib": "0.5.3",
|
||||||
"async": "3.2.4",
|
"async": "3.2.5",
|
||||||
"benchmark": "2.1.4",
|
"benchmark": "2.1.4",
|
||||||
"gm": "1.25.0",
|
"gm": "1.25.0",
|
||||||
"imagemagick": "0.1.3",
|
"imagemagick": "0.1.3",
|
||||||
"jimp": "0.22.10"
|
"jimp": "0.22.10"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@tensorflow/tfjs-node": "4.11.0",
|
"@tensorflow/tfjs-node": "4.13.0",
|
||||||
"mapnik": "4.5.9"
|
"mapnik": "4.5.9"
|
||||||
},
|
},
|
||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
|
|||||||
BIN
test/fixtures/invalid-illuminant.icc
vendored
Normal file
BIN
test/fixtures/invalid-illuminant.icc
vendored
Normal file
Binary file not shown.
@@ -1,4 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
|
||||||
if ! type valgrind >/dev/null; then
|
if ! type valgrind >/dev/null; then
|
||||||
echo "Please install valgrind before running memory leak tests"
|
echo "Please install valgrind before running memory leak tests"
|
||||||
@@ -7,14 +8,15 @@ fi
|
|||||||
|
|
||||||
curl -s -o ./test/leak/libvips.supp https://raw.githubusercontent.com/libvips/libvips/master/suppressions/valgrind.supp
|
curl -s -o ./test/leak/libvips.supp https://raw.githubusercontent.com/libvips/libvips/master/suppressions/valgrind.supp
|
||||||
|
|
||||||
for test in ./test/unit/*.js; do
|
TESTS=$(ls test/unit --ignore=svg.js --ignore=text.js)
|
||||||
|
for test in $TESTS; do
|
||||||
G_SLICE=always-malloc G_DEBUG=gc-friendly VIPS_LEAK=1 VIPS_NOVECTOR=1 valgrind \
|
G_SLICE=always-malloc G_DEBUG=gc-friendly VIPS_LEAK=1 VIPS_NOVECTOR=1 valgrind \
|
||||||
--suppressions=test/leak/libvips.supp \
|
--suppressions=test/leak/libvips.supp \
|
||||||
--suppressions=test/leak/sharp.supp \
|
--suppressions=test/leak/sharp.supp \
|
||||||
--gen-suppressions=yes \
|
--gen-suppressions=yes \
|
||||||
--leak-check=full \
|
--leak-check=full \
|
||||||
--show-leak-kinds=definite,indirect,possible \
|
--show-leak-kinds=definite,indirect \
|
||||||
--num-callers=20 \
|
--num-callers=20 \
|
||||||
--trace-children=yes \
|
--trace-children=yes \
|
||||||
node --expose-gc node_modules/.bin/mocha --no-config --slow=60000 --timeout=120000 --require test/beforeEach.js "$test";
|
node --expose-gc --zero-fill-buffers node_modules/.bin/mocha --no-config --slow=60000 --timeout=120000 --require test/beforeEach.js "test/unit/$test";
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -173,41 +173,6 @@
|
|||||||
fun:TIFFWriteEncodedTile
|
fun:TIFFWriteEncodedTile
|
||||||
}
|
}
|
||||||
|
|
||||||
# gsf
|
|
||||||
{
|
|
||||||
param_gsf_output_write
|
|
||||||
Memcheck:Param
|
|
||||||
write(buf)
|
|
||||||
fun:write
|
|
||||||
...
|
|
||||||
fun:gsf_output_write
|
|
||||||
}
|
|
||||||
{
|
|
||||||
value_gsf_output_write_crc32_little
|
|
||||||
Memcheck:Value8
|
|
||||||
fun:crc32_little
|
|
||||||
...
|
|
||||||
fun:gsf_output_write
|
|
||||||
}
|
|
||||||
{
|
|
||||||
param_gsf_new_do_write
|
|
||||||
Memcheck:Param
|
|
||||||
write(buf)
|
|
||||||
...
|
|
||||||
fun:new_do_write
|
|
||||||
...
|
|
||||||
fun:gsf_output_close
|
|
||||||
}
|
|
||||||
{
|
|
||||||
param_gsf_output_write
|
|
||||||
Memcheck:Param
|
|
||||||
write(buf)
|
|
||||||
...
|
|
||||||
fun:new_do_write
|
|
||||||
...
|
|
||||||
fun:gsf_output_write
|
|
||||||
}
|
|
||||||
|
|
||||||
# fontconfig
|
# fontconfig
|
||||||
{
|
{
|
||||||
leak_fontconfig_FcConfigSubstituteWithPat
|
leak_fontconfig_FcConfigSubstituteWithPat
|
||||||
@@ -349,11 +314,39 @@
|
|||||||
fun:heif_context_read_from_reader
|
fun:heif_context_read_from_reader
|
||||||
}
|
}
|
||||||
|
|
||||||
# orc
|
# glib
|
||||||
{
|
{
|
||||||
addr_orcexec
|
leak_glib__tls_get_addr
|
||||||
Memcheck:Addr1
|
Memcheck:Leak
|
||||||
obj:*/orcexec.*
|
match-leak-kinds: possible
|
||||||
|
...
|
||||||
|
fun:malloc
|
||||||
|
fun:allocate_dtv_entry
|
||||||
|
fun:allocate_and_init
|
||||||
|
fun:tls_get_addr_tail
|
||||||
|
fun:__tls_get_addr
|
||||||
|
}
|
||||||
|
{
|
||||||
|
value_g_utf8_make_valid_strlen
|
||||||
|
Memcheck:Value8
|
||||||
|
fun:strlen
|
||||||
|
fun:g_utf8_make_valid
|
||||||
|
}
|
||||||
|
{
|
||||||
|
value_g_utf8_make_valid_strncpy
|
||||||
|
Memcheck:Value8
|
||||||
|
fun:strncpy
|
||||||
|
fun:g_strndup
|
||||||
|
...
|
||||||
|
fun:g_utf8_make_valid
|
||||||
|
}
|
||||||
|
{
|
||||||
|
cond_g_utf8_make_valid_strncpy
|
||||||
|
Memcheck:Cond
|
||||||
|
fun:strncpy
|
||||||
|
fun:g_strndup
|
||||||
|
...
|
||||||
|
fun:g_utf8_make_valid
|
||||||
}
|
}
|
||||||
|
|
||||||
# libvips
|
# libvips
|
||||||
@@ -943,6 +936,79 @@
|
|||||||
...
|
...
|
||||||
fun:_ZN2v88internal18ArrayBufferSweeper10ReleaseAllEv
|
fun:_ZN2v88internal18ArrayBufferSweeper10ReleaseAllEv
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
cond_node_Builtins_JSEntry
|
||||||
|
Memcheck:Cond
|
||||||
|
...
|
||||||
|
fun:Builtins_JSEntry
|
||||||
|
...
|
||||||
|
fun:uv__poll_io_uring
|
||||||
|
}
|
||||||
|
{
|
||||||
|
cond_node_Builtins_TestEqualStrictHandler
|
||||||
|
Memcheck:Cond
|
||||||
|
fun:Builtins_TestEqualStrictHandler
|
||||||
|
...
|
||||||
|
fun:uv__poll_io_uring
|
||||||
|
}
|
||||||
|
{
|
||||||
|
cond_node_Builtins_TestGreaterThanHandler
|
||||||
|
Memcheck:Cond
|
||||||
|
fun:Builtins_TestGreaterThanHandler
|
||||||
|
...
|
||||||
|
fun:uv__poll_io_uring
|
||||||
|
}
|
||||||
|
{
|
||||||
|
cond_node_AfterStat
|
||||||
|
Memcheck:Cond
|
||||||
|
...
|
||||||
|
fun:_ZN4node2fs9AfterStatEP7uv_fs_s
|
||||||
|
...
|
||||||
|
fun:uv__poll_io_uring
|
||||||
|
}
|
||||||
|
{
|
||||||
|
cond_node_AfterMkdirp
|
||||||
|
Memcheck:Cond
|
||||||
|
fun:_ZN4node2fs11AfterMkdirpEP7uv_fs_s
|
||||||
|
fun:_ZN4node24MakeLibuvRequestCallbackI7uv_fs_sPFvPS1_EE7WrapperES2_
|
||||||
|
fun:_ZZZN4node2fs11MKDirpAsyncEP9uv_loop_sP7uv_fs_sPKciPFvS4_EENKUlS4_E_clES4_ENUlS4_E_4_FUNES4_
|
||||||
|
fun:uv__poll_io_uring
|
||||||
|
}
|
||||||
|
{
|
||||||
|
cond_v8_ArrayBufferSweeper_Finalize
|
||||||
|
Memcheck:Cond
|
||||||
|
fun:_ZN2v88internal18ArrayBufferSweeper8FinalizeEv
|
||||||
|
}
|
||||||
|
{
|
||||||
|
cond_v8_AdjustAmountOfExternalAllocatedMemory
|
||||||
|
Memcheck:Cond
|
||||||
|
fun:_ZN2v87Isolate37AdjustAmountOfExternalAllocatedMemoryEl
|
||||||
|
}
|
||||||
|
{
|
||||||
|
cond_v8_IncrementalMarkingLimitReached
|
||||||
|
Memcheck:Cond
|
||||||
|
fun:_ZN2v88internal4Heap30IncrementalMarkingLimitReachedEv
|
||||||
|
}
|
||||||
|
{
|
||||||
|
cond_v8_ShouldExpandOldGenerationOnSlowAllocation
|
||||||
|
Memcheck:Cond
|
||||||
|
fun:_ZN2v88internal4Heap41ShouldExpandOldGenerationOnSlowAllocationEPNS0_9LocalHeapENS0_16AllocationOriginE
|
||||||
|
}
|
||||||
|
{
|
||||||
|
cond_v8_ArrayBufferSweeper_SweepingJob_SweepListFull
|
||||||
|
Memcheck:Cond
|
||||||
|
fun:_ZN2v88internal18ArrayBufferSweeper11SweepingJob13SweepListFullEPNS0_15ArrayBufferListE
|
||||||
|
}
|
||||||
|
{
|
||||||
|
cond_v8_ArrayBufferSweeper_SweepingJob_SweepYoung
|
||||||
|
Memcheck:Cond
|
||||||
|
fun:_ZN2v88internal18ArrayBufferSweeper11SweepingJob10SweepYoungEv
|
||||||
|
}
|
||||||
|
{
|
||||||
|
cond_v8_StartIncrementalMarkingIfAllocationLimitIsReachedBackground
|
||||||
|
Memcheck:Cond
|
||||||
|
fun:_ZN2v88internal4Heap59StartIncrementalMarkingIfAllocationLimitIsReachedBackgroundEv
|
||||||
|
}
|
||||||
{
|
{
|
||||||
addr_v8_ZN2v88internal12_GLOBAL__N_119HandleApiCallHelperILb0EEENS0
|
addr_v8_ZN2v88internal12_GLOBAL__N_119HandleApiCallHelperILb0EEENS0
|
||||||
Memcheck:Addr8
|
Memcheck:Addr8
|
||||||
|
|||||||
@@ -44,6 +44,12 @@ sharp('input.png')
|
|||||||
// sharpened, with metadata, 90% quality WebP image data. Phew!
|
// sharpened, with metadata, 90% quality WebP image data. Phew!
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sharp('input.png')
|
||||||
|
.keepMetadata()
|
||||||
|
.toFile('output.png', (err, info) => {
|
||||||
|
// output.png is an image containing input.png along with all metadata(EXIF, ICC, XMP, IPTC) from input.png
|
||||||
|
})
|
||||||
|
|
||||||
sharp('input.jpg')
|
sharp('input.jpg')
|
||||||
.resize(300, 200)
|
.resize(300, 200)
|
||||||
.toFile('output.jpg', (err: Error) => {
|
.toFile('output.jpg', (err: Error) => {
|
||||||
@@ -404,7 +410,7 @@ sharp({
|
|||||||
|
|
||||||
// Taken from API documentation at
|
// Taken from API documentation at
|
||||||
// https://sharp.pixelplumbing.com/api-operation#clahe
|
// https://sharp.pixelplumbing.com/api-operation#clahe
|
||||||
// introducted
|
// introduced
|
||||||
sharp('input.jpg').clahe({ width: 10, height: 10 }).toFile('output.jpg');
|
sharp('input.jpg').clahe({ width: 10, height: 10 }).toFile('output.jpg');
|
||||||
|
|
||||||
sharp('input.jpg').clahe({ width: 10, height: 10, maxSlope: 5 }).toFile('outfile.jpg');
|
sharp('input.jpg').clahe({ width: 10, height: 10, maxSlope: 5 }).toFile('outfile.jpg');
|
||||||
@@ -589,7 +595,7 @@ sharp({
|
|||||||
rgba: true,
|
rgba: true,
|
||||||
justify: true,
|
justify: true,
|
||||||
spacing: 10,
|
spacing: 10,
|
||||||
wrap: 'charWord',
|
wrap: 'word-char',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.png()
|
.png()
|
||||||
|
|||||||
@@ -144,4 +144,10 @@ describe('AVIF', () => {
|
|||||||
/Processed image is too large for the HEIF format/
|
/Processed image is too large for the HEIF format/
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
it('Invalid bitdepth value throws error', async () => {
|
||||||
|
assert.rejects(
|
||||||
|
() => sharp().avif({ bitdepth: 11 }),
|
||||||
|
/Error: Expected 8, 10 or 12 for bitdepth but received 11 of type number/);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -77,4 +77,26 @@ describe('Clone', function () {
|
|||||||
assert.strictEqual(0, original.listenerCount('finish'));
|
assert.strictEqual(0, original.listenerCount('finish'));
|
||||||
assert.strictEqual(0, clone.listenerCount('finish'));
|
assert.strictEqual(0, clone.listenerCount('finish'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Ensure deep clone of properties, including arrays', async () => {
|
||||||
|
const alpha = await sharp({
|
||||||
|
create: { width: 320, height: 240, channels: 3, background: 'red' }
|
||||||
|
}).toColourspace('b-w').png().toBuffer();
|
||||||
|
|
||||||
|
const original = sharp();
|
||||||
|
const joiner = original.clone().joinChannel(alpha);
|
||||||
|
const negater = original.clone().negate();
|
||||||
|
|
||||||
|
fs.createReadStream(fixtures.inputJpg320x240).pipe(original);
|
||||||
|
const joined = await joiner.png({ effort: 1 }).toBuffer();
|
||||||
|
const negated = await negater.png({ effort: 1 }).toBuffer();
|
||||||
|
|
||||||
|
const joinedMetadata = await sharp(joined).metadata();
|
||||||
|
assert.strictEqual(joinedMetadata.channels, 4);
|
||||||
|
assert.strictEqual(joinedMetadata.hasAlpha, true);
|
||||||
|
|
||||||
|
const negatedMetadata = await sharp(negated).metadata();
|
||||||
|
assert.strictEqual(negatedMetadata.channels, 3);
|
||||||
|
assert.strictEqual(negatedMetadata.hasAlpha, false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -451,7 +451,7 @@ describe('composite', () => {
|
|||||||
assert.strictEqual(info.height, 40);
|
assert.strictEqual(info.height, 40);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Ensure implict unpremultiply after resize but before composite', async () => {
|
it('Ensure implicit unpremultiply after resize but before composite', async () => {
|
||||||
const [r, g, b, a] = await sharp({
|
const [r, g, b, a] = await sharp({
|
||||||
create: {
|
create: {
|
||||||
width: 1, height: 1, channels: 4, background: 'saddlebrown'
|
width: 1, height: 1, channels: 4, background: 'saddlebrown'
|
||||||
|
|||||||
@@ -73,6 +73,20 @@ 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)
|
||||||
|
|||||||
@@ -78,4 +78,21 @@ describe('HEIF', () => {
|
|||||||
sharp().heif({ compression: 'av1', chromaSubsampling: '4:4:4' });
|
sharp().heif({ compression: 'av1', chromaSubsampling: '4:4:4' });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('valid bitdepth value does not throw an error', () => {
|
||||||
|
const { heif } = sharp.versions;
|
||||||
|
delete sharp.versions.heif;
|
||||||
|
assert.doesNotThrow(() => {
|
||||||
|
sharp().heif({ compression: 'av1', bitdepth: 12 });
|
||||||
|
});
|
||||||
|
sharp.versions.heif = '1.2.3';
|
||||||
|
assert.throws(() => {
|
||||||
|
sharp().heif({ compression: 'av1', bitdepth: 10 });
|
||||||
|
}, /Error: Expected 8 for bitdepth when using prebuilt binaries but received 10 of type number/);
|
||||||
|
sharp.versions.heif = heif;
|
||||||
|
});
|
||||||
|
it('invalid bitdepth value should throw an error', () => {
|
||||||
|
assert.throws(() => {
|
||||||
|
sharp().heif({ compression: 'av1', bitdepth: 11 });
|
||||||
|
}, /Error: Expected 8, 10 or 12 for bitdepth but received 11 of type number/);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -96,27 +96,36 @@ describe('libvips binaries', function () {
|
|||||||
describe('Build time directories', () => {
|
describe('Build time directories', () => {
|
||||||
it('sharp-libvips include', () => {
|
it('sharp-libvips include', () => {
|
||||||
const dir = libvips.buildSharpLibvipsIncludeDir();
|
const dir = libvips.buildSharpLibvipsIncludeDir();
|
||||||
assert.strictEqual(fs.statSync(dir).isDirectory(), true);
|
if (dir) {
|
||||||
|
assert.strictEqual(fs.statSync(dir).isDirectory(), true);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
it('sharp-libvips cplusplus', () => {
|
it('sharp-libvips cplusplus', () => {
|
||||||
const dir = libvips.buildSharpLibvipsCPlusPlusDir();
|
const dir = libvips.buildSharpLibvipsCPlusPlusDir();
|
||||||
assert.strictEqual(fs.statSync(dir).isDirectory(), true);
|
if (dir) {
|
||||||
|
assert.strictEqual(fs.statSync(dir).isDirectory(), true);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
it('sharp-libvips lib', () => {
|
it('sharp-libvips lib', () => {
|
||||||
const dir = libvips.buildSharpLibvipsLibDir();
|
const dir = libvips.buildSharpLibvipsLibDir();
|
||||||
assert.strictEqual(fs.statSync(dir).isDirectory(), true);
|
if (dir) {
|
||||||
|
assert.strictEqual(fs.statSync(dir).isDirectory(), true);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Runtime detection', () => {
|
describe('Runtime detection', () => {
|
||||||
it('platform', () => {
|
it('platform', () => {
|
||||||
const [platform] = libvips.runtimePlatformArch().split('-');
|
const [platform] = libvips.runtimePlatformArch().split('-');
|
||||||
assert.strict(['darwin', 'linux', 'linuxmusl', 'win32'].includes(platform));
|
assert.strict(['darwin', 'freebsd', 'linux', 'linuxmusl', 'win32'].includes(platform));
|
||||||
});
|
});
|
||||||
it('arch', () => {
|
it('arch', () => {
|
||||||
const [, arch] = libvips.runtimePlatformArch().split('-');
|
const [, arch] = libvips.runtimePlatformArch().split('-');
|
||||||
assert.strict(['arm', 'arm64', 'ia32', 'x64'].includes(arch));
|
assert.strict(['arm', 'arm64', 'ia32', 'x64'].includes(arch));
|
||||||
});
|
});
|
||||||
|
it('isUnsupportedNodeRuntime', () => {
|
||||||
|
assert.strictEqual(libvips.isUnsupportedNodeRuntime(), undefined);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('logger', function () {
|
describe('logger', function () {
|
||||||
@@ -144,4 +153,26 @@ describe('libvips binaries', function () {
|
|||||||
libvips.log(new Error('problem'));
|
libvips.log(new Error('problem'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('yarn locator hash', () => {
|
||||||
|
it('known platform', () => {
|
||||||
|
const cc = process.env.CC;
|
||||||
|
delete process.env.CC;
|
||||||
|
process.env.npm_config_platform = 'linux';
|
||||||
|
process.env.npm_config_arch = 's390x';
|
||||||
|
process.env.npm_config_libc = '';
|
||||||
|
const locatorHash = libvips.yarnLocator();
|
||||||
|
assert.strictEqual(locatorHash, '45978c229d');
|
||||||
|
delete process.env.npm_config_platform;
|
||||||
|
delete process.env.npm_config_arch;
|
||||||
|
delete process.env.npm_config_libc;
|
||||||
|
process.env.CC = cc;
|
||||||
|
});
|
||||||
|
it('unknown platform', () => {
|
||||||
|
process.env.npm_config_platform = 'unknown-platform';
|
||||||
|
const locatorHash = libvips.yarnLocator();
|
||||||
|
assert.strictEqual(locatorHash, '');
|
||||||
|
delete process.env.npm_config_platform;
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -576,6 +576,19 @@ describe('Image metadata', function () {
|
|||||||
assert.strictEqual(description, 'Generic RGB Profile');
|
assert.strictEqual(description, 'Generic RGB Profile');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('keep existing CMYK ICC profile', async () => {
|
||||||
|
const data = await sharp(fixtures.inputJpgWithCmykProfile)
|
||||||
|
.pipelineColourspace('cmyk')
|
||||||
|
.toColourspace('cmyk')
|
||||||
|
.keepIccProfile()
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
const metadata = await sharp(data).metadata();
|
||||||
|
assert.strictEqual(metadata.channels, 4);
|
||||||
|
const { description } = icc.parse(metadata.icc);
|
||||||
|
assert.strictEqual(description, 'U.S. Web Coated (SWOP) v2');
|
||||||
|
});
|
||||||
|
|
||||||
it('transform to ICC profile and attach', async () => {
|
it('transform to ICC profile and attach', async () => {
|
||||||
const data = await sharp({ create })
|
const data = await sharp({ create })
|
||||||
.png()
|
.png()
|
||||||
@@ -598,6 +611,24 @@ describe('Image metadata', function () {
|
|||||||
assert.strictEqual(undefined, metadata.icc);
|
assert.strictEqual(undefined, metadata.icc);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('transform to invalid ICC profile emits warning', async () => {
|
||||||
|
const img = sharp({ create })
|
||||||
|
.png()
|
||||||
|
.withIccProfile(fixtures.path('invalid-illuminant.icc'));
|
||||||
|
|
||||||
|
let warningEmitted = '';
|
||||||
|
img.on('warning', (warning) => {
|
||||||
|
warningEmitted = warning;
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await img.toBuffer();
|
||||||
|
assert.strictEqual('Invalid profile', warningEmitted);
|
||||||
|
|
||||||
|
const metadata = await sharp(data).metadata();
|
||||||
|
assert.strictEqual(3, metadata.channels);
|
||||||
|
assert.strictEqual(undefined, metadata.icc);
|
||||||
|
});
|
||||||
|
|
||||||
it('Apply CMYK output ICC profile', function (done) {
|
it('Apply CMYK output ICC profile', function (done) {
|
||||||
const output = fixtures.path('output.icc-cmyk.jpg');
|
const output = fixtures.path('output.icc-cmyk.jpg');
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
|
|||||||
@@ -353,6 +353,21 @@ describe('Rotation', function () {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
it('Animated image rotate 180', () =>
|
||||||
|
assert.doesNotReject(() => sharp(fixtures.inputGifAnimated, { animated: true })
|
||||||
|
.rotate(180)
|
||||||
|
.toBuffer()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
it('Animated image rotate non-180 rejects', () =>
|
||||||
|
assert.rejects(() => sharp(fixtures.inputGifAnimated, { animated: true })
|
||||||
|
.rotate(90)
|
||||||
|
.toBuffer(),
|
||||||
|
/Rotate is not supported for multi-page images/
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
it('Multiple rotate emits warning', () => {
|
it('Multiple rotate emits warning', () => {
|
||||||
let warningMessage = '';
|
let warningMessage = '';
|
||||||
const s = sharp();
|
const s = sharp();
|
||||||
|
|||||||
@@ -319,21 +319,21 @@ describe('Text to image', function () {
|
|||||||
|
|
||||||
it('valid wrap throws', () => {
|
it('valid wrap throws', () => {
|
||||||
assert.doesNotThrow(() => sharp({ text: { text: 'text', wrap: 'none' } }));
|
assert.doesNotThrow(() => sharp({ text: { text: 'text', wrap: 'none' } }));
|
||||||
assert.doesNotThrow(() => sharp({ text: { text: 'text', wrap: 'wordChar' } }));
|
assert.doesNotThrow(() => sharp({ text: { text: 'text', wrap: 'word-char' } }));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invalid wrap throws', () => {
|
it('invalid wrap throws', () => {
|
||||||
assert.throws(
|
assert.throws(
|
||||||
() => sharp({ text: { text: 'text', wrap: 1 } }),
|
() => sharp({ text: { text: 'text', wrap: 1 } }),
|
||||||
/Expected one of: word, char, wordChar, none for text\.wrap but received 1 of type number/
|
/Expected one of: word, char, word-char, none for text\.wrap but received 1 of type number/
|
||||||
);
|
);
|
||||||
assert.throws(
|
assert.throws(
|
||||||
() => sharp({ text: { text: 'text', wrap: false } }),
|
() => sharp({ text: { text: 'text', wrap: false } }),
|
||||||
/Expected one of: word, char, wordChar, none for text\.wrap but received false of type boolean/
|
/Expected one of: word, char, word-char, none for text\.wrap but received false of type boolean/
|
||||||
);
|
);
|
||||||
assert.throws(
|
assert.throws(
|
||||||
() => sharp({ text: { text: 'text', wrap: 'invalid' } }),
|
() => sharp({ text: { text: 'text', wrap: 'invalid' } }),
|
||||||
/Expected one of: word, char, wordChar, none for text\.wrap but received invalid of type string/
|
/Expected one of: word, char, word-char, none for text\.wrap but received invalid of type string/
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,16 +9,19 @@ const sharp = require('../../');
|
|||||||
|
|
||||||
describe('Utilities', function () {
|
describe('Utilities', function () {
|
||||||
describe('Cache', function () {
|
describe('Cache', function () {
|
||||||
it('Can be disabled', function () {
|
it('Can be disabled', function (done) {
|
||||||
sharp.cache(false);
|
queueMicrotask(() => {
|
||||||
const cache = sharp.cache(false);
|
sharp.cache(false);
|
||||||
assert.strictEqual(cache.memory.current, 0);
|
const cache = sharp.cache(false);
|
||||||
assert.strictEqual(cache.memory.max, 0);
|
assert.strictEqual(cache.memory.current, 0);
|
||||||
assert.strictEqual(typeof cache.memory.high, 'number');
|
assert.strictEqual(cache.memory.max, 0);
|
||||||
assert.strictEqual(cache.files.current, 0);
|
assert.strictEqual(typeof cache.memory.high, 'number');
|
||||||
assert.strictEqual(cache.files.max, 0);
|
assert.strictEqual(cache.files.current, 0);
|
||||||
assert.strictEqual(cache.items.current, 0);
|
assert.strictEqual(cache.files.max, 0);
|
||||||
assert.strictEqual(cache.items.max, 0);
|
assert.strictEqual(cache.items.current, 0);
|
||||||
|
assert.strictEqual(cache.items.max, 0);
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
it('Can be enabled with defaults', function () {
|
it('Can be enabled with defaults', function () {
|
||||||
const cache = sharp.cache(true);
|
const cache = sharp.cache(true);
|
||||||
@@ -131,7 +134,7 @@ describe('Utilities', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('input fileSuffix', function () {
|
it('input fileSuffix', function () {
|
||||||
assert.deepStrictEqual(['.jpg', '.jpeg', '.jpe'], sharp.format.jpeg.input.fileSuffix);
|
assert.deepStrictEqual(['.jpg', '.jpeg', '.jpe', '.jfif'], sharp.format.jpeg.input.fileSuffix);
|
||||||
});
|
});
|
||||||
it('output alias', function () {
|
it('output alias', function () {
|
||||||
assert.deepStrictEqual(['jpe', 'jpg'], sharp.format.jpeg.output.alias);
|
assert.deepStrictEqual(['jpe', 'jpg'], sharp.format.jpeg.output.alias);
|
||||||
|
|||||||
Reference in New Issue
Block a user