Compare commits

..

28 Commits

Author SHA1 Message Date
Lovell Fuller
55466f122c Release v0.33.3 2024-03-23 11:58:44 +00:00
Lovell Fuller
ede8217ab3 Prerelease v0.33.3-rc.0 2024-03-22 12:41:51 +00:00
Lovell Fuller
2689fb4e65 Bump deps 2024-03-22 11:19:08 +00:00
Lovell Fuller
eaf31a59e5 Docs: changelog and credit for #4036 2024-03-21 18:34:35 +00:00
Lovell Fuller
aa1bbcb5c1 Guard heif bitdepth property for prebuilt binaries 2024-03-21 18:33:57 +00:00
Mert
3c26080c39 Add bitdepth option to heif output (#4036)
Prebuilt binaries support only AVIF with a bitdepth of 8
2024-03-21 14:36:17 +00:00
Lovell Fuller
dc07fd4e9c Upgrade to libvips v8.15.2 2024-03-18 15:55:01 +00:00
Lovell Fuller
7bc74feb11 Ensure clone takes deep copy of options #4029 2024-03-17 09:42:21 +00:00
Lovell Fuller
c5f318ed4d Docs: add changelog and credit for #4028 2024-03-17 09:10:42 +00:00
Aaron Che
8fbb1cd154 Ensure text.wrap property can accept word-char as value (#4028) 2024-03-17 08:15:03 +00:00
Lovell Fuller
88aee8a887 Bump devDeps 2024-03-06 21:00:44 +00:00
Lovell Fuller
0f77b18078 Rename internal property name to better reflect use
This property is used for the processing pipeline colourspace
rather than the input colourspace, so the name was confusing.
2024-03-06 20:49:47 +00:00
Lovell Fuller
3eeaee71c0 Ensure pipelineColourspace handles CMYK profiles #3906 2024-03-06 20:20:04 +00:00
Lovell Fuller
045d54e2e6 Docs: include use of fetch() in Stream-based example 2024-02-28 13:15:47 +00:00
Lovell Fuller
75fedf1b75 Ensure keepIccProfile retains P3 input profiles #4008 2024-02-26 15:23:50 +00:00
Lovell Fuller
debdacb726 Bump deps 2024-02-23 09:11:35 +00:00
Lovell Fuller
1c8ae67ed2 CI: Upgrade OS on Linux ARM64 runners 2024-02-23 09:08:11 +00:00
Lovell Fuller
0eb57698ec Docs: clarify how to achieve 16-bit PNG output 2024-02-14 10:03:18 +00:00
Lovell Fuller
bc95531f2d Docs: clarify skipBlanks default for tile-based output 2024-02-13 22:40:10 +00:00
Lovell Fuller
60f4048d6c CI: Upgrade to Python 3.12 2024-02-11 20:45:16 +00:00
Lovell Fuller
fb70fbb09f Ensure keepIccProfile retains CMYK input profiles #3906 2024-02-11 20:10:18 +00:00
idchlife
fc439bedf1 Docs: add section to help those bundling via Vite 2024-02-08 09:31:28 +00:00
Lovell Fuller
26d0b7147d Bump devDeps 2024-02-03 21:22:35 +00:00
Lovell Fuller
af6aa8a690 CI: Add macOS 14 (ARM64)
Replaces runner previously and very kindly donated by MacStadium
2024-02-01 13:21:43 +00:00
hugo-syn
bd4f1abba2 TypeScript: Fix typo s/introducted/introduced/ (#3962) 2024-01-19 11:07:41 +00:00
hugo-syn
d2656a3679 Tests: fix typo s/implict/implicit (#3961) 2024-01-19 10:30:04 +00:00
Niels de Vos
a3b45ceccc Docs: update link to new JSDoc site (#3950) 2024-01-16 08:20:45 +00:00
Lovell Fuller
0dcc7d50a8 Docs: add note about libvips 8.15.1 upgrade 2024-01-12 11:25:13 +00:00
39 changed files with 289 additions and 163 deletions

View File

@@ -24,7 +24,7 @@ jobs:
linux-arm64-glibc-node-18:
resource_class: arm.medium
machine:
image: ubuntu-2004:current
image: ubuntu-2204:current
steps:
- checkout
- run: |
@@ -46,7 +46,7 @@ jobs:
linux-arm64-glibc-node-20:
resource_class: arm.medium
machine:
image: ubuntu-2004:current
image: ubuntu-2204:current
steps:
- checkout
- run: |
@@ -69,7 +69,7 @@ jobs:
linux-arm64-musl-node-18:
resource_class: arm.medium
machine:
image: ubuntu-2004:current
image: ubuntu-2204:current
steps:
- checkout
- run: |
@@ -87,7 +87,7 @@ jobs:
linux-arm64-musl-node-20:
resource_class: arm.medium
machine:
image: ubuntu-2004:current
image: ubuntu-2204:current
steps:
- checkout
- run: |

View File

@@ -63,7 +63,7 @@ By way of example, the `background()` method present in v0.20.0 was deprecated i
## Documentation
The public API is documented with [JSDoc](http://usejsdoc.org/) annotated comments.
The public API is documented with [JSDoc](https://jsdoc.app/) annotated comments.
These can be converted to Markdown by running:
```sh

View File

@@ -47,6 +47,17 @@ jobs:
nodejs_version: "^20.3.0"
nodejs_version_major: 20
platform: darwin-x64
- os: macos-14
nodejs_arch: arm64
nodejs_version: "^18.17.0"
nodejs_version_major: 18
platform: darwin-arm64
prebuild: true
- os: macos-14
nodejs_arch: arm64
nodejs_version: "^20.3.0"
nodejs_version_major: 20
platform: darwin-arm64
- os: windows-2019
nodejs_arch: x86
nodejs_version: "18.18.2" # pinned to avoid 18.19.0 and npm 10
@@ -80,12 +91,12 @@ jobs:
run: apk add build-base git python3 font-noto --update-cache
- name: Dependencies (Python 3.11 - macOS, Windows)
if: contains(matrix.os, 'macos') || contains(matrix.os, 'windows')
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: '3.11'
python-version: "3.12"
- name: Dependencies (Node.js)
if: "!contains(matrix.platform, 'linuxmusl')"
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.nodejs_version }}
architecture: ${{ matrix.nodejs_arch }}
@@ -158,14 +169,14 @@ jobs:
contents: write
name: wasm32 - prebuild
runs-on: ubuntu-22.04
container: "emscripten/emsdk:3.1.51"
container: "emscripten/emsdk:3.1.56"
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Dependencies
run: apt-get update && apt-get install -y pkg-config
- name: Dependencies (Node.js)
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install
@@ -193,48 +204,3 @@ jobs:
npm_config_nodedir: emscripten
prebuild_upload: ${{ secrets.GITHUB_TOKEN }}
run: cd src && ln -s ../package.json && emmake npx prebuild --platform=emscripten --arch=wasm32 --strip=0
macstadium-runner:
permissions:
contents: write
name: ${{ matrix.platform }} - Node.js ${{ matrix.nodejs_version_major }} ${{ matrix.prebuild && '- prebuild' }}
runs-on: macos-m1
strategy:
fail-fast: false
matrix:
include:
- nodejs_arch: x64
nodejs_version: "^18.17.0"
nodejs_version_major: 18
platform: darwin-x64
- nodejs_arch: arm64
nodejs_version: "^18.17.0"
nodejs_version_major: 18
platform: darwin-arm64
prebuild: true
defaults:
run:
shell: /usr/bin/arch -arch arm64e /bin/bash -l {0}
steps:
- name: Dependencies (Node.js)
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.nodejs_version }}
architecture: ${{ matrix.nodejs_arch }}
- name: Checkout
uses: actions/checkout@v4
- name: Install
run: npm install --build-from-source
- name: Test
run: npm test
- name: Test packaging
run: |
npm run package-from-local-build
npm pkg set "optionalDependencies.@img/sharp-${{ matrix.platform }}=file:./npm/${{ matrix.platform }}"
npm run clean
npm install --ignore-scripts
npm test
- name: Prebuild
if: matrix.prebuild && startsWith(github.ref, 'refs/tags/')
env:
prebuild_upload: ${{ secrets.GITHUB_TOKEN }}
run: cd src && ln -s ../package.json && npx prebuild

View File

@@ -84,7 +84,7 @@ jobs:
steps:
- name: Install Node.js
if: ${{ matrix.runtime == 'node' }}
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install pnpm

View File

@@ -66,7 +66,7 @@ where the overall height is the `pageHeight` multiplied by the number of `pages`
| [options.text.dpi] | <code>number</code> | <code>72</code> | the resolution (size) at which to render the text. Does not take effect if `height` is specified. |
| [options.text.rgba] | <code>boolean</code> | <code>false</code> | set this to true to enable RGBA output. This is useful for colour emoji rendering, or support for pango markup features like `<span foreground="red">Red!</span>`. |
| [options.text.spacing] | <code>number</code> | <code>0</code> | text line height in points. Will use the font line height if none is specified. |
| [options.text.wrap] | <code>string</code> | <code>&quot;&#x27;word&#x27;&quot;</code> | word wrapping style when width is provided, one of: 'word', 'char', 'charWord' (prefer char, fallback to word) or 'none'. |
| [options.text.wrap] | <code>string</code> | <code>&quot;&#x27;word&#x27;&quot;</code> | word wrapping style when width is provided, one of: 'word', 'char', 'word-char' (prefer word, fallback to char) or 'none'. |
**Example**
```js
@@ -79,14 +79,16 @@ sharp('input.jpg')
```
**Example**
```js
// Read image data from readableStream,
// Read image data from remote URL,
// resize to 300 pixels wide,
// emit an 'info' event with calculated dimensions
// and finally write image data to writableStream
var transformer = sharp()
const { body } = fetch('https://...');
const readableStream = Readable.fromWeb(body);
const transformer = sharp()
.resize(300)
.on('info', function(info) {
console.log('Image height is ' + info.height);
.on('info', ({ height }) => {
console.log(`Image height is ${height}`);
});
readableStream.pipe(transformer).pipe(writableStream);
```

View File

@@ -367,10 +367,14 @@ const data = await sharp(input)
Use these PNG options for output image.
By default, PNG output is full colour at 8 or 16 bits per pixel.
By default, PNG output is full colour at 8 bits per pixel.
Indexed PNG input at 1, 2 or 4 bits per pixel is converted to 8 bits per pixel.
Set `palette` to `true` for slower, indexed PNG output.
For 16 bits per pixel output, convert to `rgb16` via
[toColourspace](/api-colour#tocolourspace).
**Throws**:
@@ -405,6 +409,14 @@ const data = await sharp(input)
.png({ palette: true })
.toBuffer();
```
**Example**
```js
// Output 16 bits per pixel RGB(A)
const data = await sharp(input)
.toColourspace('rgb16')
.png()
.toBuffer();
```
## webp
@@ -605,6 +617,7 @@ sharp('input.svg')
Use these AVIF options for output image.
AVIF image sequences are not supported.
Prebuilt binaries support a bitdepth of 8 only.
**Throws**:
@@ -620,6 +633,7 @@ AVIF image sequences are not supported.
| [options.lossless] | <code>boolean</code> | <code>false</code> | use lossless compression |
| [options.effort] | <code>number</code> | <code>4</code> | CPU effort, between 0 (fastest) and 9 (slowest) |
| [options.chromaSubsampling] | <code>string</code> | <code>&quot;&#x27;4:4:4&#x27;&quot;</code> | set to '4:2:0' to use chroma subsampling |
| [options.bitdepth] | <code>number</code> | <code>8</code> | set bitdepth to 8, 10 or 12 bit |
**Example**
```js
@@ -658,6 +672,7 @@ globally-installed libvips compiled with support for libheif, libde265 and x265.
| [options.lossless] | <code>boolean</code> | <code>false</code> | use lossless compression |
| [options.effort] | <code>number</code> | <code>4</code> | CPU effort, between 0 (fastest) and 9 (slowest) |
| [options.chromaSubsampling] | <code>string</code> | <code>&quot;&#x27;4:4:4&#x27;&quot;</code> | set to '4:2:0' to use chroma subsampling |
| [options.bitdepth] | <code>number</code> | <code>8</code> | set bitdepth to 8, 10 or 12 bit |
**Example**
```js
@@ -763,7 +778,7 @@ The prebuilt binaries do not include this - see
| [options.angle] | <code>number</code> | <code>0</code> | tile angle of rotation, must be a multiple of 90. |
| [options.background] | <code>string</code> \| <code>Object</code> | <code>&quot;{r: 255, g: 255, b: 255, alpha: 1}&quot;</code> | background colour, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to white without transparency. |
| [options.depth] | <code>string</code> | | how deep to make the pyramid, possible values are `onepixel`, `onetile` or `one`, default based on layout. |
| [options.skipBlanks] | <code>number</code> | <code>-1</code> | threshold to skip tile generation, a value 0 - 255 for 8-bit images or 0 - 65535 for 16-bit images |
| [options.skipBlanks] | <code>number</code> | <code>-1</code> | Threshold to skip tile generation. Range is 0-255 for 8-bit images, 0-65535 for 16-bit images. Default is 5 for `google` layout, -1 (no skip) otherwise. |
| [options.container] | <code>string</code> | <code>&quot;&#x27;fs&#x27;&quot;</code> | tile container, with value `fs` (filesystem) or `zip` (compressed file). |
| [options.layout] | <code>string</code> | <code>&quot;&#x27;dz&#x27;&quot;</code> | filesystem layout, possible values are `dz`, `iiif`, `iiif3`, `zoomify` or `google`. |
| [options.centre] | <code>boolean</code> | <code>false</code> | centre image in tile. |

View File

@@ -2,10 +2,31 @@
## v0.33 - *gauge*
Requires libvips v8.15.1
Requires libvips v8.15.2
### v0.33.3 - 23rd March 2024
* Upgrade to libvips v8.15.2 for upstream bug fixes.
* Ensure `keepIccProfile` retains P3 and CMYK input profiles.
[#3906](https://github.com/lovell/sharp/issues/3906)
[#4008](https://github.com/lovell/sharp/issues/4008)
* Ensure `text.wrap` property can accept `word-char` as value.
[#4028](https://github.com/lovell/sharp/pull/4028)
[@yolopunk](https://github.com/yolopunk)
* Ensure `clone` takes a deep copy of existing options.
[#4029](https://github.com/lovell/sharp/issues/4029)
* Add `bitdepth` option to `heif` output (prebuilt binaries support 8-bit only).
[#4036](https://github.com/lovell/sharp/pull/4036)
[@mertalev](https://github.com/mertalev)
### v0.33.2 - 12th January 2024
* Upgrade to libvips v8.15.1 for upstream bug fixes.
* TypeScript: add definition for `keepMetadata`.
[#3914](https://github.com/lovell/sharp/pull/3914)
[@abhi0498](https://github.com/abhi0498)

View File

@@ -284,3 +284,9 @@ GitHub: https://github.com/RReverser
Name: Tamás András Horváth
GitHub: https://github.com/icetee
Name: Aaron Che
GitHub: https://github.com/yolopunk
Name: Mert Alev
GitHub: https://github.com/mertalev

View File

@@ -249,6 +249,26 @@ option.
}
```
### vite
Ensure `sharp` is excluded from bundling via the
[build.rollupOptions](https://vitejs.dev/config/build-options.html)
configuration.
```js
import { defineConfig } from 'vite';
export default defineConfig({
build: {
rollupOptions: {
external: [
"sharp"
]
}
}
});
```
## TypeScript
TypeScript definitions are published as part of

File diff suppressed because one or more lines are too long

View File

@@ -90,7 +90,7 @@ function pipelineColourspace (colourspace) {
if (!is.string(colourspace)) {
throw is.invalidParameterError('colourspace', 'string', colourspace);
}
this.options.colourspaceInput = colourspace;
this.options.colourspacePipeline = colourspace;
return this;
}

View File

@@ -40,14 +40,16 @@ const debuglog = util.debuglog('sharp');
* });
*
* @example
* // Read image data from readableStream,
* // Read image data from remote URL,
* // resize to 300 pixels wide,
* // emit an 'info' event with calculated dimensions
* // and finally write image data to writableStream
* var transformer = sharp()
* const { body } = fetch('https://...');
* const readableStream = Readable.fromWeb(body);
* const transformer = sharp()
* .resize(300)
* .on('info', function(info) {
* console.log('Image height is ' + info.height);
* .on('info', ({ height }) => {
* console.log(`Image height is ${height}`);
* });
* readableStream.pipe(transformer).pipe(writableStream);
*
@@ -164,7 +166,7 @@ const debuglog = util.debuglog('sharp');
* @param {number} [options.text.dpi=72] - the resolution (size) at which to render the text. Does not take effect if `height` is specified.
* @param {boolean} [options.text.rgba=false] - set this to true to enable RGBA output. This is useful for colour emoji rendering, or support for pango markup features like `<span foreground="red">Red!</span>`.
* @param {number} [options.text.spacing=0] - text line height in points. Will use the font line height if none is specified.
* @param {string} [options.text.wrap='word'] - word wrapping style when width is provided, one of: 'word', 'char', 'charWord' (prefer char, fallback to word) or 'none'.
* @param {string} [options.text.wrap='word'] - word wrapping style when width is provided, one of: 'word', 'char', 'word-char' (prefer word, fallback to char) or 'none'.
* @returns {Sharp}
* @throws {Error} Invalid parameters
*/
@@ -255,7 +257,7 @@ const Sharp = function (input, options) {
removeAlpha: false,
ensureAlpha: -1,
colourspace: 'srgb',
colourspaceInput: 'last',
colourspacePipeline: 'last',
composite: [],
// output
fileOut: '',
@@ -323,6 +325,7 @@ const Sharp = function (input, options) {
heifCompression: 'av1',
heifEffort: 4,
heifChromaSubsampling: '4:4:4',
heifBitdepth: 8,
jxlDistance: 1,
jxlDecodingTier: 0,
jxlEffort: 7,
@@ -423,13 +426,16 @@ Object.setPrototypeOf(Sharp, stream.Duplex);
function clone () {
// Clone existing options
const clone = this.constructor.call();
clone.options = Object.assign({}, this.options);
const { debuglog, queueListener, ...options } = this.options;
clone.options = structuredClone(options);
clone.options.debuglog = debuglog;
clone.options.queueListener = queueListener;
// Pass 'finish' event to clone for Stream-based input
if (this._isStreamInput()) {
this.on('finish', () => {
// Clone inherits input data
this._flattenBufferIn();
clone.options.bufferIn = this.options.bufferIn;
clone.options.input.buffer = this.options.input.buffer;
clone.emit('finish');
});
}

8
lib/index.d.ts vendored
View File

@@ -1017,7 +1017,7 @@ declare namespace sharp {
rgba?: boolean;
/** Text line height in points. Will use the font line height if none is specified. (optional, default `0`) */
spacing?: number;
/** Word wrapping style when width is provided, one of: 'word', 'char', 'charWord' (prefer char, fallback to word) or 'none' */
/** Word wrapping style when width is provided, one of: 'word', 'char', 'word-char' (prefer word, fallback to char) or 'none' */
wrap?: TextWrap;
}
@@ -1244,6 +1244,8 @@ declare namespace sharp {
effort?: number | undefined;
/** set to '4:2:0' to use chroma subsampling, requires libvips v8.11.0 (optional, default '4:4:4') */
chromaSubsampling?: string | undefined;
/** Set bitdepth to 8, 10 or 12 bit (optional, default 8) */
bitdepth?: 8 | 10 | 12 | undefined;
}
interface HeifOptions extends OutputOptions {
@@ -1257,6 +1259,8 @@ declare namespace sharp {
effort?: number | undefined;
/** set to '4:2:0' to use chroma subsampling (optional, default '4:4:4') */
chromaSubsampling?: string | undefined;
/** Set bitdepth to 8, 10 or 12 bit (optional, default 8) */
bitdepth?: 8 | 10 | 12 | undefined;
}
interface GifOptions extends OutputOptions, AnimationOptions {
@@ -1613,7 +1617,7 @@ declare namespace sharp {
type TextAlign = 'left' | 'centre' | 'center' | 'right';
type TextWrap = 'word' | 'char' | 'charWord' | 'none';
type TextWrap = 'word' | 'char' | 'word-char' | 'none';
type TileContainer = 'fs' | 'zip';

View File

@@ -345,10 +345,10 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
}
}
if (is.defined(inputOptions.text.wrap)) {
if (is.string(inputOptions.text.wrap) && is.inArray(inputOptions.text.wrap, ['word', 'char', 'wordChar', 'none'])) {
if (is.string(inputOptions.text.wrap) && is.inArray(inputOptions.text.wrap, ['word', 'char', 'word-char', 'none'])) {
inputDescriptor.textWrap = inputOptions.text.wrap;
} else {
throw is.invalidParameterError('text.wrap', 'one of: word, char, wordChar, none', inputOptions.text.wrap);
throw is.invalidParameterError('text.wrap', 'one of: word, char, word-char, none', inputOptions.text.wrap);
}
}
delete inputDescriptor.buffer;

View File

@@ -504,10 +504,14 @@ function jpeg (options) {
/**
* Use these PNG options for output image.
*
* By default, PNG output is full colour at 8 or 16 bits per pixel.
* By default, PNG output is full colour at 8 bits per pixel.
*
* Indexed PNG input at 1, 2 or 4 bits per pixel is converted to 8 bits per pixel.
* Set `palette` to `true` for slower, indexed PNG output.
*
* For 16 bits per pixel output, convert to `rgb16` via
* {@link /api-colour#tocolourspace|toColourspace}.
*
* @example
* // Convert any input to full colour PNG output
* const data = await sharp(input)
@@ -520,6 +524,13 @@ function jpeg (options) {
* .png({ palette: true })
* .toBuffer();
*
* @example
* // Output 16 bits per pixel RGB(A)
* const data = await sharp(input)
* .toColourspace('rgb16')
* .png()
* .toBuffer();
*
* @param {Object} [options]
* @param {boolean} [options.progressive=false] - use progressive (interlace) scan
* @param {number} [options.compressionLevel=6] - zlib compression level, 0 (fastest, largest) to 9 (slowest, smallest)
@@ -1000,6 +1011,7 @@ function tiff (options) {
* Use these AVIF options for output image.
*
* AVIF image sequences are not supported.
* Prebuilt binaries support a bitdepth of 8 only.
*
* @example
* const data = await sharp(input)
@@ -1018,6 +1030,7 @@ function tiff (options) {
* @param {boolean} [options.lossless=false] - use lossless compression
* @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 9 (slowest)
* @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
* @param {number} [options.bitdepth=8] - set bitdepth to 8, 10 or 12 bit
* @returns {Sharp}
* @throws {Error} Invalid options
*/
@@ -1044,6 +1057,7 @@ function avif (options) {
* @param {boolean} [options.lossless=false] - use lossless compression
* @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 9 (slowest)
* @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
* @param {number} [options.bitdepth=8] - set bitdepth to 8, 10 or 12 bit
* @returns {Sharp}
* @throws {Error} Invalid options
*/
@@ -1082,6 +1096,16 @@ function heif (options) {
throw is.invalidParameterError('chromaSubsampling', 'one of: 4:2:0, 4:4:4', options.chromaSubsampling);
}
}
if (is.defined(options.bitdepth)) {
if (is.integer(options.bitdepth) && is.inArray(options.bitdepth, [8, 10, 12])) {
if (options.bitdepth !== 8 && this.constructor.versions.heif) {
throw is.invalidParameterError('bitdepth when using prebuilt binaries', 8, options.bitdepth);
}
this.options.heifBitdepth = options.bitdepth;
} else {
throw is.invalidParameterError('bitdepth', '8, 10 or 12', options.bitdepth);
}
}
} else {
throw is.invalidParameterError('options', 'Object', options);
}
@@ -1233,7 +1257,7 @@ function raw (options) {
* @param {number} [options.angle=0] tile angle of rotation, must be a multiple of 90.
* @param {string|Object} [options.background={r: 255, g: 255, b: 255, alpha: 1}] - background colour, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to white without transparency.
* @param {string} [options.depth] how deep to make the pyramid, possible values are `onepixel`, `onetile` or `one`, default based on layout.
* @param {number} [options.skipBlanks=-1] threshold to skip tile generation, a value 0 - 255 for 8-bit images or 0 - 65535 for 16-bit images
* @param {number} [options.skipBlanks=-1] Threshold to skip tile generation. Range is 0-255 for 8-bit images, 0-65535 for 16-bit images. Default is 5 for `google` layout, -1 (no skip) otherwise.
* @param {string} [options.container='fs'] tile container, with value `fs` (filesystem) or `zip` (compressed file).
* @param {string} [options.layout='dz'] filesystem layout, possible values are `dz`, `iiif`, `iiif3`, `zoomify` or `google`.
* @param {boolean} [options.centre=false] centre image in tile.

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-darwin-arm64",
"version": "0.33.2",
"version": "0.33.3",
"description": "Prebuilt sharp for use with macOS 64-bit ARM",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://sharp.pixelplumbing.com",
@@ -15,7 +15,7 @@
},
"preferUnplugged": true,
"optionalDependencies": {
"@img/sharp-libvips-darwin-arm64": "1.0.1"
"@img/sharp-libvips-darwin-arm64": "1.0.2"
},
"files": [
"lib"

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-darwin-x64",
"version": "0.33.2",
"version": "0.33.3",
"description": "Prebuilt sharp for use with macOS x64",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://sharp.pixelplumbing.com",
@@ -15,7 +15,7 @@
},
"preferUnplugged": true,
"optionalDependencies": {
"@img/sharp-libvips-darwin-x64": "1.0.1"
"@img/sharp-libvips-darwin-x64": "1.0.2"
},
"files": [
"lib"

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-linux-arm",
"version": "0.33.2",
"version": "0.33.3",
"description": "Prebuilt sharp for use with Linux (glibc) ARM (32-bit)",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://sharp.pixelplumbing.com",
@@ -15,7 +15,7 @@
},
"preferUnplugged": true,
"optionalDependencies": {
"@img/sharp-libvips-linux-arm": "1.0.1"
"@img/sharp-libvips-linux-arm": "1.0.2"
},
"files": [
"lib"

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-linux-arm64",
"version": "0.33.2",
"version": "0.33.3",
"description": "Prebuilt sharp for use with Linux (glibc) 64-bit ARM",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://sharp.pixelplumbing.com",
@@ -15,7 +15,7 @@
},
"preferUnplugged": true,
"optionalDependencies": {
"@img/sharp-libvips-linux-arm64": "1.0.1"
"@img/sharp-libvips-linux-arm64": "1.0.2"
},
"files": [
"lib"

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-linux-s390x",
"version": "0.33.2",
"version": "0.33.3",
"description": "Prebuilt sharp for use with Linux (glibc) s390x",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://sharp.pixelplumbing.com",
@@ -15,7 +15,7 @@
},
"preferUnplugged": true,
"optionalDependencies": {
"@img/sharp-libvips-linux-s390x": "1.0.1"
"@img/sharp-libvips-linux-s390x": "1.0.2"
},
"files": [
"lib"

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-linux-x64",
"version": "0.33.2",
"version": "0.33.3",
"description": "Prebuilt sharp for use with Linux (glibc) x64",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://sharp.pixelplumbing.com",
@@ -15,7 +15,7 @@
},
"preferUnplugged": true,
"optionalDependencies": {
"@img/sharp-libvips-linux-x64": "1.0.1"
"@img/sharp-libvips-linux-x64": "1.0.2"
},
"files": [
"lib"

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-linuxmusl-arm64",
"version": "0.33.2",
"version": "0.33.3",
"description": "Prebuilt sharp for use with Linux (musl) 64-bit ARM",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://sharp.pixelplumbing.com",
@@ -15,7 +15,7 @@
},
"preferUnplugged": true,
"optionalDependencies": {
"@img/sharp-libvips-linuxmusl-arm64": "1.0.1"
"@img/sharp-libvips-linuxmusl-arm64": "1.0.2"
},
"files": [
"lib"

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-linuxmusl-x64",
"version": "0.33.2",
"version": "0.33.3",
"description": "Prebuilt sharp for use with Linux (musl) x64",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://sharp.pixelplumbing.com",
@@ -15,7 +15,7 @@
},
"preferUnplugged": true,
"optionalDependencies": {
"@img/sharp-libvips-linuxmusl-x64": "1.0.1"
"@img/sharp-libvips-linuxmusl-x64": "1.0.2"
},
"files": [
"lib"

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp",
"version": "0.33.2",
"version": "0.33.3",
"private": "true",
"workspaces": [
"darwin-arm64",

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-wasm32",
"version": "0.33.2",
"version": "0.33.3",
"description": "Prebuilt sharp for use with wasm32",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://sharp.pixelplumbing.com",
@@ -34,7 +34,7 @@
"pnpm": ">=7.1.0"
},
"dependencies": {
"@emnapi/runtime": "^0.45.0"
"@emnapi/runtime": "^1.1.0"
},
"cpu": [
"wasm32"

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-win32-ia32",
"version": "0.33.2",
"version": "0.33.3",
"description": "Prebuilt sharp for use with Windows x86 (32-bit)",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://sharp.pixelplumbing.com",

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-win32-x64",
"version": "0.33.2",
"version": "0.33.3",
"description": "Prebuilt sharp for use with Windows x64",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://sharp.pixelplumbing.com",

View File

@@ -1,7 +1,7 @@
{
"name": "sharp",
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, GIF, AVIF and TIFF images",
"version": "0.33.2",
"version": "0.33.3",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://sharp.pixelplumbing.com",
"contributors": [
@@ -137,57 +137,57 @@
],
"dependencies": {
"color": "^4.2.3",
"detect-libc": "^2.0.2",
"semver": "^7.5.4"
"detect-libc": "^2.0.3",
"semver": "^7.6.0"
},
"optionalDependencies": {
"@img/sharp-darwin-arm64": "0.33.2",
"@img/sharp-darwin-x64": "0.33.2",
"@img/sharp-libvips-darwin-arm64": "1.0.1",
"@img/sharp-libvips-darwin-x64": "1.0.1",
"@img/sharp-libvips-linux-arm": "1.0.1",
"@img/sharp-libvips-linux-arm64": "1.0.1",
"@img/sharp-libvips-linux-s390x": "1.0.1",
"@img/sharp-libvips-linux-x64": "1.0.1",
"@img/sharp-libvips-linuxmusl-arm64": "1.0.1",
"@img/sharp-libvips-linuxmusl-x64": "1.0.1",
"@img/sharp-linux-arm": "0.33.2",
"@img/sharp-linux-arm64": "0.33.2",
"@img/sharp-linux-s390x": "0.33.2",
"@img/sharp-linux-x64": "0.33.2",
"@img/sharp-linuxmusl-arm64": "0.33.2",
"@img/sharp-linuxmusl-x64": "0.33.2",
"@img/sharp-wasm32": "0.33.2",
"@img/sharp-win32-ia32": "0.33.2",
"@img/sharp-win32-x64": "0.33.2"
"@img/sharp-darwin-arm64": "0.33.3",
"@img/sharp-darwin-x64": "0.33.3",
"@img/sharp-libvips-darwin-arm64": "1.0.2",
"@img/sharp-libvips-darwin-x64": "1.0.2",
"@img/sharp-libvips-linux-arm": "1.0.2",
"@img/sharp-libvips-linux-arm64": "1.0.2",
"@img/sharp-libvips-linux-s390x": "1.0.2",
"@img/sharp-libvips-linux-x64": "1.0.2",
"@img/sharp-libvips-linuxmusl-arm64": "1.0.2",
"@img/sharp-libvips-linuxmusl-x64": "1.0.2",
"@img/sharp-linux-arm": "0.33.3",
"@img/sharp-linux-arm64": "0.33.3",
"@img/sharp-linux-s390x": "0.33.3",
"@img/sharp-linux-x64": "0.33.3",
"@img/sharp-linuxmusl-arm64": "0.33.3",
"@img/sharp-linuxmusl-x64": "0.33.3",
"@img/sharp-wasm32": "0.33.3",
"@img/sharp-win32-ia32": "0.33.3",
"@img/sharp-win32-x64": "0.33.3"
},
"devDependencies": {
"@emnapi/runtime": "^0.45.0",
"@img/sharp-libvips-dev": "1.0.1",
"@img/sharp-libvips-dev-wasm32": "1.0.1",
"@img/sharp-libvips-win32-ia32": "1.0.1",
"@img/sharp-libvips-win32-x64": "1.0.1",
"@emnapi/runtime": "^1.1.0",
"@img/sharp-libvips-dev": "1.0.2",
"@img/sharp-libvips-dev-wasm32": "1.0.3",
"@img/sharp-libvips-win32-ia32": "1.0.2",
"@img/sharp-libvips-win32-x64": "1.0.2",
"@types/node": "*",
"async": "^3.2.5",
"cc": "^3.0.1",
"emnapi": "^0.45.0",
"exif-reader": "^2.0.0",
"emnapi": "^1.1.0",
"exif-reader": "^2.0.1",
"extract-zip": "^2.0.1",
"icc": "^3.0.0",
"jsdoc-to-markdown": "^8.0.0",
"jsdoc-to-markdown": "^8.0.1",
"license-checker": "^25.0.1",
"mocha": "^10.2.0",
"node-addon-api": "^7.0.0",
"mocha": "^10.3.0",
"node-addon-api": "^8.0.0",
"nyc": "^15.1.0",
"prebuild": "^12.1.0",
"prebuild": "^13.0.0",
"semistandard": "^17.0.0",
"tar-fs": "^3.0.4",
"tsd": "^0.30.3"
"tar-fs": "^3.0.5",
"tsd": "^0.30.7"
},
"license": "Apache-2.0",
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0",
"libvips": ">=8.15.1"
"libvips": ">=8.15.2"
},
"funding": {
"url": "https://opencollective.com/libvips"

View File

@@ -16,8 +16,8 @@
#if (VIPS_MAJOR_VERSION < 8) || \
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 15) || \
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 15 && VIPS_MICRO_VERSION < 1)
#error "libvips version 8.15.1+ is required - please see https://sharp.pixelplumbing.com/install"
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 15 && VIPS_MICRO_VERSION < 2)
#error "libvips version 8.15.2+ is required - please see https://sharp.pixelplumbing.com/install"
#endif
#if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)))

View File

@@ -54,7 +54,7 @@ class PipelineWorker : public Napi::AsyncWorker {
sharp::ImageType inputImageType;
std::tie(image, inputImageType) = sharp::OpenInput(baton->input);
VipsAccess access = baton->input->access;
image = sharp::EnsureColourspace(image, baton->colourspaceInput);
image = sharp::EnsureColourspace(image, baton->colourspacePipeline);
int nPages = baton->input->pages;
if (nPages == -1) {
@@ -189,7 +189,7 @@ class PipelineWorker : public Napi::AsyncWorker {
// - input colourspace is not specified;
bool const shouldPreShrink = (targetResizeWidth > 0 || targetResizeHeight > 0) &&
baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimThreshold < 0.0 &&
baton->colourspaceInput == VIPS_INTERPRETATION_LAST && !shouldRotateBefore;
baton->colourspacePipeline == VIPS_INTERPRETATION_LAST && !shouldRotateBefore;
if (shouldPreShrink) {
// The common part of the shrink: the bit by which both axes must be shrunk
@@ -331,6 +331,7 @@ class PipelineWorker : public Napi::AsyncWorker {
sharp::HasProfile(image) &&
image.interpretation() != VIPS_INTERPRETATION_LABS &&
image.interpretation() != VIPS_INTERPRETATION_GREY16 &&
baton->colourspacePipeline != VIPS_INTERPRETATION_CMYK &&
!baton->input->ignoreIcc
) {
// Convert to sRGB/P3 using embedded profile
@@ -344,7 +345,7 @@ class PipelineWorker : public Napi::AsyncWorker {
}
} else if (
image.interpretation() == VIPS_INTERPRETATION_CMYK &&
baton->colourspaceInput != VIPS_INTERPRETATION_CMYK
baton->colourspacePipeline != VIPS_INTERPRETATION_CMYK
) {
image = image.icc_transform(processingProfile, VImage::option()
->set("input_profile", "cmyk")
@@ -432,7 +433,7 @@ class PipelineWorker : public Napi::AsyncWorker {
for (unsigned int i = 0; i < baton->joinChannelIn.size(); i++) {
baton->joinChannelIn[i]->access = access;
std::tie(joinImage, joinImageType) = sharp::OpenInput(baton->joinChannelIn[i]);
joinImage = sharp::EnsureColourspace(joinImage, baton->colourspaceInput);
joinImage = sharp::EnsureColourspace(joinImage, baton->colourspacePipeline);
image = image.bandjoin(joinImage);
}
image = image.copy(VImage::option()->set("interpretation", baton->colourspace));
@@ -642,7 +643,7 @@ class PipelineWorker : public Napi::AsyncWorker {
sharp::ImageType compositeImageType = sharp::ImageType::UNKNOWN;
composite->input->access = access;
std::tie(compositeImage, compositeImageType) = sharp::OpenInput(composite->input);
compositeImage = sharp::EnsureColourspace(compositeImage, baton->colourspaceInput);
compositeImage = sharp::EnsureColourspace(compositeImage, baton->colourspacePipeline);
// Verify within current dimensions
if (compositeImage.width() > image.width() || compositeImage.height() > image.height()) {
throw vips::VError("Image to composite must have same dimensions or smaller");
@@ -743,7 +744,7 @@ class PipelineWorker : public Napi::AsyncWorker {
sharp::ImageType booleanImageType = sharp::ImageType::UNKNOWN;
baton->boolean->access = access;
std::tie(booleanImage, booleanImageType) = sharp::OpenInput(baton->boolean);
booleanImage = sharp::EnsureColourspace(booleanImage, baton->colourspaceInput);
booleanImage = sharp::EnsureColourspace(booleanImage, baton->colourspacePipeline);
image = sharp::Boolean(image, booleanImage, baton->booleanOp);
image = sharp::RemoveGifPalette(image);
}
@@ -776,9 +777,9 @@ class PipelineWorker : public Napi::AsyncWorker {
// 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()));
// Transform colours from embedded profile to output profile
if ((baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) &&
if ((baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) && baton->colourspacePipeline != VIPS_INTERPRETATION_CMYK &&
baton->withIccProfile.empty() && sharp::HasProfile(image)) {
image = image.icc_transform("srgb", VImage::option()
image = image.icc_transform(processingProfile, VImage::option()
->set("embedded", TRUE)
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
->set("intent", VIPS_INTENT_PERCEPTUAL));
@@ -988,7 +989,7 @@ class PipelineWorker : public Napi::AsyncWorker {
->set("Q", baton->heifQuality)
->set("compression", baton->heifCompression)
->set("effort", baton->heifEffort)
->set("bitdepth", 8)
->set("bitdepth", baton->heifBitdepth)
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
->set("lossless", baton->heifLossless)));
@@ -1181,7 +1182,7 @@ class PipelineWorker : public Napi::AsyncWorker {
->set("Q", baton->heifQuality)
->set("compression", baton->heifCompression)
->set("effort", baton->heifEffort)
->set("bitdepth", 8)
->set("bitdepth", baton->heifBitdepth)
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
->set("lossless", baton->heifLossless));
@@ -1607,10 +1608,10 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
baton->recombMatrix[i] = sharp::AttrAsDouble(recombMatrix, i);
}
}
baton->colourspaceInput = sharp::AttrAsEnum<VipsInterpretation>(
options, "colourspaceInput", VIPS_TYPE_INTERPRETATION);
if (baton->colourspaceInput == VIPS_INTERPRETATION_ERROR) {
baton->colourspaceInput = VIPS_INTERPRETATION_LAST;
baton->colourspacePipeline = sharp::AttrAsEnum<VipsInterpretation>(
options, "colourspacePipeline", VIPS_TYPE_INTERPRETATION);
if (baton->colourspacePipeline == VIPS_INTERPRETATION_ERROR) {
baton->colourspacePipeline = VIPS_INTERPRETATION_LAST;
}
baton->colourspace = sharp::AttrAsEnum<VipsInterpretation>(options, "colourspace", VIPS_TYPE_INTERPRETATION);
if (baton->colourspace == VIPS_INTERPRETATION_ERROR) {
@@ -1695,6 +1696,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
options, "heifCompression", VIPS_TYPE_FOREIGN_HEIF_COMPRESSION);
baton->heifEffort = sharp::AttrAsUint32(options, "heifEffort");
baton->heifChromaSubsampling = sharp::AttrAsStr(options, "heifChromaSubsampling");
baton->heifBitdepth = sharp::AttrAsUint32(options, "heifBitdepth");
baton->jxlDistance = sharp::AttrAsDouble(options, "jxlDistance");
baton->jxlDecodingTier = sharp::AttrAsUint32(options, "jxlDecodingTier");
baton->jxlEffort = sharp::AttrAsUint32(options, "jxlEffort");

View File

@@ -181,6 +181,7 @@ struct PipelineBaton {
int heifEffort;
std::string heifChromaSubsampling;
bool heifLossless;
int heifBitdepth;
double jxlDistance;
int jxlDecodingTier;
int jxlEffort;
@@ -205,7 +206,7 @@ struct PipelineBaton {
int extractChannel;
bool removeAlpha;
double ensureAlpha;
VipsInterpretation colourspaceInput;
VipsInterpretation colourspacePipeline;
VipsInterpretation colourspace;
std::vector<int> delay;
int loop;
@@ -349,6 +350,7 @@ struct PipelineBaton {
heifEffort(4),
heifChromaSubsampling("4:4:4"),
heifLossless(false),
heifBitdepth(8),
jxlDistance(1.0),
jxlDecodingTier(0),
jxlEffort(7),
@@ -369,7 +371,7 @@ struct PipelineBaton {
extractChannel(-1),
removeAlpha(false),
ensureAlpha(-1.0),
colourspaceInput(VIPS_INTERPRETATION_LAST),
colourspacePipeline(VIPS_INTERPRETATION_LAST),
colourspace(VIPS_INTERPRETATION_LAST),
loop(-1),
tileSize(256),

View File

@@ -410,7 +410,7 @@ sharp({
// Taken from API documentation at
// https://sharp.pixelplumbing.com/api-operation#clahe
// introducted
// introduced
sharp('input.jpg').clahe({ width: 10, height: 10 }).toFile('output.jpg');
sharp('input.jpg').clahe({ width: 10, height: 10, maxSlope: 5 }).toFile('outfile.jpg');
@@ -595,7 +595,7 @@ sharp({
rgba: true,
justify: true,
spacing: 10,
wrap: 'charWord',
wrap: 'word-char',
},
})
.png()

View File

@@ -144,4 +144,10 @@ describe('AVIF', () => {
/Processed image is too large for the HEIF format/
)
);
it('Invalid bitdepth value throws error', async () => {
assert.rejects(
() => sharp().avif({ bitdepth: 11 }),
/Error: Expected 8, 10 or 12 for bitdepth but received 11 of type number/);
});
});

View File

@@ -77,4 +77,26 @@ describe('Clone', function () {
assert.strictEqual(0, original.listenerCount('finish'));
assert.strictEqual(0, clone.listenerCount('finish'));
});
it('Ensure deep clone of properties, including arrays', async () => {
const alpha = await sharp({
create: { width: 320, height: 240, channels: 3, background: 'red' }
}).toColourspace('b-w').png().toBuffer();
const original = sharp();
const joiner = original.clone().joinChannel(alpha);
const negater = original.clone().negate();
fs.createReadStream(fixtures.inputJpg320x240).pipe(original);
const joined = await joiner.png({ effort: 1 }).toBuffer();
const negated = await negater.png({ effort: 1 }).toBuffer();
const joinedMetadata = await sharp(joined).metadata();
assert.strictEqual(joinedMetadata.channels, 4);
assert.strictEqual(joinedMetadata.hasAlpha, true);
const negatedMetadata = await sharp(negated).metadata();
assert.strictEqual(negatedMetadata.channels, 3);
assert.strictEqual(negatedMetadata.hasAlpha, false);
});
});

View File

@@ -451,7 +451,7 @@ describe('composite', () => {
assert.strictEqual(info.height, 40);
});
it('Ensure implict unpremultiply after resize but before composite', async () => {
it('Ensure implicit unpremultiply after resize but before composite', async () => {
const [r, g, b, a] = await sharp({
create: {
width: 1, height: 1, channels: 4, background: 'saddlebrown'

View File

@@ -78,4 +78,21 @@ describe('HEIF', () => {
sharp().heif({ compression: 'av1', chromaSubsampling: '4:4:4' });
});
});
it('valid bitdepth value does not throw an error', () => {
const { heif } = sharp.versions;
delete sharp.versions.heif;
assert.doesNotThrow(() => {
sharp().heif({ compression: 'av1', bitdepth: 12 });
});
sharp.versions.heif = '1.2.3';
assert.throws(() => {
sharp().heif({ compression: 'av1', bitdepth: 10 });
}, /Error: Expected 8 for bitdepth when using prebuilt binaries but received 10 of type number/);
sharp.versions.heif = heif;
});
it('invalid bitdepth value should throw an error', () => {
assert.throws(() => {
sharp().heif({ compression: 'av1', bitdepth: 11 });
}, /Error: Expected 8, 10 or 12 for bitdepth but received 11 of type number/);
});
});

View File

@@ -162,7 +162,7 @@ describe('libvips binaries', function () {
process.env.npm_config_arch = 's390x';
process.env.npm_config_libc = '';
const locatorHash = libvips.yarnLocator();
assert.strictEqual(locatorHash, 'f2bd19138a');
assert.strictEqual(locatorHash, '45978c229d');
delete process.env.npm_config_platform;
delete process.env.npm_config_arch;
delete process.env.npm_config_libc;

View File

@@ -576,6 +576,19 @@ describe('Image metadata', function () {
assert.strictEqual(description, 'Generic RGB Profile');
});
it('keep existing CMYK ICC profile', async () => {
const data = await sharp(fixtures.inputJpgWithCmykProfile)
.pipelineColourspace('cmyk')
.toColourspace('cmyk')
.keepIccProfile()
.toBuffer();
const metadata = await sharp(data).metadata();
assert.strictEqual(metadata.channels, 4);
const { description } = icc.parse(metadata.icc);
assert.strictEqual(description, 'U.S. Web Coated (SWOP) v2');
});
it('transform to ICC profile and attach', async () => {
const data = await sharp({ create })
.png()

View File

@@ -319,21 +319,21 @@ describe('Text to image', function () {
it('valid wrap throws', () => {
assert.doesNotThrow(() => sharp({ text: { text: 'text', wrap: 'none' } }));
assert.doesNotThrow(() => sharp({ text: { text: 'text', wrap: 'wordChar' } }));
assert.doesNotThrow(() => sharp({ text: { text: 'text', wrap: 'word-char' } }));
});
it('invalid wrap throws', () => {
assert.throws(
() => sharp({ text: { text: 'text', wrap: 1 } }),
/Expected one of: word, char, wordChar, none for text\.wrap but received 1 of type number/
/Expected one of: word, char, word-char, none for text\.wrap but received 1 of type number/
);
assert.throws(
() => sharp({ text: { text: 'text', wrap: false } }),
/Expected one of: word, char, wordChar, none for text\.wrap but received false of type boolean/
/Expected one of: word, char, word-char, none for text\.wrap but received false of type boolean/
);
assert.throws(
() => sharp({ text: { text: 'text', wrap: 'invalid' } }),
/Expected one of: word, char, wordChar, none for text\.wrap but received invalid of type string/
/Expected one of: word, char, word-char, none for text\.wrap but received invalid of type string/
);
});
});