mirror of
https://github.com/lovell/sharp.git
synced 2025-12-06 03:51:40 +01:00
Compare commits
32 Commits
v0.34.4-rc
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3609c61a22 | ||
|
|
dc6820b49f | ||
|
|
f2a49d19c9 | ||
|
|
e062456868 | ||
|
|
6450c704a6 | ||
|
|
f7c95d1bf0 | ||
|
|
ef86a75560 | ||
|
|
6c1e840098 | ||
|
|
e1628d8ef5 | ||
|
|
4f9f8179a6 | ||
|
|
09d5aa8cfa | ||
|
|
040b73ca74 | ||
|
|
1f2f33d9a7 | ||
|
|
69b2c45615 | ||
|
|
9e4e184132 | ||
|
|
206eb4a89a | ||
|
|
c1c16ed3e6 | ||
|
|
b7fda60a85 | ||
|
|
1bbee519aa | ||
|
|
2324d75f7f | ||
|
|
5e72ad95fa | ||
|
|
6b922b30d5 | ||
|
|
54722dd582 | ||
|
|
adb6275ae9 | ||
|
|
f2978651f0 | ||
|
|
c446d743a2 | ||
|
|
3498eb63e3 | ||
|
|
3009957120 | ||
|
|
b36237ddcb | ||
|
|
a0af662d78 | ||
|
|
ee437832e2 | ||
|
|
529901177b |
@ -1,5 +1,5 @@
|
|||||||
freebsd_instance:
|
freebsd_instance:
|
||||||
image_family: freebsd-15-0-snap
|
image_family: freebsd-15-0
|
||||||
|
|
||||||
task:
|
task:
|
||||||
name: FreeBSD
|
name: FreeBSD
|
||||||
@ -9,9 +9,10 @@ task:
|
|||||||
prerequisites_script:
|
prerequisites_script:
|
||||||
- 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/node22 www/npm
|
||||||
- pkg-config --modversion vips-cpp
|
- pkg-config --modversion vips-cpp
|
||||||
install_script:
|
install_script:
|
||||||
- npm install --build-from-source
|
- npm install
|
||||||
|
- npm run build
|
||||||
test_script:
|
test_script:
|
||||||
- npx mocha --no-config --spec=test/unit/io.js --timeout=30000
|
- node --test test/unit/io.js
|
||||||
|
|||||||
@ -7,6 +7,4 @@ indent_size = 2
|
|||||||
charset = utf-8
|
charset = utf-8
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
|
max_line_length = 120
|
||||||
[*.md]
|
|
||||||
trim_trailing_whitespace = false
|
|
||||||
|
|||||||
7
.github/CONTRIBUTING.md
vendored
7
.github/CONTRIBUTING.md
vendored
@ -6,8 +6,6 @@ Hello, thank you for your interest in helping!
|
|||||||
|
|
||||||
Please create a [new issue](https://github.com/lovell/sharp/issues/new) containing the steps to reproduce the problem.
|
Please create a [new issue](https://github.com/lovell/sharp/issues/new) containing the steps to reproduce the problem.
|
||||||
|
|
||||||
If you're having installation problems, please include the output of running `npm install --verbose sharp`.
|
|
||||||
|
|
||||||
New bugs are assigned a `triage` label whilst under investigation.
|
New bugs are assigned a `triage` label whilst under investigation.
|
||||||
|
|
||||||
## Submit a new feature request
|
## Submit a new feature request
|
||||||
@ -16,7 +14,7 @@ If a [similar request](https://github.com/lovell/sharp/labels/enhancement) exist
|
|||||||
it's probably fastest to add a comment to it about your requirement.
|
it's probably fastest to add a comment to it about your requirement.
|
||||||
|
|
||||||
Implementation is usually straightforward if libvips
|
Implementation is usually straightforward if libvips
|
||||||
[already supports](https://www.libvips.org/API/current/func-list.html)
|
[already supports](https://www.libvips.org/API/current/function-list.html)
|
||||||
the feature you need.
|
the feature you need.
|
||||||
|
|
||||||
## Submit a Pull Request to fix a bug
|
## Submit a Pull Request to fix a bug
|
||||||
@ -27,12 +25,11 @@ Please select the `main` branch as the destination for your Pull Request so your
|
|||||||
|
|
||||||
Please squash your changes into a single commit using a command like `git rebase -i upstream/main`.
|
Please squash your changes into a single commit using a command like `git rebase -i upstream/main`.
|
||||||
|
|
||||||
To test C++ changes, you can compile the module using `npm install --build-from-source` and then run the tests using `npm test`.
|
To test C++ changes, you can compile the module using `npm run build` and then run the tests using `npm test`.
|
||||||
|
|
||||||
## Submit a Pull Request with a new feature
|
## Submit a Pull Request with a new feature
|
||||||
|
|
||||||
Please add JavaScript [unit tests](https://github.com/lovell/sharp/tree/main/test/unit) to cover your new feature.
|
Please add JavaScript [unit tests](https://github.com/lovell/sharp/tree/main/test/unit) to cover your new feature.
|
||||||
A test coverage report for the JavaScript code is generated in the `coverage/lcov-report` directory.
|
|
||||||
Please also update the [TypeScript definitions](https://github.com/lovell/sharp/tree/main/lib/index.d.ts), along with the [type definition tests](https://github.com/lovell/sharp/tree/main/test/types/sharp.test-d.ts).
|
Please also update the [TypeScript definitions](https://github.com/lovell/sharp/tree/main/lib/index.d.ts), along with the [type definition tests](https://github.com/lovell/sharp/tree/main/test/types/sharp.test-d.ts).
|
||||||
|
|
||||||
Where possible, the functional tests use gradient-based perceptual hashes
|
Where possible, the functional tests use gradient-based perceptual hashes
|
||||||
|
|||||||
96
.github/workflows/ci.yml
vendored
96
.github/workflows/ci.yml
vendored
@ -4,9 +4,23 @@ on:
|
|||||||
- pull_request
|
- pull_request
|
||||||
permissions: {}
|
permissions: {}
|
||||||
jobs:
|
jobs:
|
||||||
|
lint:
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-node@v5
|
||||||
|
with:
|
||||||
|
node-version: "24"
|
||||||
|
- run: npm install --ignore-scripts
|
||||||
|
- run: npm run lint-cpp
|
||||||
|
- run: npm run lint-js
|
||||||
|
- run: npm run lint-types
|
||||||
build-native:
|
build-native:
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
needs: lint
|
||||||
name: "build-${{ matrix.platform }} [Node.js ${{ matrix.nodejs_version_major }}] ${{ matrix.package && '[package]' }}"
|
name: "build-${{ matrix.platform }} [Node.js ${{ matrix.nodejs_version_major }}] ${{ matrix.package && '[package]' }}"
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
container: ${{ matrix.container }}
|
container: ${{ matrix.container }}
|
||||||
@ -59,34 +73,34 @@ jobs:
|
|||||||
nodejs_version: "^20.3.0"
|
nodejs_version: "^20.3.0"
|
||||||
nodejs_version_major: 20
|
nodejs_version_major: 20
|
||||||
platform: linux-arm64
|
platform: linux-arm64
|
||||||
- os: macos-13
|
- os: macos-15-intel
|
||||||
nodejs_arch: x64
|
nodejs_arch: x64
|
||||||
nodejs_version: "^18.17.0"
|
nodejs_version: "^18.17.0"
|
||||||
nodejs_version_major: 18
|
nodejs_version_major: 18
|
||||||
platform: darwin-x64
|
platform: darwin-x64
|
||||||
package: true
|
package: true
|
||||||
- os: macos-13
|
- os: macos-15-intel
|
||||||
nodejs_arch: x64
|
nodejs_arch: x64
|
||||||
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-13
|
- os: macos-15-intel
|
||||||
nodejs_arch: x64
|
nodejs_arch: x64
|
||||||
nodejs_version: "^22.9.0"
|
nodejs_version: "^22.9.0"
|
||||||
nodejs_version_major: 22
|
nodejs_version_major: 22
|
||||||
platform: darwin-x64
|
platform: darwin-x64
|
||||||
- os: macos-14
|
- os: macos-15
|
||||||
nodejs_arch: arm64
|
nodejs_arch: arm64
|
||||||
nodejs_version: "^18.17.0"
|
nodejs_version: "^18.17.0"
|
||||||
nodejs_version_major: 18
|
nodejs_version_major: 18
|
||||||
platform: darwin-arm64
|
platform: darwin-arm64
|
||||||
package: true
|
package: true
|
||||||
- os: macos-14
|
- os: macos-15
|
||||||
nodejs_arch: arm64
|
nodejs_arch: arm64
|
||||||
nodejs_version: "^20.3.0"
|
nodejs_version: "^20.3.0"
|
||||||
nodejs_version_major: 20
|
nodejs_version_major: 20
|
||||||
platform: darwin-arm64
|
platform: darwin-arm64
|
||||||
- os: macos-14
|
- os: macos-15
|
||||||
nodejs_arch: arm64
|
nodejs_arch: arm64
|
||||||
nodejs_version: "^22.9.0"
|
nodejs_version: "^22.9.0"
|
||||||
nodejs_version_major: 22
|
nodejs_version_major: 22
|
||||||
@ -150,17 +164,15 @@ jobs:
|
|||||||
python-version: "3.12"
|
python-version: "3.12"
|
||||||
- name: Dependencies (Node.js)
|
- name: Dependencies (Node.js)
|
||||||
if: "!contains(matrix.platform, 'linuxmusl')"
|
if: "!contains(matrix.platform, 'linuxmusl')"
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v5
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.nodejs_version }}
|
node-version: ${{ matrix.nodejs_version }}
|
||||||
architecture: ${{ matrix.nodejs_arch }}
|
architecture: ${{ matrix.nodejs_arch }}
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Install
|
- run: npm install
|
||||||
run: npm install --build-from-source
|
- run: npm run build
|
||||||
- name: Test
|
- run: npm run test-unit
|
||||||
run: npm test
|
- if: matrix.package
|
||||||
- name: Populate npm package
|
|
||||||
if: matrix.package
|
|
||||||
run: npm run package-from-local-build
|
run: npm run package-from-local-build
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: matrix.package
|
if: matrix.package
|
||||||
@ -172,6 +184,7 @@ jobs:
|
|||||||
build-linuxmusl-arm64:
|
build-linuxmusl-arm64:
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
needs: lint
|
||||||
name: "build-linuxmusl-arm64 [Node.js ${{ matrix.nodejs_version_major }}] ${{ matrix.package && '[package]' }}"
|
name: "build-linuxmusl-arm64 [Node.js ${{ matrix.nodejs_version_major }}] ${{ matrix.package && '[package]' }}"
|
||||||
runs-on: ubuntu-24.04-arm
|
runs-on: ubuntu-24.04-arm
|
||||||
container:
|
container:
|
||||||
@ -199,12 +212,10 @@ jobs:
|
|||||||
- name: Dependencies
|
- name: Dependencies
|
||||||
run: apk add build-base git python3 font-noto --update-cache
|
run: apk add build-base git python3 font-noto --update-cache
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Install
|
- run: npm install
|
||||||
run: npm install --build-from-source
|
- run: npm run build
|
||||||
- name: Test
|
- run: npm run test-unit
|
||||||
run: npm test
|
- if: matrix.package
|
||||||
- name: Populate npm package
|
|
||||||
if: matrix.package
|
|
||||||
run: npm run package-from-local-build
|
run: npm run package-from-local-build
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: matrix.package
|
if: matrix.package
|
||||||
@ -216,6 +227,7 @@ jobs:
|
|||||||
build-qemu:
|
build-qemu:
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
needs: lint
|
||||||
name: "build-${{ matrix.platform }} [Node.js ${{ matrix.nodejs_version_major }}] [package]"
|
name: "build-${{ matrix.platform }} [Node.js ${{ matrix.nodejs_version_major }}] [package]"
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
strategy:
|
strategy:
|
||||||
@ -223,40 +235,49 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- platform: linux-arm
|
- platform: linux-arm
|
||||||
distro: bullseye
|
base_image: "balenalib/rpi-raspbian:bullseye"
|
||||||
run_on_arch: armv6
|
|
||||||
nodejs_arch: armv6l
|
nodejs_arch: armv6l
|
||||||
nodejs_hostname: unofficial-builds.nodejs.org
|
nodejs_hostname: unofficial-builds.nodejs.org
|
||||||
nodejs_version: "18.17.0"
|
nodejs_version: "18.17.0"
|
||||||
nodejs_version_major: 18
|
nodejs_version_major: 18
|
||||||
- platform: linux-s390x
|
- platform: linux-s390x
|
||||||
distro: bookworm
|
base_image: "--platform=linux/s390x s390x/debian:bookworm"
|
||||||
run_on_arch: s390x
|
|
||||||
nodejs_arch: s390x
|
nodejs_arch: s390x
|
||||||
nodejs_hostname: nodejs.org
|
nodejs_hostname: nodejs.org
|
||||||
nodejs_version: "18.17.0"
|
nodejs_version: "18.17.0"
|
||||||
nodejs_version_major: 18
|
nodejs_version_major: 18
|
||||||
- platform: linux-ppc64
|
- platform: linux-ppc64
|
||||||
distro: bookworm
|
base_image: "--platform=linux/ppc64le ppc64le/debian:bookworm"
|
||||||
run_on_arch: ppc64le
|
|
||||||
nodejs_arch: ppc64le
|
nodejs_arch: ppc64le
|
||||||
nodejs_hostname: nodejs.org
|
nodejs_hostname: nodejs.org
|
||||||
nodejs_version: "18.17.0"
|
nodejs_version: "18.17.0"
|
||||||
nodejs_version_major: 18
|
nodejs_version_major: 18
|
||||||
|
- platform: linux-riscv64
|
||||||
|
base_image: "--platform=linux/riscv64 riscv64/debian:trixie"
|
||||||
|
compiler_flags: "-march=rv64gc"
|
||||||
|
nodejs_arch: riscv64
|
||||||
|
nodejs_hostname: unofficial-builds.nodejs.org
|
||||||
|
nodejs_version: "20.19.5"
|
||||||
|
nodejs_version_major: 20
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: uraimo/run-on-arch-action@v3
|
- uses: uraimo/run-on-arch-action@v3
|
||||||
with:
|
with:
|
||||||
arch: ${{ matrix.run_on_arch }}
|
arch: none
|
||||||
distro: ${{ matrix.distro }}
|
distro: none
|
||||||
|
base_image: ${{ matrix.base_image }}
|
||||||
|
env: |
|
||||||
|
CFLAGS: "${{ matrix.compiler_flags }}"
|
||||||
|
CXXFLAGS: "${{ matrix.compiler_flags }}"
|
||||||
run: |
|
run: |
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get install -y curl g++ git libatomic1 make python3 xz-utils
|
apt-get install -y curl g++ git libatomic1 make python3 xz-utils
|
||||||
mkdir /opt/nodejs
|
mkdir /opt/nodejs
|
||||||
curl --silent https://${{ matrix.nodejs_hostname }}/download/release/v${{ matrix.nodejs_version}}/node-v${{ matrix.nodejs_version}}-linux-${{ matrix.nodejs_arch }}.tar.xz | tar xJC /opt/nodejs --strip-components=1
|
curl --silent https://${{ matrix.nodejs_hostname }}/download/release/v${{ matrix.nodejs_version}}/node-v${{ matrix.nodejs_version}}-linux-${{ matrix.nodejs_arch }}.tar.xz | tar xJC /opt/nodejs --strip-components=1
|
||||||
export PATH=$PATH:/opt/nodejs/bin
|
export PATH=$PATH:/opt/nodejs/bin
|
||||||
npm install --build-from-source
|
npm install
|
||||||
npx mocha --no-config --spec=test/unit/io.js --timeout=30000
|
npm run build
|
||||||
|
node --test test/unit/io.js
|
||||||
npm run package-from-local-build
|
npm run package-from-local-build
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
@ -267,19 +288,20 @@ jobs:
|
|||||||
build-emscripten:
|
build-emscripten:
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
needs: lint
|
||||||
name: "build-wasm32 [package]"
|
name: "build-wasm32 [package]"
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
container: "emscripten/emsdk:4.0.14"
|
container: "emscripten/emsdk:4.0.18"
|
||||||
steps:
|
steps:
|
||||||
- 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@v4
|
uses: actions/setup-node@v5
|
||||||
with:
|
with:
|
||||||
node-version: "20"
|
node-version: "20"
|
||||||
- name: Install
|
- run: npm install
|
||||||
run: emmake npm install --build-from-source
|
- run: emmake npm run build
|
||||||
- name: Verify emscripten versions match
|
- name: Verify emscripten versions match
|
||||||
run: |
|
run: |
|
||||||
EMSCRIPTEN_VERSION_LIBVIPS=$(node -p "require('@img/sharp-libvips-dev-wasm32/versions').emscripten")
|
EMSCRIPTEN_VERSION_LIBVIPS=$(node -p "require('@img/sharp-libvips-dev-wasm32/versions').emscripten")
|
||||||
@ -287,10 +309,8 @@ jobs:
|
|||||||
echo "libvips built with emscripten $EMSCRIPTEN_VERSION_LIBVIPS"
|
echo "libvips built with emscripten $EMSCRIPTEN_VERSION_LIBVIPS"
|
||||||
echo "sharp built with emscripten $EMSCRIPTEN_VERSION_SHARP"
|
echo "sharp built with emscripten $EMSCRIPTEN_VERSION_SHARP"
|
||||||
test "$EMSCRIPTEN_VERSION_LIBVIPS" = "$EMSCRIPTEN_VERSION_SHARP"
|
test "$EMSCRIPTEN_VERSION_LIBVIPS" = "$EMSCRIPTEN_VERSION_SHARP"
|
||||||
- name: Test
|
- run: emmake npm run test-unit
|
||||||
run: emmake npm test
|
- run: emmake npm run package-from-local-build
|
||||||
- name: Populate npm package
|
|
||||||
run: emmake npm run package-from-local-build
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: wasm32
|
name: wasm32
|
||||||
@ -314,7 +334,7 @@ jobs:
|
|||||||
path: npm
|
path: npm
|
||||||
- name: Create npm workspace tarball
|
- name: Create npm workspace tarball
|
||||||
run: tar -vcaf npm-workspace.tar.xz --directory npm --exclude=from-local-build.js .
|
run: tar -vcaf npm-workspace.tar.xz --directory npm --exclude=from-local-build.js .
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v5
|
||||||
with:
|
with:
|
||||||
node-version: '24'
|
node-version: '24'
|
||||||
- name: Create release notes
|
- name: Create release notes
|
||||||
|
|||||||
18
.github/workflows/npm.yml
vendored
18
.github/workflows/npm.yml
vendored
@ -43,30 +43,30 @@ jobs:
|
|||||||
runtime: bun
|
runtime: bun
|
||||||
|
|
||||||
- name: darwin-x64-node-npm
|
- name: darwin-x64-node-npm
|
||||||
runs-on: macos-13
|
runs-on: macos-15-intel
|
||||||
runtime: node
|
runtime: node
|
||||||
package-manager: npm
|
package-manager: npm
|
||||||
- name: darwin-x64-node-pnpm
|
- name: darwin-x64-node-pnpm
|
||||||
runs-on: macos-13
|
runs-on: macos-15-intel
|
||||||
runtime: node
|
runtime: node
|
||||||
package-manager: pnpm
|
package-manager: pnpm
|
||||||
- name: darwin-x64-node-yarn
|
- name: darwin-x64-node-yarn
|
||||||
runs-on: macos-13
|
runs-on: macos-15-intel
|
||||||
runtime: node
|
runtime: node
|
||||||
package-manager: yarn
|
package-manager: yarn
|
||||||
- name: darwin-x64-node-yarn-pnp
|
- name: darwin-x64-node-yarn-pnp
|
||||||
runs-on: macos-13
|
runs-on: macos-15-intel
|
||||||
runtime: node
|
runtime: node
|
||||||
package-manager: yarn-pnp
|
package-manager: yarn-pnp
|
||||||
- name: darwin-x64-node-yarn-v1
|
- name: darwin-x64-node-yarn-v1
|
||||||
runs-on: macos-13
|
runs-on: macos-15-intel
|
||||||
runtime: node
|
runtime: node
|
||||||
package-manager: yarn-v1
|
package-manager: yarn-v1
|
||||||
- name: darwin-x64-deno
|
- name: darwin-x64-deno
|
||||||
runs-on: macos-13
|
runs-on: macos-15-intel
|
||||||
runtime: deno
|
runtime: deno
|
||||||
- name: darwin-x64-bun
|
- name: darwin-x64-bun
|
||||||
runs-on: macos-13
|
runs-on: macos-15-intel
|
||||||
runtime: bun
|
runtime: bun
|
||||||
|
|
||||||
- name: win32-x64-node-npm
|
- name: win32-x64-node-npm
|
||||||
@ -185,7 +185,9 @@ jobs:
|
|||||||
|
|
||||||
- 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 install
|
||||||
|
deno run --allow-env --allow-ffi --allow-read --allow-sys release.mjs
|
||||||
|
|
||||||
- name: Run with Bun
|
- name: Run with Bun
|
||||||
if: ${{ matrix.runtime == 'bun' }}
|
if: ${{ matrix.runtime == 'bun' }}
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"parallel": true,
|
|
||||||
"slow": 1000,
|
|
||||||
"timeout": 30000,
|
|
||||||
"require": "./test/beforeEach.js",
|
|
||||||
"spec": "./test/unit/*.js"
|
|
||||||
}
|
|
||||||
26
biome.json
Normal file
26
biome.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://biomejs.dev/schemas/2.3.4/schema.json",
|
||||||
|
"vcs": {
|
||||||
|
"enabled": true,
|
||||||
|
"clientKind": "git",
|
||||||
|
"useIgnoreFile": true
|
||||||
|
},
|
||||||
|
"files": {
|
||||||
|
"ignoreUnknown": true
|
||||||
|
},
|
||||||
|
"linter": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"recommended": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"formatter": {
|
||||||
|
"enabled": false,
|
||||||
|
"useEditorconfig": true
|
||||||
|
},
|
||||||
|
"javascript": {
|
||||||
|
"formatter": {
|
||||||
|
"quoteStyle": "single"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
import { defineConfig } from 'astro/config';
|
|
||||||
import starlight from '@astrojs/starlight';
|
import starlight from '@astrojs/starlight';
|
||||||
|
import { defineConfig } from 'astro/config';
|
||||||
import starlightAutoSidebar from 'starlight-auto-sidebar';
|
import starlightAutoSidebar from 'starlight-auto-sidebar';
|
||||||
|
|
||||||
import { version } from '../package.json';
|
import { version } from '../package.json';
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
'use strict';
|
*/
|
||||||
|
|
||||||
import fs from 'node:fs/promises';
|
import fs from 'node:fs/promises';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
|
|||||||
@ -11,8 +11,8 @@
|
|||||||
"astro": "astro"
|
"astro": "astro"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/starlight": "^0.35.2",
|
"@astrojs/starlight": "^0.36.2",
|
||||||
"astro": "^5.13.5",
|
"astro": "^5.15.3",
|
||||||
"starlight-auto-sidebar": "^0.1.2"
|
"starlight-auto-sidebar": "^0.1.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ title: Channel manipulation
|
|||||||
|
|
||||||
Remove alpha channels, if any. This is a no-op if the image does not have an alpha channel.
|
Remove alpha channels, if any. This is a no-op if the image does not have an alpha channel.
|
||||||
|
|
||||||
See also [flatten](/api-operation#flatten).
|
See also [flatten](/api-operation/#flatten).
|
||||||
|
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
|
|||||||
@ -80,7 +80,7 @@ as defined by [toColourspace](#tocolourspace).
|
|||||||
|
|
||||||
| Param | Type | Description |
|
| Param | Type | Description |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| [colourspace] | <code>string</code> | pipeline colourspace e.g. `rgb16`, `scrgb`, `lab`, `grey16` [...](https://github.com/libvips/libvips/blob/41cff4e9d0838498487a00623462204eb10ee5b8/libvips/iofuncs/enumtypes.c#L774) |
|
| [colourspace] | <code>string</code> | pipeline colourspace e.g. `rgb16`, `scrgb`, `lab`, `grey16` [...](https://www.libvips.org/API/current/enum.Interpretation.html) |
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
```js
|
```js
|
||||||
@ -123,7 +123,7 @@ By default output image will be web-friendly sRGB, with additional channels inte
|
|||||||
|
|
||||||
| Param | Type | Description |
|
| Param | Type | Description |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| [colourspace] | <code>string</code> | output colourspace e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://github.com/libvips/libvips/blob/3c0bfdf74ce1dc37a6429bed47fa76f16e2cd70a/libvips/iofuncs/enumtypes.c#L777-L794) |
|
| [colourspace] | <code>string</code> | output colourspace e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://www.libvips.org/API/current/enum.Interpretation.html) |
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
```js
|
```js
|
||||||
|
|||||||
@ -21,7 +21,7 @@ The `blend` option can be one of `clear`, `source`, `over`, `in`, `out`, `atop`,
|
|||||||
`hard-light`, `soft-light`, `difference`, `exclusion`.
|
`hard-light`, `soft-light`, `difference`, `exclusion`.
|
||||||
|
|
||||||
More information about blend modes can be found at
|
More information about blend modes can be found at
|
||||||
https://www.libvips.org/API/current/libvips-conversion.html#VipsBlendMode
|
https://www.libvips.org/API/current/enum.BlendMode.html
|
||||||
and https://www.cairographics.org/operators/
|
and https://www.cairographics.org/operators/
|
||||||
|
|
||||||
|
|
||||||
@ -64,8 +64,8 @@ and https://www.cairographics.org/operators/
|
|||||||
| [images[].raw.height] | <code>Number</code> | | |
|
| [images[].raw.height] | <code>Number</code> | | |
|
||||||
| [images[].raw.channels] | <code>Number</code> | | |
|
| [images[].raw.channels] | <code>Number</code> | | |
|
||||||
| [images[].animated] | <code>boolean</code> | <code>false</code> | Set to `true` to read all frames/pages of an animated image. |
|
| [images[].animated] | <code>boolean</code> | <code>false</code> | Set to `true` to read all frames/pages of an animated image. |
|
||||||
| [images[].failOn] | <code>string</code> | <code>"'warning'"</code> | @see [constructor parameters](/api-constructor#parameters) |
|
| [images[].failOn] | <code>string</code> | <code>"'warning'"</code> | @see [constructor parameters](/api-constructor/) |
|
||||||
| [images[].limitInputPixels] | <code>number</code> \| <code>boolean</code> | <code>268402689</code> | @see [constructor parameters](/api-constructor#parameters) |
|
| [images[].limitInputPixels] | <code>number</code> \| <code>boolean</code> | <code>268402689</code> | @see [constructor parameters](/api-constructor/) |
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
```js
|
```js
|
||||||
|
|||||||
@ -13,7 +13,7 @@ It does not take into consideration any operations to be applied to the output i
|
|||||||
such as resize or rotate.
|
such as resize or rotate.
|
||||||
|
|
||||||
Dimensions in the response will respect the `page` and `pages` properties of the
|
Dimensions in the response will respect the `page` and `pages` properties of the
|
||||||
[constructor parameters](/api-constructor#parameters).
|
[constructor parameters](/api-constructor/).
|
||||||
|
|
||||||
A `Promise` is returned when `callback` is not provided.
|
A `Promise` is returned when `callback` is not provided.
|
||||||
|
|
||||||
@ -21,9 +21,9 @@ A `Promise` is returned when `callback` is not provided.
|
|||||||
- `size`: Total size of image in bytes, for Stream and Buffer input only
|
- `size`: Total size of image in bytes, for Stream and Buffer input only
|
||||||
- `width`: Number of pixels wide (EXIF orientation is not taken into consideration, see example below)
|
- `width`: Number of pixels wide (EXIF orientation is not taken into consideration, see example below)
|
||||||
- `height`: Number of pixels high (EXIF orientation is not taken into consideration, see example below)
|
- `height`: Number of pixels high (EXIF orientation is not taken into consideration, see example below)
|
||||||
- `space`: Name of colour space interpretation e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://www.libvips.org/API/current/VipsImage.html#VipsInterpretation)
|
- `space`: Name of colour space interpretation e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://www.libvips.org/API/current/enum.Interpretation.html)
|
||||||
- `channels`: Number of bands e.g. `3` for sRGB, `4` for CMYK
|
- `channels`: Number of bands e.g. `3` for sRGB, `4` for CMYK
|
||||||
- `depth`: Name of pixel depth format e.g. `uchar`, `char`, `ushort`, `float` [...](https://www.libvips.org/API/current/VipsImage.html#VipsBandFormat)
|
- `depth`: Name of pixel depth format e.g. `uchar`, `char`, `ushort`, `float` [...](https://www.libvips.org/API/current/enum.BandFormat.html)
|
||||||
- `density`: Number of pixels per inch (DPI), if present
|
- `density`: Number of pixels per inch (DPI), if present
|
||||||
- `chromaSubsampling`: String containing JPEG chroma subsampling, `4:2:0` or `4:4:4` for RGB, `4:2:0:4` or `4:4:4:4` for CMYK
|
- `chromaSubsampling`: String containing JPEG chroma subsampling, `4:2:0` or `4:4:4` for RGB, `4:2:0:4` or `4:4:4:4` for CMYK
|
||||||
- `isProgressive`: Boolean indicating whether the image is interlaced using a progressive scan
|
- `isProgressive`: Boolean indicating whether the image is interlaced using a progressive scan
|
||||||
|
|||||||
@ -179,7 +179,7 @@ When used without parameters, performs a fast, mild sharpen of the output image.
|
|||||||
When a `sigma` is provided, performs a slower, more accurate sharpen of the L channel in the LAB colour space.
|
When a `sigma` is provided, performs a slower, more accurate sharpen of the L channel in the LAB colour space.
|
||||||
Fine-grained control over the level of sharpening in "flat" (m1) and "jagged" (m2) areas is available.
|
Fine-grained control over the level of sharpening in "flat" (m1) and "jagged" (m2) areas is available.
|
||||||
|
|
||||||
See [libvips sharpen](https://www.libvips.org/API/current/libvips-convolution.html#vips-sharpen) operation.
|
See [libvips sharpen](https://www.libvips.org/API/current/method.Image.sharpen.html) operation.
|
||||||
|
|
||||||
|
|
||||||
**Throws**:
|
**Throws**:
|
||||||
|
|||||||
@ -201,7 +201,7 @@ const dataWithMergedExif = await sharp(inputWithExif)
|
|||||||
|
|
||||||
Keep ICC profile from the input image in the output image.
|
Keep ICC profile from the input image in the output image.
|
||||||
|
|
||||||
Where necessary, will attempt to convert the output colour space to match the profile.
|
When input and output colour spaces differ, use with [toColourspace](/api-colour/#tocolourspace) and optionally [pipelineColourspace](/api-colour/#pipelinecolourspace).
|
||||||
|
|
||||||
|
|
||||||
**Since**: 0.33.0
|
**Since**: 0.33.0
|
||||||
@ -211,6 +211,14 @@ const outputWithIccProfile = await sharp(inputWithIccProfile)
|
|||||||
.keepIccProfile()
|
.keepIccProfile()
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
```
|
```
|
||||||
|
**Example**
|
||||||
|
```js
|
||||||
|
const cmykOutputWithIccProfile = await sharp(cmykInputWithIccProfile)
|
||||||
|
.pipelineColourspace('cmyk')
|
||||||
|
.toColourspace('cmyk')
|
||||||
|
.keepIccProfile()
|
||||||
|
.toBuffer();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## withIccProfile
|
## withIccProfile
|
||||||
@ -430,7 +438,7 @@ 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
|
For 16 bits per pixel output, convert to `rgb16` via
|
||||||
[toColourspace](/api-colour#tocolourspace).
|
[toColourspace](/api-colour/#tocolourspace).
|
||||||
|
|
||||||
|
|
||||||
**Throws**:
|
**Throws**:
|
||||||
@ -589,7 +597,7 @@ Use these JP2 options for output image.
|
|||||||
|
|
||||||
Requires libvips compiled with support for OpenJPEG.
|
Requires libvips compiled with support for OpenJPEG.
|
||||||
The prebuilt binaries do not include this - see
|
The prebuilt binaries do not include this - see
|
||||||
[installing a custom libvips](https://sharp.pixelplumbing.com/install#custom-libvips).
|
[installing a custom libvips](/install#custom-libvips).
|
||||||
|
|
||||||
|
|
||||||
**Throws**:
|
**Throws**:
|
||||||
@ -646,6 +654,7 @@ instead of providing `xres` and `yres` in pixels/mm.
|
|||||||
| [options.quality] | <code>number</code> | <code>80</code> | quality, integer 1-100 |
|
| [options.quality] | <code>number</code> | <code>80</code> | quality, integer 1-100 |
|
||||||
| [options.force] | <code>boolean</code> | <code>true</code> | force TIFF output, otherwise attempt to use input format |
|
| [options.force] | <code>boolean</code> | <code>true</code> | force TIFF output, otherwise attempt to use input format |
|
||||||
| [options.compression] | <code>string</code> | <code>"'jpeg'"</code> | compression options: none, jpeg, deflate, packbits, ccittfax4, lzw, webp, zstd, jp2k |
|
| [options.compression] | <code>string</code> | <code>"'jpeg'"</code> | compression options: none, jpeg, deflate, packbits, ccittfax4, lzw, webp, zstd, jp2k |
|
||||||
|
| [options.bigtiff] | <code>boolean</code> | <code>false</code> | use BigTIFF variant (has no effect when compression is none) |
|
||||||
| [options.predictor] | <code>string</code> | <code>"'horizontal'"</code> | compression predictor options: none, horizontal, float |
|
| [options.predictor] | <code>string</code> | <code>"'horizontal'"</code> | compression predictor options: none, horizontal, float |
|
||||||
| [options.pyramid] | <code>boolean</code> | <code>false</code> | write an image pyramid |
|
| [options.pyramid] | <code>boolean</code> | <code>false</code> | write an image pyramid |
|
||||||
| [options.tile] | <code>boolean</code> | <code>false</code> | write a tiled tiff |
|
| [options.tile] | <code>boolean</code> | <code>false</code> | write a tiled tiff |
|
||||||
@ -753,7 +762,7 @@ This feature is experimental, please do not use in production systems.
|
|||||||
|
|
||||||
Requires libvips compiled with support for libjxl.
|
Requires libvips compiled with support for libjxl.
|
||||||
The prebuilt binaries do not include this - see
|
The prebuilt binaries do not include this - see
|
||||||
[installing a custom libvips](https://sharp.pixelplumbing.com/install#custom-libvips).
|
[installing a custom libvips](/install/#custom-libvips).
|
||||||
|
|
||||||
|
|
||||||
**Throws**:
|
**Throws**:
|
||||||
|
|||||||
@ -114,7 +114,7 @@ e.g. libaom manages its own 4 threads when encoding AVIF images,
|
|||||||
and these are independent of the value set here.
|
and these are independent of the value set here.
|
||||||
|
|
||||||
:::note
|
:::note
|
||||||
Further [control over performance](/performance) is available.
|
Further [control over performance](/performance/) is available.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: v0.34.4 - TBD
|
title: v0.34.4 - 17th September 2025
|
||||||
slug: changelog/v0.34.4
|
slug: changelog/v0.34.4
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
21
docs/src/content/docs/changelog/v0.34.5.md
Normal file
21
docs/src/content/docs/changelog/v0.34.5.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
title: v0.34.5 - 6th November 2025
|
||||||
|
slug: changelog/v0.34.5
|
||||||
|
---
|
||||||
|
|
||||||
|
* Upgrade to libvips v8.17.3 for upstream bug fixes.
|
||||||
|
|
||||||
|
* Add experimental support for prebuilt Linux RISC-V 64-bit binaries.
|
||||||
|
|
||||||
|
* Support building from source with npm v12+, deprecate `--build-from-source` flag.
|
||||||
|
[#4458](https://github.com/lovell/sharp/issues/4458)
|
||||||
|
|
||||||
|
* Add support for BigTIFF output.
|
||||||
|
[#4459](https://github.com/lovell/sharp/pull/4459)
|
||||||
|
[@throwbi](https://github.com/throwbi)
|
||||||
|
|
||||||
|
* Improve error messaging when only warnings issued.
|
||||||
|
[#4465](https://github.com/lovell/sharp/issues/4465)
|
||||||
|
|
||||||
|
* Simplify ICC processing when retaining input profiles.
|
||||||
|
[#4468](https://github.com/lovell/sharp/issues/4468)
|
||||||
@ -20,7 +20,7 @@ npm install sharp
|
|||||||
pnpm add sharp
|
pnpm add sharp
|
||||||
```
|
```
|
||||||
|
|
||||||
When using `pnpm`, you may need to add `sharp` to
|
When using `pnpm`, add `sharp` to
|
||||||
[ignoredBuiltDependencies](https://pnpm.io/settings#ignoredbuiltdependencies)
|
[ignoredBuiltDependencies](https://pnpm.io/settings#ignoredbuiltdependencies)
|
||||||
to silence warnings.
|
to silence warnings.
|
||||||
|
|
||||||
@ -33,7 +33,8 @@ bun add sharp
|
|||||||
```
|
```
|
||||||
|
|
||||||
```sh frame="none"
|
```sh frame="none"
|
||||||
deno run --allow-ffi ...
|
deno add --quiet npm:sharp
|
||||||
|
deno run --allow-env --allow-ffi --allow-read --allow-sys ...
|
||||||
```
|
```
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
@ -48,6 +49,7 @@ Ready-compiled sharp and libvips binaries are provided for use on the most commo
|
|||||||
* macOS ARM64
|
* macOS ARM64
|
||||||
* Linux ARM (glibc >= 2.31)
|
* Linux ARM (glibc >= 2.31)
|
||||||
* Linux ARM64 (glibc >= 2.26, musl >= 1.2.2)
|
* Linux ARM64 (glibc >= 2.26, musl >= 1.2.2)
|
||||||
|
* Linux RISC-V 64-bit (glibc >= 2.41)
|
||||||
* Linux ppc64 (glibc >= 2.36)
|
* Linux ppc64 (glibc >= 2.36)
|
||||||
* Linux s390x (glibc >= 2.36)
|
* Linux s390x (glibc >= 2.36)
|
||||||
* Linux x64 (glibc >= 2.26, musl >= 1.2.2, CPU with SSE4.2)
|
* Linux x64 (glibc >= 2.26, musl >= 1.2.2, CPU with SSE4.2)
|
||||||
@ -110,10 +112,11 @@ and on macOS when running Node.js under Rosetta.
|
|||||||
|
|
||||||
## Building from source
|
## Building from source
|
||||||
|
|
||||||
This module will be compiled from source at `npm install` time when:
|
This module will be compiled from source when:
|
||||||
|
|
||||||
* a globally-installed libvips is detected, or
|
* a globally-installed libvips is detected, or
|
||||||
* when the `npm install --build-from-source` flag is used.
|
* using `npm explore sharp -- npm run build`, or
|
||||||
|
* using the deprecated `npm run --build-from-source` at `npm install` time.
|
||||||
|
|
||||||
The logic to detect a globally-installed libvips can be skipped by setting the
|
The logic to detect a globally-installed libvips can be skipped by setting the
|
||||||
`SHARP_IGNORE_GLOBAL_LIBVIPS` (never try to use it) or
|
`SHARP_IGNORE_GLOBAL_LIBVIPS` (never try to use it) or
|
||||||
|
|||||||
@ -17,7 +17,8 @@ before the Node.js process starts to increase the thread pool size.
|
|||||||
export UV_THREADPOOL_SIZE="$(lscpu -p | egrep -v "^#" | sort -u -t, -k 2,4 | wc -l)"
|
export UV_THREADPOOL_SIZE="$(lscpu -p | egrep -v "^#" | sort -u -t, -k 2,4 | wc -l)"
|
||||||
```
|
```
|
||||||
|
|
||||||
libvips uses a glib-managed thread pool to avoid the overhead of spawning new threads.
|
libvips uses a shared thread pool to avoid the overhead of spawning new threads.
|
||||||
|
The size of this thread pool will grow on demand and shrink when idle.
|
||||||
|
|
||||||
The default number of threads used to concurrently process each image is the same as the number of CPU cores,
|
The default number of threads used to concurrently process each image is the same as the number of CPU cores,
|
||||||
except when using glibc-based Linux without jemalloc, where the default is `1` to help reduce memory fragmentation.
|
except when using glibc-based Linux without jemalloc, where the default is `1` to help reduce memory fragmentation.
|
||||||
@ -25,7 +26,7 @@ except when using glibc-based Linux without jemalloc, where the default is `1` t
|
|||||||
Use [`sharp.concurrency()`](/api-utility/#concurrency) to manage the number of threads per image.
|
Use [`sharp.concurrency()`](/api-utility/#concurrency) to manage the number of threads per image.
|
||||||
|
|
||||||
To reduce memory fragmentation when using the default Linux glibc memory allocator, set the
|
To reduce memory fragmentation when using the default Linux glibc memory allocator, set the
|
||||||
[`MALLOC_ARENA_MAX`](https://www.gnu.org/software/libc/manual/html_node/Memory-Allocation-Tunables.html)
|
[`MALLOC_ARENA_MAX`](https://sourceware.org/glibc/manual/latest/html_node/Memory-Allocation-Tunables.html)
|
||||||
environment variable before the Node.js process starts to reduce the number of memory pools.
|
environment variable before the Node.js process starts to reduce the number of memory pools.
|
||||||
|
|
||||||
```sh frame="none"
|
```sh frame="none"
|
||||||
|
|||||||
38
install/build.js
Normal file
38
install/build.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*!
|
||||||
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
const {
|
||||||
|
useGlobalLibvips,
|
||||||
|
globalLibvipsVersion,
|
||||||
|
log,
|
||||||
|
spawnRebuild,
|
||||||
|
} = require('../lib/libvips');
|
||||||
|
|
||||||
|
log('Attempting to build from source via node-gyp');
|
||||||
|
log('See https://sharp.pixelplumbing.com/install#building-from-source');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const addonApi = require('node-addon-api');
|
||||||
|
log(`Found node-addon-api ${addonApi.version || ''}`);
|
||||||
|
} catch (_err) {
|
||||||
|
log('Please add node-addon-api to your dependencies');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const gyp = require('node-gyp');
|
||||||
|
log(`Found node-gyp ${gyp().version}`);
|
||||||
|
} catch (_err) {
|
||||||
|
log('Please add node-gyp to your dependencies');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useGlobalLibvips(log)) {
|
||||||
|
log(`Detected globally-installed libvips v${globalLibvipsVersion()}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const status = spawnRebuild();
|
||||||
|
if (status !== 0) {
|
||||||
|
process.exit(status);
|
||||||
|
}
|
||||||
@ -1,39 +1,12 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
'use strict';
|
*/
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { useGlobalLibvips, globalLibvipsVersion, log, spawnRebuild } = require('../lib/libvips');
|
const { useGlobalLibvips } = require('../lib/libvips');
|
||||||
|
if (useGlobalLibvips() || process.env.npm_config_build_from_source) {
|
||||||
const buildFromSource = (msg) => {
|
process.exit(1);
|
||||||
log(msg);
|
|
||||||
log('Attempting to build from source via node-gyp');
|
|
||||||
try {
|
|
||||||
const addonApi = require('node-addon-api');
|
|
||||||
log(`Found node-addon-api ${addonApi.version || ''}`);
|
|
||||||
} catch (err) {
|
|
||||||
log('Please add node-addon-api to your dependencies');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const gyp = require('node-gyp');
|
|
||||||
log(`Found node-gyp ${gyp().version}`);
|
|
||||||
} catch (err) {
|
|
||||||
log('Please add node-gyp to your dependencies');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
log('See https://sharp.pixelplumbing.com/install#building-from-source');
|
|
||||||
const status = spawnRebuild();
|
|
||||||
if (status !== 0) {
|
|
||||||
process.exit(status);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (useGlobalLibvips(log)) {
|
|
||||||
buildFromSource(`Detected globally-installed libvips v${globalLibvipsVersion()}`);
|
|
||||||
} else if (process.env.npm_config_build_from_source) {
|
|
||||||
buildFromSource('Detected --build-from-source flag');
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const summary = err.message.split(/\n/).slice(0, 1);
|
const summary = err.message.split(/\n/).slice(0, 1);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
'use strict';
|
*/
|
||||||
|
|
||||||
const is = require('./is');
|
const is = require('./is');
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ const bool = {
|
|||||||
/**
|
/**
|
||||||
* Remove alpha channels, if any. This is a no-op if the image does not have an alpha channel.
|
* Remove alpha channels, if any. This is a no-op if the image does not have an alpha channel.
|
||||||
*
|
*
|
||||||
* See also {@link /api-operation#flatten|flatten}.
|
* See also {@link /api-operation/#flatten flatten}.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* sharp('rgba.png')
|
* sharp('rgba.png')
|
||||||
@ -163,7 +163,7 @@ function bandbool (boolOp) {
|
|||||||
* @module Sharp
|
* @module Sharp
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
module.exports = function (Sharp) {
|
module.exports = (Sharp) => {
|
||||||
Object.assign(Sharp.prototype, {
|
Object.assign(Sharp.prototype, {
|
||||||
// Public instance functions
|
// Public instance functions
|
||||||
removeAlpha,
|
removeAlpha,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
'use strict';
|
*/
|
||||||
|
|
||||||
const color = require('@img/colour');
|
const color = require('@img/colour');
|
||||||
const is = require('./is');
|
const is = require('./is');
|
||||||
@ -69,7 +69,7 @@ function grayscale (grayscale) {
|
|||||||
*
|
*
|
||||||
* The input image will be converted to the provided colourspace at the start of the pipeline.
|
* The input image will be converted to the provided colourspace at the start of the pipeline.
|
||||||
* All operations will use this colourspace before converting to the output colourspace,
|
* All operations will use this colourspace before converting to the output colourspace,
|
||||||
* as defined by {@link #tocolourspace|toColourspace}.
|
* as defined by {@link #tocolourspace toColourspace}.
|
||||||
*
|
*
|
||||||
* @since 0.29.0
|
* @since 0.29.0
|
||||||
*
|
*
|
||||||
@ -80,7 +80,7 @@ function grayscale (grayscale) {
|
|||||||
* .toColourspace('srgb')
|
* .toColourspace('srgb')
|
||||||
* .toFile('16bpc-pipeline-to-8bpc-output.png')
|
* .toFile('16bpc-pipeline-to-8bpc-output.png')
|
||||||
*
|
*
|
||||||
* @param {string} [colourspace] - pipeline colourspace e.g. `rgb16`, `scrgb`, `lab`, `grey16` [...](https://github.com/libvips/libvips/blob/41cff4e9d0838498487a00623462204eb10ee5b8/libvips/iofuncs/enumtypes.c#L774)
|
* @param {string} [colourspace] - pipeline colourspace e.g. `rgb16`, `scrgb`, `lab`, `grey16` [...](https://www.libvips.org/API/current/enum.Interpretation.html)
|
||||||
* @returns {Sharp}
|
* @returns {Sharp}
|
||||||
* @throws {Error} Invalid parameters
|
* @throws {Error} Invalid parameters
|
||||||
*/
|
*/
|
||||||
@ -112,7 +112,7 @@ function pipelineColorspace (colorspace) {
|
|||||||
* .toColourspace('rgb16')
|
* .toColourspace('rgb16')
|
||||||
* .toFile('16-bpp.png')
|
* .toFile('16-bpp.png')
|
||||||
*
|
*
|
||||||
* @param {string} [colourspace] - output colourspace e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://github.com/libvips/libvips/blob/3c0bfdf74ce1dc37a6429bed47fa76f16e2cd70a/libvips/iofuncs/enumtypes.c#L777-L794)
|
* @param {string} [colourspace] - output colourspace e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://www.libvips.org/API/current/enum.Interpretation.html)
|
||||||
* @returns {Sharp}
|
* @returns {Sharp}
|
||||||
* @throws {Error} Invalid parameters
|
* @throws {Error} Invalid parameters
|
||||||
*/
|
*/
|
||||||
@ -141,7 +141,10 @@ function toColorspace (colorspace) {
|
|||||||
* @throws {Error} Invalid value
|
* @throws {Error} Invalid value
|
||||||
*/
|
*/
|
||||||
function _getBackgroundColourOption (value) {
|
function _getBackgroundColourOption (value) {
|
||||||
if (is.object(value) || is.string(value)) {
|
if (
|
||||||
|
is.object(value) ||
|
||||||
|
(is.string(value) && value.length >= 3 && value.length <= 200)
|
||||||
|
) {
|
||||||
const colour = color(value);
|
const colour = color(value);
|
||||||
return [
|
return [
|
||||||
colour.red(),
|
colour.red(),
|
||||||
@ -172,7 +175,7 @@ function _setBackgroundColourOption (key, value) {
|
|||||||
* @module Sharp
|
* @module Sharp
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
module.exports = function (Sharp) {
|
module.exports = (Sharp) => {
|
||||||
Object.assign(Sharp.prototype, {
|
Object.assign(Sharp.prototype, {
|
||||||
// Public
|
// Public
|
||||||
tint,
|
tint,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
'use strict';
|
*/
|
||||||
|
|
||||||
const is = require('./is');
|
const is = require('./is');
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ const blend = {
|
|||||||
* `hard-light`, `soft-light`, `difference`, `exclusion`.
|
* `hard-light`, `soft-light`, `difference`, `exclusion`.
|
||||||
*
|
*
|
||||||
* More information about blend modes can be found at
|
* More information about blend modes can be found at
|
||||||
* https://www.libvips.org/API/current/libvips-conversion.html#VipsBlendMode
|
* https://www.libvips.org/API/current/enum.BlendMode.html
|
||||||
* and https://www.cairographics.org/operators/
|
* and https://www.cairographics.org/operators/
|
||||||
*
|
*
|
||||||
* @since 0.22.0
|
* @since 0.22.0
|
||||||
@ -123,8 +123,8 @@ const blend = {
|
|||||||
* @param {Number} [images[].raw.height]
|
* @param {Number} [images[].raw.height]
|
||||||
* @param {Number} [images[].raw.channels]
|
* @param {Number} [images[].raw.channels]
|
||||||
* @param {boolean} [images[].animated=false] - Set to `true` to read all frames/pages of an animated image.
|
* @param {boolean} [images[].animated=false] - Set to `true` to read all frames/pages of an animated image.
|
||||||
* @param {string} [images[].failOn='warning'] - @see {@link /api-constructor#parameters|constructor parameters}
|
* @param {string} [images[].failOn='warning'] - @see {@link /api-constructor/ constructor parameters}
|
||||||
* @param {number|boolean} [images[].limitInputPixels=268402689] - @see {@link /api-constructor#parameters|constructor parameters}
|
* @param {number|boolean} [images[].limitInputPixels=268402689] - @see {@link /api-constructor/ constructor parameters}
|
||||||
* @returns {Sharp}
|
* @returns {Sharp}
|
||||||
* @throws {Error} Invalid parameters
|
* @throws {Error} Invalid parameters
|
||||||
*/
|
*/
|
||||||
@ -206,7 +206,7 @@ function composite (images) {
|
|||||||
* @module Sharp
|
* @module Sharp
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
module.exports = function (Sharp) {
|
module.exports = (Sharp) => {
|
||||||
Sharp.prototype.composite = composite;
|
Sharp.prototype.composite = composite;
|
||||||
Sharp.blend = blend;
|
Sharp.blend = blend;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
'use strict';
|
*/
|
||||||
|
|
||||||
const util = require('node:util');
|
const util = require('node:util');
|
||||||
const stream = require('node:stream');
|
const stream = require('node:stream');
|
||||||
@ -12,6 +12,10 @@ require('./sharp');
|
|||||||
// Use NODE_DEBUG=sharp to enable libvips warnings
|
// Use NODE_DEBUG=sharp to enable libvips warnings
|
||||||
const debuglog = util.debuglog('sharp');
|
const debuglog = util.debuglog('sharp');
|
||||||
|
|
||||||
|
const queueListener = (queueLength) => {
|
||||||
|
Sharp.queue.emit('change', queueLength);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor factory to create an instance of `sharp`, to which further methods are chained.
|
* Constructor factory to create an instance of `sharp`, to which further methods are chained.
|
||||||
*
|
*
|
||||||
@ -205,6 +209,7 @@ const debuglog = util.debuglog('sharp');
|
|||||||
* @throws {Error} Invalid parameters
|
* @throws {Error} Invalid parameters
|
||||||
*/
|
*/
|
||||||
const Sharp = function (input, options) {
|
const Sharp = function (input, options) {
|
||||||
|
// biome-ignore lint/complexity/noArguments: constructor factory
|
||||||
if (arguments.length === 1 && !is.defined(input)) {
|
if (arguments.length === 1 && !is.defined(input)) {
|
||||||
throw new Error('Invalid input');
|
throw new Error('Invalid input');
|
||||||
}
|
}
|
||||||
@ -353,6 +358,7 @@ const Sharp = function (input, options) {
|
|||||||
gifProgressive: false,
|
gifProgressive: false,
|
||||||
tiffQuality: 80,
|
tiffQuality: 80,
|
||||||
tiffCompression: 'jpeg',
|
tiffCompression: 'jpeg',
|
||||||
|
tiffBigtiff: false,
|
||||||
tiffPredictor: 'horizontal',
|
tiffPredictor: 'horizontal',
|
||||||
tiffPyramid: false,
|
tiffPyramid: false,
|
||||||
tiffMiniswhite: false,
|
tiffMiniswhite: false,
|
||||||
@ -396,9 +402,7 @@ const Sharp = function (input, options) {
|
|||||||
debuglog(warning);
|
debuglog(warning);
|
||||||
},
|
},
|
||||||
// Function to notify of queue length changes
|
// Function to notify of queue length changes
|
||||||
queueListener: function (queueLength) {
|
queueListener
|
||||||
Sharp.queue.emit('change', queueLength);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
this.options.input = this._createInputDescriptor(input, options, { allowStream: true });
|
this.options.input = this._createInputDescriptor(input, options, { allowStream: true });
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
25
lib/index.d.ts
vendored
25
lib/index.d.ts
vendored
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
|
|
||||||
import { Duplex } from 'stream';
|
import type { Duplex } from 'node:stream';
|
||||||
|
|
||||||
//#region Constructor functions
|
//#region Constructor functions
|
||||||
|
|
||||||
@ -860,6 +860,7 @@ declare namespace sharp {
|
|||||||
| JxlOptions
|
| JxlOptions
|
||||||
| GifOptions
|
| GifOptions
|
||||||
| Jp2Options
|
| Jp2Options
|
||||||
|
| RawOptions
|
||||||
| TiffOptions,
|
| TiffOptions,
|
||||||
): Sharp;
|
): Sharp;
|
||||||
|
|
||||||
@ -1027,11 +1028,11 @@ declare namespace sharp {
|
|||||||
openSlide?: OpenSlideInputOptions | undefined;
|
openSlide?: OpenSlideInputOptions | undefined;
|
||||||
/** JPEG 2000 specific input options */
|
/** JPEG 2000 specific input options */
|
||||||
jp2?: Jp2InputOptions | undefined;
|
jp2?: Jp2InputOptions | undefined;
|
||||||
/** Deprecated: use tiff.subifd instead */
|
/** @deprecated Use {@link SharpOptions.tiff} instead */
|
||||||
subifd?: number | undefined;
|
subifd?: number | undefined;
|
||||||
/** Deprecated: use pdf.background instead */
|
/** @deprecated Use {@link SharpOptions.pdf} instead */
|
||||||
pdfBackground?: Colour | Color | undefined;
|
pdfBackground?: Colour | Color | undefined;
|
||||||
/** Deprecated: use openSlide.level instead */
|
/** @deprecated Use {@link SharpOptions.openSlide} instead */
|
||||||
level?: number | undefined;
|
level?: number | undefined;
|
||||||
/** Set to `true` to read all frames/pages of an animated image (equivalent of setting `pages` to `-1`). (optional, default false) */
|
/** Set to `true` to read all frames/pages of an animated image (equivalent of setting `pages` to `-1`). (optional, default false) */
|
||||||
animated?: boolean | undefined;
|
animated?: boolean | undefined;
|
||||||
@ -1181,6 +1182,10 @@ declare namespace sharp {
|
|||||||
'IFD3'?: ExifDir;
|
'IFD3'?: ExifDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HeifCompression = 'av1' | 'hevc';
|
||||||
|
|
||||||
|
type Unit = 'inch' | 'cm';
|
||||||
|
|
||||||
interface WriteableMetadata {
|
interface WriteableMetadata {
|
||||||
/** Number of pixels per inch (DPI) */
|
/** Number of pixels per inch (DPI) */
|
||||||
density?: number | undefined;
|
density?: number | undefined;
|
||||||
@ -1259,7 +1264,7 @@ declare namespace sharp {
|
|||||||
/** Buffer containing raw TIFFTAG_PHOTOSHOP data, if present */
|
/** Buffer containing raw TIFFTAG_PHOTOSHOP data, if present */
|
||||||
tifftagPhotoshop?: Buffer | undefined;
|
tifftagPhotoshop?: Buffer | undefined;
|
||||||
/** The encoder used to compress an HEIF file, `av1` (AVIF) or `hevc` (HEIC) */
|
/** The encoder used to compress an HEIF file, `av1` (AVIF) or `hevc` (HEIC) */
|
||||||
compression?: 'av1' | 'hevc';
|
compression?: HeifCompression | undefined;
|
||||||
/** Default background colour, if present, for PNG (bKGD) and GIF images */
|
/** Default background colour, if present, for PNG (bKGD) and GIF images */
|
||||||
background?: { r: number; g: number; b: number } | { gray: number };
|
background?: { r: number; g: number; b: number } | { gray: number };
|
||||||
/** Details of each level in a multi-level image provided as an array of objects, requires libvips compiled with support for OpenSlide */
|
/** Details of each level in a multi-level image provided as an array of objects, requires libvips compiled with support for OpenSlide */
|
||||||
@ -1267,7 +1272,7 @@ declare namespace sharp {
|
|||||||
/** Number of Sub Image File Directories in an OME-TIFF image */
|
/** Number of Sub Image File Directories in an OME-TIFF image */
|
||||||
subifds?: number | undefined;
|
subifds?: number | undefined;
|
||||||
/** The unit of resolution (density) */
|
/** The unit of resolution (density) */
|
||||||
resolutionUnit?: 'inch' | 'cm' | undefined;
|
resolutionUnit?: Unit | undefined;
|
||||||
/** String containing format for images loaded via *magick */
|
/** String containing format for images loaded via *magick */
|
||||||
formatMagick?: string | undefined;
|
formatMagick?: string | undefined;
|
||||||
/** Array of keyword/text pairs representing PNG text blocks, if present. */
|
/** Array of keyword/text pairs representing PNG text blocks, if present. */
|
||||||
@ -1423,7 +1428,7 @@ declare namespace sharp {
|
|||||||
/** quality, integer 1-100 (optional, default 50) */
|
/** quality, integer 1-100 (optional, default 50) */
|
||||||
quality?: number | undefined;
|
quality?: number | undefined;
|
||||||
/** compression format: av1, hevc (optional, default 'av1') */
|
/** compression format: av1, hevc (optional, default 'av1') */
|
||||||
compression?: 'av1' | 'hevc' | undefined;
|
compression?: HeifCompression | undefined;
|
||||||
/** use lossless compression (optional, default false) */
|
/** use lossless compression (optional, default false) */
|
||||||
lossless?: boolean | undefined;
|
lossless?: boolean | undefined;
|
||||||
/** Level of CPU effort to reduce file size, between 0 (fastest) and 9 (slowest) (optional, default 4) */
|
/** Level of CPU effort to reduce file size, between 0 (fastest) and 9 (slowest) (optional, default 4) */
|
||||||
@ -1460,6 +1465,8 @@ declare namespace sharp {
|
|||||||
quality?: number | undefined;
|
quality?: number | undefined;
|
||||||
/** Compression options: none, jpeg, deflate, packbits, ccittfax4, lzw, webp, zstd, jp2k (optional, default 'jpeg') */
|
/** Compression options: none, jpeg, deflate, packbits, ccittfax4, lzw, webp, zstd, jp2k (optional, default 'jpeg') */
|
||||||
compression?: string | undefined;
|
compression?: string | undefined;
|
||||||
|
/** Use BigTIFF variant (has no effect when compression is none) (optional, default false) */
|
||||||
|
bigtiff?: boolean | undefined;
|
||||||
/** Compression predictor options: none, horizontal, float (optional, default 'horizontal') */
|
/** Compression predictor options: none, horizontal, float (optional, default 'horizontal') */
|
||||||
predictor?: string | undefined;
|
predictor?: string | undefined;
|
||||||
/** Write an image pyramid (optional, default false) */
|
/** Write an image pyramid (optional, default false) */
|
||||||
@ -1479,7 +1486,7 @@ declare namespace sharp {
|
|||||||
/** Write 1-bit images as miniswhite (optional, default false) */
|
/** Write 1-bit images as miniswhite (optional, default false) */
|
||||||
miniswhite?: boolean | undefined;
|
miniswhite?: boolean | undefined;
|
||||||
/** Resolution unit options: inch, cm (optional, default 'inch') */
|
/** Resolution unit options: inch, cm (optional, default 'inch') */
|
||||||
resolutionUnit?: 'inch' | 'cm' | undefined;
|
resolutionUnit?: Unit | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PngOptions extends OutputOptions {
|
interface PngOptions extends OutputOptions {
|
||||||
@ -1604,7 +1611,7 @@ declare namespace sharp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface RawOptions {
|
interface RawOptions {
|
||||||
depth?: 'char' | 'uchar' | 'short' | 'ushort' | 'int' | 'uint' | 'float' | 'complex' | 'double' | 'dpcomplex';
|
depth?: keyof DepthEnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 1 for grayscale, 2 for grayscale + alpha, 3 for sRGB, 4 for CMYK or RGBA */
|
/** 1 for grayscale, 2 for grayscale + alpha, 3 for sRGB, 4 for CMYK or RGBA */
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
'use strict';
|
*/
|
||||||
|
|
||||||
const Sharp = require('./constructor');
|
const Sharp = require('./constructor');
|
||||||
require('./input')(Sharp);
|
require('./input')(Sharp);
|
||||||
|
|||||||
26
lib/input.js
26
lib/input.js
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
'use strict';
|
*/
|
||||||
|
|
||||||
const is = require('./is');
|
const is = require('./is');
|
||||||
const sharp = require('./sharp');
|
const sharp = require('./sharp');
|
||||||
@ -54,7 +54,7 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|||||||
const inputDescriptor = {
|
const inputDescriptor = {
|
||||||
autoOrient: false,
|
autoOrient: false,
|
||||||
failOn: 'warning',
|
failOn: 'warning',
|
||||||
limitInputPixels: Math.pow(0x3FFF, 2),
|
limitInputPixels: 0x3FFF ** 2,
|
||||||
ignoreIcc: false,
|
ignoreIcc: false,
|
||||||
unlimited: false,
|
unlimited: false,
|
||||||
sequentialRead: true
|
sequentialRead: true
|
||||||
@ -150,7 +150,7 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|||||||
if (is.defined(inputOptions.limitInputPixels)) {
|
if (is.defined(inputOptions.limitInputPixels)) {
|
||||||
if (is.bool(inputOptions.limitInputPixels)) {
|
if (is.bool(inputOptions.limitInputPixels)) {
|
||||||
inputDescriptor.limitInputPixels = inputOptions.limitInputPixels
|
inputDescriptor.limitInputPixels = inputOptions.limitInputPixels
|
||||||
? Math.pow(0x3FFF, 2)
|
? 0x3FFF ** 2
|
||||||
: 0;
|
: 0;
|
||||||
} else if (is.integer(inputOptions.limitInputPixels) && is.inRange(inputOptions.limitInputPixels, 0, Number.MAX_SAFE_INTEGER)) {
|
} else if (is.integer(inputOptions.limitInputPixels) && is.inRange(inputOptions.limitInputPixels, 0, Number.MAX_SAFE_INTEGER)) {
|
||||||
inputDescriptor.limitInputPixels = inputOptions.limitInputPixels;
|
inputDescriptor.limitInputPixels = inputOptions.limitInputPixels;
|
||||||
@ -513,7 +513,7 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (is.defined(inputOptions)) {
|
} else if (is.defined(inputOptions)) {
|
||||||
throw new Error('Invalid input options ' + inputOptions);
|
throw new Error(`Invalid input options ${inputOptions}`);
|
||||||
}
|
}
|
||||||
return inputDescriptor;
|
return inputDescriptor;
|
||||||
}
|
}
|
||||||
@ -525,10 +525,8 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|||||||
* @param {string} encoding - unused
|
* @param {string} encoding - unused
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
function _write (chunk, encoding, callback) {
|
function _write (chunk, _encoding, callback) {
|
||||||
/* istanbul ignore else */
|
|
||||||
if (Array.isArray(this.options.input.buffer)) {
|
if (Array.isArray(this.options.input.buffer)) {
|
||||||
/* istanbul ignore else */
|
|
||||||
if (is.buffer(chunk)) {
|
if (is.buffer(chunk)) {
|
||||||
if (this.options.input.buffer.length === 0) {
|
if (this.options.input.buffer.length === 0) {
|
||||||
this.on('finish', () => {
|
this.on('finish', () => {
|
||||||
@ -572,7 +570,7 @@ function _isStreamInput () {
|
|||||||
* such as resize or rotate.
|
* such as resize or rotate.
|
||||||
*
|
*
|
||||||
* Dimensions in the response will respect the `page` and `pages` properties of the
|
* Dimensions in the response will respect the `page` and `pages` properties of the
|
||||||
* {@link /api-constructor#parameters|constructor parameters}.
|
* {@link /api-constructor/ constructor parameters}.
|
||||||
*
|
*
|
||||||
* A `Promise` is returned when `callback` is not provided.
|
* A `Promise` is returned when `callback` is not provided.
|
||||||
*
|
*
|
||||||
@ -580,9 +578,9 @@ function _isStreamInput () {
|
|||||||
* - `size`: Total size of image in bytes, for Stream and Buffer input only
|
* - `size`: Total size of image in bytes, for Stream and Buffer input only
|
||||||
* - `width`: Number of pixels wide (EXIF orientation is not taken into consideration, see example below)
|
* - `width`: Number of pixels wide (EXIF orientation is not taken into consideration, see example below)
|
||||||
* - `height`: Number of pixels high (EXIF orientation is not taken into consideration, see example below)
|
* - `height`: Number of pixels high (EXIF orientation is not taken into consideration, see example below)
|
||||||
* - `space`: Name of colour space interpretation e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://www.libvips.org/API/current/VipsImage.html#VipsInterpretation)
|
* - `space`: Name of colour space interpretation e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://www.libvips.org/API/current/enum.Interpretation.html)
|
||||||
* - `channels`: Number of bands e.g. `3` for sRGB, `4` for CMYK
|
* - `channels`: Number of bands e.g. `3` for sRGB, `4` for CMYK
|
||||||
* - `depth`: Name of pixel depth format e.g. `uchar`, `char`, `ushort`, `float` [...](https://www.libvips.org/API/current/VipsImage.html#VipsBandFormat)
|
* - `depth`: Name of pixel depth format e.g. `uchar`, `char`, `ushort`, `float` [...](https://www.libvips.org/API/current/enum.BandFormat.html)
|
||||||
* - `density`: Number of pixels per inch (DPI), if present
|
* - `density`: Number of pixels per inch (DPI), if present
|
||||||
* - `chromaSubsampling`: String containing JPEG chroma subsampling, `4:2:0` or `4:4:4` for RGB, `4:2:0:4` or `4:4:4:4` for CMYK
|
* - `chromaSubsampling`: String containing JPEG chroma subsampling, `4:2:0` or `4:4:4` for RGB, `4:2:0:4` or `4:4:4:4` for CMYK
|
||||||
* - `isProgressive`: Boolean indicating whether the image is interlaced using a progressive scan
|
* - `isProgressive`: Boolean indicating whether the image is interlaced using a progressive scan
|
||||||
@ -794,7 +792,7 @@ function stats (callback) {
|
|||||||
* @module Sharp
|
* @module Sharp
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
module.exports = function (Sharp) {
|
module.exports = (Sharp) => {
|
||||||
Object.assign(Sharp.prototype, {
|
Object.assign(Sharp.prototype, {
|
||||||
// Private
|
// Private
|
||||||
_inputOptionsFromObject,
|
_inputOptionsFromObject,
|
||||||
|
|||||||
64
lib/is.js
64
lib/is.js
@ -1,61 +1,49 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
'use strict';
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this value defined and not null?
|
* Is this value defined and not null?
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
const defined = function (val) {
|
const defined = (val) => typeof val !== 'undefined' && val !== null;
|
||||||
return typeof val !== 'undefined' && val !== null;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this value an object?
|
* Is this value an object?
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
const object = function (val) {
|
const object = (val) => typeof val === 'object';
|
||||||
return typeof val === 'object';
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this value a plain object?
|
* Is this value a plain object?
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
const plainObject = function (val) {
|
const plainObject = (val) => Object.prototype.toString.call(val) === '[object Object]';
|
||||||
return Object.prototype.toString.call(val) === '[object Object]';
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this value a function?
|
* Is this value a function?
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
const fn = function (val) {
|
const fn = (val) => typeof val === 'function';
|
||||||
return typeof val === 'function';
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this value a boolean?
|
* Is this value a boolean?
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
const bool = function (val) {
|
const bool = (val) => typeof val === 'boolean';
|
||||||
return typeof val === 'boolean';
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this value a Buffer object?
|
* Is this value a Buffer object?
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
const buffer = function (val) {
|
const buffer = (val) => val instanceof Buffer;
|
||||||
return val instanceof Buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this value a typed array object?. E.g. Uint8Array or Uint8ClampedArray?
|
* Is this value a typed array object?. E.g. Uint8Array or Uint8ClampedArray?
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
const typedArray = function (val) {
|
const typedArray = (val) => {
|
||||||
if (defined(val)) {
|
if (defined(val)) {
|
||||||
switch (val.constructor) {
|
switch (val.constructor) {
|
||||||
case Uint8Array:
|
case Uint8Array:
|
||||||
@ -78,49 +66,37 @@ const typedArray = function (val) {
|
|||||||
* Is this value an ArrayBuffer object?
|
* Is this value an ArrayBuffer object?
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
const arrayBuffer = function (val) {
|
const arrayBuffer = (val) => val instanceof ArrayBuffer;
|
||||||
return val instanceof ArrayBuffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this value a non-empty string?
|
* Is this value a non-empty string?
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
const string = function (val) {
|
const string = (val) => typeof val === 'string' && val.length > 0;
|
||||||
return typeof val === 'string' && val.length > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this value a real number?
|
* Is this value a real number?
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
const number = function (val) {
|
const number = (val) => typeof val === 'number' && !Number.isNaN(val);
|
||||||
return typeof val === 'number' && !Number.isNaN(val);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this value an integer?
|
* Is this value an integer?
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
const integer = function (val) {
|
const integer = (val) => Number.isInteger(val);
|
||||||
return Number.isInteger(val);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this value within an inclusive given range?
|
* Is this value within an inclusive given range?
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
const inRange = function (val, min, max) {
|
const inRange = (val, min, max) => val >= min && val <= max;
|
||||||
return val >= min && val <= max;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this value within the elements of an array?
|
* Is this value within the elements of an array?
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
const inArray = function (val, list) {
|
const inArray = (val, list) => list.includes(val);
|
||||||
return list.includes(val);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an Error with a message relating to an invalid parameter.
|
* Create an Error with a message relating to an invalid parameter.
|
||||||
@ -131,11 +107,9 @@ const inArray = function (val, list) {
|
|||||||
* @returns {Error} Containing the formatted message.
|
* @returns {Error} Containing the formatted message.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
const invalidParameterError = function (name, expected, actual) {
|
const invalidParameterError = (name, expected, actual) => new Error(
|
||||||
return new Error(
|
|
||||||
`Expected ${expected} for ${name} but received ${actual} of type ${typeof actual}`
|
`Expected ${expected} for ${name} but received ${actual} of type ${typeof actual}`
|
||||||
);
|
);
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensures an Error from C++ contains a JS stack.
|
* Ensures an Error from C++ contains a JS stack.
|
||||||
@ -145,7 +119,7 @@ const invalidParameterError = function (name, expected, actual) {
|
|||||||
* @returns {Error} Error with message and stack.
|
* @returns {Error} Error with message and stack.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
const nativeError = function (native, context) {
|
const nativeError = (native, context) => {
|
||||||
context.message = native.message;
|
context.message = native.message;
|
||||||
return context;
|
return context;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
'use strict';
|
*/
|
||||||
|
|
||||||
const { spawnSync } = require('node:child_process');
|
const { spawnSync } = require('node:child_process');
|
||||||
const { createHash } = require('node:crypto');
|
const { createHash } = require('node:crypto');
|
||||||
@ -12,13 +12,13 @@ const detectLibc = require('detect-libc');
|
|||||||
|
|
||||||
const { config, engines, optionalDependencies } = require('../package.json');
|
const { config, engines, optionalDependencies } = require('../package.json');
|
||||||
|
|
||||||
const minimumLibvipsVersionLabelled = process.env.npm_package_config_libvips || /* istanbul ignore next */
|
/* node:coverage ignore next */
|
||||||
config.libvips;
|
const minimumLibvipsVersionLabelled = process.env.npm_package_config_libvips || config.libvips;
|
||||||
const minimumLibvipsVersion = semverCoerce(minimumLibvipsVersionLabelled).version;
|
const minimumLibvipsVersion = semverCoerce(minimumLibvipsVersionLabelled).version;
|
||||||
|
|
||||||
const prebuiltPlatforms = [
|
const prebuiltPlatforms = [
|
||||||
'darwin-arm64', 'darwin-x64',
|
'darwin-arm64', 'darwin-x64',
|
||||||
'linux-arm', 'linux-arm64', 'linux-ppc64', 'linux-s390x', 'linux-x64',
|
'linux-arm', 'linux-arm64', 'linux-ppc64', 'linux-riscv64', 'linux-s390x', 'linux-x64',
|
||||||
'linuxmusl-arm64', 'linuxmusl-x64',
|
'linuxmusl-arm64', 'linuxmusl-x64',
|
||||||
'win32-arm64', 'win32-ia32', 'win32-x64'
|
'win32-arm64', 'win32-ia32', 'win32-x64'
|
||||||
];
|
];
|
||||||
@ -36,17 +36,16 @@ const log = (item) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* node:coverage ignore next */
|
||||||
const runtimeLibc = () => detectLibc.isNonGlibcLinuxSync() ? detectLibc.familySync() : '';
|
const runtimeLibc = () => detectLibc.isNonGlibcLinuxSync() ? detectLibc.familySync() : '';
|
||||||
|
|
||||||
const runtimePlatformArch = () => `${process.platform}${runtimeLibc()}-${process.arch}`;
|
const runtimePlatformArch = () => `${process.platform}${runtimeLibc()}-${process.arch}`;
|
||||||
|
|
||||||
/* istanbul ignore next */
|
|
||||||
const buildPlatformArch = () => {
|
const buildPlatformArch = () => {
|
||||||
|
/* node:coverage ignore next 3 */
|
||||||
if (isEmscripten()) {
|
if (isEmscripten()) {
|
||||||
return 'wasm32';
|
return 'wasm32';
|
||||||
}
|
}
|
||||||
/* eslint camelcase: ["error", { allow: ["^npm_config_"] }] */
|
|
||||||
const { npm_config_arch, npm_config_platform, npm_config_libc } = process.env;
|
const { npm_config_arch, npm_config_platform, npm_config_libc } = process.env;
|
||||||
const libc = typeof npm_config_libc === 'string' ? npm_config_libc : runtimeLibc();
|
const libc = typeof npm_config_libc === 'string' ? npm_config_libc : runtimeLibc();
|
||||||
return `${npm_config_platform || process.platform}${libc}-${npm_config_arch || process.arch}`;
|
return `${npm_config_platform || process.platform}${libc}-${npm_config_arch || process.arch}`;
|
||||||
@ -56,19 +55,19 @@ const buildSharpLibvipsIncludeDir = () => {
|
|||||||
try {
|
try {
|
||||||
return require(`@img/sharp-libvips-dev-${buildPlatformArch()}/include`);
|
return require(`@img/sharp-libvips-dev-${buildPlatformArch()}/include`);
|
||||||
} catch {
|
} catch {
|
||||||
|
/* node:coverage ignore next 5 */
|
||||||
try {
|
try {
|
||||||
return require('@img/sharp-libvips-dev/include');
|
return require('@img/sharp-libvips-dev/include');
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
/* istanbul ignore next */
|
|
||||||
return '';
|
return '';
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildSharpLibvipsCPlusPlusDir = () => {
|
const buildSharpLibvipsCPlusPlusDir = () => {
|
||||||
|
/* node:coverage ignore next 4 */
|
||||||
try {
|
try {
|
||||||
return require('@img/sharp-libvips-dev/cplusplus');
|
return require('@img/sharp-libvips-dev/cplusplus');
|
||||||
} catch {}
|
} catch {}
|
||||||
/* istanbul ignore next */
|
|
||||||
return '';
|
return '';
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -76,16 +75,17 @@ const buildSharpLibvipsLibDir = () => {
|
|||||||
try {
|
try {
|
||||||
return require(`@img/sharp-libvips-dev-${buildPlatformArch()}/lib`);
|
return require(`@img/sharp-libvips-dev-${buildPlatformArch()}/lib`);
|
||||||
} catch {
|
} catch {
|
||||||
|
/* node:coverage ignore next 5 */
|
||||||
try {
|
try {
|
||||||
return require(`@img/sharp-libvips-${buildPlatformArch()}/lib`);
|
return require(`@img/sharp-libvips-${buildPlatformArch()}/lib`);
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
/* istanbul ignore next */
|
|
||||||
return '';
|
return '';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* node:coverage disable */
|
||||||
|
|
||||||
const isUnsupportedNodeRuntime = () => {
|
const isUnsupportedNodeRuntime = () => {
|
||||||
/* istanbul ignore next */
|
|
||||||
if (process.release?.name === 'node' && process.versions) {
|
if (process.release?.name === 'node' && process.versions) {
|
||||||
if (!semverSatisfies(process.versions.node, engines.node)) {
|
if (!semverSatisfies(process.versions.node, engines.node)) {
|
||||||
return { found: process.versions.node, expected: engines.node };
|
return { found: process.versions.node, expected: engines.node };
|
||||||
@ -93,14 +93,12 @@ const isUnsupportedNodeRuntime = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* istanbul ignore next */
|
|
||||||
const isEmscripten = () => {
|
const isEmscripten = () => {
|
||||||
const { CC } = process.env;
|
const { CC } = process.env;
|
||||||
return Boolean(CC && CC.endsWith('/emcc'));
|
return Boolean(CC?.endsWith('/emcc'));
|
||||||
};
|
};
|
||||||
|
|
||||||
const isRosetta = () => {
|
const isRosetta = () => {
|
||||||
/* istanbul ignore next */
|
|
||||||
if (process.platform === 'darwin' && process.arch === 'x64') {
|
if (process.platform === 'darwin' && process.arch === 'x64') {
|
||||||
const translated = spawnSync('sysctl sysctl.proc_translated', spawnSyncOptions).stdout;
|
const translated = spawnSync('sysctl sysctl.proc_translated', spawnSyncOptions).stdout;
|
||||||
return (translated || '').trim() === 'sysctl.proc_translated: 1';
|
return (translated || '').trim() === 'sysctl.proc_translated: 1';
|
||||||
@ -108,6 +106,8 @@ const isRosetta = () => {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* node:coverage enable */
|
||||||
|
|
||||||
const sha512 = (s) => createHash('sha512').update(s).digest('hex');
|
const sha512 = (s) => createHash('sha512').update(s).digest('hex');
|
||||||
|
|
||||||
const yarnLocator = () => {
|
const yarnLocator = () => {
|
||||||
@ -121,7 +121,8 @@ const yarnLocator = () => {
|
|||||||
return '';
|
return '';
|
||||||
};
|
};
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* node:coverage disable */
|
||||||
|
|
||||||
const spawnRebuild = () =>
|
const spawnRebuild = () =>
|
||||||
spawnSync(`node-gyp rebuild --directory=src ${isEmscripten() ? '--nodedir=emscripten' : ''}`, {
|
spawnSync(`node-gyp rebuild --directory=src ${isEmscripten() ? '--nodedir=emscripten' : ''}`, {
|
||||||
...spawnSyncOptions,
|
...spawnSyncOptions,
|
||||||
@ -137,16 +138,17 @@ const globalLibvipsVersion = () => {
|
|||||||
PKG_CONFIG_PATH: pkgConfigPath()
|
PKG_CONFIG_PATH: pkgConfigPath()
|
||||||
}
|
}
|
||||||
}).stdout;
|
}).stdout;
|
||||||
/* istanbul ignore next */
|
|
||||||
return (globalLibvipsVersion || '').trim();
|
return (globalLibvipsVersion || '').trim();
|
||||||
} else {
|
} else {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* node:coverage enable */
|
||||||
|
|
||||||
const pkgConfigPath = () => {
|
const pkgConfigPath = () => {
|
||||||
if (process.platform !== 'win32') {
|
if (process.platform !== 'win32') {
|
||||||
|
/* node:coverage ignore next 4 */
|
||||||
const brewPkgConfigPath = spawnSync(
|
const brewPkgConfigPath = spawnSync(
|
||||||
'which brew >/dev/null 2>&1 && brew environment --plain | grep PKG_CONFIG_LIBDIR | cut -d" " -f2',
|
'which brew >/dev/null 2>&1 && brew environment --plain | grep PKG_CONFIG_LIBDIR | cut -d" " -f2',
|
||||||
spawnSyncOptions
|
spawnSyncOptions
|
||||||
@ -178,13 +180,13 @@ const useGlobalLibvips = (logger) => {
|
|||||||
if (Boolean(process.env.SHARP_FORCE_GLOBAL_LIBVIPS) === true) {
|
if (Boolean(process.env.SHARP_FORCE_GLOBAL_LIBVIPS) === true) {
|
||||||
return skipSearch(true, 'SHARP_FORCE_GLOBAL_LIBVIPS', logger);
|
return skipSearch(true, 'SHARP_FORCE_GLOBAL_LIBVIPS', logger);
|
||||||
}
|
}
|
||||||
/* istanbul ignore next */
|
/* node:coverage ignore next 3 */
|
||||||
if (isRosetta()) {
|
if (isRosetta()) {
|
||||||
return skipSearch(false, 'Rosetta', logger);
|
return skipSearch(false, 'Rosetta', logger);
|
||||||
}
|
}
|
||||||
const globalVipsVersion = globalLibvipsVersion();
|
const globalVipsVersion = globalLibvipsVersion();
|
||||||
return !!globalVipsVersion && /* istanbul ignore next */
|
/* node:coverage ignore next */
|
||||||
semverGreaterThanOrEqualTo(globalVipsVersion, minimumLibvipsVersion);
|
return !!globalVipsVersion && semverGreaterThanOrEqualTo(globalVipsVersion, minimumLibvipsVersion);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
'use strict';
|
*/
|
||||||
|
|
||||||
const is = require('./is');
|
const is = require('./is');
|
||||||
|
|
||||||
@ -239,7 +239,7 @@ function affine (matrix, options) {
|
|||||||
* When a `sigma` is provided, performs a slower, more accurate sharpen of the L channel in the LAB colour space.
|
* When a `sigma` is provided, performs a slower, more accurate sharpen of the L channel in the LAB colour space.
|
||||||
* Fine-grained control over the level of sharpening in "flat" (m1) and "jagged" (m2) areas is available.
|
* Fine-grained control over the level of sharpening in "flat" (m1) and "jagged" (m2) areas is available.
|
||||||
*
|
*
|
||||||
* See {@link https://www.libvips.org/API/current/libvips-convolution.html#vips-sharpen|libvips sharpen} operation.
|
* See {@link https://www.libvips.org/API/current/method.Image.sharpen.html libvips sharpen} operation.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* const data = await sharp(input).sharpen().toBuffer();
|
* const data = await sharp(input).sharpen().toBuffer();
|
||||||
@ -485,7 +485,7 @@ function erode (width) {
|
|||||||
/**
|
/**
|
||||||
* Merge alpha transparency channel, if any, with a background, then remove the alpha channel.
|
* Merge alpha transparency channel, if any, with a background, then remove the alpha channel.
|
||||||
*
|
*
|
||||||
* See also {@link /api-channel#removealpha|removeAlpha}.
|
* See also {@link /api-channel#removealpha removeAlpha}.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* await sharp(rgbaInput)
|
* await sharp(rgbaInput)
|
||||||
@ -660,7 +660,7 @@ function normalize (options) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform contrast limiting adaptive histogram equalization
|
* Perform contrast limiting adaptive histogram equalization
|
||||||
* {@link https://en.wikipedia.org/wiki/Adaptive_histogram_equalization#Contrast_Limited_AHE|CLAHE}.
|
* {@link https://en.wikipedia.org/wiki/Adaptive_histogram_equalization#Contrast_Limited_AHE CLAHE}.
|
||||||
*
|
*
|
||||||
* This will, in general, enhance the clarity of the image by bringing out darker details.
|
* This will, in general, enhance the clarity of the image by bringing out darker details.
|
||||||
*
|
*
|
||||||
@ -742,9 +742,7 @@ function convolve (kernel) {
|
|||||||
}
|
}
|
||||||
// Default scale is sum of kernel values
|
// Default scale is sum of kernel values
|
||||||
if (!is.integer(kernel.scale)) {
|
if (!is.integer(kernel.scale)) {
|
||||||
kernel.scale = kernel.kernel.reduce(function (a, b) {
|
kernel.scale = kernel.kernel.reduce((a, b) => a + b, 0);
|
||||||
return a + b;
|
|
||||||
}, 0);
|
|
||||||
}
|
}
|
||||||
// Clip scale to a minimum value of 1
|
// Clip scale to a minimum value of 1
|
||||||
if (kernel.scale < 1) {
|
if (kernel.scale < 1) {
|
||||||
@ -989,7 +987,7 @@ function modulate (options) {
|
|||||||
* @module Sharp
|
* @module Sharp
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
module.exports = function (Sharp) {
|
module.exports = (Sharp) => {
|
||||||
Object.assign(Sharp.prototype, {
|
Object.assign(Sharp.prototype, {
|
||||||
autoOrient,
|
autoOrient,
|
||||||
rotate,
|
rotate,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
'use strict';
|
*/
|
||||||
|
|
||||||
const path = require('node:path');
|
const path = require('node:path');
|
||||||
const is = require('./is');
|
const is = require('./is');
|
||||||
@ -43,7 +43,7 @@ const bitdepthFromColourCount = (colours) => 1 << 31 - Math.clz32(Math.ceil(Math
|
|||||||
* Note that raw pixel data is only supported for buffer output.
|
* Note that raw pixel data is only supported for buffer output.
|
||||||
*
|
*
|
||||||
* By default all metadata will be removed, which includes EXIF-based orientation.
|
* By default all metadata will be removed, which includes EXIF-based orientation.
|
||||||
* See {@link #withmetadata|withMetadata} for control over this.
|
* See {@link #withmetadata withMetadata} for control over this.
|
||||||
*
|
*
|
||||||
* The caller is responsible for ensuring directory structures and permissions exist.
|
* The caller is responsible for ensuring directory structures and permissions exist.
|
||||||
*
|
*
|
||||||
@ -97,12 +97,12 @@ function toFile (fileOut, callback) {
|
|||||||
* Write output to a Buffer.
|
* Write output to a Buffer.
|
||||||
* JPEG, PNG, WebP, AVIF, TIFF, GIF and raw pixel data output are supported.
|
* JPEG, PNG, WebP, AVIF, TIFF, GIF and raw pixel data output are supported.
|
||||||
*
|
*
|
||||||
* Use {@link #toformat|toFormat} or one of the format-specific functions such as {@link jpeg}, {@link png} etc. to set the output format.
|
* Use {@link #toformat toFormat} or one of the format-specific functions such as {@link #jpeg jpeg}, {@link #png png} etc. to set the output format.
|
||||||
*
|
*
|
||||||
* If no explicit format is set, the output format will match the input image, except SVG input which becomes PNG output.
|
* If no explicit format is set, the output format will match the input image, except SVG input which becomes PNG output.
|
||||||
*
|
*
|
||||||
* By default all metadata will be removed, which includes EXIF-based orientation.
|
* By default all metadata will be removed, which includes EXIF-based orientation.
|
||||||
* See {@link #withmetadata|withMetadata} for control over this.
|
* See {@link #withmetadata withMetadata} for control over this.
|
||||||
*
|
*
|
||||||
* `callback`, if present, gets three arguments `(err, data, info)` where:
|
* `callback`, if present, gets three arguments `(err, data, info)` where:
|
||||||
* - `err` is an error, if any.
|
* - `err` is an error, if any.
|
||||||
@ -256,7 +256,7 @@ function withExifMerge (exif) {
|
|||||||
/**
|
/**
|
||||||
* Keep ICC profile from the input image in the output image.
|
* Keep ICC profile from the input image in the output image.
|
||||||
*
|
*
|
||||||
* Where necessary, will attempt to convert the output colour space to match the profile.
|
* When input and output colour spaces differ, use with {@link /api-colour/#tocolourspace toColourspace} and optionally {@link /api-colour/#pipelinecolourspace pipelineColourspace}.
|
||||||
*
|
*
|
||||||
* @since 0.33.0
|
* @since 0.33.0
|
||||||
*
|
*
|
||||||
@ -265,6 +265,13 @@ function withExifMerge (exif) {
|
|||||||
* .keepIccProfile()
|
* .keepIccProfile()
|
||||||
* .toBuffer();
|
* .toBuffer();
|
||||||
*
|
*
|
||||||
|
* @example
|
||||||
|
* const cmykOutputWithIccProfile = await sharp(cmykInputWithIccProfile)
|
||||||
|
* .pipelineColourspace('cmyk')
|
||||||
|
* .toColourspace('cmyk')
|
||||||
|
* .keepIccProfile()
|
||||||
|
* .toBuffer();
|
||||||
|
*
|
||||||
* @returns {Sharp}
|
* @returns {Sharp}
|
||||||
*/
|
*/
|
||||||
function keepIccProfile () {
|
function keepIccProfile () {
|
||||||
@ -565,7 +572,7 @@ function jpeg (options) {
|
|||||||
* 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
|
* For 16 bits per pixel output, convert to `rgb16` via
|
||||||
* {@link /api-colour#tocolourspace|toColourspace}.
|
* {@link /api-colour/#tocolourspace toColourspace}.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* // Convert any input to full colour PNG output
|
* // Convert any input to full colour PNG output
|
||||||
@ -845,13 +852,12 @@ function gif (options) {
|
|||||||
return this._updateFormatOut('gif', options);
|
return this._updateFormatOut('gif', options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* istanbul ignore next */
|
|
||||||
/**
|
/**
|
||||||
* Use these JP2 options for output image.
|
* Use these JP2 options for output image.
|
||||||
*
|
*
|
||||||
* Requires libvips compiled with support for OpenJPEG.
|
* Requires libvips compiled with support for OpenJPEG.
|
||||||
* The prebuilt binaries do not include this - see
|
* The prebuilt binaries do not include this - see
|
||||||
* {@link https://sharp.pixelplumbing.com/install#custom-libvips installing a custom libvips}.
|
* {@link /install#custom-libvips installing a custom libvips}.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* // Convert any input to lossless JP2 output
|
* // Convert any input to lossless JP2 output
|
||||||
@ -880,6 +886,7 @@ function gif (options) {
|
|||||||
* @throws {Error} Invalid options
|
* @throws {Error} Invalid options
|
||||||
*/
|
*/
|
||||||
function jp2 (options) {
|
function jp2 (options) {
|
||||||
|
/* node:coverage ignore next 41 */
|
||||||
if (!this.constructor.format.jp2k.output.buffer) {
|
if (!this.constructor.format.jp2k.output.buffer) {
|
||||||
throw errJp2Save();
|
throw errJp2Save();
|
||||||
}
|
}
|
||||||
@ -959,7 +966,7 @@ function trySetAnimationOptions (source, target) {
|
|||||||
/**
|
/**
|
||||||
* Use these TIFF options for output image.
|
* Use these TIFF options for output image.
|
||||||
*
|
*
|
||||||
* The `density` can be set in pixels/inch via {@link #withmetadata|withMetadata}
|
* The `density` can be set in pixels/inch via {@link #withmetadata withMetadata}
|
||||||
* instead of providing `xres` and `yres` in pixels/mm.
|
* instead of providing `xres` and `yres` in pixels/mm.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
@ -976,6 +983,7 @@ function trySetAnimationOptions (source, target) {
|
|||||||
* @param {number} [options.quality=80] - quality, integer 1-100
|
* @param {number} [options.quality=80] - quality, integer 1-100
|
||||||
* @param {boolean} [options.force=true] - force TIFF output, otherwise attempt to use input format
|
* @param {boolean} [options.force=true] - force TIFF output, otherwise attempt to use input format
|
||||||
* @param {string} [options.compression='jpeg'] - compression options: none, jpeg, deflate, packbits, ccittfax4, lzw, webp, zstd, jp2k
|
* @param {string} [options.compression='jpeg'] - compression options: none, jpeg, deflate, packbits, ccittfax4, lzw, webp, zstd, jp2k
|
||||||
|
* @param {boolean} [options.bigtiff=false] - use BigTIFF variant (has no effect when compression is none)
|
||||||
* @param {string} [options.predictor='horizontal'] - compression predictor options: none, horizontal, float
|
* @param {string} [options.predictor='horizontal'] - compression predictor options: none, horizontal, float
|
||||||
* @param {boolean} [options.pyramid=false] - write an image pyramid
|
* @param {boolean} [options.pyramid=false] - write an image pyramid
|
||||||
* @param {boolean} [options.tile=false] - write a tiled tiff
|
* @param {boolean} [options.tile=false] - write a tiled tiff
|
||||||
@ -1054,6 +1062,10 @@ function tiff (options) {
|
|||||||
throw is.invalidParameterError('compression', 'one of: none, jpeg, deflate, packbits, ccittfax4, lzw, webp, zstd, jp2k', options.compression);
|
throw is.invalidParameterError('compression', 'one of: none, jpeg, deflate, packbits, ccittfax4, lzw, webp, zstd, jp2k', options.compression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// bigtiff
|
||||||
|
if (is.defined(options.bigtiff)) {
|
||||||
|
this._setBooleanOption('tiffBigtiff', options.bigtiff);
|
||||||
|
}
|
||||||
// predictor
|
// predictor
|
||||||
if (is.defined(options.predictor)) {
|
if (is.defined(options.predictor)) {
|
||||||
if (is.string(options.predictor) && is.inArray(options.predictor, ['none', 'horizontal', 'float'])) {
|
if (is.string(options.predictor) && is.inArray(options.predictor, ['none', 'horizontal', 'float'])) {
|
||||||
@ -1189,7 +1201,7 @@ function heif (options) {
|
|||||||
*
|
*
|
||||||
* Requires libvips compiled with support for libjxl.
|
* Requires libvips compiled with support for libjxl.
|
||||||
* The prebuilt binaries do not include this - see
|
* The prebuilt binaries do not include this - see
|
||||||
* {@link https://sharp.pixelplumbing.com/install#custom-libvips installing a custom libvips}.
|
* {@link /install/#custom-libvips installing a custom libvips}.
|
||||||
*
|
*
|
||||||
* @since 0.31.3
|
* @since 0.31.3
|
||||||
*
|
*
|
||||||
@ -1502,7 +1514,6 @@ function _setBooleanOption (key, val) {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function _read () {
|
function _read () {
|
||||||
/* istanbul ignore else */
|
|
||||||
if (!this.options.streamOut) {
|
if (!this.options.streamOut) {
|
||||||
this.options.streamOut = true;
|
this.options.streamOut = true;
|
||||||
const stack = Error();
|
const stack = Error();
|
||||||
@ -1619,7 +1630,7 @@ function _pipeline (callback, stack) {
|
|||||||
* @module Sharp
|
* @module Sharp
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
module.exports = function (Sharp) {
|
module.exports = (Sharp) => {
|
||||||
Object.assign(Sharp.prototype, {
|
Object.assign(Sharp.prototype, {
|
||||||
// Public
|
// Public
|
||||||
toFile,
|
toFile,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
'use strict';
|
*/
|
||||||
|
|
||||||
const is = require('./is');
|
const is = require('./is');
|
||||||
|
|
||||||
@ -579,7 +579,7 @@ function trim (options) {
|
|||||||
* @module Sharp
|
* @module Sharp
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
module.exports = function (Sharp) {
|
module.exports = (Sharp) => {
|
||||||
Object.assign(Sharp.prototype, {
|
Object.assign(Sharp.prototype, {
|
||||||
resize,
|
resize,
|
||||||
extend,
|
extend,
|
||||||
|
|||||||
15
lib/sharp.js
15
lib/sharp.js
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
'use strict';
|
*/
|
||||||
|
|
||||||
// Inspects the runtime environment and exports the relevant sharp.node binary
|
// Inspects the runtime environment and exports the relevant sharp.node binary
|
||||||
|
|
||||||
@ -17,6 +17,8 @@ const paths = [
|
|||||||
'@img/sharp-wasm32/sharp.node'
|
'@img/sharp-wasm32/sharp.node'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/* node:coverage disable */
|
||||||
|
|
||||||
let path, sharp;
|
let path, sharp;
|
||||||
const errors = [];
|
const errors = [];
|
||||||
for (path of paths) {
|
for (path of paths) {
|
||||||
@ -24,12 +26,10 @@ for (path of paths) {
|
|||||||
sharp = require(path);
|
sharp = require(path);
|
||||||
break;
|
break;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
/* istanbul ignore next */
|
|
||||||
errors.push(err);
|
errors.push(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* istanbul ignore next */
|
|
||||||
if (sharp && path.startsWith('@img/sharp-linux-x64') && !sharp._isUsingX64V2()) {
|
if (sharp && path.startsWith('@img/sharp-linux-x64') && !sharp._isUsingX64V2()) {
|
||||||
const err = new Error('Prebuilt binaries for linux-x64 require v2 microarchitecture');
|
const err = new Error('Prebuilt binaries for linux-x64 require v2 microarchitecture');
|
||||||
err.code = 'Unsupported CPU';
|
err.code = 'Unsupported CPU';
|
||||||
@ -37,7 +37,6 @@ if (sharp && path.startsWith('@img/sharp-linux-x64') && !sharp._isUsingX64V2())
|
|||||||
sharp = null;
|
sharp = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* istanbul ignore next */
|
|
||||||
if (sharp) {
|
if (sharp) {
|
||||||
module.exports = sharp;
|
module.exports = sharp;
|
||||||
} else {
|
} else {
|
||||||
@ -88,7 +87,7 @@ if (sharp) {
|
|||||||
` Found ${libcFound}`,
|
` Found ${libcFound}`,
|
||||||
` Requires ${libcRequires}`
|
` Requires ${libcRequires}`
|
||||||
);
|
);
|
||||||
} catch (errEngines) {}
|
} catch (_errEngines) {}
|
||||||
}
|
}
|
||||||
if (isLinux && /\/snap\/core[0-9]{2}/.test(messages)) {
|
if (isLinux && /\/snap\/core[0-9]{2}/.test(messages)) {
|
||||||
help.push(
|
help.push(
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
'use strict';
|
*/
|
||||||
|
|
||||||
const events = require('node:events');
|
const events = require('node:events');
|
||||||
const detectLibc = require('detect-libc');
|
const detectLibc = require('detect-libc');
|
||||||
@ -57,7 +57,7 @@ const interpolators = {
|
|||||||
let versions = {
|
let versions = {
|
||||||
vips: libvipsVersion.semver
|
vips: libvipsVersion.semver
|
||||||
};
|
};
|
||||||
/* istanbul ignore next */
|
/* node:coverage ignore next 15 */
|
||||||
if (!libvipsVersion.isGlobal) {
|
if (!libvipsVersion.isGlobal) {
|
||||||
if (!libvipsVersion.isWasm) {
|
if (!libvipsVersion.isWasm) {
|
||||||
try {
|
try {
|
||||||
@ -75,7 +75,7 @@ if (!libvipsVersion.isGlobal) {
|
|||||||
}
|
}
|
||||||
versions.sharp = require('../package.json').version;
|
versions.sharp = require('../package.json').version;
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* node:coverage ignore next 5 */
|
||||||
if (versions.heif && format.heif) {
|
if (versions.heif && format.heif) {
|
||||||
// Prebuilt binaries provide AV1
|
// Prebuilt binaries provide AV1
|
||||||
format.heif.input.fileSuffix = ['.avif'];
|
format.heif.input.fileSuffix = ['.avif'];
|
||||||
@ -136,7 +136,7 @@ cache(true);
|
|||||||
* and these are independent of the value set here.
|
* and these are independent of the value set here.
|
||||||
*
|
*
|
||||||
* :::note
|
* :::note
|
||||||
* Further {@link /performance|control over performance} is available.
|
* Further {@link /performance/ control over performance} is available.
|
||||||
* :::
|
* :::
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
@ -150,7 +150,7 @@ cache(true);
|
|||||||
function concurrency (concurrency) {
|
function concurrency (concurrency) {
|
||||||
return sharp.concurrency(is.integer(concurrency) ? concurrency : null);
|
return sharp.concurrency(is.integer(concurrency) ? concurrency : null);
|
||||||
}
|
}
|
||||||
/* istanbul ignore next */
|
/* node:coverage ignore next 7 */
|
||||||
if (detectLibc.familySync() === detectLibc.GLIBC && !sharp._isUsingJemalloc()) {
|
if (detectLibc.familySync() === detectLibc.GLIBC && !sharp._isUsingJemalloc()) {
|
||||||
// Reduce default concurrency to 1 when using glibc memory allocator
|
// Reduce default concurrency to 1 when using glibc memory allocator
|
||||||
sharp.concurrency(1);
|
sharp.concurrency(1);
|
||||||
@ -277,7 +277,7 @@ function unblock (options) {
|
|||||||
* @module Sharp
|
* @module Sharp
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
module.exports = function (Sharp) {
|
module.exports = (Sharp) => {
|
||||||
Sharp.cache = cache;
|
Sharp.cache = cache;
|
||||||
Sharp.concurrency = concurrency;
|
Sharp.concurrency = concurrency;
|
||||||
Sharp.counters = counters;
|
Sharp.counters = counters;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-darwin-arm64",
|
"name": "@img/sharp-darwin-arm64",
|
||||||
"version": "0.34.4-rc.4",
|
"version": "0.34.5",
|
||||||
"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.2.3"
|
"@img/sharp-libvips-darwin-arm64": "1.2.4"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"lib"
|
"lib"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-darwin-x64",
|
"name": "@img/sharp-darwin-x64",
|
||||||
"version": "0.34.4-rc.4",
|
"version": "0.34.5",
|
||||||
"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.2.3"
|
"@img/sharp-libvips-darwin-x64": "1.2.4"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"lib"
|
"lib"
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
'use strict';
|
*/
|
||||||
|
|
||||||
// Populate the npm package for the current platform with the local build
|
// Populate the npm package for the current platform with the local build
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linux-arm",
|
"name": "@img/sharp-linux-arm",
|
||||||
"version": "0.34.4-rc.4",
|
"version": "0.34.5",
|
||||||
"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.2.3"
|
"@img/sharp-libvips-linux-arm": "1.2.4"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"lib"
|
"lib"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linux-arm64",
|
"name": "@img/sharp-linux-arm64",
|
||||||
"version": "0.34.4-rc.4",
|
"version": "0.34.5",
|
||||||
"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.2.3"
|
"@img/sharp-libvips-linux-arm64": "1.2.4"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"lib"
|
"lib"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linux-ppc64",
|
"name": "@img/sharp-linux-ppc64",
|
||||||
"version": "0.34.4-rc.4",
|
"version": "0.34.5",
|
||||||
"description": "Prebuilt sharp for use with Linux (glibc) ppc64",
|
"description": "Prebuilt sharp for use with Linux (glibc) ppc64",
|
||||||
"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-ppc64": "1.2.3"
|
"@img/sharp-libvips-linux-ppc64": "1.2.4"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"lib"
|
"lib"
|
||||||
|
|||||||
46
npm/linux-riscv64/package.json
Normal file
46
npm/linux-riscv64/package.json
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"name": "@img/sharp-linux-riscv64",
|
||||||
|
"version": "0.34.5",
|
||||||
|
"description": "Prebuilt sharp for use with Linux (glibc) RISC-V 64-bit",
|
||||||
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/lovell/sharp.git",
|
||||||
|
"directory": "npm/linux-riscv64"
|
||||||
|
},
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/libvips"
|
||||||
|
},
|
||||||
|
"preferUnplugged": true,
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@img/sharp-libvips-linux-riscv64": "1.2.4"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"lib"
|
||||||
|
],
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"type": "commonjs",
|
||||||
|
"exports": {
|
||||||
|
"./sharp.node": "./lib/sharp-linux-riscv64.node",
|
||||||
|
"./package": "./package.json"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"glibc": ">=2.41"
|
||||||
|
},
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"libc": [
|
||||||
|
"glibc"
|
||||||
|
],
|
||||||
|
"cpu": [
|
||||||
|
"riscv64"
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linux-s390x",
|
"name": "@img/sharp-linux-s390x",
|
||||||
"version": "0.34.4-rc.4",
|
"version": "0.34.5",
|
||||||
"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.2.3"
|
"@img/sharp-libvips-linux-s390x": "1.2.4"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"lib"
|
"lib"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linux-x64",
|
"name": "@img/sharp-linux-x64",
|
||||||
"version": "0.34.4-rc.4",
|
"version": "0.34.5",
|
||||||
"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.2.3"
|
"@img/sharp-libvips-linux-x64": "1.2.4"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"lib"
|
"lib"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linuxmusl-arm64",
|
"name": "@img/sharp-linuxmusl-arm64",
|
||||||
"version": "0.34.4-rc.4",
|
"version": "0.34.5",
|
||||||
"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.2.3"
|
"@img/sharp-libvips-linuxmusl-arm64": "1.2.4"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"lib"
|
"lib"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linuxmusl-x64",
|
"name": "@img/sharp-linuxmusl-x64",
|
||||||
"version": "0.34.4-rc.4",
|
"version": "0.34.5",
|
||||||
"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.2.3"
|
"@img/sharp-libvips-linuxmusl-x64": "1.2.4"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"lib"
|
"lib"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp",
|
"name": "@img/sharp",
|
||||||
"version": "0.34.4-rc.4",
|
"version": "0.34.5",
|
||||||
"private": "true",
|
"private": "true",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"darwin-arm64",
|
"darwin-arm64",
|
||||||
@ -8,6 +8,7 @@
|
|||||||
"linux-arm",
|
"linux-arm",
|
||||||
"linux-arm64",
|
"linux-arm64",
|
||||||
"linux-ppc64",
|
"linux-ppc64",
|
||||||
|
"linux-riscv64",
|
||||||
"linux-s390x",
|
"linux-s390x",
|
||||||
"linux-x64",
|
"linux-x64",
|
||||||
"linuxmusl-arm64",
|
"linuxmusl-arm64",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-wasm32",
|
"name": "@img/sharp-wasm32",
|
||||||
"version": "0.34.4-rc.4",
|
"version": "0.34.5",
|
||||||
"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",
|
||||||
@ -31,7 +31,7 @@
|
|||||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emnapi/runtime": "^1.5.0"
|
"@emnapi/runtime": "^1.7.0"
|
||||||
},
|
},
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"wasm32"
|
"wasm32"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-win32-arm64",
|
"name": "@img/sharp-win32-arm64",
|
||||||
"version": "0.34.4-rc.4",
|
"version": "0.34.5",
|
||||||
"description": "Prebuilt sharp for use with Windows 64-bit ARM",
|
"description": "Prebuilt sharp for use with Windows 64-bit ARM",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-win32-ia32",
|
"name": "@img/sharp-win32-ia32",
|
||||||
"version": "0.34.4-rc.4",
|
"version": "0.34.5",
|
||||||
"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.34.4-rc.4",
|
"version": "0.34.5",
|
||||||
"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",
|
||||||
|
|||||||
112
package.json
112
package.json
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "sharp",
|
"name": "sharp",
|
||||||
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, GIF, AVIF and TIFF images",
|
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, GIF, AVIF and TIFF images",
|
||||||
"version": "0.34.4-rc.4",
|
"version": "0.34.5",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
@ -92,14 +92,16 @@
|
|||||||
"Don Denton <don@happycollision.com>"
|
"Don Denton <don@happycollision.com>"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"install": "node install/check.js",
|
"build": "node install/build.js",
|
||||||
|
"install": "node install/check.js || npm run build",
|
||||||
"clean": "rm -rf src/build/ .nyc_output/ coverage/ test/fixtures/output.*",
|
"clean": "rm -rf src/build/ .nyc_output/ coverage/ test/fixtures/output.*",
|
||||||
"test": "npm run test-lint && npm run test-unit && npm run test-licensing && npm run test-types",
|
"test": "npm run lint && npm run test-unit",
|
||||||
"test-lint": "semistandard && cpplint",
|
"lint": "npm run lint-cpp && npm run lint-js && npm run lint-types",
|
||||||
"test-unit": "nyc --reporter=lcov --reporter=text --check-coverage --branches=100 mocha",
|
"lint-cpp": "cpplint --quiet src/*.h src/*.cc",
|
||||||
"test-licensing": "license-checker --production --summary --onlyAllow=\"Apache-2.0;BSD;ISC;LGPL-3.0-or-later;MIT\"",
|
"lint-js": "biome lint",
|
||||||
|
"lint-types": "tsd --files ./test/types/sharp.test-d.ts",
|
||||||
"test-leak": "./test/leak/leak.sh",
|
"test-leak": "./test/leak/leak.sh",
|
||||||
"test-types": "tsd",
|
"test-unit": "node --experimental-test-coverage test/unit.mjs",
|
||||||
"package-from-local-build": "node npm/from-local-build.js",
|
"package-from-local-build": "node npm/from-local-build.js",
|
||||||
"package-release-notes": "node npm/release-notes.js",
|
"package-release-notes": "node npm/release-notes.js",
|
||||||
"docs-build": "node docs/build.mjs",
|
"docs-build": "node docs/build.mjs",
|
||||||
@ -138,53 +140,52 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@img/colour": "^1.0.0",
|
"@img/colour": "^1.0.0",
|
||||||
"detect-libc": "^2.1.0",
|
"detect-libc": "^2.1.2",
|
||||||
"semver": "^7.7.2"
|
"semver": "^7.7.3"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-darwin-arm64": "0.34.4-rc.4",
|
"@img/sharp-darwin-arm64": "0.34.5",
|
||||||
"@img/sharp-darwin-x64": "0.34.4-rc.4",
|
"@img/sharp-darwin-x64": "0.34.5",
|
||||||
"@img/sharp-libvips-darwin-arm64": "1.2.3",
|
"@img/sharp-libvips-darwin-arm64": "1.2.4",
|
||||||
"@img/sharp-libvips-darwin-x64": "1.2.3",
|
"@img/sharp-libvips-darwin-x64": "1.2.4",
|
||||||
"@img/sharp-libvips-linux-arm": "1.2.3",
|
"@img/sharp-libvips-linux-arm": "1.2.4",
|
||||||
"@img/sharp-libvips-linux-arm64": "1.2.3",
|
"@img/sharp-libvips-linux-arm64": "1.2.4",
|
||||||
"@img/sharp-libvips-linux-ppc64": "1.2.3",
|
"@img/sharp-libvips-linux-ppc64": "1.2.4",
|
||||||
"@img/sharp-libvips-linux-s390x": "1.2.3",
|
"@img/sharp-libvips-linux-riscv64": "1.2.4",
|
||||||
"@img/sharp-libvips-linux-x64": "1.2.3",
|
"@img/sharp-libvips-linux-s390x": "1.2.4",
|
||||||
"@img/sharp-libvips-linuxmusl-arm64": "1.2.3",
|
"@img/sharp-libvips-linux-x64": "1.2.4",
|
||||||
"@img/sharp-libvips-linuxmusl-x64": "1.2.3",
|
"@img/sharp-libvips-linuxmusl-arm64": "1.2.4",
|
||||||
"@img/sharp-linux-arm": "0.34.4-rc.4",
|
"@img/sharp-libvips-linuxmusl-x64": "1.2.4",
|
||||||
"@img/sharp-linux-arm64": "0.34.4-rc.4",
|
"@img/sharp-linux-arm": "0.34.5",
|
||||||
"@img/sharp-linux-ppc64": "0.34.4-rc.4",
|
"@img/sharp-linux-arm64": "0.34.5",
|
||||||
"@img/sharp-linux-s390x": "0.34.4-rc.4",
|
"@img/sharp-linux-ppc64": "0.34.5",
|
||||||
"@img/sharp-linux-x64": "0.34.4-rc.4",
|
"@img/sharp-linux-riscv64": "0.34.5",
|
||||||
"@img/sharp-linuxmusl-arm64": "0.34.4-rc.4",
|
"@img/sharp-linux-s390x": "0.34.5",
|
||||||
"@img/sharp-linuxmusl-x64": "0.34.4-rc.4",
|
"@img/sharp-linux-x64": "0.34.5",
|
||||||
"@img/sharp-wasm32": "0.34.4-rc.4",
|
"@img/sharp-linuxmusl-arm64": "0.34.5",
|
||||||
"@img/sharp-win32-arm64": "0.34.4-rc.4",
|
"@img/sharp-linuxmusl-x64": "0.34.5",
|
||||||
"@img/sharp-win32-ia32": "0.34.4-rc.4",
|
"@img/sharp-wasm32": "0.34.5",
|
||||||
"@img/sharp-win32-x64": "0.34.4-rc.4"
|
"@img/sharp-win32-arm64": "0.34.5",
|
||||||
|
"@img/sharp-win32-ia32": "0.34.5",
|
||||||
|
"@img/sharp-win32-x64": "0.34.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@emnapi/runtime": "^1.5.0",
|
"@biomejs/biome": "^2.3.4",
|
||||||
"@img/sharp-libvips-dev": "1.2.3",
|
"@cpplint/cli": "^0.1.0",
|
||||||
"@img/sharp-libvips-dev-wasm32": "1.2.3",
|
"@emnapi/runtime": "^1.7.0",
|
||||||
"@img/sharp-libvips-win32-arm64": "1.2.3",
|
"@img/sharp-libvips-dev": "1.2.4",
|
||||||
"@img/sharp-libvips-win32-ia32": "1.2.3",
|
"@img/sharp-libvips-dev-wasm32": "1.2.4",
|
||||||
"@img/sharp-libvips-win32-x64": "1.2.3",
|
"@img/sharp-libvips-win32-arm64": "1.2.4",
|
||||||
|
"@img/sharp-libvips-win32-ia32": "1.2.4",
|
||||||
|
"@img/sharp-libvips-win32-x64": "1.2.4",
|
||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"cc": "^3.0.1",
|
"emnapi": "^1.7.0",
|
||||||
"emnapi": "^1.5.0",
|
|
||||||
"exif-reader": "^2.0.2",
|
"exif-reader": "^2.0.2",
|
||||||
"extract-zip": "^2.0.1",
|
"extract-zip": "^2.0.1",
|
||||||
"icc": "^3.0.0",
|
"icc": "^3.0.0",
|
||||||
"jsdoc-to-markdown": "^9.1.2",
|
"jsdoc-to-markdown": "^9.1.3",
|
||||||
"license-checker": "^25.0.1",
|
|
||||||
"mocha": "^11.7.2",
|
|
||||||
"node-addon-api": "^8.5.0",
|
"node-addon-api": "^8.5.0",
|
||||||
"node-gyp": "^11.4.2",
|
"node-gyp": "^11.5.0",
|
||||||
"nyc": "^17.1.0",
|
|
||||||
"semistandard": "^17.0.0",
|
|
||||||
"tar-fs": "^3.1.1",
|
"tar-fs": "^3.1.1",
|
||||||
"tsd": "^0.33.0"
|
"tsd": "^0.33.0"
|
||||||
},
|
},
|
||||||
@ -193,28 +194,9 @@
|
|||||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"libvips": ">=8.17.2"
|
"libvips": ">=8.17.3"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
},
|
|
||||||
"semistandard": {
|
|
||||||
"env": [
|
|
||||||
"mocha"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"cc": {
|
|
||||||
"linelength": "120",
|
|
||||||
"filter": [
|
|
||||||
"build/include"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nyc": {
|
|
||||||
"include": [
|
|
||||||
"lib"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"tsd": {
|
|
||||||
"directory": "test/types/"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/CPPLINT.cfg
Normal file
10
src/CPPLINT.cfg
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
set noparent
|
||||||
|
|
||||||
|
linelength=120
|
||||||
|
|
||||||
|
filter=-build/include
|
||||||
|
filter=+build/include_alpha
|
||||||
|
filter=+build/include_subdir
|
||||||
|
filter=+build/include_what_you_use
|
||||||
|
|
||||||
|
filter=-whitespace/indent_namespace
|
||||||
@ -120,7 +120,7 @@
|
|||||||
'conditions': [
|
'conditions': [
|
||||||
['use_global_libvips == "true"', {
|
['use_global_libvips == "true"', {
|
||||||
# Use pkg-config for include and lib
|
# Use pkg-config for include and lib
|
||||||
'include_dirs': ['<!@(PKG_CONFIG_PATH="<(pkg_config_path)" pkg-config --cflags-only-I vips-cpp vips glib-2.0 | sed s\/-I//g)'],
|
'include_dirs': ['<!@(PKG_CONFIG_PATH="<(pkg_config_path)" pkg-config --cflags-only-I vips-cpp vips glib-2.0 | sed s/-I//g)'],
|
||||||
'libraries': ['<!@(PKG_CONFIG_PATH="<(pkg_config_path)" pkg-config --libs vips-cpp)'],
|
'libraries': ['<!@(PKG_CONFIG_PATH="<(pkg_config_path)" pkg-config --libs vips-cpp)'],
|
||||||
'defines': [
|
'defines': [
|
||||||
'SHARP_USE_GLOBAL_LIBVIPS'
|
'SHARP_USE_GLOBAL_LIBVIPS'
|
||||||
|
|||||||
@ -1,18 +1,22 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <string>
|
|
||||||
#include <string.h>
|
|
||||||
#include <vector>
|
|
||||||
#include <queue>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <mutex> // NOLINT(build/c++11)
|
#include <mutex>
|
||||||
|
#include <queue>
|
||||||
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <napi.h>
|
#include <napi.h>
|
||||||
#include <vips/vips8>
|
#include <vips/vips8>
|
||||||
|
|
||||||
#include "common.h"
|
#include "./common.h"
|
||||||
|
|
||||||
using vips::VImage;
|
using vips::VImage;
|
||||||
|
|
||||||
|
|||||||
15
src/common.h
15
src/common.h
@ -1,13 +1,16 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef SRC_COMMON_H_
|
#ifndef SRC_COMMON_H_
|
||||||
#define SRC_COMMON_H_
|
#define SRC_COMMON_H_
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <atomic>
|
|
||||||
|
|
||||||
#include <napi.h>
|
#include <napi.h>
|
||||||
#include <vips/vips8>
|
#include <vips/vips8>
|
||||||
@ -16,8 +19,8 @@
|
|||||||
|
|
||||||
#if (VIPS_MAJOR_VERSION < 8) || \
|
#if (VIPS_MAJOR_VERSION < 8) || \
|
||||||
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 17) || \
|
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 17) || \
|
||||||
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 17 && VIPS_MICRO_VERSION < 2)
|
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 17 && VIPS_MICRO_VERSION < 3)
|
||||||
#error "libvips version 8.17.2+ is required - please see https://sharp.pixelplumbing.com/install"
|
#error "libvips version 8.17.3+ is required - please see https://sharp.pixelplumbing.com/install"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__has_include)
|
#if defined(__has_include)
|
||||||
@ -30,7 +33,7 @@ using vips::VImage;
|
|||||||
|
|
||||||
namespace sharp {
|
namespace sharp {
|
||||||
|
|
||||||
struct InputDescriptor { // NOLINT(runtime/indentation_namespace)
|
struct InputDescriptor {
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string file;
|
std::string file;
|
||||||
bool autoOrient;
|
bool autoOrient;
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
/* global Module, ENV, _vips_shutdown, _uv_library_shutdown */
|
/* global Module, ENV, _vips_shutdown, _uv_library_shutdown */
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,19 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
#include <numeric>
|
|
||||||
#include <vector>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <numeric>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <napi.h>
|
#include <napi.h>
|
||||||
#include <vips/vips8>
|
#include <vips/vips8>
|
||||||
|
|
||||||
#include "common.h"
|
#include "./common.h"
|
||||||
#include "metadata.h"
|
#include "./metadata.h"
|
||||||
|
|
||||||
static void* readPNGComment(VipsImage *image, const char *field, GValue *value, void *p);
|
static void* readPNGComment(VipsImage *image, const char *field, GValue *value, void *p);
|
||||||
|
|
||||||
@ -215,10 +219,10 @@ class MetadataWorker : public Napi::AsyncWorker {
|
|||||||
if (!baton->levels.empty()) {
|
if (!baton->levels.empty()) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
Napi::Array levels = Napi::Array::New(env, static_cast<size_t>(baton->levels.size()));
|
Napi::Array levels = Napi::Array::New(env, static_cast<size_t>(baton->levels.size()));
|
||||||
for (std::pair<int, int> const &l : baton->levels) {
|
for (const auto& [width, height] : baton->levels) {
|
||||||
Napi::Object level = Napi::Object::New(env);
|
Napi::Object level = Napi::Object::New(env);
|
||||||
level.Set("width", l.first);
|
level.Set("width", width);
|
||||||
level.Set("height", l.second);
|
level.Set("height", height);
|
||||||
levels.Set(i++, level);
|
levels.Set(i++, level);
|
||||||
}
|
}
|
||||||
info.Set("levels", levels);
|
info.Set("levels", levels);
|
||||||
@ -275,10 +279,10 @@ class MetadataWorker : public Napi::AsyncWorker {
|
|||||||
if (baton->comments.size() > 0) {
|
if (baton->comments.size() > 0) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
Napi::Array comments = Napi::Array::New(env, baton->comments.size());
|
Napi::Array comments = Napi::Array::New(env, baton->comments.size());
|
||||||
for (auto &c : baton->comments) {
|
for (const auto& [keyword, text] : baton->comments) {
|
||||||
Napi::Object comment = Napi::Object::New(env);
|
Napi::Object comment = Napi::Object::New(env);
|
||||||
comment.Set("keyword", c.first);
|
comment.Set("keyword", keyword);
|
||||||
comment.Set("text", c.second);
|
comment.Set("text", text);
|
||||||
comments.Set(i++, comment);
|
comments.Set(i++, comment);
|
||||||
}
|
}
|
||||||
info.Set("comments", comments);
|
info.Set("comments", comments);
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef SRC_METADATA_H_
|
#ifndef SRC_METADATA_H_
|
||||||
#define SRC_METADATA_H_
|
#define SRC_METADATA_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
#include <napi.h>
|
#include <napi.h>
|
||||||
|
|
||||||
#include "./common.h"
|
#include "./common.h"
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@ -8,8 +10,8 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <vips/vips8>
|
#include <vips/vips8>
|
||||||
|
|
||||||
#include "common.h"
|
#include "./common.h"
|
||||||
#include "operations.h"
|
#include "./operations.h"
|
||||||
|
|
||||||
using vips::VImage;
|
using vips::VImage;
|
||||||
using vips::VError;
|
using vips::VError;
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef SRC_OPERATIONS_H_
|
#ifndef SRC_OPERATIONS_H_
|
||||||
#define SRC_OPERATIONS_H_
|
#define SRC_OPERATIONS_H_
|
||||||
@ -8,6 +10,7 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
#include <vector>
|
||||||
#include <vips/vips8>
|
#include <vips/vips8>
|
||||||
|
|
||||||
using vips::VImage;
|
using vips::VImage;
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <filesystem>
|
#include <filesystem> // NOLINT(build/c++17)
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
@ -17,9 +19,9 @@
|
|||||||
#include <vips/vips8>
|
#include <vips/vips8>
|
||||||
#include <napi.h>
|
#include <napi.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "./common.h"
|
||||||
#include "operations.h"
|
#include "./operations.h"
|
||||||
#include "pipeline.h"
|
#include "./pipeline.h"
|
||||||
|
|
||||||
class PipelineWorker : public Napi::AsyncWorker {
|
class PipelineWorker : public Napi::AsyncWorker {
|
||||||
public:
|
public:
|
||||||
@ -453,12 +455,10 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
std::tie(image, background) = sharp::ApplyAlpha(image, baton->resizeBackground, shouldPremultiplyAlpha);
|
std::tie(image, background) = sharp::ApplyAlpha(image, baton->resizeBackground, shouldPremultiplyAlpha);
|
||||||
|
|
||||||
// Embed
|
// Embed
|
||||||
int left;
|
const auto& [left, top] = sharp::CalculateEmbedPosition(
|
||||||
int top;
|
|
||||||
std::tie(left, top) = sharp::CalculateEmbedPosition(
|
|
||||||
inputWidth, inputHeight, baton->width, baton->height, baton->position);
|
inputWidth, inputHeight, baton->width, baton->height, baton->position);
|
||||||
int width = std::max(inputWidth, baton->width);
|
const int width = std::max(inputWidth, baton->width);
|
||||||
int height = std::max(inputHeight, baton->height);
|
const int height = std::max(inputHeight, baton->height);
|
||||||
|
|
||||||
image = nPages > 1
|
image = nPages > 1
|
||||||
? sharp::EmbedMultiPage(image,
|
? sharp::EmbedMultiPage(image,
|
||||||
@ -477,13 +477,10 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
// Crop
|
// Crop
|
||||||
if (baton->position < 9) {
|
if (baton->position < 9) {
|
||||||
// Gravity-based crop
|
// Gravity-based crop
|
||||||
int left;
|
const auto& [left, top] = sharp::CalculateCrop(
|
||||||
int top;
|
|
||||||
|
|
||||||
std::tie(left, top) = sharp::CalculateCrop(
|
|
||||||
inputWidth, inputHeight, baton->width, baton->height, baton->position);
|
inputWidth, inputHeight, baton->width, baton->height, baton->position);
|
||||||
int width = std::min(inputWidth, baton->width);
|
const int width = std::min(inputWidth, baton->width);
|
||||||
int height = std::min(inputHeight, baton->height);
|
const int height = std::min(inputHeight, baton->height);
|
||||||
|
|
||||||
image = nPages > 1
|
image = nPages > 1
|
||||||
? sharp::CropMultiPage(image,
|
? sharp::CropMultiPage(image,
|
||||||
@ -795,20 +792,14 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
image = sharp::EnsureAlpha(image, baton->ensureAlpha);
|
image = sharp::EnsureAlpha(image, baton->ensureAlpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert image to sRGB, if not already
|
// Ensure output colour space
|
||||||
if (sharp::Is16Bit(image.interpretation())) {
|
if (sharp::Is16Bit(image.interpretation())) {
|
||||||
image = image.cast(VIPS_FORMAT_USHORT);
|
image = image.cast(VIPS_FORMAT_USHORT);
|
||||||
}
|
}
|
||||||
if (image.interpretation() != baton->colourspace) {
|
if (image.interpretation() != baton->colourspace) {
|
||||||
// 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
|
if (inputProfile.first != nullptr && baton->withIccProfile.empty()) {
|
||||||
if ((baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) && baton->colourspacePipeline != VIPS_INTERPRETATION_CMYK &&
|
image = sharp::SetProfile(image, inputProfile);
|
||||||
baton->withIccProfile.empty() && sharp::HasProfile(image)) {
|
|
||||||
image = image.icc_transform(processingProfile, VImage::option()
|
|
||||||
->set("embedded", true)
|
|
||||||
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
|
||||||
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -843,8 +834,6 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
} catch(...) {
|
} catch(...) {
|
||||||
sharp::VipsWarningCallback(nullptr, G_LOG_LEVEL_WARNING, "Invalid profile", nullptr);
|
sharp::VipsWarningCallback(nullptr, G_LOG_LEVEL_WARNING, "Invalid profile", nullptr);
|
||||||
}
|
}
|
||||||
} else if (baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) {
|
|
||||||
image = sharp::SetProfile(image, inputProfile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Negate the colours in the image
|
// Negate the colours in the image
|
||||||
@ -866,8 +855,8 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
if (!baton->withExifMerge) {
|
if (!baton->withExifMerge) {
|
||||||
image = sharp::RemoveExif(image);
|
image = sharp::RemoveExif(image);
|
||||||
}
|
}
|
||||||
for (const auto& s : baton->withExif) {
|
for (const auto& [key, value] : baton->withExif) {
|
||||||
image.set(s.first.data(), s.second.data());
|
image.set(key.c_str(), value.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// XMP buffer
|
// XMP buffer
|
||||||
@ -1009,6 +998,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
->set("Q", baton->tiffQuality)
|
->set("Q", baton->tiffQuality)
|
||||||
->set("bitdepth", baton->tiffBitdepth)
|
->set("bitdepth", baton->tiffBitdepth)
|
||||||
->set("compression", baton->tiffCompression)
|
->set("compression", baton->tiffCompression)
|
||||||
|
->set("bigtiff", baton->tiffBigtiff)
|
||||||
->set("miniswhite", baton->tiffMiniswhite)
|
->set("miniswhite", baton->tiffMiniswhite)
|
||||||
->set("predictor", baton->tiffPredictor)
|
->set("predictor", baton->tiffPredictor)
|
||||||
->set("pyramid", baton->tiffPyramid)
|
->set("pyramid", baton->tiffPyramid)
|
||||||
@ -1211,6 +1201,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
->set("Q", baton->tiffQuality)
|
->set("Q", baton->tiffQuality)
|
||||||
->set("bitdepth", baton->tiffBitdepth)
|
->set("bitdepth", baton->tiffBitdepth)
|
||||||
->set("compression", baton->tiffCompression)
|
->set("compression", baton->tiffCompression)
|
||||||
|
->set("bigtiff", baton->tiffBigtiff)
|
||||||
->set("miniswhite", baton->tiffMiniswhite)
|
->set("miniswhite", baton->tiffMiniswhite)
|
||||||
->set("predictor", baton->tiffPredictor)
|
->set("predictor", baton->tiffPredictor)
|
||||||
->set("pyramid", baton->tiffPyramid)
|
->set("pyramid", baton->tiffPyramid)
|
||||||
@ -1276,7 +1267,12 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
if (what && what[0]) {
|
if (what && what[0]) {
|
||||||
(baton->err).append(what);
|
(baton->err).append(what);
|
||||||
} else {
|
} else {
|
||||||
(baton->err).append("Unknown error");
|
if (baton->input->failOn == VIPS_FAIL_ON_WARNING) {
|
||||||
|
(baton->err).append("Warning treated as error due to failOn setting");
|
||||||
|
baton->errUseWarning = true;
|
||||||
|
} else {
|
||||||
|
(baton->err).append("Unknown error");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Clean up libvips' per-request data and threads
|
// Clean up libvips' per-request data and threads
|
||||||
@ -1291,7 +1287,11 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
// Handle warnings
|
// Handle warnings
|
||||||
std::string warning = sharp::VipsWarningPop();
|
std::string warning = sharp::VipsWarningPop();
|
||||||
while (!warning.empty()) {
|
while (!warning.empty()) {
|
||||||
debuglog.Call(Receiver().Value(), { Napi::String::New(env, warning) });
|
if (baton->errUseWarning) {
|
||||||
|
(baton->err).append("\n").append(warning);
|
||||||
|
} else {
|
||||||
|
debuglog.Call(Receiver().Value(), { Napi::String::New(env, warning) });
|
||||||
|
}
|
||||||
warning = sharp::VipsWarningPop();
|
warning = sharp::VipsWarningPop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1435,11 +1435,11 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
std::string
|
std::string
|
||||||
AssembleSuffixString(std::string extname, std::vector<std::pair<std::string, std::string>> options) {
|
AssembleSuffixString(std::string extname, std::vector<std::pair<std::string, std::string>> options) {
|
||||||
std::string argument;
|
std::string argument;
|
||||||
for (auto const &option : options) {
|
for (const auto& [key, value] : options) {
|
||||||
if (!argument.empty()) {
|
if (!argument.empty()) {
|
||||||
argument += ",";
|
argument += ",";
|
||||||
}
|
}
|
||||||
argument += option.first + "=" + option.second;
|
argument += key + "=" + value;
|
||||||
}
|
}
|
||||||
return extname + "[" + argument + "]";
|
return extname + "[" + argument + "]";
|
||||||
}
|
}
|
||||||
@ -1750,6 +1750,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|||||||
baton->gifReuse = sharp::AttrAsBool(options, "gifReuse");
|
baton->gifReuse = sharp::AttrAsBool(options, "gifReuse");
|
||||||
baton->gifProgressive = sharp::AttrAsBool(options, "gifProgressive");
|
baton->gifProgressive = sharp::AttrAsBool(options, "gifProgressive");
|
||||||
baton->tiffQuality = sharp::AttrAsUint32(options, "tiffQuality");
|
baton->tiffQuality = sharp::AttrAsUint32(options, "tiffQuality");
|
||||||
|
baton->tiffBigtiff = sharp::AttrAsBool(options, "tiffBigtiff");
|
||||||
baton->tiffPyramid = sharp::AttrAsBool(options, "tiffPyramid");
|
baton->tiffPyramid = sharp::AttrAsBool(options, "tiffPyramid");
|
||||||
baton->tiffMiniswhite = sharp::AttrAsBool(options, "tiffMiniswhite");
|
baton->tiffMiniswhite = sharp::AttrAsBool(options, "tiffMiniswhite");
|
||||||
baton->tiffBitdepth = sharp::AttrAsUint32(options, "tiffBitdepth");
|
baton->tiffBitdepth = sharp::AttrAsUint32(options, "tiffBitdepth");
|
||||||
|
|||||||
@ -1,13 +1,15 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef SRC_PIPELINE_H_
|
#ifndef SRC_PIPELINE_H_
|
||||||
#define SRC_PIPELINE_H_
|
#define SRC_PIPELINE_H_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <napi.h>
|
#include <napi.h>
|
||||||
#include <vips/vips8>
|
#include <vips/vips8>
|
||||||
@ -175,6 +177,7 @@ struct PipelineBaton {
|
|||||||
bool gifProgressive;
|
bool gifProgressive;
|
||||||
int tiffQuality;
|
int tiffQuality;
|
||||||
VipsForeignTiffCompression tiffCompression;
|
VipsForeignTiffCompression tiffCompression;
|
||||||
|
bool tiffBigtiff;
|
||||||
VipsForeignTiffPredictor tiffPredictor;
|
VipsForeignTiffPredictor tiffPredictor;
|
||||||
bool tiffPyramid;
|
bool tiffPyramid;
|
||||||
int tiffBitdepth;
|
int tiffBitdepth;
|
||||||
@ -197,6 +200,7 @@ struct PipelineBaton {
|
|||||||
bool jxlLossless;
|
bool jxlLossless;
|
||||||
VipsBandFormat rawDepth;
|
VipsBandFormat rawDepth;
|
||||||
std::string err;
|
std::string err;
|
||||||
|
bool errUseWarning;
|
||||||
int keepMetadata;
|
int keepMetadata;
|
||||||
int withMetadataOrientation;
|
int withMetadataOrientation;
|
||||||
double withMetadataDensity;
|
double withMetadataDensity;
|
||||||
@ -350,6 +354,7 @@ struct PipelineBaton {
|
|||||||
gifProgressive(false),
|
gifProgressive(false),
|
||||||
tiffQuality(80),
|
tiffQuality(80),
|
||||||
tiffCompression(VIPS_FOREIGN_TIFF_COMPRESSION_JPEG),
|
tiffCompression(VIPS_FOREIGN_TIFF_COMPRESSION_JPEG),
|
||||||
|
tiffBigtiff(false),
|
||||||
tiffPredictor(VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL),
|
tiffPredictor(VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL),
|
||||||
tiffPyramid(false),
|
tiffPyramid(false),
|
||||||
tiffBitdepth(8),
|
tiffBitdepth(8),
|
||||||
@ -371,6 +376,7 @@ struct PipelineBaton {
|
|||||||
jxlEffort(7),
|
jxlEffort(7),
|
||||||
jxlLossless(false),
|
jxlLossless(false),
|
||||||
rawDepth(VIPS_FORMAT_UCHAR),
|
rawDepth(VIPS_FORMAT_UCHAR),
|
||||||
|
errUseWarning(false),
|
||||||
keepMetadata(0),
|
keepMetadata(0),
|
||||||
withMetadataOrientation(-1),
|
withMetadataOrientation(-1),
|
||||||
withMetadataDensity(0.0),
|
withMetadataDensity(0.0),
|
||||||
|
|||||||
18
src/sharp.cc
18
src/sharp.cc
@ -1,16 +1,18 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
#include <mutex> // NOLINT(build/c++11)
|
#include <mutex>
|
||||||
|
|
||||||
#include <napi.h>
|
#include <napi.h>
|
||||||
#include <vips/vips8>
|
#include <vips/vips8>
|
||||||
|
|
||||||
#include "common.h"
|
#include "./common.h"
|
||||||
#include "metadata.h"
|
#include "./metadata.h"
|
||||||
#include "pipeline.h"
|
#include "./pipeline.h"
|
||||||
#include "utilities.h"
|
#include "./stats.h"
|
||||||
#include "stats.h"
|
#include "./utilities.h"
|
||||||
|
|
||||||
Napi::Object init(Napi::Env env, Napi::Object exports) {
|
Napi::Object init(Napi::Env env, Napi::Object exports) {
|
||||||
static std::once_flag sharp_vips_init_once;
|
static std::once_flag sharp_vips_init_once;
|
||||||
|
|||||||
15
src/stats.cc
15
src/stats.cc
@ -1,15 +1,18 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
#include <numeric>
|
|
||||||
#include <vector>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <numeric>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <napi.h>
|
#include <napi.h>
|
||||||
#include <vips/vips8>
|
#include <vips/vips8>
|
||||||
|
|
||||||
#include "common.h"
|
#include "./common.h"
|
||||||
#include "stats.h"
|
#include "./stats.h"
|
||||||
|
|
||||||
class StatsWorker : public Napi::AsyncWorker {
|
class StatsWorker : public Napi::AsyncWorker {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef SRC_STATS_H_
|
#ifndef SRC_STATS_H_
|
||||||
#define SRC_STATS_H_
|
#define SRC_STATS_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
#include <napi.h>
|
#include <napi.h>
|
||||||
|
|
||||||
#include "./common.h"
|
#include "./common.h"
|
||||||
@ -24,7 +27,7 @@ struct ChannelStats {
|
|||||||
|
|
||||||
ChannelStats(int minVal, int maxVal, double sumVal, double squaresSumVal,
|
ChannelStats(int minVal, int maxVal, double sumVal, double squaresSumVal,
|
||||||
double meanVal, double stdevVal, int minXVal, int minYVal, int maxXVal, int maxYVal):
|
double meanVal, double stdevVal, int minXVal, int minYVal, int maxXVal, int maxYVal):
|
||||||
min(minVal), max(maxVal), sum(sumVal), squaresSum(squaresSumVal),
|
min(minVal), max(maxVal), sum(sumVal), squaresSum(squaresSumVal), // NOLINT(build/include_what_you_use)
|
||||||
mean(meanVal), stdev(stdevVal), minX(minXVal), minY(minYVal), maxX(maxXVal), maxY(maxYVal) {}
|
mean(meanVal), stdev(stdevVal), minX(minXVal), minY(minYVal), maxX(maxXVal), maxY(maxYVal) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,17 +1,19 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <string>
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <napi.h>
|
#include <napi.h>
|
||||||
#include <vips/vips8>
|
#include <vips/vips8>
|
||||||
#include <vips/vector.h>
|
#include <vips/vector.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "./common.h"
|
||||||
#include "operations.h"
|
#include "./operations.h"
|
||||||
#include "utilities.h"
|
#include "./utilities.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get and set cache limits
|
Get and set cache limits
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef SRC_UTILITIES_H_
|
#ifndef SRC_UTILITIES_H_
|
||||||
#define SRC_UTILITIES_H_
|
#define SRC_UTILITIES_H_
|
||||||
|
|||||||
@ -1,24 +0,0 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const sharp = require('../');
|
|
||||||
|
|
||||||
const usingCache = !process.env.G_DEBUG;
|
|
||||||
const usingSimd = !process.env.VIPS_NOVECTOR;
|
|
||||||
const concurrency = Number(process.env.VIPS_CONCURRENCY) || 0;
|
|
||||||
|
|
||||||
exports.mochaHooks = {
|
|
||||||
beforeEach () {
|
|
||||||
sharp.cache(usingCache);
|
|
||||||
sharp.simd(usingSimd);
|
|
||||||
sharp.concurrency(concurrency);
|
|
||||||
},
|
|
||||||
|
|
||||||
afterEach () {
|
|
||||||
if (global.gc) {
|
|
||||||
global.gc();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -15,7 +15,7 @@ RUN apt-get install -y imagemagick libmagick++-dev graphicsmagick
|
|||||||
# Install sharp
|
# Install sharp
|
||||||
RUN mkdir /tmp/sharp
|
RUN mkdir /tmp/sharp
|
||||||
RUN cd /tmp && git clone --single-branch --branch $BRANCH https://github.com/lovell/sharp.git
|
RUN cd /tmp && git clone --single-branch --branch $BRANCH https://github.com/lovell/sharp.git
|
||||||
RUN cd /tmp/sharp && npm install --build-from-source
|
RUN cd /tmp/sharp && npm install && npm run build
|
||||||
|
|
||||||
# Install benchmark test
|
# Install benchmark test
|
||||||
RUN cd /tmp/sharp/test/bench && npm install --omit optional
|
RUN cd /tmp/sharp/test/bench && npm install --omit optional
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
'use strict';
|
*/
|
||||||
|
|
||||||
process.env.UV_THREADPOOL_SIZE = 64;
|
process.env.UV_THREADPOOL_SIZE = 64;
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('node:assert');
|
||||||
const async = require('async');
|
const async = require('async');
|
||||||
|
|
||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
@ -16,32 +16,29 @@ const height = 480;
|
|||||||
|
|
||||||
sharp.concurrency(1);
|
sharp.concurrency(1);
|
||||||
|
|
||||||
const timer = setInterval(function () {
|
const timer = setInterval(() => {
|
||||||
console.dir(sharp.counters());
|
console.dir(sharp.counters());
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
async.mapSeries([1, 1, 2, 4, 8, 16, 32, 64], function (parallelism, next) {
|
async.mapSeries([1, 1, 2, 4, 8, 16, 32, 64], (parallelism, next) => {
|
||||||
const start = new Date().getTime();
|
const start = Date.now();
|
||||||
async.times(parallelism,
|
async.times(parallelism,
|
||||||
function (id, callback) {
|
(_id, callback) => {
|
||||||
/* jslint unused: false */
|
sharp(fixtures.inputJpg).resize(width, height).toBuffer((err, buffer) => {
|
||||||
sharp(fixtures.inputJpg).resize(width, height).toBuffer(function (err, buffer) {
|
|
||||||
buffer = null;
|
buffer = null;
|
||||||
callback(err, new Date().getTime() - start);
|
callback(err, Date.now() - start);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
function (err, ids) {
|
(err, ids) => {
|
||||||
assert(!err);
|
assert(!err);
|
||||||
assert(ids.length === parallelism);
|
assert(ids.length === parallelism);
|
||||||
ids.sort();
|
ids.sort();
|
||||||
const mean = ids.reduce(function (a, b) {
|
const mean = ids.reduce((a, b) => a + b) / ids.length;
|
||||||
return a + b;
|
console.log(`${parallelism} parallel calls: fastest=${ids[0]}ms slowest=${ids[ids.length - 1]}ms mean=${mean}ms`);
|
||||||
}) / ids.length;
|
|
||||||
console.log(parallelism + ' parallel calls: fastest=' + ids[0] + 'ms slowest=' + ids[ids.length - 1] + 'ms mean=' + mean + 'ms');
|
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}, function () {
|
}, () => {
|
||||||
clearInterval(timer);
|
clearInterval(timer);
|
||||||
console.dir(sharp.counters());
|
console.dir(sharp.counters());
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
const fs = require('node:fs');
|
||||||
|
const { execSync } = require('node:child_process');
|
||||||
const fs = require('fs');
|
|
||||||
const { execSync } = require('child_process');
|
|
||||||
|
|
||||||
const async = require('async');
|
const async = require('async');
|
||||||
const Benchmark = require('benchmark');
|
const Benchmark = require('benchmark');
|
||||||
@ -12,7 +12,7 @@ const Benchmark = require('benchmark');
|
|||||||
const safeRequire = (name) => {
|
const safeRequire = (name) => {
|
||||||
try {
|
try {
|
||||||
return require(name);
|
return require(name);
|
||||||
} catch (err) {}
|
} catch (_err) {}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -45,13 +45,13 @@ console.log(`Detected ${physicalCores} physical cores`);
|
|||||||
sharp.concurrency(physicalCores);
|
sharp.concurrency(physicalCores);
|
||||||
|
|
||||||
async.series({
|
async.series({
|
||||||
jpeg: function (callback) {
|
jpeg: (callback) => {
|
||||||
const inputJpgBuffer = fs.readFileSync(fixtures.inputJpg);
|
const inputJpgBuffer = fs.readFileSync(fixtures.inputJpg);
|
||||||
const jpegSuite = new Benchmark.Suite('jpeg');
|
const jpegSuite = new Benchmark.Suite('jpeg');
|
||||||
// jimp
|
// jimp
|
||||||
jpegSuite.add('jimp-buffer-buffer', {
|
jpegSuite.add('jimp-buffer-buffer', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: async function (deferred) {
|
fn: async (deferred) => {
|
||||||
const image = await Jimp.read(inputJpgBuffer);
|
const image = await Jimp.read(inputJpgBuffer);
|
||||||
await image
|
await image
|
||||||
.resize({ w: width, h: height, mode: Jimp.RESIZE_BICUBIC })
|
.resize({ w: width, h: height, mode: Jimp.RESIZE_BICUBIC })
|
||||||
@ -60,7 +60,7 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('jimp-file-file', {
|
}).add('jimp-file-file', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: async function (deferred) {
|
fn: async (deferred) => {
|
||||||
const image = await Jimp.read(fixtures.inputJpg);
|
const image = await Jimp.read(fixtures.inputJpg);
|
||||||
await image
|
await image
|
||||||
.resize({ w: width, h: height, mode: Jimp.RESIZE_BICUBIC })
|
.resize({ w: width, h: height, mode: Jimp.RESIZE_BICUBIC })
|
||||||
@ -71,14 +71,14 @@ async.series({
|
|||||||
// mapnik
|
// mapnik
|
||||||
mapnik && jpegSuite.add('mapnik-file-file', {
|
mapnik && jpegSuite.add('mapnik-file-file', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
mapnik.Image.open(fixtures.inputJpg, function (err, img) {
|
mapnik.Image.open(fixtures.inputJpg, (err, img) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
img
|
img
|
||||||
.resize(width, height, {
|
.resize(width, height, {
|
||||||
scaling_method: mapnik.imageScaling.lanczos
|
scaling_method: mapnik.imageScaling.lanczos
|
||||||
})
|
})
|
||||||
.save(outputJpg, 'jpeg:quality=80', function (err) {
|
.save(outputJpg, 'jpeg:quality=80', (err) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
});
|
});
|
||||||
@ -86,14 +86,14 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('mapnik-buffer-buffer', {
|
}).add('mapnik-buffer-buffer', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
mapnik.Image.fromBytes(inputJpgBuffer, { max_size: 3000 }, function (err, img) {
|
mapnik.Image.fromBytes(inputJpgBuffer, { max_size: 3000 }, (err, img) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
img
|
img
|
||||||
.resize(width, height, {
|
.resize(width, height, {
|
||||||
scaling_method: mapnik.imageScaling.lanczos
|
scaling_method: mapnik.imageScaling.lanczos
|
||||||
})
|
})
|
||||||
.encode('jpeg:quality=80', function (err) {
|
.encode('jpeg:quality=80', (err) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
});
|
});
|
||||||
@ -103,7 +103,7 @@ async.series({
|
|||||||
// imagemagick
|
// imagemagick
|
||||||
jpegSuite.add('imagemagick-file-file', {
|
jpegSuite.add('imagemagick-file-file', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
imagemagick.resize({
|
imagemagick.resize({
|
||||||
srcPath: fixtures.inputJpg,
|
srcPath: fixtures.inputJpg,
|
||||||
dstPath: outputJpg,
|
dstPath: outputJpg,
|
||||||
@ -112,7 +112,7 @@ async.series({
|
|||||||
height,
|
height,
|
||||||
format: 'jpg',
|
format: 'jpg',
|
||||||
filter: 'Lanczos'
|
filter: 'Lanczos'
|
||||||
}, function (err) {
|
}, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -124,12 +124,12 @@ async.series({
|
|||||||
// gm
|
// gm
|
||||||
jpegSuite.add('gm-buffer-file', {
|
jpegSuite.add('gm-buffer-file', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
gm(inputJpgBuffer)
|
gm(inputJpgBuffer)
|
||||||
.filter('Lanczos')
|
.filter('Lanczos')
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.quality(80)
|
.quality(80)
|
||||||
.write(outputJpg, function (err) {
|
.write(outputJpg, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -139,12 +139,12 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('gm-buffer-buffer', {
|
}).add('gm-buffer-buffer', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
gm(inputJpgBuffer)
|
gm(inputJpgBuffer)
|
||||||
.filter('Lanczos')
|
.filter('Lanczos')
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.quality(80)
|
.quality(80)
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -154,12 +154,12 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('gm-file-file', {
|
}).add('gm-file-file', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
gm(fixtures.inputJpg)
|
gm(fixtures.inputJpg)
|
||||||
.filter('Lanczos')
|
.filter('Lanczos')
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.quality(80)
|
.quality(80)
|
||||||
.write(outputJpg, function (err) {
|
.write(outputJpg, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -169,12 +169,12 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('gm-file-buffer', {
|
}).add('gm-file-buffer', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
gm(fixtures.inputJpg)
|
gm(fixtures.inputJpg)
|
||||||
.filter('Lanczos')
|
.filter('Lanczos')
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.quality(80)
|
.quality(80)
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -186,17 +186,17 @@ async.series({
|
|||||||
// tfjs
|
// tfjs
|
||||||
tfjs && jpegSuite.add('tfjs-node-buffer-buffer', {
|
tfjs && jpegSuite.add('tfjs-node-buffer-buffer', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
const decoded = tfjs.node.decodeJpeg(inputJpgBuffer);
|
const decoded = tfjs.node.decodeJpeg(inputJpgBuffer);
|
||||||
const resized = tfjs.image.resizeBilinear(decoded, [height, width]);
|
const resized = tfjs.image.resizeBilinear(decoded, [height, width]);
|
||||||
tfjs
|
tfjs
|
||||||
.node
|
.node
|
||||||
.encodeJpeg(resized, 'rgb', 80)
|
.encodeJpeg(resized, 'rgb', 80)
|
||||||
.then(function () {
|
.then(() => {
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
tfjs.disposeVariables();
|
tfjs.disposeVariables();
|
||||||
})
|
})
|
||||||
.catch(function (err) {
|
.catch((err) => {
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -204,10 +204,10 @@ async.series({
|
|||||||
// sharp
|
// sharp
|
||||||
jpegSuite.add('sharp-buffer-file', {
|
jpegSuite.add('sharp-buffer-file', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.toFile(outputJpg, function (err) {
|
.toFile(outputJpg, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -217,10 +217,10 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-buffer-buffer', {
|
}).add('sharp-buffer-buffer', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -230,10 +230,10 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-file-file', {
|
}).add('sharp-file-file', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.toFile(outputJpg, function (err) {
|
.toFile(outputJpg, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -243,10 +243,10 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-stream-stream', {
|
}).add('sharp-stream-stream', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
const readable = fs.createReadStream(fixtures.inputJpg);
|
const readable = fs.createReadStream(fixtures.inputJpg);
|
||||||
const writable = fs.createWriteStream(outputJpg);
|
const writable = fs.createWriteStream(outputJpg);
|
||||||
writable.on('finish', function () {
|
writable.on('finish', () => {
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
});
|
});
|
||||||
const pipeline = sharp()
|
const pipeline = sharp()
|
||||||
@ -255,10 +255,10 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-file-buffer', {
|
}).add('sharp-file-buffer', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -268,34 +268,34 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-promise', {
|
}).add('sharp-promise', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.toBuffer()
|
.toBuffer()
|
||||||
.then(function () {
|
.then(() => {
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
})
|
})
|
||||||
.catch(function (err) {
|
.catch((err) => {
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).on('cycle', function (event) {
|
}).on('cycle', (event) => {
|
||||||
console.log('jpeg ' + String(event.target));
|
console.log(`jpeg ${String(event.target)}`);
|
||||||
}).on('complete', function () {
|
}).on('complete', function () {
|
||||||
callback(null, this.filter('fastest').map('name'));
|
callback(null, this.filter('fastest').map('name'));
|
||||||
}).run();
|
}).run();
|
||||||
},
|
},
|
||||||
// Effect of applying operations
|
// Effect of applying operations
|
||||||
operations: function (callback) {
|
operations: (callback) => {
|
||||||
const inputJpgBuffer = fs.readFileSync(fixtures.inputJpg);
|
const inputJpgBuffer = fs.readFileSync(fixtures.inputJpg);
|
||||||
const operationsSuite = new Benchmark.Suite('operations');
|
const operationsSuite = new Benchmark.Suite('operations');
|
||||||
operationsSuite.add('sharp-sharpen-mild', {
|
operationsSuite.add('sharp-sharpen-mild', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.sharpen()
|
.sharpen()
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -305,11 +305,11 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-sharpen-radius', {
|
}).add('sharp-sharpen-radius', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.sharpen(3, 1, 3)
|
.sharpen(3, 1, 3)
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -319,11 +319,11 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-blur-mild', {
|
}).add('sharp-blur-mild', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.blur()
|
.blur()
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -333,11 +333,11 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-blur-radius', {
|
}).add('sharp-blur-radius', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.blur(3)
|
.blur(3)
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -347,11 +347,11 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-gamma', {
|
}).add('sharp-gamma', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.gamma()
|
.gamma()
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -361,11 +361,11 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-normalise', {
|
}).add('sharp-normalise', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.normalise()
|
.normalise()
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -375,11 +375,11 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-greyscale', {
|
}).add('sharp-greyscale', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.greyscale()
|
.greyscale()
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -389,12 +389,12 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-greyscale-gamma', {
|
}).add('sharp-greyscale-gamma', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.gamma()
|
.gamma()
|
||||||
.greyscale()
|
.greyscale()
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -404,11 +404,11 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-progressive', {
|
}).add('sharp-progressive', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.jpeg({ progressive: true })
|
.jpeg({ progressive: true })
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -418,11 +418,11 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-without-chroma-subsampling', {
|
}).add('sharp-without-chroma-subsampling', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.jpeg({ chromaSubsampling: '4:4:4' })
|
.jpeg({ chromaSubsampling: '4:4:4' })
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -432,11 +432,11 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-rotate', {
|
}).add('sharp-rotate', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.rotate(90)
|
.rotate(90)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -446,11 +446,11 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-without-simd', {
|
}).add('sharp-without-simd', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp.simd(false);
|
sharp.simd(false);
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
sharp.simd(true);
|
sharp.simd(true);
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
@ -461,10 +461,10 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-random-access-read', {
|
}).add('sharp-random-access-read', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer, { sequentialRead: false })
|
sharp(inputJpgBuffer, { sequentialRead: false })
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -474,13 +474,13 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-crop-entropy', {
|
}).add('sharp-crop-entropy', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height, {
|
.resize(width, height, {
|
||||||
fit: 'cover',
|
fit: 'cover',
|
||||||
position: sharp.strategy.entropy
|
position: sharp.strategy.entropy
|
||||||
})
|
})
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -490,13 +490,13 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-crop-attention', {
|
}).add('sharp-crop-attention', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height, {
|
.resize(width, height, {
|
||||||
fit: 'cover',
|
fit: 'cover',
|
||||||
position: sharp.strategy.attention
|
position: sharp.strategy.attention
|
||||||
})
|
})
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -504,21 +504,21 @@ async.series({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).on('cycle', function (event) {
|
}).on('cycle', (event) => {
|
||||||
console.log('operations ' + String(event.target));
|
console.log(`operations ${String(event.target)}`);
|
||||||
}).on('complete', function () {
|
}).on('complete', function () {
|
||||||
callback(null, this.filter('fastest').map('name'));
|
callback(null, this.filter('fastest').map('name'));
|
||||||
}).run();
|
}).run();
|
||||||
},
|
},
|
||||||
// Comparative speed of kernels
|
// Comparative speed of kernels
|
||||||
kernels: function (callback) {
|
kernels: (callback) => {
|
||||||
const inputJpgBuffer = fs.readFileSync(fixtures.inputJpg);
|
const inputJpgBuffer = fs.readFileSync(fixtures.inputJpg);
|
||||||
(new Benchmark.Suite('kernels')).add('sharp-cubic', {
|
(new Benchmark.Suite('kernels')).add('sharp-cubic', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height, { kernel: 'cubic' })
|
.resize(width, height, { kernel: 'cubic' })
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -528,10 +528,10 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-lanczos2', {
|
}).add('sharp-lanczos2', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height, { kernel: 'lanczos2' })
|
.resize(width, height, { kernel: 'lanczos2' })
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -541,10 +541,10 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-lanczos3', {
|
}).add('sharp-lanczos3', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height, { kernel: 'lanczos3' })
|
.resize(width, height, { kernel: 'lanczos3' })
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -554,10 +554,10 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-mks2013', {
|
}).add('sharp-mks2013', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height, { kernel: 'mks2013' })
|
.resize(width, height, { kernel: 'mks2013' })
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -567,10 +567,10 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-mks2021', {
|
}).add('sharp-mks2021', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height, { kernel: 'mks2021' })
|
.resize(width, height, { kernel: 'mks2021' })
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -578,21 +578,21 @@ async.series({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).on('cycle', function (event) {
|
}).on('cycle', (event) => {
|
||||||
console.log('kernels ' + String(event.target));
|
console.log(`kernels ${String(event.target)}`);
|
||||||
}).on('complete', function () {
|
}).on('complete', function () {
|
||||||
callback(null, this.filter('fastest').map('name'));
|
callback(null, this.filter('fastest').map('name'));
|
||||||
}).run();
|
}).run();
|
||||||
},
|
},
|
||||||
// PNG
|
// PNG
|
||||||
png: function (callback) {
|
png: (callback) => {
|
||||||
const inputPngBuffer = fs.readFileSync(fixtures.inputPngAlphaPremultiplicationLarge);
|
const inputPngBuffer = fs.readFileSync(fixtures.inputPngAlphaPremultiplicationLarge);
|
||||||
const pngSuite = new Benchmark.Suite('png');
|
const pngSuite = new Benchmark.Suite('png');
|
||||||
const minSamples = 64;
|
const minSamples = 64;
|
||||||
// jimp
|
// jimp
|
||||||
pngSuite.add('jimp-buffer-buffer', {
|
pngSuite.add('jimp-buffer-buffer', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: async function (deferred) {
|
fn: async (deferred) => {
|
||||||
const image = await Jimp.read(inputPngBuffer);
|
const image = await Jimp.read(inputPngBuffer);
|
||||||
await image
|
await image
|
||||||
.resize({ w: width, h: heightPng, mode: Jimp.RESIZE_BICUBIC })
|
.resize({ w: width, h: heightPng, mode: Jimp.RESIZE_BICUBIC })
|
||||||
@ -601,7 +601,7 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('jimp-file-file', {
|
}).add('jimp-file-file', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: async function (deferred) {
|
fn: async (deferred) => {
|
||||||
const image = await Jimp.read(fixtures.inputPngAlphaPremultiplicationLarge);
|
const image = await Jimp.read(fixtures.inputPngAlphaPremultiplicationLarge);
|
||||||
await image
|
await image
|
||||||
.resize({ w: width, h: heightPng, mode: Jimp.RESIZE_BICUBIC })
|
.resize({ w: width, h: heightPng, mode: Jimp.RESIZE_BICUBIC })
|
||||||
@ -612,18 +612,18 @@ async.series({
|
|||||||
// mapnik
|
// mapnik
|
||||||
mapnik && pngSuite.add('mapnik-file-file', {
|
mapnik && pngSuite.add('mapnik-file-file', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
mapnik.Image.open(fixtures.inputPngAlphaPremultiplicationLarge, function (err, img) {
|
mapnik.Image.open(fixtures.inputPngAlphaPremultiplicationLarge, (err, img) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
img.premultiply(function (err, img) {
|
img.premultiply((err, img) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
img.resize(width, heightPng, {
|
img.resize(width, heightPng, {
|
||||||
scaling_method: mapnik.imageScaling.lanczos
|
scaling_method: mapnik.imageScaling.lanczos
|
||||||
}, function (err, img) {
|
}, (err, img) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
img.demultiply(function (err, img) {
|
img.demultiply((err, img) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
img.save(outputPng, 'png32:f=no:z=6', function (err) {
|
img.save(outputPng, 'png32:f=no:z=6', (err) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
});
|
});
|
||||||
@ -634,18 +634,18 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('mapnik-buffer-buffer', {
|
}).add('mapnik-buffer-buffer', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
mapnik.Image.fromBytes(inputPngBuffer, { max_size: 3000 }, function (err, img) {
|
mapnik.Image.fromBytes(inputPngBuffer, { max_size: 3000 }, (err, img) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
img.premultiply(function (err, img) {
|
img.premultiply((err, img) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
img.resize(width, heightPng, {
|
img.resize(width, heightPng, {
|
||||||
scaling_method: mapnik.imageScaling.lanczos
|
scaling_method: mapnik.imageScaling.lanczos
|
||||||
}, function (err, img) {
|
}, (err, img) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
img.demultiply(function (err, img) {
|
img.demultiply((err, img) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
img.encode('png32:f=no:z=6', function (err) {
|
img.encode('png32:f=no:z=6', (err) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
});
|
});
|
||||||
@ -658,7 +658,7 @@ async.series({
|
|||||||
// imagemagick
|
// imagemagick
|
||||||
pngSuite.add('imagemagick-file-file', {
|
pngSuite.add('imagemagick-file-file', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
imagemagick.resize({
|
imagemagick.resize({
|
||||||
srcPath: fixtures.inputPngAlphaPremultiplicationLarge,
|
srcPath: fixtures.inputPngAlphaPremultiplicationLarge,
|
||||||
dstPath: outputPng,
|
dstPath: outputPng,
|
||||||
@ -669,7 +669,7 @@ async.series({
|
|||||||
'-define', 'PNG:compression-level=6',
|
'-define', 'PNG:compression-level=6',
|
||||||
'-define', 'PNG:compression-filter=0'
|
'-define', 'PNG:compression-filter=0'
|
||||||
]
|
]
|
||||||
}, function (err) {
|
}, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -681,13 +681,13 @@ async.series({
|
|||||||
// gm
|
// gm
|
||||||
pngSuite.add('gm-file-file', {
|
pngSuite.add('gm-file-file', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
gm(fixtures.inputPngAlphaPremultiplicationLarge)
|
gm(fixtures.inputPngAlphaPremultiplicationLarge)
|
||||||
.filter('Lanczos')
|
.filter('Lanczos')
|
||||||
.resize(width, heightPng)
|
.resize(width, heightPng)
|
||||||
.define('PNG:compression-level=6')
|
.define('PNG:compression-level=6')
|
||||||
.define('PNG:compression-filter=0')
|
.define('PNG:compression-filter=0')
|
||||||
.write(outputPng, function (err) {
|
.write(outputPng, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -697,13 +697,13 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('gm-file-buffer', {
|
}).add('gm-file-buffer', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
gm(fixtures.inputPngAlphaPremultiplicationLarge)
|
gm(fixtures.inputPngAlphaPremultiplicationLarge)
|
||||||
.filter('Lanczos')
|
.filter('Lanczos')
|
||||||
.resize(width, heightPng)
|
.resize(width, heightPng)
|
||||||
.define('PNG:compression-level=6')
|
.define('PNG:compression-level=6')
|
||||||
.define('PNG:compression-filter=0')
|
.define('PNG:compression-filter=0')
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -716,11 +716,11 @@ async.series({
|
|||||||
pngSuite.add('sharp-buffer-file', {
|
pngSuite.add('sharp-buffer-file', {
|
||||||
defer: true,
|
defer: true,
|
||||||
minSamples,
|
minSamples,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputPngBuffer)
|
sharp(inputPngBuffer)
|
||||||
.resize(width, heightPng)
|
.resize(width, heightPng)
|
||||||
.png({ compressionLevel: 6 })
|
.png({ compressionLevel: 6 })
|
||||||
.toFile(outputPng, function (err) {
|
.toFile(outputPng, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -731,11 +731,11 @@ async.series({
|
|||||||
}).add('sharp-buffer-buffer', {
|
}).add('sharp-buffer-buffer', {
|
||||||
defer: true,
|
defer: true,
|
||||||
minSamples,
|
minSamples,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputPngBuffer)
|
sharp(inputPngBuffer)
|
||||||
.resize(width, heightPng)
|
.resize(width, heightPng)
|
||||||
.png({ compressionLevel: 6 })
|
.png({ compressionLevel: 6 })
|
||||||
.toBuffer(function (err, data) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -746,11 +746,11 @@ async.series({
|
|||||||
}).add('sharp-file-file', {
|
}).add('sharp-file-file', {
|
||||||
defer: true,
|
defer: true,
|
||||||
minSamples,
|
minSamples,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(fixtures.inputPngAlphaPremultiplicationLarge)
|
sharp(fixtures.inputPngAlphaPremultiplicationLarge)
|
||||||
.resize(width, heightPng)
|
.resize(width, heightPng)
|
||||||
.png({ compressionLevel: 6 })
|
.png({ compressionLevel: 6 })
|
||||||
.toFile(outputPng, function (err) {
|
.toFile(outputPng, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -761,11 +761,11 @@ async.series({
|
|||||||
}).add('sharp-file-buffer', {
|
}).add('sharp-file-buffer', {
|
||||||
defer: true,
|
defer: true,
|
||||||
minSamples,
|
minSamples,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(fixtures.inputPngAlphaPremultiplicationLarge)
|
sharp(fixtures.inputPngAlphaPremultiplicationLarge)
|
||||||
.resize(width, heightPng)
|
.resize(width, heightPng)
|
||||||
.png({ compressionLevel: 6 })
|
.png({ compressionLevel: 6 })
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -776,11 +776,11 @@ async.series({
|
|||||||
}).add('sharp-progressive', {
|
}).add('sharp-progressive', {
|
||||||
defer: true,
|
defer: true,
|
||||||
minSamples,
|
minSamples,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputPngBuffer)
|
sharp(inputPngBuffer)
|
||||||
.resize(width, heightPng)
|
.resize(width, heightPng)
|
||||||
.png({ compressionLevel: 6, progressive: true })
|
.png({ compressionLevel: 6, progressive: true })
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -791,11 +791,11 @@ async.series({
|
|||||||
}).add('sharp-adaptiveFiltering', {
|
}).add('sharp-adaptiveFiltering', {
|
||||||
defer: true,
|
defer: true,
|
||||||
minSamples,
|
minSamples,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputPngBuffer)
|
sharp(inputPngBuffer)
|
||||||
.resize(width, heightPng)
|
.resize(width, heightPng)
|
||||||
.png({ adaptiveFiltering: true, compressionLevel: 6 })
|
.png({ adaptiveFiltering: true, compressionLevel: 6 })
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -806,11 +806,11 @@ async.series({
|
|||||||
}).add('sharp-compressionLevel=9', {
|
}).add('sharp-compressionLevel=9', {
|
||||||
defer: true,
|
defer: true,
|
||||||
minSamples,
|
minSamples,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputPngBuffer)
|
sharp(inputPngBuffer)
|
||||||
.resize(width, heightPng)
|
.resize(width, heightPng)
|
||||||
.png({ compressionLevel: 9 })
|
.png({ compressionLevel: 9 })
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -819,21 +819,21 @@ async.series({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
pngSuite.on('cycle', function (event) {
|
pngSuite.on('cycle', (event) => {
|
||||||
console.log(' png ' + String(event.target));
|
console.log(` png ${String(event.target)}`);
|
||||||
}).on('complete', function () {
|
}).on('complete', function () {
|
||||||
callback(null, this.filter('fastest').map('name'));
|
callback(null, this.filter('fastest').map('name'));
|
||||||
}).run();
|
}).run();
|
||||||
},
|
},
|
||||||
// WebP
|
// WebP
|
||||||
webp: function (callback) {
|
webp: (callback) => {
|
||||||
const inputWebPBuffer = fs.readFileSync(fixtures.inputWebP);
|
const inputWebPBuffer = fs.readFileSync(fixtures.inputWebP);
|
||||||
(new Benchmark.Suite('webp')).add('sharp-buffer-file', {
|
(new Benchmark.Suite('webp')).add('sharp-buffer-file', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputWebPBuffer)
|
sharp(inputWebPBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.toFile(outputWebP, function (err) {
|
.toFile(outputWebP, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -843,10 +843,10 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-buffer-buffer', {
|
}).add('sharp-buffer-buffer', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(inputWebPBuffer)
|
sharp(inputWebPBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -856,10 +856,10 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-file-file', {
|
}).add('sharp-file-file', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(fixtures.inputWebP)
|
sharp(fixtures.inputWebP)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.toFile(outputWebP, function (err) {
|
.toFile(outputWebP, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -869,10 +869,10 @@ async.series({
|
|||||||
}
|
}
|
||||||
}).add('sharp-file-buffer', {
|
}).add('sharp-file-buffer', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(fixtures.inputWebP)
|
sharp(fixtures.inputWebP)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -880,19 +880,19 @@ async.series({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).on('cycle', function (event) {
|
}).on('cycle', (event) => {
|
||||||
console.log('webp ' + String(event.target));
|
console.log(`webp ${String(event.target)}`);
|
||||||
}).on('complete', function () {
|
}).on('complete', function () {
|
||||||
callback(null, this.filter('fastest').map('name'));
|
callback(null, this.filter('fastest').map('name'));
|
||||||
}).run();
|
}).run();
|
||||||
}
|
}
|
||||||
}, function (err, results) {
|
}, (err, results) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
Object.keys(results).forEach(function (format) {
|
Object.keys(results).forEach((format) => {
|
||||||
if (results[format].toString().substr(0, 5) !== 'sharp') {
|
if (results[format].toString().substr(0, 5) !== 'sharp') {
|
||||||
console.log('sharp was slower than ' + results[format] + ' for ' + format);
|
console.log(`sharp was slower than ${results[format]} for ${format}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
console.dir(sharp.cache());
|
console.dir(sharp.cache());
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
'use strict';
|
*/
|
||||||
|
|
||||||
const imagemagick = require('imagemagick');
|
const imagemagick = require('imagemagick');
|
||||||
const gm = require('gm');
|
const gm = require('gm');
|
||||||
const assert = require('assert');
|
const assert = require('node:assert');
|
||||||
const Benchmark = require('benchmark');
|
const Benchmark = require('benchmark');
|
||||||
|
|
||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
@ -16,13 +16,11 @@ sharp.cache(false);
|
|||||||
const min = 320;
|
const min = 320;
|
||||||
const max = 960;
|
const max = 960;
|
||||||
|
|
||||||
const randomDimension = function () {
|
const randomDimension = () => Math.ceil((Math.random() * (max - min)) + min);
|
||||||
return Math.ceil((Math.random() * (max - min)) + min);
|
|
||||||
};
|
|
||||||
|
|
||||||
new Benchmark.Suite('random').add('imagemagick', {
|
new Benchmark.Suite('random').add('imagemagick', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
imagemagick.resize({
|
imagemagick.resize({
|
||||||
srcPath: fixtures.inputJpg,
|
srcPath: fixtures.inputJpg,
|
||||||
dstPath: fixtures.path('output.jpg'),
|
dstPath: fixtures.path('output.jpg'),
|
||||||
@ -31,7 +29,7 @@ new Benchmark.Suite('random').add('imagemagick', {
|
|||||||
height: randomDimension(),
|
height: randomDimension(),
|
||||||
format: 'jpg',
|
format: 'jpg',
|
||||||
filter: 'Lanczos'
|
filter: 'Lanczos'
|
||||||
}, function (err) {
|
}, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -41,12 +39,12 @@ new Benchmark.Suite('random').add('imagemagick', {
|
|||||||
}
|
}
|
||||||
}).add('gm', {
|
}).add('gm', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
gm(fixtures.inputJpg)
|
gm(fixtures.inputJpg)
|
||||||
.resize(randomDimension(), randomDimension())
|
.resize(randomDimension(), randomDimension())
|
||||||
.filter('Lanczos')
|
.filter('Lanczos')
|
||||||
.quality(80)
|
.quality(80)
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer((err, buffer) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -57,10 +55,10 @@ new Benchmark.Suite('random').add('imagemagick', {
|
|||||||
}
|
}
|
||||||
}).add('sharp', {
|
}).add('sharp', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function (deferred) {
|
fn: (deferred) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(randomDimension(), randomDimension())
|
.resize(randomDimension(), randomDimension())
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer((err, buffer) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -69,9 +67,9 @@ new Benchmark.Suite('random').add('imagemagick', {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).on('cycle', function (event) {
|
}).on('cycle', (event) => {
|
||||||
console.log(String(event.target));
|
console.log(String(event.target));
|
||||||
}).on('complete', function () {
|
}).on('complete', function () {
|
||||||
const winner = this.filter('fastest').map('name');
|
const winner = this.filter('fastest').map('name');
|
||||||
assert.strictEqual('sharp', String(winner), 'sharp was slower than ' + winner);
|
assert.strictEqual('sharp', String(winner), `sharp was slower than ${winner}`);
|
||||||
}).run();
|
}).run();
|
||||||
|
|||||||
BIN
test/fixtures/bonne.geo.tif
vendored
Normal file
BIN
test/fixtures/bonne.geo.tif
vendored
Normal file
Binary file not shown.
31
test/fixtures/index.js
vendored
31
test/fixtures/index.js
vendored
@ -1,16 +1,14 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
const path = require('node:path');
|
||||||
|
|
||||||
const path = require('path');
|
|
||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
const maxColourDistance = require('../../lib/sharp')._maxColourDistance;
|
const maxColourDistance = require('../../lib/sharp')._maxColourDistance;
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
const getPath = function (filename) {
|
const getPath = (filename) => path.join(__dirname, filename);
|
||||||
return path.join(__dirname, filename);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Generates a 64-bit-as-binary-string image fingerprint
|
// Generates a 64-bit-as-binary-string image fingerprint
|
||||||
// Based on the dHash gradient method - see http://www.hackerfactor.com/blog/index.php?/archives/529-Kind-of-Like-That.html
|
// Based on the dHash gradient method - see http://www.hackerfactor.com/blog/index.php?/archives/529-Kind-of-Like-That.html
|
||||||
@ -22,7 +20,7 @@ async function fingerprint (image) {
|
|||||||
.resize(9, 8, { fit: sharp.fit.fill })
|
.resize(9, 8, { fit: sharp.fit.fill })
|
||||||
.raw()
|
.raw()
|
||||||
.toBuffer()
|
.toBuffer()
|
||||||
.then(function (data) {
|
.then((data) => {
|
||||||
let fingerprint = '';
|
let fingerprint = '';
|
||||||
for (let col = 0; col < 8; col++) {
|
for (let col = 0; col < 8; col++) {
|
||||||
for (let row = 0; row < 8; row++) {
|
for (let row = 0; row < 8; row++) {
|
||||||
@ -115,6 +113,7 @@ module.exports = {
|
|||||||
inputTiff8BitDepth: getPath('8bit_depth.tiff'),
|
inputTiff8BitDepth: getPath('8bit_depth.tiff'),
|
||||||
inputTifftagPhotoshop: getPath('tifftag-photoshop.tiff'), // https://github.com/lovell/sharp/issues/1600
|
inputTifftagPhotoshop: getPath('tifftag-photoshop.tiff'), // https://github.com/lovell/sharp/issues/1600
|
||||||
inputTiffFogra: getPath('fogra-0-100-100-0.tif'), // https://github.com/lovell/sharp/issues/4045
|
inputTiffFogra: getPath('fogra-0-100-100-0.tif'), // https://github.com/lovell/sharp/issues/4045
|
||||||
|
inputTiffGeo: getPath('bonne.geo.tif'), // https://download.osgeo.org/geotiff/samples/intergraph
|
||||||
|
|
||||||
inputJp2: getPath('relax.jp2'), // https://www.fnordware.com/j2k/relax.jp2
|
inputJp2: getPath('relax.jp2'), // https://www.fnordware.com/j2k/relax.jp2
|
||||||
inputJp2TileParts: getPath('relax_tileparts.jp2'), // kdu_expand -i relax.jp2 -o relax-tmp.tif ; kdu_compress -i relax-tmp.tif -o relax_tileparts.jp2 -jp2_space sRGB Clayers=8 -rate 1.0,0.04 Stiles='{128,128}' ORGtparts=L ; rm relax-tmp.tif
|
inputJp2TileParts: getPath('relax_tileparts.jp2'), // kdu_expand -i relax.jp2 -o relax-tmp.tif ; kdu_compress -i relax-tmp.tif -o relax_tileparts.jp2 -jp2_space sRGB Clayers=8 -rate 1.0,0.04 Stiles='{128,128}' ORGtparts=L ; rm relax-tmp.tif
|
||||||
@ -147,14 +146,12 @@ module.exports = {
|
|||||||
path: getPath,
|
path: getPath,
|
||||||
|
|
||||||
// Path for expected output images
|
// Path for expected output images
|
||||||
expected: function (filename) {
|
expected: (filename) => getPath(path.join('expected', filename)),
|
||||||
return getPath(path.join('expected', filename));
|
|
||||||
},
|
|
||||||
|
|
||||||
// Verify similarity of expected vs actual images via fingerprint
|
// Verify similarity of expected vs actual images via fingerprint
|
||||||
// Specify distance threshold using `options={threshold: 42}`, default
|
// Specify distance threshold using `options={threshold: 42}`, default
|
||||||
// `threshold` is 5;
|
// `threshold` is 5;
|
||||||
assertSimilar: async function (expectedImage, actualImage, options, callback) {
|
assertSimilar: async (expectedImage, actualImage, options, callback) => {
|
||||||
if (typeof options === 'function') {
|
if (typeof options === 'function') {
|
||||||
callback = options;
|
callback = options;
|
||||||
options = {};
|
options = {};
|
||||||
@ -194,12 +191,12 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
assertMaxColourDistance: function (actualImagePath, expectedImagePath, acceptedDistance) {
|
assertMaxColourDistance: (actualImagePath, expectedImagePath, acceptedDistance) => {
|
||||||
if (typeof actualImagePath !== 'string') {
|
if (typeof actualImagePath !== 'string') {
|
||||||
throw new TypeError('`actualImagePath` must be a string; got ' + actualImagePath);
|
throw new TypeError(`\`actualImagePath\` must be a string; got ${actualImagePath}`);
|
||||||
}
|
}
|
||||||
if (typeof expectedImagePath !== 'string') {
|
if (typeof expectedImagePath !== 'string') {
|
||||||
throw new TypeError('`expectedImagePath` must be a string; got ' + expectedImagePath);
|
throw new TypeError(`\`expectedImagePath\` must be a string; got ${expectedImagePath}`);
|
||||||
}
|
}
|
||||||
if (typeof acceptedDistance !== 'number') {
|
if (typeof acceptedDistance !== 'number') {
|
||||||
// Default threshold
|
// Default threshold
|
||||||
@ -207,7 +204,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
const distance = maxColourDistance(actualImagePath, expectedImagePath);
|
const distance = maxColourDistance(actualImagePath, expectedImagePath);
|
||||||
if (distance > acceptedDistance) {
|
if (distance > acceptedDistance) {
|
||||||
throw new Error('Expected maximum absolute distance of ' + acceptedDistance + ', actual ' + distance);
|
throw new Error(`Expected maximum absolute distance of ${acceptedDistance}, actual ${distance}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,5 +18,5 @@ for test in $TESTS; do
|
|||||||
--show-leak-kinds=definite,indirect \
|
--show-leak-kinds=definite,indirect \
|
||||||
--num-callers=20 \
|
--num-callers=20 \
|
||||||
--trace-children=yes \
|
--trace-children=yes \
|
||||||
node --expose-gc --zero-fill-buffers node_modules/.bin/mocha --no-config --slow=60000 --timeout=120000 --require test/beforeEach.js "test/unit/$test";
|
node --zero-fill-buffers --test "test/unit/$test";
|
||||||
done
|
done
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
|
// biome-ignore-all lint/correctness/noUnusedFunctionParameters: types only test file
|
||||||
|
// biome-ignore-all lint/correctness/noUnusedVariables: types only test file
|
||||||
|
|
||||||
import sharp = require('../../');
|
import sharp = require('../../');
|
||||||
|
|
||||||
import { createReadStream, createWriteStream } from 'fs';
|
import { createReadStream, createWriteStream } from 'node:fs';
|
||||||
|
|
||||||
const input: Buffer = Buffer.alloc(0);
|
const input: Buffer = Buffer.alloc(0);
|
||||||
const readableStream: NodeJS.ReadableStream = createReadStream(input);
|
const readableStream: NodeJS.ReadableStream = createReadStream(input);
|
||||||
@ -79,7 +82,7 @@ sharp({
|
|||||||
let transformer = sharp()
|
let transformer = sharp()
|
||||||
.resize(300)
|
.resize(300)
|
||||||
.on('info', (info: sharp.OutputInfo) => {
|
.on('info', (info: sharp.OutputInfo) => {
|
||||||
console.log('Image height is ' + info.height);
|
console.log(`Image height is ${info.height}`);
|
||||||
});
|
});
|
||||||
readableStream.pipe(transformer).pipe(writableStream);
|
readableStream.pipe(transformer).pipe(writableStream);
|
||||||
|
|
||||||
@ -318,7 +321,7 @@ sharp('input.gif')
|
|||||||
// From https://sharp.pixelplumbing.com/api-output#examples-9
|
// From https://sharp.pixelplumbing.com/api-output#examples-9
|
||||||
// Extract raw RGB pixel data from JPEG input
|
// Extract raw RGB pixel data from JPEG input
|
||||||
sharp('input.jpg')
|
sharp('input.jpg')
|
||||||
.raw()
|
.raw({ depth: 'ushort' })
|
||||||
.toBuffer({ resolveWithObject: true })
|
.toBuffer({ resolveWithObject: true })
|
||||||
.then(({ data, info }) => {
|
.then(({ data, info }) => {
|
||||||
console.log(data);
|
console.log(data);
|
||||||
|
|||||||
16
test/unit.mjs
Normal file
16
test/unit.mjs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { readdir } from 'node:fs/promises';
|
||||||
|
import { run } from 'node:test';
|
||||||
|
import { spec } from 'node:test/reporters';
|
||||||
|
|
||||||
|
const files = (await readdir('./test/unit')).map((f) => `./test/unit/${f}`);
|
||||||
|
|
||||||
|
run({
|
||||||
|
files,
|
||||||
|
concurrency: true,
|
||||||
|
timeout: 60000,
|
||||||
|
coverage: true,
|
||||||
|
coverageIncludeGlobs: ['lib/*.js'],
|
||||||
|
branchCoverage: 100,
|
||||||
|
})
|
||||||
|
.compose(new spec())
|
||||||
|
.pipe(process.stdout);
|
||||||
@ -1,9 +1,10 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
const { describe, it } = require('node:test');
|
||||||
|
const assert = require('node:assert');
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
|
|||||||
@ -1,18 +1,19 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
const { describe, it } = require('node:test');
|
||||||
|
const assert = require('node:assert');
|
||||||
const assert = require('assert');
|
|
||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
|
|
||||||
describe('Alpha transparency', function () {
|
describe('Alpha transparency', () => {
|
||||||
it('Flatten to black', function (done) {
|
it('Flatten to black', (_t, done) => {
|
||||||
sharp(fixtures.inputPngWithTransparency)
|
sharp(fixtures.inputPngWithTransparency)
|
||||||
.flatten()
|
.flatten()
|
||||||
.resize(400, 300)
|
.resize(400, 300)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(400, info.width);
|
assert.strictEqual(400, info.width);
|
||||||
assert.strictEqual(300, info.height);
|
assert.strictEqual(300, info.height);
|
||||||
@ -20,14 +21,14 @@ describe('Alpha transparency', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Flatten to RGB orange', function (done) {
|
it('Flatten to RGB orange', (_t, done) => {
|
||||||
sharp(fixtures.inputPngWithTransparency)
|
sharp(fixtures.inputPngWithTransparency)
|
||||||
.resize(400, 300)
|
.resize(400, 300)
|
||||||
.flatten({
|
.flatten({
|
||||||
background: { r: 255, g: 102, b: 0 }
|
background: { r: 255, g: 102, b: 0 }
|
||||||
})
|
})
|
||||||
.jpeg({ chromaSubsampling: '4:4:4' })
|
.jpeg({ chromaSubsampling: '4:4:4' })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(400, info.width);
|
assert.strictEqual(400, info.width);
|
||||||
assert.strictEqual(300, info.height);
|
assert.strictEqual(300, info.height);
|
||||||
@ -35,12 +36,12 @@ describe('Alpha transparency', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Flatten to CSS/hex orange', function (done) {
|
it('Flatten to CSS/hex orange', (_t, done) => {
|
||||||
sharp(fixtures.inputPngWithTransparency)
|
sharp(fixtures.inputPngWithTransparency)
|
||||||
.resize(400, 300)
|
.resize(400, 300)
|
||||||
.flatten({ background: '#ff6600' })
|
.flatten({ background: '#ff6600' })
|
||||||
.jpeg({ chromaSubsampling: '4:4:4' })
|
.jpeg({ chromaSubsampling: '4:4:4' })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(400, info.width);
|
assert.strictEqual(400, info.width);
|
||||||
assert.strictEqual(300, info.height);
|
assert.strictEqual(300, info.height);
|
||||||
@ -48,13 +49,13 @@ describe('Alpha transparency', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Flatten 16-bit PNG with transparency to orange', function (done) {
|
it('Flatten 16-bit PNG with transparency to orange', (_t, done) => {
|
||||||
const output = fixtures.path('output.flatten-rgb16-orange.jpg');
|
const output = fixtures.path('output.flatten-rgb16-orange.jpg');
|
||||||
sharp(fixtures.inputPngWithTransparency16bit)
|
sharp(fixtures.inputPngWithTransparency16bit)
|
||||||
.flatten({
|
.flatten({
|
||||||
background: { r: 255, g: 102, b: 0 }
|
background: { r: 255, g: 102, b: 0 }
|
||||||
})
|
})
|
||||||
.toFile(output, function (err, info) {
|
.toFile(output, (err, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(true, info.size > 0);
|
assert.strictEqual(true, info.size > 0);
|
||||||
assert.strictEqual(32, info.width);
|
assert.strictEqual(32, info.width);
|
||||||
@ -64,10 +65,10 @@ describe('Alpha transparency', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Do not flatten', function (done) {
|
it('Do not flatten', (_t, done) => {
|
||||||
sharp(fixtures.inputPngWithTransparency)
|
sharp(fixtures.inputPngWithTransparency)
|
||||||
.flatten(false)
|
.flatten(false)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, _data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('png', info.format);
|
assert.strictEqual('png', info.format);
|
||||||
assert.strictEqual(4, info.channels);
|
assert.strictEqual(4, info.channels);
|
||||||
@ -75,10 +76,10 @@ describe('Alpha transparency', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Ignored for JPEG', function (done) {
|
it('Ignored for JPEG', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.flatten({ background: '#ff0000' })
|
.flatten({ background: '#ff0000' })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, _data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
assert.strictEqual(3, info.channels);
|
assert.strictEqual(3, info.channels);
|
||||||
@ -98,68 +99,60 @@ describe('Alpha transparency', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Enlargement with non-nearest neighbor interpolation shouldn’t cause dark edges', function () {
|
it('Enlargement with non-nearest neighbor interpolation shouldn’t cause dark edges', () => {
|
||||||
const base = 'alpha-premultiply-enlargement-2048x1536-paper.png';
|
const base = 'alpha-premultiply-enlargement-2048x1536-paper.png';
|
||||||
const actual = fixtures.path('output.' + base);
|
const actual = fixtures.path(`output.${base}`);
|
||||||
const expected = fixtures.expected(base);
|
const expected = fixtures.expected(base);
|
||||||
return sharp(fixtures.inputPngAlphaPremultiplicationSmall)
|
return sharp(fixtures.inputPngAlphaPremultiplicationSmall)
|
||||||
.resize(2048, 1536)
|
.resize(2048, 1536)
|
||||||
.toFile(actual)
|
.toFile(actual)
|
||||||
.then(function () {
|
.then(() => {
|
||||||
fixtures.assertMaxColourDistance(actual, expected, 102);
|
fixtures.assertMaxColourDistance(actual, expected, 102);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Reduction with non-nearest neighbor interpolation shouldn’t cause dark edges', function () {
|
it('Reduction with non-nearest neighbor interpolation shouldn’t cause dark edges', () => {
|
||||||
const base = 'alpha-premultiply-reduction-1024x768-paper.png';
|
const base = 'alpha-premultiply-reduction-1024x768-paper.png';
|
||||||
const actual = fixtures.path('output.' + base);
|
const actual = fixtures.path(`output.${base}`);
|
||||||
const expected = fixtures.expected(base);
|
const expected = fixtures.expected(base);
|
||||||
return sharp(fixtures.inputPngAlphaPremultiplicationLarge)
|
return sharp(fixtures.inputPngAlphaPremultiplicationLarge)
|
||||||
.resize(1024, 768)
|
.resize(1024, 768)
|
||||||
.toFile(actual)
|
.toFile(actual)
|
||||||
.then(function () {
|
.then(() => {
|
||||||
fixtures.assertMaxColourDistance(actual, expected, 102);
|
fixtures.assertMaxColourDistance(actual, expected, 102);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Removes alpha from fixtures with transparency, ignores those without', function () {
|
it('Removes alpha from fixtures with transparency, ignores those without', () => Promise.all([
|
||||||
return Promise.all([
|
|
||||||
fixtures.inputPngWithTransparency,
|
fixtures.inputPngWithTransparency,
|
||||||
fixtures.inputPngWithTransparency16bit,
|
fixtures.inputPngWithTransparency16bit,
|
||||||
fixtures.inputWebPWithTransparency,
|
fixtures.inputWebPWithTransparency,
|
||||||
fixtures.inputJpg,
|
fixtures.inputJpg,
|
||||||
fixtures.inputPng,
|
fixtures.inputPng,
|
||||||
fixtures.inputWebP
|
fixtures.inputWebP
|
||||||
].map(function (input) {
|
].map((input) => sharp(input)
|
||||||
return sharp(input)
|
|
||||||
.resize(10)
|
.resize(10)
|
||||||
.removeAlpha()
|
.removeAlpha()
|
||||||
.toBuffer({ resolveWithObject: true })
|
.toBuffer({ resolveWithObject: true })
|
||||||
.then(function (result) {
|
.then((result) => {
|
||||||
assert.strictEqual(3, result.info.channels);
|
assert.strictEqual(3, result.info.channels);
|
||||||
});
|
}))));
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Ensures alpha from fixtures without transparency, ignores those with', function () {
|
it('Ensures alpha from fixtures without transparency, ignores those with', () => Promise.all([
|
||||||
return Promise.all([
|
|
||||||
fixtures.inputPngWithTransparency,
|
fixtures.inputPngWithTransparency,
|
||||||
fixtures.inputPngWithTransparency16bit,
|
fixtures.inputPngWithTransparency16bit,
|
||||||
fixtures.inputWebPWithTransparency,
|
fixtures.inputWebPWithTransparency,
|
||||||
fixtures.inputJpg,
|
fixtures.inputJpg,
|
||||||
fixtures.inputPng,
|
fixtures.inputPng,
|
||||||
fixtures.inputWebP
|
fixtures.inputWebP
|
||||||
].map(function (input) {
|
].map((input) => sharp(input)
|
||||||
return sharp(input)
|
|
||||||
.resize(10)
|
.resize(10)
|
||||||
.ensureAlpha()
|
.ensureAlpha()
|
||||||
.png()
|
.png()
|
||||||
.toBuffer({ resolveWithObject: true })
|
.toBuffer({ resolveWithObject: true })
|
||||||
.then(function (result) {
|
.then((result) => {
|
||||||
assert.strictEqual(4, result.info.channels);
|
assert.strictEqual(4, result.info.channels);
|
||||||
});
|
}))));
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Valid ensureAlpha value used for alpha channel', async () => {
|
it('Valid ensureAlpha value used for alpha channel', async () => {
|
||||||
const background = { r: 255, g: 0, b: 0 };
|
const background = { r: 255, g: 0, b: 0 };
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
const { describe, it } = require('node:test');
|
||||||
|
const assert = require('node:assert');
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
const { inputAvif, inputJpg, inputGifAnimated } = require('../fixtures');
|
const { inputAvif, inputJpg, inputGifAnimated } = require('../fixtures');
|
||||||
@ -20,8 +21,8 @@ describe('AVIF', () => {
|
|||||||
.resize(32)
|
.resize(32)
|
||||||
.jpeg()
|
.jpeg()
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
const { size, ...metadata } = await sharp(data)
|
const { size, ...metadata } = await sharp(data).metadata();
|
||||||
.metadata();
|
void size;
|
||||||
assert.deepStrictEqual(metadata, {
|
assert.deepStrictEqual(metadata, {
|
||||||
autoOrient: {
|
autoOrient: {
|
||||||
height: 13,
|
height: 13,
|
||||||
@ -49,8 +50,8 @@ describe('AVIF', () => {
|
|||||||
.resize(32)
|
.resize(32)
|
||||||
.avif({ effort: 0 })
|
.avif({ effort: 0 })
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
const { size, ...metadata } = await sharp(data)
|
const { size, ...metadata } = await sharp(data).metadata();
|
||||||
.metadata();
|
void size;
|
||||||
assert.deepStrictEqual(metadata, {
|
assert.deepStrictEqual(metadata, {
|
||||||
autoOrient: {
|
autoOrient: {
|
||||||
height: 26,
|
height: 26,
|
||||||
@ -77,8 +78,8 @@ describe('AVIF', () => {
|
|||||||
const data = await sharp(inputAvif)
|
const data = await sharp(inputAvif)
|
||||||
.resize(32)
|
.resize(32)
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
const { size, ...metadata } = await sharp(data)
|
const { size, ...metadata } = await sharp(data).metadata();
|
||||||
.metadata();
|
void size;
|
||||||
assert.deepStrictEqual(metadata, {
|
assert.deepStrictEqual(metadata, {
|
||||||
autoOrient: {
|
autoOrient: {
|
||||||
height: 13,
|
height: 13,
|
||||||
@ -106,8 +107,8 @@ describe('AVIF', () => {
|
|||||||
.resize(10)
|
.resize(10)
|
||||||
.avif({ effort: 0 })
|
.avif({ effort: 0 })
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
const { size, ...metadata } = await sharp(data)
|
const { size, ...metadata } = await sharp(data).metadata();
|
||||||
.metadata();
|
void size;
|
||||||
assert.deepStrictEqual(metadata, {
|
assert.deepStrictEqual(metadata, {
|
||||||
autoOrient: {
|
autoOrient: {
|
||||||
height: 300,
|
height: 300,
|
||||||
@ -136,8 +137,8 @@ describe('AVIF', () => {
|
|||||||
.sharpen()
|
.sharpen()
|
||||||
.avif({ effort: 0 })
|
.avif({ effort: 0 })
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
const { size, ...metadata } = await sharp(data)
|
const { size, ...metadata } = await sharp(data).metadata();
|
||||||
.metadata();
|
void size;
|
||||||
assert.deepStrictEqual(metadata, {
|
assert.deepStrictEqual(metadata, {
|
||||||
autoOrient: {
|
autoOrient: {
|
||||||
height: 26,
|
height: 26,
|
||||||
@ -174,9 +175,10 @@ describe('AVIF', () => {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
it('Invalid bitdepth value throws error', async () => {
|
it('Invalid bitdepth value throws error', () =>
|
||||||
assert.rejects(
|
assert.throws(
|
||||||
() => sharp().avif({ bitdepth: 11 }),
|
() => sharp().avif({ bitdepth: 11 }),
|
||||||
/Error: Expected 8, 10 or 12 for bitdepth but received 11 of type number/);
|
/Expected 8, 10 or 12 for bitdepth but received 11 of type number/
|
||||||
});
|
)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,51 +1,52 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
const { describe, it } = require('node:test');
|
||||||
|
const assert = require('node:assert');
|
||||||
const assert = require('assert');
|
|
||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
|
|
||||||
describe('Bandbool per-channel boolean operations', function () {
|
describe('Bandbool per-channel boolean operations', () => {
|
||||||
[
|
[
|
||||||
sharp.bool.and,
|
sharp.bool.and,
|
||||||
sharp.bool.or,
|
sharp.bool.or,
|
||||||
sharp.bool.eor
|
sharp.bool.eor
|
||||||
]
|
]
|
||||||
.forEach(function (op) {
|
.forEach((op) => {
|
||||||
it(op + ' operation', function (done) {
|
it(`${op} operation`, (_t, done) => {
|
||||||
sharp(fixtures.inputPngBooleanNoAlpha)
|
sharp(fixtures.inputPngBooleanNoAlpha)
|
||||||
.bandbool(op)
|
.bandbool(op)
|
||||||
.toColourspace('b-w')
|
.toColourspace('b-w')
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(200, info.width);
|
assert.strictEqual(200, info.width);
|
||||||
assert.strictEqual(200, info.height);
|
assert.strictEqual(200, info.height);
|
||||||
assert.strictEqual(1, info.channels);
|
assert.strictEqual(1, info.channels);
|
||||||
fixtures.assertSimilar(fixtures.expected('bandbool_' + op + '_result.png'), data, done);
|
fixtures.assertSimilar(fixtures.expected(`bandbool_${op}_result.png`), data, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sRGB image retains 3 channels', function (done) {
|
it('sRGB image retains 3 channels', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.bandbool('and')
|
.bandbool('and')
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, _data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(3, info.channels);
|
assert.strictEqual(3, info.channels);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Invalid operation', function () {
|
it('Invalid operation', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp().bandbool('fail');
|
sharp().bandbool('fail');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Missing operation', function () {
|
it('Missing operation', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp().bandbool();
|
sharp().bandbool();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,19 +1,20 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
const { describe, it } = require('node:test');
|
||||||
|
const assert = require('node:assert');
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
|
|
||||||
describe('Blur', function () {
|
describe('Blur', () => {
|
||||||
it('specific radius 1', function (done) {
|
it('specific radius 1', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
.blur(1)
|
.blur(1)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
@ -22,11 +23,11 @@ describe('Blur', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('specific radius 10', function (done) {
|
it('specific radius 10', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
.blur(10)
|
.blur(10)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
@ -35,11 +36,11 @@ describe('Blur', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('specific options.sigma 10', function (done) {
|
it('specific options.sigma 10', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
.blur({ sigma: 10 })
|
.blur({ sigma: 10 })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
@ -48,11 +49,11 @@ describe('Blur', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('specific radius 0.3', function (done) {
|
it('specific radius 0.3', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
.blur(0.3)
|
.blur(0.3)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
@ -61,11 +62,11 @@ describe('Blur', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('mild blur', function (done) {
|
it('mild blur', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
.blur()
|
.blur()
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
@ -74,17 +75,17 @@ describe('Blur', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invalid radius', function () {
|
it('invalid radius', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg).blur(0.1);
|
sharp(fixtures.inputJpg).blur(0.1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('blurred image is smaller than non-blurred', function (done) {
|
it('blurred image is smaller than non-blurred', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
.blur(false)
|
.blur(false)
|
||||||
.toBuffer(function (err, notBlurred, info) {
|
.toBuffer((err, notBlurred, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(true, notBlurred.length > 0);
|
assert.strictEqual(true, notBlurred.length > 0);
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
@ -93,7 +94,7 @@ describe('Blur', function () {
|
|||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
.blur(true)
|
.blur(true)
|
||||||
.toBuffer(function (err, blurred, info) {
|
.toBuffer((err, blurred, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(true, blurred.length > 0);
|
assert.strictEqual(true, blurred.length > 0);
|
||||||
assert.strictEqual(true, blurred.length < notBlurred.length);
|
assert.strictEqual(true, blurred.length < notBlurred.length);
|
||||||
@ -105,18 +106,18 @@ describe('Blur', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invalid precision', function () {
|
it('invalid precision', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg).blur({ sigma: 1, precision: 'invalid' });
|
sharp(fixtures.inputJpg).blur({ sigma: 1, precision: 'invalid' });
|
||||||
}, /Expected one of: integer, float, approximate for precision but received invalid of type string/);
|
}, /Expected one of: integer, float, approximate for precision but received invalid of type string/);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invalid minAmplitude', function () {
|
it('invalid minAmplitude', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg).blur({ sigma: 1, minAmplitude: 0 });
|
sharp(fixtures.inputJpg).blur({ sigma: 1, minAmplitude: 0 });
|
||||||
}, /Expected number between 0.001 and 1 for minAmplitude but received 0 of type number/);
|
}, /Expected number between 0.001 and 1 for minAmplitude but received 0 of type number/);
|
||||||
|
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg).blur({ sigma: 1, minAmplitude: 1.01 });
|
sharp(fixtures.inputJpg).blur({ sigma: 1, minAmplitude: 1.01 });
|
||||||
}, /Expected number between 0.001 and 1 for minAmplitude but received 1.01 of type number/);
|
}, /Expected number between 0.001 and 1 for minAmplitude but received 1.01 of type number/);
|
||||||
});
|
});
|
||||||
@ -149,8 +150,8 @@ describe('Blur', function () {
|
|||||||
await fixtures.assertSimilar(fixtures.expected('blur-10.jpg'), minAmplitudeLow);
|
await fixtures.assertSimilar(fixtures.expected('blur-10.jpg'), minAmplitudeLow);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('options.sigma is required if options object is passed', function () {
|
it('options.sigma is required if options object is passed', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg).blur({ precision: 'invalid' });
|
sharp(fixtures.inputJpg).blur({ precision: 'invalid' });
|
||||||
}, /Expected number between 0.3 and 1000 for options.sigma but received undefined of type undefined/);
|
}, /Expected number between 0.3 and 1000 for options.sigma but received undefined of type undefined/);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,15 +1,16 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
const fs = require('node:fs');
|
||||||
|
const { describe, it } = require('node:test');
|
||||||
const fs = require('fs');
|
const assert = require('node:assert');
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
|
|
||||||
describe('Boolean operation between two images', function () {
|
describe('Boolean operation between two images', () => {
|
||||||
const inputJpgBooleanTestBuffer = fs.readFileSync(fixtures.inputJpgBooleanTest);
|
const inputJpgBooleanTestBuffer = fs.readFileSync(fixtures.inputJpgBooleanTest);
|
||||||
|
|
||||||
[
|
[
|
||||||
@ -17,63 +18,63 @@ describe('Boolean operation between two images', function () {
|
|||||||
sharp.bool.or,
|
sharp.bool.or,
|
||||||
sharp.bool.eor
|
sharp.bool.eor
|
||||||
]
|
]
|
||||||
.forEach(function (op) {
|
.forEach((op) => {
|
||||||
it(op + ' operation, file', function (done) {
|
it(`${op} operation, file`, (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
.boolean(fixtures.inputJpgBooleanTest, op)
|
.boolean(fixtures.inputJpgBooleanTest, op)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
assert.strictEqual(240, info.height);
|
assert.strictEqual(240, info.height);
|
||||||
fixtures.assertSimilar(fixtures.expected('boolean_' + op + '_result.jpg'), data, done);
|
fixtures.assertSimilar(fixtures.expected(`boolean_${op}_result.jpg`), data, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it(op + ' operation, buffer', function (done) {
|
it(`${op} operation, buffer`, (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
.boolean(inputJpgBooleanTestBuffer, op)
|
.boolean(inputJpgBooleanTestBuffer, op)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
assert.strictEqual(240, info.height);
|
assert.strictEqual(240, info.height);
|
||||||
fixtures.assertSimilar(fixtures.expected('boolean_' + op + '_result.jpg'), data, done);
|
fixtures.assertSimilar(fixtures.expected(`boolean_${op}_result.jpg`), data, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it(op + ' operation, raw', function (done) {
|
it(`${op} operation, raw`, (_t, done) => {
|
||||||
sharp(fixtures.inputJpgBooleanTest)
|
sharp(fixtures.inputJpgBooleanTest)
|
||||||
.raw()
|
.raw()
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
.boolean(data, op, { raw: info })
|
.boolean(data, op, { raw: info })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
assert.strictEqual(240, info.height);
|
assert.strictEqual(240, info.height);
|
||||||
fixtures.assertSimilar(fixtures.expected('boolean_' + op + '_result.jpg'), data, done);
|
fixtures.assertSimilar(fixtures.expected(`boolean_${op}_result.jpg`), data, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Invalid operation', function () {
|
it('Invalid operation', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp().boolean(fixtures.inputJpgBooleanTest, 'fail');
|
sharp().boolean(fixtures.inputJpgBooleanTest, 'fail');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Invalid operation, non-string', function () {
|
it('Invalid operation, non-string', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp().boolean(fixtures.inputJpgBooleanTest, null);
|
sharp().boolean(fixtures.inputJpgBooleanTest, null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Missing input', function () {
|
it('Missing input', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp().boolean();
|
sharp().boolean();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,139 +1,140 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
const { describe, it } = require('node:test');
|
||||||
|
const assert = require('node:assert');
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
const sharp = require('../../lib');
|
const sharp = require('../../lib');
|
||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
|
|
||||||
describe('Clahe', function () {
|
describe('Clahe', () => {
|
||||||
it('width 5 width 5 maxSlope 0', function (done) {
|
it('width 5 width 5 maxSlope 0', (_t, done) => {
|
||||||
sharp(fixtures.inputJpgClahe)
|
sharp(fixtures.inputJpgClahe)
|
||||||
.clahe({ width: 5, height: 5, maxSlope: 0 })
|
.clahe({ width: 5, height: 5, maxSlope: 0 })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
fixtures.assertSimilar(fixtures.expected('clahe-5-5-0.jpg'), data, { threshold: 10 }, done);
|
fixtures.assertSimilar(fixtures.expected('clahe-5-5-0.jpg'), data, { threshold: 10 }, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('width 5 width 5 maxSlope 5', function (done) {
|
it('width 5 width 5 maxSlope 5', (_t, done) => {
|
||||||
sharp(fixtures.inputJpgClahe)
|
sharp(fixtures.inputJpgClahe)
|
||||||
.clahe({ width: 5, height: 5, maxSlope: 5 })
|
.clahe({ width: 5, height: 5, maxSlope: 5 })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
fixtures.assertSimilar(fixtures.expected('clahe-5-5-5.jpg'), data, done);
|
fixtures.assertSimilar(fixtures.expected('clahe-5-5-5.jpg'), data, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('width 11 width 25 maxSlope 14', function (done) {
|
it('width 11 width 25 maxSlope 14', (_t, done) => {
|
||||||
sharp(fixtures.inputJpgClahe)
|
sharp(fixtures.inputJpgClahe)
|
||||||
.clahe({ width: 11, height: 25, maxSlope: 14 })
|
.clahe({ width: 11, height: 25, maxSlope: 14 })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
fixtures.assertSimilar(fixtures.expected('clahe-11-25-14.jpg'), data, done);
|
fixtures.assertSimilar(fixtures.expected('clahe-11-25-14.jpg'), data, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('width 50 width 50 maxSlope 0', function (done) {
|
it('width 50 width 50 maxSlope 0', (_t, done) => {
|
||||||
sharp(fixtures.inputJpgClahe)
|
sharp(fixtures.inputJpgClahe)
|
||||||
.clahe({ width: 50, height: 50, maxSlope: 0 })
|
.clahe({ width: 50, height: 50, maxSlope: 0 })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
fixtures.assertSimilar(fixtures.expected('clahe-50-50-0.jpg'), data, done);
|
fixtures.assertSimilar(fixtures.expected('clahe-50-50-0.jpg'), data, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('width 50 width 50 maxSlope 14', function (done) {
|
it('width 50 width 50 maxSlope 14', (_t, done) => {
|
||||||
sharp(fixtures.inputJpgClahe)
|
sharp(fixtures.inputJpgClahe)
|
||||||
.clahe({ width: 50, height: 50, maxSlope: 14 })
|
.clahe({ width: 50, height: 50, maxSlope: 14 })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
fixtures.assertSimilar(fixtures.expected('clahe-50-50-14.jpg'), data, done);
|
fixtures.assertSimilar(fixtures.expected('clahe-50-50-14.jpg'), data, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('width 100 width 50 maxSlope 3', function (done) {
|
it('width 100 width 50 maxSlope 3', (_t, done) => {
|
||||||
sharp(fixtures.inputJpgClahe)
|
sharp(fixtures.inputJpgClahe)
|
||||||
.clahe({ width: 100, height: 50, maxSlope: 3 })
|
.clahe({ width: 100, height: 50, maxSlope: 3 })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
fixtures.assertSimilar(fixtures.expected('clahe-100-50-3.jpg'), data, done);
|
fixtures.assertSimilar(fixtures.expected('clahe-100-50-3.jpg'), data, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('width 100 width 100 maxSlope 0', function (done) {
|
it('width 100 width 100 maxSlope 0', (_t, done) => {
|
||||||
sharp(fixtures.inputJpgClahe)
|
sharp(fixtures.inputJpgClahe)
|
||||||
.clahe({ width: 100, height: 100, maxSlope: 0 })
|
.clahe({ width: 100, height: 100, maxSlope: 0 })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
fixtures.assertSimilar(fixtures.expected('clahe-100-100-0.jpg'), data, done);
|
fixtures.assertSimilar(fixtures.expected('clahe-100-100-0.jpg'), data, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invalid maxSlope', function () {
|
it('invalid maxSlope', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: 100, maxSlope: -5 });
|
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: 100, maxSlope: -5 });
|
||||||
});
|
});
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: 100, maxSlope: 110 });
|
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: 100, maxSlope: 110 });
|
||||||
});
|
});
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: 100, maxSlope: 5.5 });
|
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: 100, maxSlope: 5.5 });
|
||||||
});
|
});
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: 100, maxSlope: 'a string' });
|
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: 100, maxSlope: 'a string' });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invalid width', function () {
|
it('invalid width', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpgClahe).clahe({ width: 100.5, height: 100 });
|
sharp(fixtures.inputJpgClahe).clahe({ width: 100.5, height: 100 });
|
||||||
});
|
});
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpgClahe).clahe({ width: -5, height: 100 });
|
sharp(fixtures.inputJpgClahe).clahe({ width: -5, height: 100 });
|
||||||
});
|
});
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpgClahe).clahe({ width: true, height: 100 });
|
sharp(fixtures.inputJpgClahe).clahe({ width: true, height: 100 });
|
||||||
});
|
});
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpgClahe).clahe({ width: 'string test', height: 100 });
|
sharp(fixtures.inputJpgClahe).clahe({ width: 'string test', height: 100 });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invalid height', function () {
|
it('invalid height', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: 100.5 });
|
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: 100.5 });
|
||||||
});
|
});
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: -5 });
|
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: -5 });
|
||||||
});
|
});
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: true });
|
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: true });
|
||||||
});
|
});
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: 'string test' });
|
sharp(fixtures.inputJpgClahe).clahe({ width: 100, height: 'string test' });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invalid options object', function () {
|
it('invalid options object', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpgClahe).clahe(100, 100, 5);
|
sharp(fixtures.inputJpgClahe).clahe(100, 100, 5);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('uses default maxSlope of 3', function (done) {
|
it('uses default maxSlope of 3', (_t, done) => {
|
||||||
sharp(fixtures.inputJpgClahe)
|
sharp(fixtures.inputJpgClahe)
|
||||||
.clahe({ width: 100, height: 50 })
|
.clahe({ width: 100, height: 50 })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
fixtures.assertSimilar(fixtures.expected('clahe-100-50-3.jpg'), data, done);
|
fixtures.assertSimilar(fixtures.expected('clahe-100-50-3.jpg'), data, done);
|
||||||
|
|||||||
@ -1,29 +1,30 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
const fs = require('node:fs');
|
||||||
|
const { afterEach, beforeEach, describe, it } = require('node:test');
|
||||||
const fs = require('fs');
|
const assert = require('node:assert');
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
|
|
||||||
describe('Clone', function () {
|
describe('Clone', () => {
|
||||||
beforeEach(function () {
|
beforeEach(() => {
|
||||||
sharp.cache(false);
|
sharp.cache(false);
|
||||||
});
|
});
|
||||||
afterEach(function () {
|
afterEach(() => {
|
||||||
sharp.cache(true);
|
sharp.cache(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Read from Stream and write to multiple Streams', function (done) {
|
it('Read from Stream and write to multiple Streams', (_t, done) => {
|
||||||
let finishEventsExpected = 2;
|
let finishEventsExpected = 2;
|
||||||
// Output stream 1
|
// Output stream 1
|
||||||
const output1 = fixtures.path('output.multi-stream.1.jpg');
|
const output1 = fixtures.path('output.multi-stream.1.jpg');
|
||||||
const writable1 = fs.createWriteStream(output1);
|
const writable1 = fs.createWriteStream(output1);
|
||||||
writable1.on('finish', function () {
|
writable1.on('finish', () => {
|
||||||
sharp(output1).toBuffer(function (err, data, info) {
|
sharp(output1).toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(true, data.length > 0);
|
assert.strictEqual(true, data.length > 0);
|
||||||
assert.strictEqual(data.length, info.size);
|
assert.strictEqual(data.length, info.size);
|
||||||
@ -40,8 +41,8 @@ describe('Clone', function () {
|
|||||||
// Output stream 2
|
// Output stream 2
|
||||||
const output2 = fixtures.path('output.multi-stream.2.jpg');
|
const output2 = fixtures.path('output.multi-stream.2.jpg');
|
||||||
const writable2 = fs.createWriteStream(output2);
|
const writable2 = fs.createWriteStream(output2);
|
||||||
writable2.on('finish', function () {
|
writable2.on('finish', () => {
|
||||||
sharp(output2).toBuffer(function (err, data, info) {
|
sharp(output2).toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(true, data.length > 0);
|
assert.strictEqual(true, data.length > 0);
|
||||||
assert.strictEqual(data.length, info.size);
|
assert.strictEqual(data.length, info.size);
|
||||||
@ -64,14 +65,14 @@ describe('Clone', function () {
|
|||||||
fs.createReadStream(fixtures.inputJpg).pipe(rotator);
|
fs.createReadStream(fixtures.inputJpg).pipe(rotator);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Stream-based input attaches finish event listener to original', function () {
|
it('Stream-based input attaches finish event listener to original', () => {
|
||||||
const original = sharp();
|
const original = sharp();
|
||||||
const clone = original.clone();
|
const clone = original.clone();
|
||||||
assert.strictEqual(1, original.listenerCount('finish'));
|
assert.strictEqual(1, original.listenerCount('finish'));
|
||||||
assert.strictEqual(0, clone.listenerCount('finish'));
|
assert.strictEqual(0, clone.listenerCount('finish'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Non Stream-based input does not attach finish event listeners', function () {
|
it('Non Stream-based input does not attach finish event listeners', () => {
|
||||||
const original = sharp(fixtures.inputJpg);
|
const original = sharp(fixtures.inputJpg);
|
||||||
const clone = original.clone();
|
const clone = original.clone();
|
||||||
assert.strictEqual(0, original.listenerCount('finish'));
|
assert.strictEqual(0, original.listenerCount('finish'));
|
||||||
|
|||||||
@ -1,22 +1,23 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
const { describe, it } = require('node:test');
|
||||||
|
const assert = require('node:assert');
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
|
|
||||||
describe('Colour space conversion', function () {
|
describe('Colour space conversion', () => {
|
||||||
it('To greyscale', function (done) {
|
it('To greyscale', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
.greyscale()
|
.greyscale()
|
||||||
.toFile(fixtures.path('output.greyscale-gamma-0.0.jpg'), done);
|
.toFile(fixtures.path('output.greyscale-gamma-0.0.jpg'), done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('To greyscale with gamma correction', function (done) {
|
it('To greyscale with gamma correction', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
.gamma()
|
.gamma()
|
||||||
@ -24,19 +25,19 @@ describe('Colour space conversion', function () {
|
|||||||
.toFile(fixtures.path('output.greyscale-gamma-2.2.jpg'), done);
|
.toFile(fixtures.path('output.greyscale-gamma-2.2.jpg'), done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Not to greyscale', function (done) {
|
it('Not to greyscale', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
.greyscale(false)
|
.greyscale(false)
|
||||||
.toFile(fixtures.path('output.greyscale-not.jpg'), done);
|
.toFile(fixtures.path('output.greyscale-not.jpg'), done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Greyscale with single channel output', function (done) {
|
it('Greyscale with single channel output', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
.greyscale()
|
.greyscale()
|
||||||
.toColourspace('b-w')
|
.toColourspace('b-w')
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(1, info.channels);
|
assert.strictEqual(1, info.channels);
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
@ -55,10 +56,10 @@ describe('Colour space conversion', function () {
|
|||||||
assert.strictEqual(format, 'webp');
|
assert.strictEqual(format, 'webp');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('From CMYK to sRGB', function (done) {
|
it('From CMYK to sRGB', (_t, done) => {
|
||||||
sharp(fixtures.inputJpgWithCmykProfile)
|
sharp(fixtures.inputJpgWithCmykProfile)
|
||||||
.resize(320)
|
.resize(320)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(true, data.length > 0);
|
assert.strictEqual(true, data.length > 0);
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
@ -67,13 +68,13 @@ describe('Colour space conversion', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('From CMYK to sRGB with white background, not yellow', function (done) {
|
it('From CMYK to sRGB with white background, not yellow', (_t, done) => {
|
||||||
sharp(fixtures.inputJpgWithCmykProfile)
|
sharp(fixtures.inputJpgWithCmykProfile)
|
||||||
.resize(320, 240, {
|
.resize(320, 240, {
|
||||||
fit: sharp.fit.contain,
|
fit: sharp.fit.contain,
|
||||||
background: 'white'
|
background: 'white'
|
||||||
})
|
})
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
@ -82,10 +83,10 @@ describe('Colour space conversion', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('From profile-less CMYK to sRGB', function (done) {
|
it('From profile-less CMYK to sRGB', (_t, done) => {
|
||||||
sharp(fixtures.inputJpgWithCmykNoProfile)
|
sharp(fixtures.inputJpgWithCmykNoProfile)
|
||||||
.resize(320)
|
.resize(320)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
@ -122,14 +123,14 @@ describe('Colour space conversion', function () {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('CMYK profile to CMYK profile with negate', (done) => {
|
it('CMYK profile to CMYK profile with negate', (_t, done) => {
|
||||||
sharp(fixtures.inputTiffFogra)
|
sharp(fixtures.inputTiffFogra)
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
.toColourspace('cmyk')
|
.toColourspace('cmyk')
|
||||||
.pipelineColourspace('cmyk')
|
.pipelineColourspace('cmyk')
|
||||||
.withIccProfile(fixtures.path('XCMYK 2017.icc'))
|
.withIccProfile(fixtures.path('XCMYK 2017.icc'))
|
||||||
.negate()
|
.negate()
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('tiff', info.format);
|
assert.strictEqual('tiff', info.format);
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
@ -143,13 +144,13 @@ describe('Colour space conversion', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('From sRGB with RGB16 pipeline, resize with gamma, to sRGB', function (done) {
|
it('From sRGB with RGB16 pipeline, resize with gamma, to sRGB', (_t, done) => {
|
||||||
sharp(fixtures.inputPngGradients)
|
sharp(fixtures.inputPngGradients)
|
||||||
.pipelineColourspace('rgb16')
|
.pipelineColourspace('rgb16')
|
||||||
.resize(320)
|
.resize(320)
|
||||||
.gamma()
|
.gamma()
|
||||||
.toColourspace('srgb')
|
.toColourspace('srgb')
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
fixtures.assertSimilar(fixtures.expected('colourspace-gradients-gamma-resize.png'), data, {
|
fixtures.assertSimilar(fixtures.expected('colourspace-gradients-gamma-resize.png'), data, {
|
||||||
@ -177,15 +178,15 @@ describe('Colour space conversion', function () {
|
|||||||
assert.strictEqual(b, 34);
|
assert.strictEqual(b, 34);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Invalid pipelineColourspace input', function () {
|
it('Invalid pipelineColourspace input', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.pipelineColorspace(null);
|
.pipelineColorspace(null);
|
||||||
}, /Expected string for colourspace but received null of type object/);
|
}, /Expected string for colourspace but received null of type object/);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Invalid toColourspace input', function () {
|
it('Invalid toColourspace input', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.toColourspace(null);
|
.toColourspace(null);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
const { describe, it } = require('node:test');
|
||||||
|
const assert = require('node:assert');
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
@ -322,7 +323,7 @@ describe('composite', () => {
|
|||||||
describe('string gravity', () => {
|
describe('string gravity', () => {
|
||||||
Object.keys(sharp.gravity).forEach(gravity => {
|
Object.keys(sharp.gravity).forEach(gravity => {
|
||||||
it(gravity, done => {
|
it(gravity, done => {
|
||||||
const expected = fixtures.expected('overlay-gravity-' + gravity + '.jpg');
|
const expected = fixtures.expected(`overlay-gravity-${gravity}.jpg`);
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(80)
|
.resize(80)
|
||||||
.composite([{
|
.composite([{
|
||||||
@ -344,7 +345,7 @@ describe('composite', () => {
|
|||||||
describe('tile and gravity', () => {
|
describe('tile and gravity', () => {
|
||||||
Object.keys(sharp.gravity).forEach(gravity => {
|
Object.keys(sharp.gravity).forEach(gravity => {
|
||||||
it(gravity, done => {
|
it(gravity, done => {
|
||||||
const expected = fixtures.expected('overlay-tile-gravity-' + gravity + '.jpg');
|
const expected = fixtures.expected(`overlay-tile-gravity-${gravity}.jpg`);
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(80)
|
.resize(80)
|
||||||
.composite([{
|
.composite([{
|
||||||
|
|||||||
@ -1,15 +1,16 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
const { describe, it } = require('node:test');
|
||||||
|
const assert = require('node:assert');
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
|
|
||||||
describe('Convolve', function () {
|
describe('Convolve', () => {
|
||||||
it('specific convolution kernel 1', function (done) {
|
it('specific convolution kernel 1', (_t, done) => {
|
||||||
sharp(fixtures.inputPngStripesV)
|
sharp(fixtures.inputPngStripesV)
|
||||||
.convolve({
|
.convolve({
|
||||||
width: 3,
|
width: 3,
|
||||||
@ -22,7 +23,7 @@ describe('Convolve', function () {
|
|||||||
10, 20, 10
|
10, 20, 10
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('png', info.format);
|
assert.strictEqual('png', info.format);
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
@ -31,7 +32,7 @@ describe('Convolve', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('specific convolution kernel 2', function (done) {
|
it('specific convolution kernel 2', (_t, done) => {
|
||||||
sharp(fixtures.inputPngStripesH)
|
sharp(fixtures.inputPngStripesH)
|
||||||
.convolve({
|
.convolve({
|
||||||
width: 3,
|
width: 3,
|
||||||
@ -42,7 +43,7 @@ describe('Convolve', function () {
|
|||||||
1, 0, 1
|
1, 0, 1
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('png', info.format);
|
assert.strictEqual('png', info.format);
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
@ -51,7 +52,7 @@ describe('Convolve', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('horizontal Sobel operator', function (done) {
|
it('horizontal Sobel operator', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
.convolve({
|
.convolve({
|
||||||
@ -63,7 +64,7 @@ describe('Convolve', function () {
|
|||||||
-1, 0, 1
|
-1, 0, 1
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
@ -72,14 +73,14 @@ describe('Convolve', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('invalid kernel specification', function () {
|
describe('invalid kernel specification', () => {
|
||||||
it('missing', function () {
|
it('missing', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg).convolve({});
|
sharp(fixtures.inputJpg).convolve({});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('incorrect data format', function () {
|
it('incorrect data format', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg).convolve({
|
sharp(fixtures.inputJpg).convolve({
|
||||||
width: 3,
|
width: 3,
|
||||||
height: 3,
|
height: 3,
|
||||||
@ -87,8 +88,8 @@ describe('Convolve', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('incorrect dimensions', function () {
|
it('incorrect dimensions', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg).convolve({
|
sharp(fixtures.inputJpg).convolve({
|
||||||
width: 3,
|
width: 3,
|
||||||
height: 4,
|
height: 4,
|
||||||
|
|||||||
@ -1,15 +1,14 @@
|
|||||||
'use strict';
|
const { describe, it } = require('node:test');
|
||||||
|
const assert = require('node:assert');
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
|
|
||||||
describe('Dilate', function () {
|
describe('Dilate', () => {
|
||||||
it('dilate 1 png', function (done) {
|
it('dilate 1 png', (_t, done) => {
|
||||||
sharp(fixtures.inputPngDotAndLines)
|
sharp(fixtures.inputPngDotAndLines)
|
||||||
.dilate(1)
|
.dilate(1)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('png', info.format);
|
assert.strictEqual('png', info.format);
|
||||||
assert.strictEqual(100, info.width);
|
assert.strictEqual(100, info.width);
|
||||||
@ -18,10 +17,10 @@ describe('Dilate', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('dilate 1 png - default width', function (done) {
|
it('dilate 1 png - default width', (_t, done) => {
|
||||||
sharp(fixtures.inputPngDotAndLines)
|
sharp(fixtures.inputPngDotAndLines)
|
||||||
.dilate()
|
.dilate()
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('png', info.format);
|
assert.strictEqual('png', info.format);
|
||||||
assert.strictEqual(100, info.width);
|
assert.strictEqual(100, info.width);
|
||||||
@ -30,8 +29,8 @@ describe('Dilate', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invalid dilation width', function () {
|
it('invalid dilation width', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg).dilate(-1);
|
sharp(fixtures.inputJpg).dilate(-1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,15 +1,14 @@
|
|||||||
'use strict';
|
const { describe, it } = require('node:test');
|
||||||
|
const assert = require('node:assert');
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
|
|
||||||
describe('Erode', function () {
|
describe('Erode', () => {
|
||||||
it('erode 1 png', function (done) {
|
it('erode 1 png', (_t, done) => {
|
||||||
sharp(fixtures.inputPngDotAndLines)
|
sharp(fixtures.inputPngDotAndLines)
|
||||||
.erode(1)
|
.erode(1)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('png', info.format);
|
assert.strictEqual('png', info.format);
|
||||||
assert.strictEqual(100, info.width);
|
assert.strictEqual(100, info.width);
|
||||||
@ -18,10 +17,10 @@ describe('Erode', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('erode 1 png - default width', function (done) {
|
it('erode 1 png - default width', (_t, done) => {
|
||||||
sharp(fixtures.inputPngDotAndLines)
|
sharp(fixtures.inputPngDotAndLines)
|
||||||
.erode()
|
.erode()
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('png', info.format);
|
assert.strictEqual('png', info.format);
|
||||||
assert.strictEqual(100, info.width);
|
assert.strictEqual(100, info.width);
|
||||||
@ -30,8 +29,8 @@ describe('Erode', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invalid erosion width', function () {
|
it('invalid erosion width', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg).erode(-1);
|
sharp(fixtures.inputJpg).erode(-1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,20 +1,21 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
const { describe, it } = require('node:test');
|
||||||
|
const assert = require('node:assert');
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
|
|
||||||
describe('Extend', function () {
|
describe('Extend', () => {
|
||||||
describe('extend all sides equally via a single value', function () {
|
describe('extend all sides equally via a single value', () => {
|
||||||
it('JPEG', function (done) {
|
it('JPEG', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(120)
|
.resize(120)
|
||||||
.extend(10)
|
.extend(10)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(140, info.width);
|
assert.strictEqual(140, info.width);
|
||||||
assert.strictEqual(118, info.height);
|
assert.strictEqual(118, info.height);
|
||||||
@ -22,11 +23,11 @@ describe('Extend', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Animated WebP', function (done) {
|
it('Animated WebP', (_t, done) => {
|
||||||
sharp(fixtures.inputWebPAnimated, { pages: -1 })
|
sharp(fixtures.inputWebPAnimated, { pages: -1 })
|
||||||
.resize(120)
|
.resize(120)
|
||||||
.extend(10)
|
.extend(10)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(140, info.width);
|
assert.strictEqual(140, info.width);
|
||||||
assert.strictEqual(140 * 9, info.height);
|
assert.strictEqual(140 * 9, info.height);
|
||||||
@ -36,7 +37,7 @@ describe('Extend', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
['background', 'copy', 'mirror', 'repeat'].forEach(extendWith => {
|
['background', 'copy', 'mirror', 'repeat'].forEach(extendWith => {
|
||||||
it(`extends all sides with animated WebP (${extendWith})`, function (done) {
|
it(`extends all sides with animated WebP (${extendWith})`, (_t, done) => {
|
||||||
sharp(fixtures.inputWebPAnimated, { pages: -1 })
|
sharp(fixtures.inputWebPAnimated, { pages: -1 })
|
||||||
.resize(120)
|
.resize(120)
|
||||||
.extend({
|
.extend({
|
||||||
@ -46,7 +47,7 @@ describe('Extend', function () {
|
|||||||
left: 40,
|
left: 40,
|
||||||
right: 40
|
right: 40
|
||||||
})
|
})
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(200, info.width);
|
assert.strictEqual(200, info.width);
|
||||||
assert.strictEqual(200 * 9, info.height);
|
assert.strictEqual(200 * 9, info.height);
|
||||||
@ -54,7 +55,7 @@ describe('Extend', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`extend all sides equally with RGB (${extendWith})`, function (done) {
|
it(`extend all sides equally with RGB (${extendWith})`, (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(120)
|
.resize(120)
|
||||||
.extend({
|
.extend({
|
||||||
@ -65,7 +66,7 @@ describe('Extend', function () {
|
|||||||
right: 10,
|
right: 10,
|
||||||
background: { r: 255, g: 0, b: 0 }
|
background: { r: 255, g: 0, b: 0 }
|
||||||
})
|
})
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(140, info.width);
|
assert.strictEqual(140, info.width);
|
||||||
assert.strictEqual(118, info.height);
|
assert.strictEqual(118, info.height);
|
||||||
@ -73,7 +74,7 @@ describe('Extend', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`extend sides unequally with RGBA (${extendWith})`, function (done) {
|
it(`extend sides unequally with RGBA (${extendWith})`, (_t, done) => {
|
||||||
sharp(fixtures.inputPngWithTransparency16bit)
|
sharp(fixtures.inputPngWithTransparency16bit)
|
||||||
.resize(120)
|
.resize(120)
|
||||||
.extend({
|
.extend({
|
||||||
@ -83,7 +84,7 @@ describe('Extend', function () {
|
|||||||
right: 35,
|
right: 35,
|
||||||
background: { r: 0, g: 0, b: 0, alpha: 0 }
|
background: { r: 0, g: 0, b: 0, alpha: 0 }
|
||||||
})
|
})
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(165, info.width);
|
assert.strictEqual(165, info.width);
|
||||||
assert.strictEqual(170, info.height);
|
assert.strictEqual(170, info.height);
|
||||||
@ -91,7 +92,7 @@ describe('Extend', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`PNG with 2 channels (${extendWith})`, function (done) {
|
it(`PNG with 2 channels (${extendWith})`, (_t, done) => {
|
||||||
sharp(fixtures.inputPngWithGreyAlpha)
|
sharp(fixtures.inputPngWithGreyAlpha)
|
||||||
.extend({
|
.extend({
|
||||||
extendWith,
|
extendWith,
|
||||||
@ -101,7 +102,7 @@ describe('Extend', function () {
|
|||||||
right: 80,
|
right: 80,
|
||||||
background: 'transparent'
|
background: 'transparent'
|
||||||
})
|
})
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(true, data.length > 0);
|
assert.strictEqual(true, data.length > 0);
|
||||||
assert.strictEqual('png', info.format);
|
assert.strictEqual('png', info.format);
|
||||||
@ -146,13 +147,13 @@ describe('Extend', function () {
|
|||||||
assert.strictEqual(1470, height);
|
assert.strictEqual(1470, height);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('missing parameter fails', function () {
|
it('missing parameter fails', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp().extend();
|
sharp().extend();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('negative fails', function () {
|
it('negative fails', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp().extend(-1);
|
sharp().extend(-1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -190,7 +191,7 @@ describe('Extend', function () {
|
|||||||
assert.doesNotThrow(() => sharp().extend({ top: 1, left: 2, bottom: 3 }));
|
assert.doesNotThrow(() => sharp().extend({ top: 1, left: 2, bottom: 3 }));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add alpha channel before extending with a transparent Background', function (done) {
|
it('should add alpha channel before extending with a transparent Background', (_t, done) => {
|
||||||
sharp(fixtures.inputJpgWithLandscapeExif1)
|
sharp(fixtures.inputJpgWithLandscapeExif1)
|
||||||
.extend({
|
.extend({
|
||||||
bottom: 10,
|
bottom: 10,
|
||||||
@ -198,7 +199,7 @@ describe('Extend', function () {
|
|||||||
background: { r: 0, g: 0, b: 0, alpha: 0 }
|
background: { r: 0, g: 0, b: 0, alpha: 0 }
|
||||||
})
|
})
|
||||||
.toFormat(sharp.format.png)
|
.toFormat(sharp.format.png)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(610, info.width);
|
assert.strictEqual(610, info.width);
|
||||||
assert.strictEqual(460, info.height);
|
assert.strictEqual(460, info.height);
|
||||||
|
|||||||
@ -1,18 +1,19 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
const { describe, it } = require('node:test');
|
||||||
|
const assert = require('node:assert');
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
|
|
||||||
describe('Partial image extraction', function () {
|
describe('Partial image extraction', () => {
|
||||||
it('JPEG', function (done) {
|
it('JPEG', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.extract({ left: 2, top: 2, width: 20, height: 20 })
|
.extract({ left: 2, top: 2, width: 20, height: 20 })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(20, info.width);
|
assert.strictEqual(20, info.width);
|
||||||
assert.strictEqual(20, info.height);
|
assert.strictEqual(20, info.height);
|
||||||
@ -20,10 +21,10 @@ describe('Partial image extraction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('PNG', function (done) {
|
it('PNG', (_t, done) => {
|
||||||
sharp(fixtures.inputPng)
|
sharp(fixtures.inputPng)
|
||||||
.extract({ left: 200, top: 300, width: 400, height: 200 })
|
.extract({ left: 200, top: 300, width: 400, height: 200 })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(400, info.width);
|
assert.strictEqual(400, info.width);
|
||||||
assert.strictEqual(200, info.height);
|
assert.strictEqual(200, info.height);
|
||||||
@ -31,10 +32,10 @@ describe('Partial image extraction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('WebP', function (done) {
|
it('WebP', (_t, done) => {
|
||||||
sharp(fixtures.inputWebP)
|
sharp(fixtures.inputWebP)
|
||||||
.extract({ left: 100, top: 50, width: 125, height: 200 })
|
.extract({ left: 100, top: 50, width: 125, height: 200 })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(125, info.width);
|
assert.strictEqual(125, info.width);
|
||||||
assert.strictEqual(200, info.height);
|
assert.strictEqual(200, info.height);
|
||||||
@ -42,12 +43,12 @@ describe('Partial image extraction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Animated WebP', function () {
|
describe('Animated WebP', () => {
|
||||||
it('Before resize', function (done) {
|
it('Before resize', (_t, done) => {
|
||||||
sharp(fixtures.inputWebPAnimated, { pages: -1 })
|
sharp(fixtures.inputWebPAnimated, { pages: -1 })
|
||||||
.extract({ left: 0, top: 30, width: 80, height: 20 })
|
.extract({ left: 0, top: 30, width: 80, height: 20 })
|
||||||
.resize(320, 80)
|
.resize(320, 80)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
assert.strictEqual(80 * 9, info.height);
|
assert.strictEqual(80 * 9, info.height);
|
||||||
@ -55,11 +56,11 @@ describe('Partial image extraction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('After resize', function (done) {
|
it('After resize', (_t, done) => {
|
||||||
sharp(fixtures.inputWebPAnimated, { pages: -1 })
|
sharp(fixtures.inputWebPAnimated, { pages: -1 })
|
||||||
.resize(320, 320)
|
.resize(320, 320)
|
||||||
.extract({ left: 0, top: 120, width: 320, height: 80 })
|
.extract({ left: 0, top: 120, width: 320, height: 80 })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
assert.strictEqual(80 * 9, info.height);
|
assert.strictEqual(80 * 9, info.height);
|
||||||
@ -68,10 +69,10 @@ describe('Partial image extraction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('TIFF', function (done) {
|
it('TIFF', (_t, done) => {
|
||||||
sharp(fixtures.inputTiff)
|
sharp(fixtures.inputTiff)
|
||||||
.extract({ left: 34, top: 63, width: 341, height: 529 })
|
.extract({ left: 34, top: 63, width: 341, height: 529 })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(341, info.width);
|
assert.strictEqual(341, info.width);
|
||||||
assert.strictEqual(529, info.height);
|
assert.strictEqual(529, info.height);
|
||||||
@ -79,11 +80,11 @@ describe('Partial image extraction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Before resize', function (done) {
|
it('Before resize', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.extract({ left: 10, top: 10, width: 10, height: 500 })
|
.extract({ left: 10, top: 10, width: 10, height: 500 })
|
||||||
.resize(100, 100)
|
.resize(100, 100)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(100, info.width);
|
assert.strictEqual(100, info.width);
|
||||||
assert.strictEqual(100, info.height);
|
assert.strictEqual(100, info.height);
|
||||||
@ -91,13 +92,13 @@ describe('Partial image extraction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('After resize and crop', function (done) {
|
it('After resize and crop', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(500, 500, {
|
.resize(500, 500, {
|
||||||
position: sharp.gravity.north
|
position: sharp.gravity.north
|
||||||
})
|
})
|
||||||
.extract({ left: 10, top: 10, width: 100, height: 100 })
|
.extract({ left: 10, top: 10, width: 100, height: 100 })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(100, info.width);
|
assert.strictEqual(100, info.width);
|
||||||
assert.strictEqual(100, info.height);
|
assert.strictEqual(100, info.height);
|
||||||
@ -105,14 +106,14 @@ describe('Partial image extraction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Before and after resize and crop', function (done) {
|
it('Before and after resize and crop', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.extract({ left: 0, top: 0, width: 700, height: 700 })
|
.extract({ left: 0, top: 0, width: 700, height: 700 })
|
||||||
.resize(500, 500, {
|
.resize(500, 500, {
|
||||||
position: sharp.gravity.north
|
position: sharp.gravity.north
|
||||||
})
|
})
|
||||||
.extract({ left: 10, top: 10, width: 100, height: 100 })
|
.extract({ left: 10, top: 10, width: 100, height: 100 })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(100, info.width);
|
assert.strictEqual(100, info.width);
|
||||||
assert.strictEqual(100, info.height);
|
assert.strictEqual(100, info.height);
|
||||||
@ -120,12 +121,12 @@ describe('Partial image extraction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Extract then rotate', function (done) {
|
it('Extract then rotate', (_t, done) => {
|
||||||
sharp(fixtures.inputPngWithGreyAlpha)
|
sharp(fixtures.inputPngWithGreyAlpha)
|
||||||
.extract({ left: 20, top: 10, width: 380, height: 280 })
|
.extract({ left: 20, top: 10, width: 380, height: 280 })
|
||||||
.rotate(90)
|
.rotate(90)
|
||||||
.jpeg()
|
.jpeg()
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(280, info.width);
|
assert.strictEqual(280, info.width);
|
||||||
assert.strictEqual(380, info.height);
|
assert.strictEqual(380, info.height);
|
||||||
@ -133,11 +134,11 @@ describe('Partial image extraction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Rotate then extract', function (done) {
|
it('Rotate then extract', (_t, done) => {
|
||||||
sharp(fixtures.inputPngWithGreyAlpha)
|
sharp(fixtures.inputPngWithGreyAlpha)
|
||||||
.rotate(90)
|
.rotate(90)
|
||||||
.extract({ left: 20, top: 10, width: 280, height: 380 })
|
.extract({ left: 20, top: 10, width: 280, height: 380 })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(280, info.width);
|
assert.strictEqual(280, info.width);
|
||||||
assert.strictEqual(380, info.height);
|
assert.strictEqual(380, info.height);
|
||||||
@ -145,12 +146,12 @@ describe('Partial image extraction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Extract then rotate then extract', function (done) {
|
it('Extract then rotate then extract', (_t, done) => {
|
||||||
sharp(fixtures.inputPngWithGreyAlpha)
|
sharp(fixtures.inputPngWithGreyAlpha)
|
||||||
.extract({ left: 20, top: 10, width: 180, height: 280 })
|
.extract({ left: 20, top: 10, width: 180, height: 280 })
|
||||||
.rotate(90)
|
.rotate(90)
|
||||||
.extract({ left: 20, top: 10, width: 200, height: 100 })
|
.extract({ left: 20, top: 10, width: 200, height: 100 })
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(200, info.width);
|
assert.strictEqual(200, info.width);
|
||||||
assert.strictEqual(100, info.height);
|
assert.strictEqual(100, info.height);
|
||||||
@ -158,12 +159,12 @@ describe('Partial image extraction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Extract then rotate non-90 anagle', function (done) {
|
it('Extract then rotate non-90 anagle', (_t, done) => {
|
||||||
sharp(fixtures.inputPngWithGreyAlpha)
|
sharp(fixtures.inputPngWithGreyAlpha)
|
||||||
.extract({ left: 20, top: 10, width: 380, height: 280 })
|
.extract({ left: 20, top: 10, width: 380, height: 280 })
|
||||||
.rotate(45)
|
.rotate(45)
|
||||||
.jpeg()
|
.jpeg()
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(467, info.width);
|
assert.strictEqual(467, info.width);
|
||||||
assert.strictEqual(467, info.height);
|
assert.strictEqual(467, info.height);
|
||||||
@ -171,12 +172,12 @@ describe('Partial image extraction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Rotate then extract non-90 angle', function (done) {
|
it('Rotate then extract non-90 angle', (_t, done) => {
|
||||||
sharp(fixtures.inputPngWithGreyAlpha)
|
sharp(fixtures.inputPngWithGreyAlpha)
|
||||||
.rotate(45)
|
.rotate(45)
|
||||||
.extract({ left: 20, top: 10, width: 380, height: 280 })
|
.extract({ left: 20, top: 10, width: 380, height: 280 })
|
||||||
.jpeg()
|
.jpeg()
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(380, info.width);
|
assert.strictEqual(380, info.width);
|
||||||
assert.strictEqual(280, info.height);
|
assert.strictEqual(280, info.height);
|
||||||
@ -219,11 +220,11 @@ describe('Partial image extraction', function () {
|
|||||||
image: fixtures.inputJpgWithLandscapeExif8
|
image: fixtures.inputJpgWithLandscapeExif8
|
||||||
}
|
}
|
||||||
].forEach(({ name, image }) => {
|
].forEach(({ name, image }) => {
|
||||||
it(name, function (done) {
|
it(name, (_t, done) => {
|
||||||
sharp(image)
|
sharp(image)
|
||||||
.rotate()
|
.rotate()
|
||||||
.extract({ left: 0, top: 208, width: 60, height: 40 })
|
.extract({ left: 0, top: 208, width: 60, height: 40 })
|
||||||
.toBuffer(function (err, data) {
|
.toBuffer((err, data) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
fixtures.assertSimilar(fixtures.expected('rotate-mirror-extract.jpg'), data, done);
|
fixtures.assertSimilar(fixtures.expected('rotate-mirror-extract.jpg'), data, done);
|
||||||
});
|
});
|
||||||
@ -231,67 +232,67 @@ describe('Partial image extraction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Invalid parameters', function () {
|
describe('Invalid parameters', () => {
|
||||||
describe('using the legacy extract(top,left,width,height) syntax', function () {
|
describe('using the legacy extract(top,left,width,height) syntax', () => {
|
||||||
it('String top', function () {
|
it('String top', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg).extract('spoons', 10, 10, 10);
|
sharp(fixtures.inputJpg).extract('spoons', 10, 10, 10);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Non-integral left', function () {
|
it('Non-integral left', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg).extract(10, 10.2, 10, 10);
|
sharp(fixtures.inputJpg).extract(10, 10.2, 10, 10);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Negative width - negative', function () {
|
it('Negative width - negative', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg).extract(10, 10, -10, 10);
|
sharp(fixtures.inputJpg).extract(10, 10, -10, 10);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Null height', function () {
|
it('Null height', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg).extract(10, 10, 10, null);
|
sharp(fixtures.inputJpg).extract(10, 10, 10, null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Undefined', function () {
|
it('Undefined', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg).extract();
|
sharp(fixtures.inputJpg).extract();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('String top', function () {
|
it('String top', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg).extract({ left: 10, top: 'spoons', width: 10, height: 10 });
|
sharp(fixtures.inputJpg).extract({ left: 10, top: 'spoons', width: 10, height: 10 });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Non-integral left', function () {
|
it('Non-integral left', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg).extract({ left: 10.2, top: 10, width: 10, height: 10 });
|
sharp(fixtures.inputJpg).extract({ left: 10.2, top: 10, width: 10, height: 10 });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Negative width - negative', function () {
|
it('Negative width - negative', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg).extract({ left: 10, top: 10, width: -10, height: 10 });
|
sharp(fixtures.inputJpg).extract({ left: 10, top: 10, width: -10, height: 10 });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Null height', function () {
|
it('Null height', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg).extract({ left: 10, top: 10, width: 10, height: null });
|
sharp(fixtures.inputJpg).extract({ left: 10, top: 10, width: 10, height: null });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Bad image area', function (done) {
|
it('Bad image area', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.extract({ left: 3000, top: 10, width: 10, height: 10 })
|
.extract({ left: 3000, top: 10, width: 10, height: 10 })
|
||||||
.toBuffer(function (err) {
|
.toBuffer((err) => {
|
||||||
assert(err instanceof Error);
|
assert(err instanceof Error);
|
||||||
assert.strictEqual(err.message, 'extract_area: bad extract area');
|
assert.strictEqual(err.message, 'extract_area: bad extract area');
|
||||||
done();
|
done();
|
||||||
@ -301,7 +302,7 @@ describe('Partial image extraction', function () {
|
|||||||
it('Multiple extract emits warning', () => {
|
it('Multiple extract emits warning', () => {
|
||||||
let warningMessage = '';
|
let warningMessage = '';
|
||||||
const s = sharp();
|
const s = sharp();
|
||||||
s.on('warning', function (msg) { warningMessage = msg; });
|
s.on('warning', (msg) => { warningMessage = msg; });
|
||||||
const options = { top: 0, left: 0, width: 1, height: 1 };
|
const options = { top: 0, left: 0, width: 1, height: 1 };
|
||||||
s.extract(options).extract(options);
|
s.extract(options).extract(options);
|
||||||
assert.strictEqual(warningMessage, '');
|
assert.strictEqual(warningMessage, '');
|
||||||
@ -312,7 +313,7 @@ describe('Partial image extraction', function () {
|
|||||||
it('Multiple rotate+extract emits warning', () => {
|
it('Multiple rotate+extract emits warning', () => {
|
||||||
let warningMessage = '';
|
let warningMessage = '';
|
||||||
const s = sharp().rotate();
|
const s = sharp().rotate();
|
||||||
s.on('warning', function (msg) { warningMessage = msg; });
|
s.on('warning', (msg) => { warningMessage = msg; });
|
||||||
const options = { top: 0, left: 0, width: 1, height: 1 };
|
const options = { top: 0, left: 0, width: 1, height: 1 };
|
||||||
s.extract(options).extract(options);
|
s.extract(options).extract(options);
|
||||||
assert.strictEqual(warningMessage, '');
|
assert.strictEqual(warningMessage, '');
|
||||||
@ -323,7 +324,7 @@ describe('Partial image extraction', function () {
|
|||||||
it('Multiple extract+resize emits warning', () => {
|
it('Multiple extract+resize emits warning', () => {
|
||||||
let warningMessage = '';
|
let warningMessage = '';
|
||||||
const s = sharp();
|
const s = sharp();
|
||||||
s.on('warning', function (msg) { warningMessage = msg; });
|
s.on('warning', (msg) => { warningMessage = msg; });
|
||||||
const options = { top: 0, left: 0, width: 1, height: 1 };
|
const options = { top: 0, left: 0, width: 1, height: 1 };
|
||||||
s.extract(options).extract(options);
|
s.extract(options).extract(options);
|
||||||
assert.strictEqual(warningMessage, '');
|
assert.strictEqual(warningMessage, '');
|
||||||
|
|||||||
@ -1,19 +1,20 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
const { describe, it } = require('node:test');
|
||||||
|
const assert = require('node:assert');
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
|
|
||||||
describe('Image channel extraction', function () {
|
describe('Image channel extraction', () => {
|
||||||
it('Red channel', function (done) {
|
it('Red channel', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.extractChannel('red')
|
.extractChannel('red')
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
assert.strictEqual(240, info.height);
|
assert.strictEqual(240, info.height);
|
||||||
@ -21,11 +22,11 @@ describe('Image channel extraction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Green channel', function (done) {
|
it('Green channel', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.extractChannel('green')
|
.extractChannel('green')
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
assert.strictEqual(240, info.height);
|
assert.strictEqual(240, info.height);
|
||||||
@ -33,11 +34,11 @@ describe('Image channel extraction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Blue channel', function (done) {
|
it('Blue channel', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.extractChannel('blue')
|
.extractChannel('blue')
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
assert.strictEqual(240, info.height);
|
assert.strictEqual(240, info.height);
|
||||||
@ -45,11 +46,11 @@ describe('Image channel extraction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Blue channel by number', function (done) {
|
it('Blue channel by number', (_t, done) => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.extractChannel(2)
|
.extractChannel(2)
|
||||||
.resize(320, 240)
|
.resize(320, 240)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
assert.strictEqual(240, info.height);
|
assert.strictEqual(240, info.height);
|
||||||
@ -66,23 +67,23 @@ describe('Image channel extraction', function () {
|
|||||||
assert.strictEqual(chroma, 104);
|
assert.strictEqual(chroma, 104);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Alpha from 16-bit PNG', function (done) {
|
it('Alpha from 16-bit PNG', (_t, done) => {
|
||||||
const output = fixtures.path('output.extract-alpha-16bit.png');
|
const output = fixtures.path('output.extract-alpha-16bit.png');
|
||||||
sharp(fixtures.inputPngWithTransparency16bit)
|
sharp(fixtures.inputPngWithTransparency16bit)
|
||||||
.resize(16)
|
.resize(16)
|
||||||
.extractChannel(3)
|
.extractChannel(3)
|
||||||
.toFile(output, function (err) {
|
.toFile(output, (err) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
fixtures.assertMaxColourDistance(output, fixtures.expected('extract-alpha-16bit.png'));
|
fixtures.assertMaxColourDistance(output, fixtures.expected('extract-alpha-16bit.png'));
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Alpha from 2-channel input', function (done) {
|
it('Alpha from 2-channel input', (_t, done) => {
|
||||||
const output = fixtures.path('output.extract-alpha-2-channel.png');
|
const output = fixtures.path('output.extract-alpha-2-channel.png');
|
||||||
sharp(fixtures.inputPngWithGreyAlpha)
|
sharp(fixtures.inputPngWithGreyAlpha)
|
||||||
.extractChannel('alpha')
|
.extractChannel('alpha')
|
||||||
.toFile(output, function (err, info) {
|
.toFile(output, (err, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(1, info.channels);
|
assert.strictEqual(1, info.channels);
|
||||||
fixtures.assertMaxColourDistance(output, fixtures.expected('extract-alpha-2-channel.png'));
|
fixtures.assertMaxColourDistance(output, fixtures.expected('extract-alpha-2-channel.png'));
|
||||||
@ -90,15 +91,15 @@ describe('Image channel extraction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Invalid channel number', function () {
|
it('Invalid channel number', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.extractChannel(-1);
|
.extractChannel(-1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('No arguments', function () {
|
it('No arguments', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.extractChannel();
|
.extractChannel();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,19 +1,20 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
const { describe, it } = require('node:test');
|
||||||
|
const assert = require('node:assert');
|
||||||
const assert = require('assert');
|
const fs = require('node:fs');
|
||||||
const fs = require('fs');
|
|
||||||
|
|
||||||
const sharp = require('../../lib');
|
const sharp = require('../../lib');
|
||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
|
|
||||||
describe('failOn', () => {
|
describe('failOn', () => {
|
||||||
it('handles truncated JPEG', function (done) {
|
it('handles truncated JPEG', (_t, done) => {
|
||||||
sharp(fixtures.inputJpgTruncated, { failOn: 'none' })
|
sharp(fixtures.inputJpgTruncated, { failOn: 'none' })
|
||||||
.resize(32, 24)
|
.resize(32, 24)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
assert.strictEqual(32, info.width);
|
assert.strictEqual(32, info.width);
|
||||||
@ -22,17 +23,17 @@ describe('failOn', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles truncated PNG, emits warnings', function (done) {
|
it('handles truncated PNG, emits warnings', (_t, done) => {
|
||||||
let isWarningEmitted = false;
|
let isWarningEmitted = false;
|
||||||
sharp(fixtures.inputPngTruncated, { failOn: 'none' })
|
sharp(fixtures.inputPngTruncated, { failOn: 'none' })
|
||||||
.on('warning', function (warning) {
|
.on('warning', (warning) => {
|
||||||
assert.ok(
|
assert.ok(
|
||||||
['read gave 2 warnings', 'not enough data', 'end of stream']
|
['read gave 2 warnings', 'not enough data', 'end of stream']
|
||||||
.some(m => warning.includes(m)));
|
.some(m => warning.includes(m)));
|
||||||
isWarningEmitted = true;
|
isWarningEmitted = true;
|
||||||
})
|
})
|
||||||
.resize(32, 24)
|
.resize(32, 24)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, _data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(true, isWarningEmitted);
|
assert.strictEqual(true, isWarningEmitted);
|
||||||
assert.strictEqual('png', info.format);
|
assert.strictEqual('png', info.format);
|
||||||
@ -70,8 +71,8 @@ describe('failOn', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns errors to callback for truncated JPEG', function (done) {
|
it('returns errors to callback for truncated JPEG', (_t, done) => {
|
||||||
sharp(fixtures.inputJpgTruncated, { failOn: 'truncated' }).toBuffer(function (err, data, info) {
|
sharp(fixtures.inputJpgTruncated, { failOn: 'truncated' }).toBuffer((err, data, info) => {
|
||||||
assert.ok(err.message.includes('VipsJpeg: premature end of'), err);
|
assert.ok(err.message.includes('VipsJpeg: premature end of'), err);
|
||||||
assert.strictEqual(data, undefined);
|
assert.strictEqual(data, undefined);
|
||||||
assert.strictEqual(info, undefined);
|
assert.strictEqual(info, undefined);
|
||||||
@ -79,8 +80,8 @@ describe('failOn', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns errors to callback for truncated PNG', function (done) {
|
it('returns errors to callback for truncated PNG', (_t, done) => {
|
||||||
sharp(fixtures.inputPngTruncated, { failOn: 'truncated' }).toBuffer(function (err, data, info) {
|
sharp(fixtures.inputPngTruncated, { failOn: 'truncated' }).toBuffer((err, data, info) => {
|
||||||
assert.ok(err.message.includes('read error'), err);
|
assert.ok(err.message.includes('read error'), err);
|
||||||
assert.strictEqual(data, undefined);
|
assert.strictEqual(data, undefined);
|
||||||
assert.strictEqual(info, undefined);
|
assert.strictEqual(info, undefined);
|
||||||
@ -88,7 +89,7 @@ describe('failOn', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('rejects promises for truncated JPEG', function (done) {
|
it('rejects promises for truncated JPEG', (_t, done) => {
|
||||||
sharp(fixtures.inputJpgTruncated, { failOn: 'error' })
|
sharp(fixtures.inputJpgTruncated, { failOn: 'error' })
|
||||||
.toBuffer()
|
.toBuffer()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@ -104,4 +105,11 @@ describe('failOn', () => {
|
|||||||
fs.createReadStream(fixtures.inputJpgTruncated).pipe(writable);
|
fs.createReadStream(fixtures.inputJpgTruncated).pipe(writable);
|
||||||
return writable.toBuffer();
|
return writable.toBuffer();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('converts warnings to error for GeoTIFF', async () => {
|
||||||
|
await assert.rejects(
|
||||||
|
sharp(fixtures.inputTiffGeo).toBuffer(),
|
||||||
|
/Tag 34737/
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,28 +1,29 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
const { describe, it } = require('node:test');
|
||||||
|
const assert = require('node:assert');
|
||||||
const assert = require('assert');
|
|
||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
|
|
||||||
describe('Test fixtures', function () {
|
describe('Test fixtures', () => {
|
||||||
describe('assertMaxColourDistance', function () {
|
describe('assertMaxColourDistance', () => {
|
||||||
it('should throw an Error when images have a different number of channels', function () {
|
it('should throw an Error when images have a different number of channels', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
fixtures.assertMaxColourDistance(fixtures.inputPngOverlayLayer1, fixtures.inputJpg);
|
fixtures.assertMaxColourDistance(fixtures.inputPngOverlayLayer1, fixtures.inputJpg);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('should throw an Error when images have different dimensions', function () {
|
it('should throw an Error when images have different dimensions', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
fixtures.assertMaxColourDistance(fixtures.inputJpg, fixtures.inputJpgWithExif);
|
fixtures.assertMaxColourDistance(fixtures.inputJpg, fixtures.inputJpgWithExif);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('should accept a zero threshold when comparing an image to itself', function () {
|
it('should accept a zero threshold when comparing an image to itself', () => {
|
||||||
const image = fixtures.inputPngOverlayLayer0;
|
const image = fixtures.inputPngOverlayLayer0;
|
||||||
fixtures.assertMaxColourDistance(image, image, 0);
|
fixtures.assertMaxColourDistance(image, image, 0);
|
||||||
});
|
});
|
||||||
it('should accept a numeric threshold for two different images', function () {
|
it('should accept a numeric threshold for two different images', () => {
|
||||||
fixtures.assertMaxColourDistance(fixtures.inputPngOverlayLayer0, fixtures.inputPngOverlayLayer1, 100);
|
fixtures.assertMaxColourDistance(fixtures.inputPngOverlayLayer0, fixtures.inputPngOverlayLayer1, 100);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,18 +1,19 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
const { describe, it } = require('node:test');
|
||||||
|
const assert = require('node:assert');
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
|
|
||||||
describe('Gamma correction', function () {
|
describe('Gamma correction', () => {
|
||||||
it('value of 0.0 (disabled)', function (done) {
|
it('value of 0.0 (disabled)', (_t, done) => {
|
||||||
sharp(fixtures.inputJpgWithGammaHoliness)
|
sharp(fixtures.inputJpgWithGammaHoliness)
|
||||||
.resize(129, 111)
|
.resize(129, 111)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
assert.strictEqual(129, info.width);
|
assert.strictEqual(129, info.width);
|
||||||
@ -21,11 +22,11 @@ describe('Gamma correction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('value of 2.2 (default)', function (done) {
|
it('value of 2.2 (default)', (_t, done) => {
|
||||||
sharp(fixtures.inputJpgWithGammaHoliness)
|
sharp(fixtures.inputJpgWithGammaHoliness)
|
||||||
.resize(129, 111)
|
.resize(129, 111)
|
||||||
.gamma()
|
.gamma()
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
assert.strictEqual(129, info.width);
|
assert.strictEqual(129, info.width);
|
||||||
@ -34,11 +35,11 @@ describe('Gamma correction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('value of 3.0', function (done) {
|
it('value of 3.0', (_t, done) => {
|
||||||
sharp(fixtures.inputJpgWithGammaHoliness)
|
sharp(fixtures.inputJpgWithGammaHoliness)
|
||||||
.resize(129, 111)
|
.resize(129, 111)
|
||||||
.gamma(3)
|
.gamma(3)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
assert.strictEqual(129, info.width);
|
assert.strictEqual(129, info.width);
|
||||||
@ -47,11 +48,11 @@ describe('Gamma correction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('input value of 2.2, output value of 3.0', function (done) {
|
it('input value of 2.2, output value of 3.0', (_t, done) => {
|
||||||
sharp(fixtures.inputJpgWithGammaHoliness)
|
sharp(fixtures.inputJpgWithGammaHoliness)
|
||||||
.resize(129, 111)
|
.resize(129, 111)
|
||||||
.gamma(2.2, 3.0)
|
.gamma(2.2, 3.0)
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
assert.strictEqual(129, info.width);
|
assert.strictEqual(129, info.width);
|
||||||
@ -60,12 +61,12 @@ describe('Gamma correction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('alpha transparency', function (done) {
|
it('alpha transparency', (_t, done) => {
|
||||||
sharp(fixtures.inputPngOverlayLayer1)
|
sharp(fixtures.inputPngOverlayLayer1)
|
||||||
.resize(320)
|
.resize(320)
|
||||||
.gamma()
|
.gamma()
|
||||||
.jpeg()
|
.jpeg()
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual('jpeg', info.format);
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
@ -73,14 +74,14 @@ describe('Gamma correction', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invalid first parameter value', function () {
|
it('invalid first parameter value', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpgWithGammaHoliness).gamma(4);
|
sharp(fixtures.inputJpgWithGammaHoliness).gamma(4);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invalid second parameter value', function () {
|
it('invalid second parameter value', () => {
|
||||||
assert.throws(function () {
|
assert.throws(() => {
|
||||||
sharp(fixtures.inputJpgWithGammaHoliness).gamma(2.2, 4);
|
sharp(fixtures.inputJpgWithGammaHoliness).gamma(2.2, 4);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
// Copyright 2013 Lovell Fuller and others.
|
/*!
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
Copyright 2013 Lovell Fuller and others.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict';
|
const fs = require('node:fs');
|
||||||
|
const { describe, it } = require('node:test');
|
||||||
const fs = require('fs');
|
const assert = require('node:assert');
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
@ -198,11 +199,11 @@ describe('GIF input', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should work with streams when only animated is set', function (done) {
|
it('should work with streams when only animated is set', (_t, done) => {
|
||||||
fs.createReadStream(fixtures.inputGifAnimated)
|
fs.createReadStream(fixtures.inputGifAnimated)
|
||||||
.pipe(sharp({ animated: true }))
|
.pipe(sharp({ animated: true }))
|
||||||
.gif()
|
.gif()
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(true, data.length > 0);
|
assert.strictEqual(true, data.length > 0);
|
||||||
assert.strictEqual('gif', info.format);
|
assert.strictEqual('gif', info.format);
|
||||||
@ -210,11 +211,11 @@ describe('GIF input', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should work with streams when only pages is set', function (done) {
|
it('should work with streams when only pages is set', (_t, done) => {
|
||||||
fs.createReadStream(fixtures.inputGifAnimated)
|
fs.createReadStream(fixtures.inputGifAnimated)
|
||||||
.pipe(sharp({ pages: -1 }))
|
.pipe(sharp({ pages: -1 }))
|
||||||
.gif()
|
.gif()
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer((err, data, info) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(true, data.length > 0);
|
assert.strictEqual(true, data.length > 0);
|
||||||
assert.strictEqual('gif', info.format);
|
assert.strictEqual('gif', info.format);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user