mirror of
https://github.com/lovell/sharp.git
synced 2026-02-05 14:16:17 +01:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9fa516e849 | ||
|
|
12f472126d | ||
|
|
18be09f1d7 | ||
|
|
b3c3290f90 | ||
|
|
123f95c85a | ||
|
|
5b0fba4c01 | ||
|
|
37f7ccfff4 | ||
|
|
51811d06e2 | ||
|
|
181731f8f4 | ||
|
|
ae79d26ead | ||
|
|
eacb8337fa | ||
|
|
99bf279de8 | ||
|
|
1b0eb6ab53 | ||
|
|
891cf67d0b | ||
|
|
eaf8a86bf2 | ||
|
|
3400976d61 | ||
|
|
2d49f0e93e | ||
|
|
b0c69f1ee9 | ||
|
|
27d0c35a01 | ||
|
|
32a22b5420 | ||
|
|
d1004eed02 | ||
|
|
70e6bb0162 | ||
|
|
32aa3b4b20 | ||
|
|
df24b30755 | ||
|
|
4de74bea94 | ||
|
|
28b87db760 | ||
|
|
fbd4970b57 | ||
|
|
f5da147a58 | ||
|
|
eee0dd36d9 |
16
.github/workflows/ci-darwin-arm64v8.yml
vendored
16
.github/workflows/ci-darwin-arm64v8.yml
vendored
@@ -2,29 +2,33 @@ name: CI (MacStadium)
|
|||||||
on:
|
on:
|
||||||
- push
|
- push
|
||||||
- pull_request
|
- pull_request
|
||||||
|
permissions: {}
|
||||||
jobs:
|
jobs:
|
||||||
CI:
|
CI:
|
||||||
|
permissions:
|
||||||
|
contents: write # for npx prebuild to make release
|
||||||
|
name: Node.js ${{ matrix.nodejs_version }} ${{ matrix.nodejs_arch }} ${{ matrix.prebuild && '- prebuild' }}
|
||||||
runs-on: macos-m1
|
runs-on: macos-m1
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- nodejs_version: 14
|
- nodejs_version: 14
|
||||||
nodejs_architecture: x64
|
nodejs_arch: x64
|
||||||
- nodejs_version: 18
|
- nodejs_version: 18
|
||||||
nodejs_architecture: arm64
|
nodejs_arch: arm64
|
||||||
prebuild: true
|
prebuild: true
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: /usr/bin/arch -arch arm64e /bin/bash -l {0}
|
shell: /usr/bin/arch -arch arm64e /bin/bash -l {0}
|
||||||
steps:
|
steps:
|
||||||
- name: Dependencies
|
- name: Dependencies (Node.js)
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.nodejs_version }}
|
node-version: ${{ matrix.nodejs_version }}
|
||||||
architecture: ${{ matrix.nodejs_architecture }}
|
architecture: ${{ matrix.nodejs_arch }}
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
- name: Install
|
- name: Install
|
||||||
run: npm install --build-from-source --unsafe-perm
|
run: npm install --build-from-source --unsafe-perm
|
||||||
- name: Test
|
- name: Test
|
||||||
|
|||||||
31
.github/workflows/ci.yml
vendored
31
.github/workflows/ci.yml
vendored
@@ -2,31 +2,34 @@ name: CI (GitHub)
|
|||||||
on:
|
on:
|
||||||
- push
|
- push
|
||||||
- pull_request
|
- pull_request
|
||||||
|
permissions: {}
|
||||||
jobs:
|
jobs:
|
||||||
CI:
|
CI:
|
||||||
|
permissions:
|
||||||
|
contents: write # for npx prebuild to make release
|
||||||
|
name: ${{ matrix.container || matrix.os }} - Node.js ${{ matrix.nodejs_version }} ${{ matrix.nodejs_arch }} ${{ matrix.prebuild && '- prebuild' }}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
container: ${{ matrix.container }}
|
container: ${{ matrix.container }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-20.04
|
- os: ubuntu-22.04
|
||||||
container: centos:7
|
container: centos:7
|
||||||
nodejs_version: 14
|
nodejs_version: 14
|
||||||
coverage: true
|
|
||||||
prebuild: true
|
prebuild: true
|
||||||
- os: ubuntu-20.04
|
- os: ubuntu-22.04
|
||||||
container: centos:7
|
container: centos:7
|
||||||
nodejs_version: 16
|
nodejs_version: 16
|
||||||
- os: ubuntu-20.04
|
- os: ubuntu-22.04
|
||||||
container: rockylinux:8
|
container: rockylinux:8
|
||||||
nodejs_version: 18
|
nodejs_version: 18
|
||||||
- os: ubuntu-20.04
|
- os: ubuntu-22.04
|
||||||
container: node:14-alpine3.12
|
container: node:14-alpine3.12
|
||||||
prebuild: true
|
prebuild: true
|
||||||
- os: ubuntu-20.04
|
- os: ubuntu-22.04
|
||||||
container: node:16-alpine3.12
|
container: node:16-alpine3.12
|
||||||
- os: ubuntu-20.04
|
- os: ubuntu-22.04
|
||||||
container: node:18-alpine3.14
|
container: node:18-alpine3.14
|
||||||
- os: macos-11
|
- os: macos-11
|
||||||
nodejs_version: 14
|
nodejs_version: 14
|
||||||
@@ -75,14 +78,19 @@ jobs:
|
|||||||
- name: Dependencies (Linux musl)
|
- name: Dependencies (Linux musl)
|
||||||
if: contains(matrix.container, 'alpine')
|
if: contains(matrix.container, 'alpine')
|
||||||
run: apk add build-base git python3 font-noto --update-cache
|
run: apk add build-base git python3 font-noto --update-cache
|
||||||
- name: Dependencies (macOS, Windows)
|
- name: Dependencies (Python 3.10 - macOS, Windows)
|
||||||
|
if: contains(matrix.os, 'macos') || contains(matrix.os, 'windows')
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.10'
|
||||||
|
- name: Dependencies (Node.js - macOS, Windows)
|
||||||
if: contains(matrix.os, 'macos') || contains(matrix.os, 'windows')
|
if: contains(matrix.os, 'macos') || contains(matrix.os, 'windows')
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.nodejs_version }}
|
node-version: ${{ matrix.nodejs_version }}
|
||||||
architecture: ${{ matrix.nodejs_arch }}
|
architecture: ${{ matrix.nodejs_arch }}
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
- name: Fix working directory ownership
|
- name: Fix working directory ownership
|
||||||
if: matrix.container
|
if: matrix.container
|
||||||
run: chown root.root .
|
run: chown root.root .
|
||||||
@@ -90,11 +98,6 @@ jobs:
|
|||||||
run: npm install --build-from-source --unsafe-perm
|
run: npm install --build-from-source --unsafe-perm
|
||||||
- name: Test
|
- name: Test
|
||||||
run: npm test
|
run: npm test
|
||||||
- name: Coverage
|
|
||||||
if: matrix.coverage
|
|
||||||
uses: coverallsapp/github-action@v1.1.2
|
|
||||||
with:
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: Prebuild
|
- name: Prebuild
|
||||||
if: matrix.prebuild && startsWith(github.ref, 'refs/tags/')
|
if: matrix.prebuild && startsWith(github.ref, 'refs/tags/')
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -98,7 +98,6 @@ readableStream
|
|||||||
A [guide for contributors](https://github.com/lovell/sharp/blob/main/.github/CONTRIBUTING.md)
|
A [guide for contributors](https://github.com/lovell/sharp/blob/main/.github/CONTRIBUTING.md)
|
||||||
covers reporting bugs, requesting features and submitting code changes.
|
covers reporting bugs, requesting features and submitting code changes.
|
||||||
|
|
||||||
[](https://coveralls.io/r/lovell/sharp?branch=main)
|
|
||||||
[](https://nodejs.org/dist/latest/docs/api/n-api.html#n_api_n_api_version_matrix)
|
[](https://nodejs.org/dist/latest/docs/api/n-api.html#n_api_n_api_version_matrix)
|
||||||
|
|
||||||
## Licensing
|
## Licensing
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ When both a `width` and `height` are provided, the possible methods by which the
|
|||||||
|
|
||||||
Some of these values are based on the [object-fit][1] CSS property.
|
Some of these values are based on the [object-fit][1] CSS property.
|
||||||
|
|
||||||
When using a `fit` of `cover` or `contain`, the default **position** is `centre`. Other options are:
|
When using a **fit** of `cover` or `contain`, the default **position** is `centre`. Other options are:
|
||||||
|
|
||||||
* `sharp.position`: `top`, `right top`, `right`, `right bottom`, `bottom`, `left bottom`, `left`, `left top`.
|
* `sharp.position`: `top`, `right top`, `right`, `right bottom`, `bottom`, `left bottom`, `left`, `left top`.
|
||||||
* `sharp.gravity`: `north`, `northeast`, `east`, `southeast`, `south`, `southwest`, `west`, `northwest`, `center` or `centre`.
|
* `sharp.gravity`: `north`, `northeast`, `east`, `southeast`, `south`, `southwest`, `west`, `northwest`, `center` or `centre`.
|
||||||
|
|||||||
@@ -2,7 +2,37 @@
|
|||||||
|
|
||||||
## v0.31 - *eagle*
|
## v0.31 - *eagle*
|
||||||
|
|
||||||
Requires libvips v8.13.1
|
Requires libvips v8.13.3
|
||||||
|
|
||||||
|
### v0.31.2 - 4th November 2022
|
||||||
|
|
||||||
|
* Upgrade to libvips v8.13.3 for upstream bug fixes.
|
||||||
|
|
||||||
|
* Ensure manual flip, rotate, resize operation ordering (regression in 0.31.1)
|
||||||
|
[#3391](https://github.com/lovell/sharp/issues/3391)
|
||||||
|
|
||||||
|
* Ensure auto-rotation works without resize (regression in 0.31.1)
|
||||||
|
[#3422](https://github.com/lovell/sharp/issues/3422)
|
||||||
|
|
||||||
|
### v0.31.1 - 29th September 2022
|
||||||
|
|
||||||
|
* Upgrade to libvips v8.13.2 for upstream bug fixes.
|
||||||
|
|
||||||
|
* Ensure `close` event occurs after `end` event for Stream-based output.
|
||||||
|
[#3313](https://github.com/lovell/sharp/issues/3313)
|
||||||
|
|
||||||
|
* Ensure `limitInputPixels` constructor option uses uint64.
|
||||||
|
[#3349](https://github.com/lovell/sharp/pull/3349)
|
||||||
|
[@marcosc90](https://github.com/marcosc90)
|
||||||
|
|
||||||
|
* Ensure auto-rotation works with shrink-on-load and extract (regression in 0.31.0).
|
||||||
|
[#3352](https://github.com/lovell/sharp/issues/3352)
|
||||||
|
|
||||||
|
* Ensure AVIF output is always 8-bit.
|
||||||
|
[#3358](https://github.com/lovell/sharp/issues/3358)
|
||||||
|
|
||||||
|
* Ensure greyscale images can be trimmed (regression in 0.31.0).
|
||||||
|
[#3386](https://github.com/lovell/sharp/issues/3386)
|
||||||
|
|
||||||
### v0.31.0 - 5th September 2022
|
### v0.31.0 - 5th September 2022
|
||||||
|
|
||||||
|
|||||||
@@ -260,3 +260,6 @@ GitHub: https://github.com/brahima
|
|||||||
|
|
||||||
Name: Anton Marsden
|
Name: Anton Marsden
|
||||||
GitHub: https://github.com/antonmarsden
|
GitHub: https://github.com/antonmarsden
|
||||||
|
|
||||||
|
Name: Marcos Casagrande
|
||||||
|
GitHub: https://github.com/marcosc90
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ const removeVendoredLibvips = function () {
|
|||||||
rm(vendorPath, { recursive: true, maxRetries: 3, force: true });
|
rm(vendorPath, { recursive: true, maxRetries: 3, force: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* istanbul ignore next */
|
||||||
const pkgConfigPath = function () {
|
const pkgConfigPath = function () {
|
||||||
if (process.platform !== 'win32') {
|
if (process.platform !== 'win32') {
|
||||||
const brewPkgConfigPath = spawnSync(
|
const brewPkgConfigPath = spawnSync(
|
||||||
|
|||||||
@@ -1205,7 +1205,7 @@ function _pipeline (callback) {
|
|||||||
this.push(data);
|
this.push(data);
|
||||||
}
|
}
|
||||||
this.push(null);
|
this.push(null);
|
||||||
this.emit('close');
|
this.on('end', () => this.emit('close'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
if (this.streamInFinished) {
|
if (this.streamInFinished) {
|
||||||
@@ -1221,7 +1221,7 @@ function _pipeline (callback) {
|
|||||||
this.push(data);
|
this.push(data);
|
||||||
}
|
}
|
||||||
this.push(null);
|
this.push(null);
|
||||||
this.emit('close');
|
this.on('end', () => this.emit('close'));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ function isResizeExpected (options) {
|
|||||||
*
|
*
|
||||||
* Some of these values are based on the [object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) CSS property.
|
* Some of these values are based on the [object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) CSS property.
|
||||||
*
|
*
|
||||||
* When using a `fit` of `cover` or `contain`, the default **position** is `centre`. Other options are:
|
* When using a **fit** of `cover` or `contain`, the default **position** is `centre`. Other options are:
|
||||||
* - `sharp.position`: `top`, `right top`, `right`, `right bottom`, `bottom`, `left bottom`, `left`, `left top`.
|
* - `sharp.position`: `top`, `right top`, `right`, `right bottom`, `bottom`, `left bottom`, `left`, `left top`.
|
||||||
* - `sharp.gravity`: `north`, `northeast`, `east`, `southeast`, `south`, `southwest`, `west`, `northwest`, `center` or `centre`.
|
* - `sharp.gravity`: `north`, `northeast`, `east`, `southeast`, `south`, `southwest`, `west`, `northwest`, `center` or `centre`.
|
||||||
* - `sharp.strategy`: `cover` only, dynamically crop using either the `entropy` or `attention` strategy.
|
* - `sharp.strategy`: `cover` only, dynamically crop using either the `entropy` or `attention` strategy.
|
||||||
@@ -428,7 +428,7 @@ function extend (extend) {
|
|||||||
* @throws {Error} Invalid parameters
|
* @throws {Error} Invalid parameters
|
||||||
*/
|
*/
|
||||||
function extract (options) {
|
function extract (options) {
|
||||||
const suffix = isResizeExpected(this.options) || isRotationExpected(this.options) ? 'Post' : 'Pre';
|
const suffix = isResizeExpected(this.options) || this.options.widthPre !== -1 ? 'Post' : 'Pre';
|
||||||
if (this.options[`width${suffix}`] !== -1) {
|
if (this.options[`width${suffix}`] !== -1) {
|
||||||
this.options.debuglog('ignoring previous extract options');
|
this.options.debuglog('ignoring previous extract options');
|
||||||
}
|
}
|
||||||
@@ -511,16 +511,13 @@ function trim (trim) {
|
|||||||
}
|
}
|
||||||
} else if (is.object(trim)) {
|
} else if (is.object(trim)) {
|
||||||
this._setBackgroundColourOption('trimBackground', trim.background);
|
this._setBackgroundColourOption('trimBackground', trim.background);
|
||||||
|
|
||||||
if (!is.defined(trim.threshold)) {
|
if (!is.defined(trim.threshold)) {
|
||||||
this.options.trimThreshold = 10;
|
this.options.trimThreshold = 10;
|
||||||
} else if (is.number(trim.threshold)) {
|
} else if (is.number(trim.threshold) && trim.threshold >= 0) {
|
||||||
if (trim.threshold >= 0) {
|
|
||||||
this.options.trimThreshold = trim.threshold;
|
this.options.trimThreshold = trim.threshold;
|
||||||
} else {
|
} else {
|
||||||
throw is.invalidParameterError('threshold', 'positive number', trim);
|
throw is.invalidParameterError('threshold', 'positive number', trim);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
throw is.invalidParameterError('trim', 'string, number or object', trim);
|
throw is.invalidParameterError('trim', 'string, number or object', trim);
|
||||||
}
|
}
|
||||||
|
|||||||
35
package.json
35
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.31.0",
|
"version": "0.31.2",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://github.com/lovell/sharp",
|
"homepage": "https://github.com/lovell/sharp",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
@@ -92,9 +92,8 @@
|
|||||||
"clean": "rm -rf node_modules/ build/ vendor/ .nyc_output/ coverage/ test/fixtures/output.*",
|
"clean": "rm -rf node_modules/ build/ vendor/ .nyc_output/ coverage/ test/fixtures/output.*",
|
||||||
"test": "npm run test-lint && npm run test-unit && npm run test-licensing",
|
"test": "npm run test-lint && npm run test-unit && npm run test-licensing",
|
||||||
"test-lint": "semistandard && cpplint",
|
"test-lint": "semistandard && cpplint",
|
||||||
"test-unit": "nyc --reporter=lcov --branches=99 mocha --slow=1000 --timeout=60000 ./test/unit/*.js",
|
"test-unit": "nyc --reporter=lcov --reporter=text --check-coverage --branches=100 mocha --slow=1000 --timeout=30000 ./test/unit/*.js",
|
||||||
"test-licensing": "license-checker --production --summary --onlyAllow=\"Apache-2.0;BSD;ISC;MIT\"",
|
"test-licensing": "license-checker --production --summary --onlyAllow=\"Apache-2.0;BSD;ISC;MIT\"",
|
||||||
"test-coverage": "./test/coverage/report.sh",
|
|
||||||
"test-leak": "./test/leak/leak.sh",
|
"test-leak": "./test/leak/leak.sh",
|
||||||
"docs-build": "documentation lint lib && node docs/build && node docs/search-index/build",
|
"docs-build": "documentation lint lib && node docs/build && node docs/search-index/build",
|
||||||
"docs-serve": "cd docs && npx serve",
|
"docs-serve": "cd docs && npx serve",
|
||||||
@@ -134,7 +133,7 @@
|
|||||||
"detect-libc": "^2.0.1",
|
"detect-libc": "^2.0.1",
|
||||||
"node-addon-api": "^5.0.0",
|
"node-addon-api": "^5.0.0",
|
||||||
"prebuild-install": "^7.1.1",
|
"prebuild-install": "^7.1.1",
|
||||||
"semver": "^7.3.7",
|
"semver": "^7.3.8",
|
||||||
"simple-get": "^4.0.1",
|
"simple-get": "^4.0.1",
|
||||||
"tar-fs": "^2.1.1",
|
"tar-fs": "^2.1.1",
|
||||||
"tunnel-agent": "^0.6.0"
|
"tunnel-agent": "^0.6.0"
|
||||||
@@ -147,8 +146,8 @@
|
|||||||
"extract-zip": "^2.0.1",
|
"extract-zip": "^2.0.1",
|
||||||
"icc": "^2.0.0",
|
"icc": "^2.0.0",
|
||||||
"license-checker": "^25.0.1",
|
"license-checker": "^25.0.1",
|
||||||
"mocha": "^10.0.0",
|
"mocha": "^10.1.0",
|
||||||
"mock-fs": "^5.1.4",
|
"mock-fs": "^5.2.0",
|
||||||
"nyc": "^15.1.0",
|
"nyc": "^15.1.0",
|
||||||
"prebuild": "^11.0.4",
|
"prebuild": "^11.0.4",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
@@ -156,19 +155,19 @@
|
|||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"config": {
|
"config": {
|
||||||
"libvips": "8.13.1",
|
"libvips": "8.13.3",
|
||||||
"integrity": {
|
"integrity": {
|
||||||
"darwin-arm64v8": "sha512-JdpGTx67RDbvRkg3ljFvTzqoq+oBXmMdDFEp0expDYXmP5HLH+GCkikmsROlGltgfKE2KqL/qwpxTEhIwMK/3A==",
|
"darwin-arm64v8": "sha512-xFgYt7CtQSZcWoyUdzPTDNHbioZIrZSEU+gkMxzH4Cgjhi4/N49UsonnIZhKQoTBGloAqEexHeMx4rYTQ2Kgvw==",
|
||||||
"darwin-x64": "sha512-0Oh4/hEDnzV+X8MiiyUQ4G/Zh/MHw9rKstfuX0P1czgaxS2hX8Pxdbzdk1oqwTOEYVEGO/hMm9ItCVZ3RVPPaA==",
|
"darwin-x64": "sha512-6SivWKzu15aUMMohe0wg7sNYMPETVnOe40BuWsnKOgzl3o5FpQqNSgs+68Mi8Za3Qti9/DaR+H/fyD0x48Af2w==",
|
||||||
"linux-arm64v8": "sha512-9pSlPzEojt6ue5vXfASNMhQO1YS1p4i4Wydu+bzOfMtIPSBRXbu/+y8WELbbo03Ts7pftm9KtrMHitCVdy5EXw==",
|
"linux-arm64v8": "sha512-b+iI9V/ehgDabXYRQcvqa5CEysh+1FQsgFmYc358StCrJCDahwNmsQdsiH1GOVd5WaWh5wHUGByPwMmFOO16Aw==",
|
||||||
"linux-armv6": "sha512-sv2FqS/ggpQly7h5/+nh8txQDulolE5ptaE90PO7iwfTont8N42pudeqootWKsuf0fRmkW4M92184VfVVYCvGw==",
|
"linux-armv6": "sha512-zRP2F+EiustLE4bXSH8AHCxwfemh9d+QuvmPjira/HL6uJOUuA7SyQgVV1TPwTQle2ioCNnKPm7FEB/MAiT+ug==",
|
||||||
"linux-armv7": "sha512-LmQIB8FDfasK6BsFhnE7ZI3LMlxh/rF5tZRNQ/uoTbF2xrtWQqqgiZgCifJByiEM+1tR7RxwNdnjxZhWvM9WmQ==",
|
"linux-armv7": "sha512-6OCChowE5lBXXXAZrnGdA9dVktg7UdODEBpE5qTroiAJYZv4yXRMgyDFYajok7du2NTgoklhxGk8d9+4vGv5hg==",
|
||||||
"linux-x64": "sha512-JBRf8WBnlVw/K1jpSvmeZpnGZGjeqhG2NDEiQV/hUze3zgDGwDza4oiworaQExQmKcDrc2LJKF14Nsz1qQSNJw==",
|
"linux-x64": "sha512-OTmlmP2r8ozGKdB96X+K5oQE1ojVZanqLqqKlwDpEnfixyIaDGYbVzcjWBNGU3ai/26bvkaCkjynnc2ecYcsuA==",
|
||||||
"linuxmusl-arm64v8": "sha512-yzUQO5isDwsRpEUxbMXBeWp0sKhWghebrSK46SUF5mvB/kq6hZ7JbRuJ2aZjE84K/HUTyuCc0kE+M3m8naOs+g==",
|
"linuxmusl-arm64v8": "sha512-Qh5Wi+bkKTohFYHzSPssfjMhIkD6z6EHbVmnwmWSsgY9zsUBStFp6+mKcNTQfP5YM5Mz06vJOkLHX2OzEr5TzA==",
|
||||||
"linuxmusl-x64": "sha512-H3Vz1QaaZ6X5iEbfPST7TPFwDO01tI8dk1osLm6l4a17BWCaOMaBQlqxgTgYrtd09JJ9CvGoq5fo5j5TPxUc4Q==",
|
"linuxmusl-x64": "sha512-DwB4Fs3+ISw9etaLCANkueZDdk758iOS+wNp4TKZkHdq0al6B/3Pk7OHLR8a9E3H6wYDD328u++dcJzip5tacA==",
|
||||||
"win32-arm64v8": "sha512-b5Ver+uwOJhdOGqvZVM+qF2KLKcowcac/wKK5Fg0czqlSMqP/KxDF2kxw2eKXUJNgfqe4eDH1QG/yTg2pQSetQ==",
|
"win32-arm64v8": "sha512-96r3W+O4BtX602B1MtxU5Ru4lKzRRTZqM4OQEBJ//TNL3fiCZdd9agD+RQBjaeR4KFIyBSt3F7IE425ZWmxz+w==",
|
||||||
"win32-ia32": "sha512-h/SJ/Yfn0ce9H70vt1wS8rZ4PfHnguCCTsOGik7e6O/e2AlBQOM0mKsPIB9jSOquoCP8rP0qF6AOPOjXKnCk+w==",
|
"win32-ia32": "sha512-qfN1MsfQGek1QQd1UNW7JT+5K5Ne1suFQ2GpgpYm3JLSpIve/tz2vOGEGzvTVssOBADJvAkTDFt+yIi3PgU9pA==",
|
||||||
"win32-x64": "sha512-p9qpdWdhZooPteib92Kk+qF1vvzcScxvOwdIP8muhgo/A8uDI4/mqXCpEbMBw6vjETKlS3qo2JUbVF6+0/lyWQ=="
|
"win32-x64": "sha512-eb3aAmjbVVBVRbiYgebQwoxkAt69WI8nwmKlilSQ3kWqoc0pXfIe322rF2UR8ebbISCGvYRUfzD2r1k92RXISQ=="
|
||||||
},
|
},
|
||||||
"runtime": "napi",
|
"runtime": "napi",
|
||||||
"target": 7
|
"target": 7
|
||||||
|
|||||||
@@ -507,9 +507,10 @@ namespace sharp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Limit input images to a given number of pixels, where pixels = width * height
|
// Limit input images to a given number of pixels, where pixels = width * height
|
||||||
if (descriptor->limitInputPixels > 0 &&
|
if (descriptor->limitInputPixels > 0 &&
|
||||||
static_cast<uint64_t>(image.width() * image.height()) > descriptor->limitInputPixels) {
|
static_cast<uint64_t>(image.width()) * image.height() > descriptor->limitInputPixels) {
|
||||||
throw vips::VError("Input image exceeds pixel limit");
|
throw vips::VError("Input image exceeds pixel limit");
|
||||||
}
|
}
|
||||||
return std::make_tuple(image, imageType);
|
return std::make_tuple(image, imageType);
|
||||||
@@ -556,6 +557,7 @@ namespace sharp {
|
|||||||
VImage RemoveExifOrientation(VImage image) {
|
VImage RemoveExifOrientation(VImage image) {
|
||||||
VImage copy = image.copy();
|
VImage copy = image.copy();
|
||||||
copy.remove(VIPS_META_ORIENTATION);
|
copy.remove(VIPS_META_ORIENTATION);
|
||||||
|
copy.remove("exif-ifd0-Orientation");
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,8 +26,8 @@
|
|||||||
|
|
||||||
#if (VIPS_MAJOR_VERSION < 8) || \
|
#if (VIPS_MAJOR_VERSION < 8) || \
|
||||||
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 13) || \
|
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 13) || \
|
||||||
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 13 && VIPS_MICRO_VERSION < 1)
|
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 13 && VIPS_MICRO_VERSION < 3)
|
||||||
#error "libvips version 8.13.1+ is required - please see https://sharp.pixelplumbing.com/install"
|
#error "libvips version 8.13.3+ is required - please see https://sharp.pixelplumbing.com/install"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)))
|
#if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)))
|
||||||
|
|||||||
@@ -289,17 +289,20 @@ namespace sharp {
|
|||||||
background = image.extract_area(0, 0, 1, 1)(0, 0);
|
background = image.extract_area(0, 0, 1, 1)(0, 0);
|
||||||
multiplier = 1.0;
|
multiplier = 1.0;
|
||||||
}
|
}
|
||||||
if (background.size() == 4) {
|
if (HasAlpha(image) && background.size() == 4) {
|
||||||
// Just discard the alpha because flattening the background colour with
|
// Just discard the alpha because flattening the background colour with
|
||||||
// itself (effectively what find_trim() does) gives the same result
|
// itself (effectively what find_trim() does) gives the same result
|
||||||
backgroundAlpha[0] = background[3] * multiplier;
|
backgroundAlpha[0] = background[3] * multiplier;
|
||||||
}
|
}
|
||||||
|
if (image.bands() > 2) {
|
||||||
background = {
|
background = {
|
||||||
background[0] * multiplier,
|
background[0] * multiplier,
|
||||||
background[1] * multiplier,
|
background[1] * multiplier,
|
||||||
background[2] * multiplier
|
background[2] * multiplier
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
|
background[0] = background[0] * multiplier;
|
||||||
|
}
|
||||||
int left, top, width, height;
|
int left, top, width, height;
|
||||||
left = image.find_trim(&top, &width, &height, VImage::option()
|
left = image.find_trim(&top, &width, &height, VImage::option()
|
||||||
->set("background", background)
|
->set("background", background)
|
||||||
|
|||||||
@@ -81,32 +81,47 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
int pageHeight = sharp::GetPageHeight(image);
|
int pageHeight = sharp::GetPageHeight(image);
|
||||||
|
|
||||||
// Calculate angle of rotation
|
// Calculate angle of rotation
|
||||||
VipsAngle rotation;
|
VipsAngle rotation = VIPS_ANGLE_D0;
|
||||||
bool flip = FALSE;
|
VipsAngle autoRotation = VIPS_ANGLE_D0;
|
||||||
bool flop = FALSE;
|
bool autoFlip = FALSE;
|
||||||
|
bool autoFlop = FALSE;
|
||||||
if (baton->useExifOrientation) {
|
if (baton->useExifOrientation) {
|
||||||
// Rotate and flip image according to Exif orientation
|
// Rotate and flip image according to Exif orientation
|
||||||
std::tie(rotation, flip, flop) = CalculateExifRotationAndFlip(sharp::ExifOrientation(image));
|
std::tie(autoRotation, autoFlip, autoFlop) = CalculateExifRotationAndFlip(sharp::ExifOrientation(image));
|
||||||
|
image = sharp::RemoveExifOrientation(image);
|
||||||
} else {
|
} else {
|
||||||
rotation = CalculateAngleRotation(baton->angle);
|
rotation = CalculateAngleRotation(baton->angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rotate pre-extract
|
// Rotate pre-extract
|
||||||
if (baton->rotateBeforePreExtract) {
|
bool const shouldRotateBefore = baton->rotateBeforePreExtract &&
|
||||||
|
(rotation != VIPS_ANGLE_D0 || autoRotation != VIPS_ANGLE_D0 ||
|
||||||
|
autoFlip || baton->flip || autoFlop || baton->flop ||
|
||||||
|
baton->rotationAngle != 0.0);
|
||||||
|
|
||||||
|
if (shouldRotateBefore) {
|
||||||
|
if (autoRotation != VIPS_ANGLE_D0) {
|
||||||
|
image = image.rot(autoRotation);
|
||||||
|
autoRotation = VIPS_ANGLE_D0;
|
||||||
|
}
|
||||||
|
if (autoFlip) {
|
||||||
|
image = image.flip(VIPS_DIRECTION_VERTICAL);
|
||||||
|
autoFlip = FALSE;
|
||||||
|
} else if (baton->flip) {
|
||||||
|
image = image.flip(VIPS_DIRECTION_VERTICAL);
|
||||||
|
baton->flip = FALSE;
|
||||||
|
}
|
||||||
|
if (autoFlop) {
|
||||||
|
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
|
||||||
|
autoFlop = FALSE;
|
||||||
|
} else if (baton->flop) {
|
||||||
|
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
|
||||||
|
baton->flop = FALSE;
|
||||||
|
}
|
||||||
if (rotation != VIPS_ANGLE_D0) {
|
if (rotation != VIPS_ANGLE_D0) {
|
||||||
image = image.rot(rotation);
|
image = image.rot(rotation);
|
||||||
|
rotation = VIPS_ANGLE_D0;
|
||||||
}
|
}
|
||||||
if (flip) {
|
|
||||||
image = image.flip(VIPS_DIRECTION_VERTICAL);
|
|
||||||
}
|
|
||||||
if (flop) {
|
|
||||||
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
|
|
||||||
}
|
|
||||||
if (rotation != VIPS_ANGLE_D0 || flip || flop) {
|
|
||||||
image = sharp::RemoveExifOrientation(image);
|
|
||||||
}
|
|
||||||
flop = FALSE;
|
|
||||||
flip = FALSE;
|
|
||||||
if (baton->rotationAngle != 0.0) {
|
if (baton->rotationAngle != 0.0) {
|
||||||
MultiPageUnsupported(nPages, "Rotate");
|
MultiPageUnsupported(nPages, "Rotate");
|
||||||
std::vector<double> background;
|
std::vector<double> background;
|
||||||
@@ -147,7 +162,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
int targetResizeHeight = baton->height;
|
int targetResizeHeight = baton->height;
|
||||||
|
|
||||||
// Swap input output width and height when rotating by 90 or 270 degrees
|
// Swap input output width and height when rotating by 90 or 270 degrees
|
||||||
bool swap = !baton->rotateBeforePreExtract && (rotation == VIPS_ANGLE_D90 || rotation == VIPS_ANGLE_D270);
|
bool swap = !baton->rotateBeforePreExtract &&
|
||||||
|
(rotation == VIPS_ANGLE_D90 || rotation == VIPS_ANGLE_D270 ||
|
||||||
|
autoRotation == VIPS_ANGLE_D90 || autoRotation == VIPS_ANGLE_D270);
|
||||||
|
|
||||||
// Shrink to pageHeight, so we work for multi-page images
|
// Shrink to pageHeight, so we work for multi-page images
|
||||||
std::tie(hshrink, vshrink) = sharp::ResolveShrink(
|
std::tie(hshrink, vshrink) = sharp::ResolveShrink(
|
||||||
@@ -167,7 +184,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
// - input colourspace is not specified;
|
// - input colourspace is not specified;
|
||||||
bool const shouldPreShrink = (targetResizeWidth > 0 || targetResizeHeight > 0) &&
|
bool const shouldPreShrink = (targetResizeWidth > 0 || targetResizeHeight > 0) &&
|
||||||
baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimThreshold == 0.0 &&
|
baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimThreshold == 0.0 &&
|
||||||
baton->colourspaceInput == VIPS_INTERPRETATION_LAST;
|
baton->colourspaceInput == VIPS_INTERPRETATION_LAST && !shouldRotateBefore;
|
||||||
|
|
||||||
if (shouldPreShrink) {
|
if (shouldPreShrink) {
|
||||||
// The common part of the shrink: the bit by which both axes must be shrunk
|
// The common part of the shrink: the bit by which both axes must be shrunk
|
||||||
@@ -364,30 +381,21 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
->set("kernel", baton->kernel));
|
->set("kernel", baton->kernel));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Auto-rotate post-extract
|
||||||
|
if (autoRotation != VIPS_ANGLE_D0) {
|
||||||
|
image = image.rot(autoRotation);
|
||||||
|
}
|
||||||
// Flip (mirror about Y axis)
|
// Flip (mirror about Y axis)
|
||||||
if (baton->flip || flip) {
|
if (baton->flip || autoFlip) {
|
||||||
image = image.flip(VIPS_DIRECTION_VERTICAL);
|
image = image.flip(VIPS_DIRECTION_VERTICAL);
|
||||||
image = sharp::RemoveExifOrientation(image);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flop (mirror about X axis)
|
// Flop (mirror about X axis)
|
||||||
if (baton->flop || flop) {
|
if (baton->flop || autoFlop) {
|
||||||
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
|
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
|
||||||
image = sharp::RemoveExifOrientation(image);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rotate post-extract 90-angle
|
// Rotate post-extract 90-angle
|
||||||
if (!baton->rotateBeforePreExtract && rotation != VIPS_ANGLE_D0) {
|
if (rotation != VIPS_ANGLE_D0) {
|
||||||
image = image.rot(rotation);
|
image = image.rot(rotation);
|
||||||
if (flip) {
|
|
||||||
image = image.flip(VIPS_DIRECTION_VERTICAL);
|
|
||||||
flip = FALSE;
|
|
||||||
}
|
|
||||||
if (flop) {
|
|
||||||
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
|
|
||||||
flop = FALSE;
|
|
||||||
}
|
|
||||||
image = sharp::RemoveExifOrientation(image);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Join additional color channels to the image
|
// Join additional color channels to the image
|
||||||
@@ -899,12 +907,13 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
} else if (baton->formatOut == "heif" ||
|
} else if (baton->formatOut == "heif" ||
|
||||||
(baton->formatOut == "input" && inputImageType == sharp::ImageType::HEIF)) {
|
(baton->formatOut == "input" && inputImageType == sharp::ImageType::HEIF)) {
|
||||||
// Write HEIF to buffer
|
// Write HEIF to buffer
|
||||||
image = sharp::RemoveAnimationProperties(image);
|
image = sharp::RemoveAnimationProperties(image).cast(VIPS_FORMAT_UCHAR);
|
||||||
VipsArea *area = reinterpret_cast<VipsArea*>(image.heifsave_buffer(VImage::option()
|
VipsArea *area = reinterpret_cast<VipsArea*>(image.heifsave_buffer(VImage::option()
|
||||||
->set("strip", !baton->withMetadata)
|
->set("strip", !baton->withMetadata)
|
||||||
->set("Q", baton->heifQuality)
|
->set("Q", baton->heifQuality)
|
||||||
->set("compression", baton->heifCompression)
|
->set("compression", baton->heifCompression)
|
||||||
->set("effort", baton->heifEffort)
|
->set("effort", baton->heifEffort)
|
||||||
|
->set("bitdepth", 8)
|
||||||
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
||||||
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
||||||
->set("lossless", baton->heifLossless)));
|
->set("lossless", baton->heifLossless)));
|
||||||
@@ -1070,12 +1079,13 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
} else if (baton->formatOut == "heif" || (mightMatchInput && isHeif) ||
|
} else if (baton->formatOut == "heif" || (mightMatchInput && isHeif) ||
|
||||||
(willMatchInput && inputImageType == sharp::ImageType::HEIF)) {
|
(willMatchInput && inputImageType == sharp::ImageType::HEIF)) {
|
||||||
// Write HEIF to file
|
// Write HEIF to file
|
||||||
image = sharp::RemoveAnimationProperties(image);
|
image = sharp::RemoveAnimationProperties(image).cast(VIPS_FORMAT_UCHAR);
|
||||||
image.heifsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
image.heifsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
||||||
->set("strip", !baton->withMetadata)
|
->set("strip", !baton->withMetadata)
|
||||||
->set("Q", baton->heifQuality)
|
->set("Q", baton->heifQuality)
|
||||||
->set("compression", baton->heifCompression)
|
->set("compression", baton->heifCompression)
|
||||||
->set("effort", baton->heifEffort)
|
->set("effort", baton->heifEffort)
|
||||||
|
->set("bitdepth", 8)
|
||||||
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
||||||
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
||||||
->set("lossless", baton->heifLossless));
|
->set("lossless", baton->heifLossless));
|
||||||
|
|||||||
@@ -10,11 +10,12 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@squoosh/cli": "0.7.2",
|
"@squoosh/cli": "0.7.2",
|
||||||
"@squoosh/lib": "0.4.0",
|
"@squoosh/lib": "0.4.0",
|
||||||
|
"@tensorflow/tfjs-node": "3.20.0",
|
||||||
"async": "3.2.4",
|
"async": "3.2.4",
|
||||||
"benchmark": "2.1.4",
|
"benchmark": "2.1.4",
|
||||||
"gm": "1.23.1",
|
"gm": "1.24.0",
|
||||||
"imagemagick": "0.1.3",
|
"imagemagick": "0.1.3",
|
||||||
"jimp": "0.16.1",
|
"jimp": "0.16.2",
|
||||||
"mapnik": "4.5.9",
|
"mapnik": "4.5.9",
|
||||||
"semver": "7.3.7"
|
"semver": "7.3.7"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ const fs = require('fs');
|
|||||||
const { exec } = require('child_process');
|
const { exec } = require('child_process');
|
||||||
|
|
||||||
const async = require('async');
|
const async = require('async');
|
||||||
const assert = require('assert');
|
|
||||||
const Benchmark = require('benchmark');
|
const Benchmark = require('benchmark');
|
||||||
|
|
||||||
// Contenders
|
// Contenders
|
||||||
@@ -15,6 +14,8 @@ const imagemagick = require('imagemagick');
|
|||||||
const mapnik = require('mapnik');
|
const mapnik = require('mapnik');
|
||||||
const jimp = require('jimp');
|
const jimp = require('jimp');
|
||||||
const squoosh = require('@squoosh/lib');
|
const squoosh = require('@squoosh/lib');
|
||||||
|
process.env.TF_CPP_MIN_LOG_LEVEL = 1;
|
||||||
|
const tfjs = require('@tensorflow/tfjs-node');
|
||||||
|
|
||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
|
|
||||||
@@ -212,11 +213,10 @@ async.series({
|
|||||||
.filter('Lanczos')
|
.filter('Lanczos')
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.quality(80)
|
.quality(80)
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -243,16 +243,33 @@ async.series({
|
|||||||
.filter('Lanczos')
|
.filter('Lanczos')
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.quality(80)
|
.quality(80)
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// tfjs
|
||||||
|
jpegSuite.add('tfjs-node-buffer-buffer', {
|
||||||
|
defer: true,
|
||||||
|
fn: function (deferred) {
|
||||||
|
const decoded = tfjs.node.decodeJpeg(inputJpgBuffer);
|
||||||
|
const resized = tfjs.image.resizeBilinear(decoded, [height, width]);
|
||||||
|
tfjs
|
||||||
|
.node
|
||||||
|
.encodeJpeg(resized, 'rgb', 80)
|
||||||
|
.then(function () {
|
||||||
|
deferred.resolve();
|
||||||
|
tfjs.disposeVariables();
|
||||||
|
})
|
||||||
|
.catch(function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
// sharp
|
// sharp
|
||||||
jpegSuite.add('sharp-buffer-file', {
|
jpegSuite.add('sharp-buffer-file', {
|
||||||
defer: true,
|
defer: true,
|
||||||
@@ -272,11 +289,10 @@ async.series({
|
|||||||
fn: function (deferred) {
|
fn: function (deferred) {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -311,11 +327,10 @@ async.series({
|
|||||||
fn: function (deferred) {
|
fn: function (deferred) {
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -326,8 +341,7 @@ async.series({
|
|||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.toBuffer()
|
.toBuffer()
|
||||||
.then(function (buffer) {
|
.then(function () {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
})
|
})
|
||||||
.catch(function (err) {
|
.catch(function (err) {
|
||||||
@@ -350,11 +364,10 @@ async.series({
|
|||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.sharpen()
|
.sharpen()
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -365,11 +378,10 @@ async.series({
|
|||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.sharpen(3, 1, 3)
|
.sharpen(3, 1, 3)
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -380,11 +392,10 @@ async.series({
|
|||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.blur()
|
.blur()
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -395,11 +406,10 @@ async.series({
|
|||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.blur(3)
|
.blur(3)
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -410,11 +420,10 @@ async.series({
|
|||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.gamma()
|
.gamma()
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -425,11 +434,10 @@ async.series({
|
|||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.normalise()
|
.normalise()
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -440,11 +448,10 @@ async.series({
|
|||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.greyscale()
|
.greyscale()
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -456,11 +463,10 @@ async.series({
|
|||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.gamma()
|
.gamma()
|
||||||
.greyscale()
|
.greyscale()
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -471,11 +477,10 @@ async.series({
|
|||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.jpeg({ progressive: true })
|
.jpeg({ progressive: true })
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -486,11 +491,10 @@ async.series({
|
|||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.jpeg({ chromaSubsampling: '4:4:4' })
|
.jpeg({ chromaSubsampling: '4:4:4' })
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -501,11 +505,10 @@ async.series({
|
|||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.rotate(90)
|
.rotate(90)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -516,12 +519,11 @@ async.series({
|
|||||||
sharp.simd(false);
|
sharp.simd(false);
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
sharp.simd(true);
|
sharp.simd(true);
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -531,11 +533,10 @@ async.series({
|
|||||||
fn: function (deferred) {
|
fn: function (deferred) {
|
||||||
sharp(inputJpgBuffer, { sequentialRead: true })
|
sharp(inputJpgBuffer, { sequentialRead: true })
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -548,11 +549,10 @@ async.series({
|
|||||||
fit: 'cover',
|
fit: 'cover',
|
||||||
position: sharp.strategy.entropy
|
position: sharp.strategy.entropy
|
||||||
})
|
})
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -565,11 +565,10 @@ async.series({
|
|||||||
fit: 'cover',
|
fit: 'cover',
|
||||||
position: sharp.strategy.attention
|
position: sharp.strategy.attention
|
||||||
})
|
})
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -588,11 +587,10 @@ async.series({
|
|||||||
fn: function (deferred) {
|
fn: function (deferred) {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height, { kernel: 'cubic' })
|
.resize(width, height, { kernel: 'cubic' })
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -602,11 +600,10 @@ async.series({
|
|||||||
fn: function (deferred) {
|
fn: function (deferred) {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height, { kernel: 'lanczos2' })
|
.resize(width, height, { kernel: 'lanczos2' })
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -616,11 +613,10 @@ async.series({
|
|||||||
fn: function (deferred) {
|
fn: function (deferred) {
|
||||||
sharp(inputJpgBuffer)
|
sharp(inputJpgBuffer)
|
||||||
.resize(width, height, { kernel: 'lanczos3' })
|
.resize(width, height, { kernel: 'lanczos3' })
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -774,11 +770,10 @@ async.series({
|
|||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.define('PNG:compression-level=6')
|
.define('PNG:compression-level=6')
|
||||||
.define('PNG:compression-filter=0')
|
.define('PNG:compression-filter=0')
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -807,11 +802,10 @@ async.series({
|
|||||||
sharp(inputPngBuffer)
|
sharp(inputPngBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.png({ compressionLevel: 6 })
|
.png({ compressionLevel: 6 })
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -838,11 +832,10 @@ async.series({
|
|||||||
sharp(fixtures.inputPngAlphaPremultiplicationLarge)
|
sharp(fixtures.inputPngAlphaPremultiplicationLarge)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.png({ compressionLevel: 6 })
|
.png({ compressionLevel: 6 })
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -854,11 +847,10 @@ async.series({
|
|||||||
sharp(inputPngBuffer)
|
sharp(inputPngBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.png({ compressionLevel: 6, progressive: true })
|
.png({ compressionLevel: 6, progressive: true })
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -870,11 +862,10 @@ async.series({
|
|||||||
sharp(inputPngBuffer)
|
sharp(inputPngBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.png({ adaptiveFiltering: true, compressionLevel: 6 })
|
.png({ adaptiveFiltering: true, compressionLevel: 6 })
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -886,11 +877,10 @@ async.series({
|
|||||||
sharp(inputPngBuffer)
|
sharp(inputPngBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.png({ compressionLevel: 9 })
|
.png({ compressionLevel: 9 })
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -923,11 +913,10 @@ async.series({
|
|||||||
fn: function (deferred) {
|
fn: function (deferred) {
|
||||||
sharp(inputWebPBuffer)
|
sharp(inputWebPBuffer)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -950,11 +939,10 @@ async.series({
|
|||||||
fn: function (deferred) {
|
fn: function (deferred) {
|
||||||
sharp(fixtures.inputWebP)
|
sharp(fixtures.inputWebP)
|
||||||
.resize(width, height)
|
.resize(width, height)
|
||||||
.toBuffer(function (err, buffer) {
|
.toBuffer(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
assert.notStrictEqual(null, buffer);
|
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -966,7 +954,9 @@ async.series({
|
|||||||
}).run();
|
}).run();
|
||||||
}
|
}
|
||||||
}, function (err, results) {
|
}, function (err, results) {
|
||||||
assert(!err, err);
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
Object.keys(results).forEach(function (format) {
|
Object.keys(results).forEach(function (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);
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
CPPFLAGS="--coverage" LDFLAGS="--coverage" npm rebuild
|
|
||||||
npm test
|
|
||||||
geninfo --no-external --base-directory src --output-file coverage/sharp.info build/Release/obj.target/sharp/src
|
|
||||||
genhtml --title sharp --demangle-cpp --output-directory coverage/sharp coverage/*.info
|
|
||||||
BIN
test/fixtures/65536-uint32-limit.png
vendored
Normal file
BIN
test/fixtures/65536-uint32-limit.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 510 KiB |
1
test/fixtures/index.js
vendored
1
test/fixtures/index.js
vendored
@@ -98,6 +98,7 @@ module.exports = {
|
|||||||
inputPngTrimSpecificColour: getPath('Flag_of_the_Netherlands.png'), // https://commons.wikimedia.org/wiki/File:Flag_of_the_Netherlands.svg
|
inputPngTrimSpecificColour: getPath('Flag_of_the_Netherlands.png'), // https://commons.wikimedia.org/wiki/File:Flag_of_the_Netherlands.svg
|
||||||
inputPngTrimSpecificColour16bit: getPath('Flag_of_the_Netherlands-16bit.png'), // convert Flag_of_the_Netherlands.png -depth 16 Flag_of_the_Netherlands-16bit.png
|
inputPngTrimSpecificColour16bit: getPath('Flag_of_the_Netherlands-16bit.png'), // convert Flag_of_the_Netherlands.png -depth 16 Flag_of_the_Netherlands-16bit.png
|
||||||
inputPngTrimSpecificColourIncludeAlpha: getPath('Flag_of_the_Netherlands-alpha.png'), // convert Flag_of_the_Netherlands.png -alpha set -background none -channel A -evaluate multiply 0.5 +channel Flag_of_the_Netherlands-alpha.png
|
inputPngTrimSpecificColourIncludeAlpha: getPath('Flag_of_the_Netherlands-alpha.png'), // convert Flag_of_the_Netherlands.png -alpha set -background none -channel A -evaluate multiply 0.5 +channel Flag_of_the_Netherlands-alpha.png
|
||||||
|
inputPngUint32Limit: getPath('65536-uint32-limit.png'), // https://alexandre.alapetite.fr/doc-alex/large-image/
|
||||||
|
|
||||||
inputWebP: getPath('4.webp'), // http://www.gstatic.com/webp/gallery/4.webp
|
inputWebP: getPath('4.webp'), // http://www.gstatic.com/webp/gallery/4.webp
|
||||||
inputWebPWithTransparency: getPath('5_webp_a.webp'), // http://www.gstatic.com/webp/gallery3/5_webp_a.webp
|
inputWebPWithTransparency: getPath('5_webp_a.webp'), // http://www.gstatic.com/webp/gallery3/5_webp_a.webp
|
||||||
|
|||||||
@@ -103,4 +103,28 @@ describe('AVIF', () => {
|
|||||||
width: 10
|
width: 10
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should cast to uchar', async () => {
|
||||||
|
const data = await sharp(inputJpg)
|
||||||
|
.resize(32)
|
||||||
|
.sharpen()
|
||||||
|
.avif({ effort: 0 })
|
||||||
|
.toBuffer();
|
||||||
|
const { size, ...metadata } = await sharp(data)
|
||||||
|
.metadata();
|
||||||
|
assert.deepStrictEqual(metadata, {
|
||||||
|
channels: 3,
|
||||||
|
compression: 'av1',
|
||||||
|
depth: 'uchar',
|
||||||
|
format: 'heif',
|
||||||
|
hasAlpha: false,
|
||||||
|
hasProfile: false,
|
||||||
|
height: 26,
|
||||||
|
isProgressive: false,
|
||||||
|
pagePrimary: 0,
|
||||||
|
pages: 1,
|
||||||
|
space: 'srgb',
|
||||||
|
width: 32
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -300,7 +300,7 @@ describe('Partial image extraction', function () {
|
|||||||
const s = sharp();
|
const s = sharp();
|
||||||
s.on('warning', function (msg) { warningMessage = msg; });
|
s.on('warning', function (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);
|
s.extract(options).extract(options);
|
||||||
assert.strictEqual(warningMessage, '');
|
assert.strictEqual(warningMessage, '');
|
||||||
s.extract(options);
|
s.extract(options);
|
||||||
assert.strictEqual(warningMessage, 'ignoring previous extract options');
|
assert.strictEqual(warningMessage, 'ignoring previous extract options');
|
||||||
@@ -311,7 +311,7 @@ describe('Partial image extraction', function () {
|
|||||||
const s = sharp().rotate();
|
const s = sharp().rotate();
|
||||||
s.on('warning', function (msg) { warningMessage = msg; });
|
s.on('warning', function (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);
|
s.extract(options).extract(options);
|
||||||
assert.strictEqual(warningMessage, '');
|
assert.strictEqual(warningMessage, '');
|
||||||
s.extract(options);
|
s.extract(options);
|
||||||
assert.strictEqual(warningMessage, 'ignoring previous extract options');
|
assert.strictEqual(warningMessage, 'ignoring previous extract options');
|
||||||
|
|||||||
@@ -745,6 +745,17 @@ describe('Input/output', function () {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
it('Enabling default limit works and fails for an image with resolution higher than uint32 limit', () =>
|
||||||
|
sharp(fixtures.inputPngUint32Limit, { limitInputPixels: true })
|
||||||
|
.toBuffer()
|
||||||
|
.then(() => {
|
||||||
|
assert.fail('Expected to fail');
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
assert.strictEqual(err.message, 'Input image exceeds pixel limit');
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
it('Smaller than input fails', () =>
|
it('Smaller than input fails', () =>
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.metadata()
|
.metadata()
|
||||||
|
|||||||
@@ -128,11 +128,26 @@ describe('PNG', function () {
|
|||||||
assert.strictEqual(alphaMeanAfter, alphaMeanBefore);
|
assert.strictEqual(alphaMeanAfter, alphaMeanBefore);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('palette decode/encode roundtrip', () =>
|
it('palette decode/encode roundtrip', async () => {
|
||||||
sharp(fixtures.inputPngPalette)
|
const data = await sharp(fixtures.inputPngPalette)
|
||||||
.png({ effort: 1, palette: true })
|
.png({ effort: 1, palette: true })
|
||||||
.toBuffer()
|
.toBuffer();
|
||||||
);
|
|
||||||
|
const { size, ...metadata } = await sharp(data).metadata();
|
||||||
|
assert.deepStrictEqual(metadata, {
|
||||||
|
format: 'png',
|
||||||
|
width: 68,
|
||||||
|
height: 68,
|
||||||
|
space: 'srgb',
|
||||||
|
channels: 3,
|
||||||
|
density: 72,
|
||||||
|
depth: 'uchar',
|
||||||
|
isProgressive: false,
|
||||||
|
paletteBitDepth: 8,
|
||||||
|
hasProfile: false,
|
||||||
|
hasAlpha: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Valid PNG libimagequant palette value does not throw error', function () {
|
it('Valid PNG libimagequant palette value does not throw error', function () {
|
||||||
assert.doesNotThrow(function () {
|
assert.doesNotThrow(function () {
|
||||||
|
|||||||
@@ -8,16 +8,43 @@ const fixtures = require('../fixtures');
|
|||||||
describe('Rotation', function () {
|
describe('Rotation', function () {
|
||||||
['Landscape', 'Portrait'].forEach(function (orientation) {
|
['Landscape', 'Portrait'].forEach(function (orientation) {
|
||||||
[1, 2, 3, 4, 5, 6, 7, 8].forEach(function (exifTag) {
|
[1, 2, 3, 4, 5, 6, 7, 8].forEach(function (exifTag) {
|
||||||
it('Input image has Orientation EXIF tag value of (' + exifTag + '), auto-rotate', function (done) {
|
const input = fixtures[`inputJpgWith${orientation}Exif${exifTag}`];
|
||||||
sharp(fixtures['inputJpgWith' + orientation + 'Exif' + exifTag])
|
const expectedOutput = fixtures.expected(`${orientation}_${exifTag}-out.jpg`);
|
||||||
|
it(`Auto-rotate ${orientation} image with EXIF Orientation ${exifTag}`, function (done) {
|
||||||
|
const [expectedWidth, expectedHeight] = orientation === 'Landscape' ? [600, 450] : [450, 600];
|
||||||
|
sharp(input)
|
||||||
.rotate()
|
.rotate()
|
||||||
.resize(320)
|
|
||||||
.toBuffer(function (err, data, info) {
|
.toBuffer(function (err, data, info) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual('jpeg', info.format);
|
assert.strictEqual(info.width, expectedWidth);
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(info.height, expectedHeight);
|
||||||
assert.strictEqual(orientation === 'Landscape' ? 240 : 427, info.height);
|
fixtures.assertSimilar(expectedOutput, data, done);
|
||||||
fixtures.assertSimilar(fixtures.expected(orientation + '_' + exifTag + '-out.jpg'), data, done);
|
});
|
||||||
|
});
|
||||||
|
it(`Auto-rotate then resize ${orientation} image with EXIF Orientation ${exifTag}`, function (done) {
|
||||||
|
const [expectedWidth, expectedHeight] = orientation === 'Landscape' ? [320, 240] : [320, 427];
|
||||||
|
sharp(input)
|
||||||
|
.rotate()
|
||||||
|
.resize({ width: 320 })
|
||||||
|
.toBuffer(function (err, data, info) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual(info.width, expectedWidth);
|
||||||
|
assert.strictEqual(info.height, expectedHeight);
|
||||||
|
fixtures.assertSimilar(expectedOutput, data, done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it(`Resize then auto-rotate ${orientation} image with EXIF Orientation ${exifTag}`, function (done) {
|
||||||
|
const [expectedWidth, expectedHeight] = orientation === 'Landscape'
|
||||||
|
? (exifTag < 5) ? [320, 240] : [320, 240]
|
||||||
|
: [320, 427];
|
||||||
|
sharp(input)
|
||||||
|
.resize({ width: 320 })
|
||||||
|
.rotate()
|
||||||
|
.toBuffer(function (err, data, info) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual(info.width, expectedWidth);
|
||||||
|
assert.strictEqual(info.height, expectedHeight);
|
||||||
|
fixtures.assertSimilar(expectedOutput, data, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -406,4 +433,41 @@ describe('Rotation', function () {
|
|||||||
fixtures.assertSimilar(fixtures.expected('rotate-and-flop.jpg'), data, done);
|
fixtures.assertSimilar(fixtures.expected('rotate-and-flop.jpg'), data, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Auto-rotate and shrink-on-load', async () => {
|
||||||
|
const [r, g, b] = await sharp(fixtures.inputJpgWithLandscapeExif3)
|
||||||
|
.rotate()
|
||||||
|
.resize(8)
|
||||||
|
.raw()
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
assert.strictEqual(r, 60);
|
||||||
|
assert.strictEqual(g, 73);
|
||||||
|
assert.strictEqual(b, 52);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Flip and rotate ordering', async () => {
|
||||||
|
const [r, g, b] = await sharp(fixtures.inputJpgWithPortraitExif5)
|
||||||
|
.flip()
|
||||||
|
.rotate(90)
|
||||||
|
.raw()
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
assert.strictEqual(r, 55);
|
||||||
|
assert.strictEqual(g, 65);
|
||||||
|
assert.strictEqual(b, 31);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Flip, rotate and resize ordering', async () => {
|
||||||
|
const [r, g, b] = await sharp(fixtures.inputJpgWithPortraitExif5)
|
||||||
|
.flip()
|
||||||
|
.rotate(90)
|
||||||
|
.resize(449)
|
||||||
|
.raw()
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
assert.strictEqual(r, 54);
|
||||||
|
assert.strictEqual(g, 64);
|
||||||
|
assert.strictEqual(b, 30);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ describe('Text to image', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('fontfile input', function () {
|
it('fontfile input', function () {
|
||||||
// Added for code coverage
|
assert.doesNotThrow(function () {
|
||||||
sharp({
|
sharp({
|
||||||
text: {
|
text: {
|
||||||
text: 'text',
|
text: 'text',
|
||||||
@@ -183,6 +183,7 @@ describe('Text to image', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('bad font input', function () {
|
it('bad font input', function () {
|
||||||
assert.throws(function () {
|
assert.throws(function () {
|
||||||
|
|||||||
@@ -124,6 +124,32 @@ describe('Trim borders', function () {
|
|||||||
assert.strictEqual(trimOffsetLeft, -13);
|
assert.strictEqual(trimOffsetLeft, -13);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Ensure greyscale image can be trimmed', async () => {
|
||||||
|
const greyscale = await sharp({
|
||||||
|
create: {
|
||||||
|
width: 16,
|
||||||
|
height: 8,
|
||||||
|
channels: 3,
|
||||||
|
background: 'silver'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.extend({ left: 12, right: 24, background: 'gray' })
|
||||||
|
.toColourspace('b-w')
|
||||||
|
.png({ compressionLevel: 0 })
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
const { info } = await sharp(greyscale)
|
||||||
|
.trim()
|
||||||
|
.raw()
|
||||||
|
.toBuffer({ resolveWithObject: true });
|
||||||
|
|
||||||
|
const { width, height, trimOffsetTop, trimOffsetLeft } = info;
|
||||||
|
assert.strictEqual(width, 16);
|
||||||
|
assert.strictEqual(height, 8);
|
||||||
|
assert.strictEqual(trimOffsetTop, 0);
|
||||||
|
assert.strictEqual(trimOffsetLeft, -12);
|
||||||
|
});
|
||||||
|
|
||||||
it('Ensure trim of image with all pixels same is no-op', async () => {
|
it('Ensure trim of image with all pixels same is no-op', async () => {
|
||||||
const { info } = await sharp({
|
const { info } = await sharp({
|
||||||
create: {
|
create: {
|
||||||
|
|||||||
Reference in New Issue
Block a user