Compare commits

...

11 Commits

Author SHA1 Message Date
Lovell Fuller
deecb81b86 Add version to shared library filename to help avoid collision 2025-12-19 23:55:21 +00:00
Lovell Fuller
aaeded2b67 Add withGainMap to process HDR JPEGs with embedded gain map #4314 2025-12-19 15:41:09 +00:00
Lovell Fuller
f6cdd36559 Bump devDeps 2025-12-18 22:47:14 +00:00
Lovell Fuller
283c7d3f0c Drop Node.js 18, now requires Node.js >= 20.9.0 2025-12-17 15:08:34 +00:00
Lovell Fuller
34c39fa194 Upgrade to libvips v8.18.0-rc.2 2025-12-17 13:26:51 +00:00
Lovell Fuller
7b4c476243 CI: Update to latest FreeBSD 16 2025-12-16 19:59:31 +00:00
Lovell Fuller
084a30f8bf Docs: clarify metadata 'format' property #4483 2025-12-10 15:38:14 +00:00
Kleis Auke Wolthuizen
3609c61a22 Tests: fix JP2 suite with global libvips (#4477) 2025-11-15 10:55:58 +00:00
Jiralite
dc6820b49f TypeScript: tag deprecated constructor properties (#4474) 2025-11-10 16:41:22 +00:00
Sylvester Keil
f2a49d19c9 Fix invalid escape sequence (#4471) 2025-11-07 11:39:39 +00:00
Lovell Fuller
e062456868 Release v0.34.5 2025-11-06 14:06:31 +00:00
47 changed files with 406 additions and 199 deletions

View File

@@ -1,5 +1,5 @@
freebsd_instance:
image_family: freebsd-15-0
image_family: freebsd-16-0-snap
task:
name: FreeBSD

View File

@@ -31,7 +31,7 @@ please open an issue against that package instead.
<!-- Please place an [x] in the relevant box to confirm. -->
- [ ] I am using Node.js with a version that satisfies `^18.17.0 || ^20.3.0 || >=21.0.0`
- [ ] I am using Node.js with a version that satisfies `>=20.9.0`
- [ ] I am using Deno
- [ ] I am using Bun

View File

@@ -9,8 +9,8 @@ jobs:
contents: read
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v5
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: "24"
- run: npm install --ignore-scripts
@@ -31,123 +31,129 @@ jobs:
- os: ubuntu-24.04
container: rockylinux:8
nodejs_arch: x64
nodejs_version: "^18.17.0"
nodejs_version_major: 18
nodejs_version: "^20.9.0"
nodejs_version_major: 20
platform: linux-x64
package: true
- os: ubuntu-24.04
container: rockylinux:8
nodejs_arch: x64
nodejs_version: "^20.3.0"
nodejs_version_major: 20
platform: linux-x64
- os: ubuntu-24.04
container: rockylinux:8
nodejs_arch: x64
nodejs_version: "^22.9.0"
nodejs_version: "^22"
nodejs_version_major: 22
platform: linux-x64
- os: ubuntu-24.04
container: node:18-alpine3.17
nodejs_version_major: 18
platform: linuxmusl-x64
package: true
container: rockylinux:8
nodejs_arch: x64
nodejs_version: "^24"
nodejs_version_major: 24
platform: linux-x64
- os: ubuntu-24.04
container: node:20-alpine3.18
nodejs_version_major: 20
platform: linuxmusl-x64
package: true
- os: ubuntu-24.04
container: node:22-alpine3.20
nodejs_version_major: 22
platform: linuxmusl-x64
- os: ubuntu-24.04
container: node:24-alpine3.22
nodejs_version_major: 24
platform: linuxmusl-x64
- os: ubuntu-24.04-arm
container: arm64v8/rockylinux:8
nodejs_arch: arm64
nodejs_version: "^18.17.0"
nodejs_version_major: 18
nodejs_version: "^20.9.0"
nodejs_version_major: 20
platform: linux-arm64
package: true
- os: ubuntu-24.04-arm
container: arm64v8/rockylinux:8
nodejs_arch: arm64
nodejs_version: "^20.3.0"
nodejs_version_major: 20
nodejs_version: "^22"
nodejs_version_major: 22
platform: linux-arm64
- os: ubuntu-24.04-arm
container: arm64v8/rockylinux:8
nodejs_arch: arm64
nodejs_version: "^24"
nodejs_version_major: 24
platform: linux-arm64
- os: macos-15-intel
nodejs_arch: x64
nodejs_version: "^18.17.0"
nodejs_version_major: 18
nodejs_version: "^20.9.0"
nodejs_version_major: 20
platform: darwin-x64
package: true
- os: macos-15-intel
nodejs_arch: x64
nodejs_version: "^20.3.0"
nodejs_version_major: 20
nodejs_version: "^22"
nodejs_version_major: 22
platform: darwin-x64
- os: macos-15-intel
nodejs_arch: x64
nodejs_version: "^22.9.0"
nodejs_version_major: 22
nodejs_version: "^24"
nodejs_version_major: 24
platform: darwin-x64
- os: macos-15
nodejs_arch: arm64
nodejs_version: "^18.17.0"
nodejs_version_major: 18
nodejs_version: "^20.9.0"
nodejs_version_major: 20
platform: darwin-arm64
package: true
- os: macos-15
nodejs_arch: arm64
nodejs_version: "^20.3.0"
nodejs_version_major: 20
nodejs_version: "^22"
nodejs_version_major: 22
platform: darwin-arm64
- os: macos-15
nodejs_arch: arm64
nodejs_version: "^22.9.0"
nodejs_version_major: 22
nodejs_version: "^24"
nodejs_version_major: 24
platform: darwin-arm64
- os: windows-2022
nodejs_arch: x86
nodejs_version: "18.18.2" # pinned to avoid 18.19.0 and npm 10
nodejs_version_major: 18
nodejs_version: "^20.9.0"
nodejs_version_major: 20
platform: win32-ia32
package: true
- os: windows-2022
nodejs_arch: x86
nodejs_version: "^20.3.0"
nodejs_version_major: 20
platform: win32-ia32
- os: windows-2022
nodejs_arch: x86
nodejs_version: "^22.9.0"
nodejs_version: "^22"
nodejs_version_major: 22
platform: win32-ia32
- os: windows-2022
nodejs_arch: x64
nodejs_version: "^18.17.0"
nodejs_version_major: 18
nodejs_version: "^20.9.0"
nodejs_version_major: 20
platform: win32-x64
package: true
- os: windows-2022
nodejs_arch: x64
nodejs_version: "^20.3.0"
nodejs_version_major: 20
nodejs_version: "^22"
nodejs_version_major: 22
platform: win32-x64
- os: windows-2022
nodejs_arch: x64
nodejs_version: "^22.9.0"
nodejs_version_major: 22
nodejs_version: "^24"
nodejs_version_major: 24
platform: win32-x64
- os: windows-11-arm
nodejs_arch: arm64
nodejs_version: "^20.3.0"
nodejs_version: "^20.9.0"
nodejs_version_major: 20
platform: win32-arm64
package: true
- os: windows-11-arm
nodejs_arch: arm64
nodejs_version: "^22.9.0"
nodejs_version: "^22"
nodejs_version_major: 22
platform: win32-arm64
- os: windows-11-arm
nodejs_arch: arm64
nodejs_version: "^24"
nodejs_version_major: 24
platform: win32-arm64
steps:
- name: Dependencies (Rocky Linux glibc)
if: contains(matrix.container, 'rockylinux')
@@ -159,22 +165,22 @@ 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@v5
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Dependencies (Node.js)
if: "!contains(matrix.platform, 'linuxmusl')"
uses: actions/setup-node@v5
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.nodejs_version }}
architecture: ${{ matrix.nodejs_arch }}
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- run: npm install
- run: npm run build
- run: npm run test-unit
- if: matrix.package
run: npm run package-from-local-build
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v6
if: matrix.package
with:
name: ${{ matrix.platform }}
@@ -191,16 +197,18 @@ jobs:
image: ${{ matrix.container }}
volumes:
- /opt:/opt:rw,rshared
- /opt:/__e/node20:ro,rshared
- /opt:/__e/node24:ro,rshared
strategy:
fail-fast: false
matrix:
include:
- container: node:18-alpine3.17
nodejs_version_major: 18
package: true
- container: node:20-alpine3.18
- container: node:20-alpine3.20
nodejs_version_major: 20
package: true
- container: node:22-alpine3.20
nodejs_version_major: 22
- container: node:24-alpine3.22
nodejs_version_major: 24
steps:
- name: Allow Linux musl containers on ARM64 runners # https://github.com/actions/runner/issues/801#issuecomment-2394425757
shell: sh
@@ -211,13 +219,13 @@ jobs:
ln -s /usr/bin/node /opt/bin/node
- name: Dependencies
run: apk add build-base git python3 font-noto --update-cache
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- run: npm install
- run: npm run build
- run: npm run test-unit
- if: matrix.package
run: npm run package-from-local-build
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v6
if: matrix.package
with:
name: linuxmusl-arm64
@@ -238,20 +246,20 @@ jobs:
base_image: "balenalib/rpi-raspbian:bullseye"
nodejs_arch: armv6l
nodejs_hostname: unofficial-builds.nodejs.org
nodejs_version: "18.17.0"
nodejs_version_major: 18
nodejs_version: "20.9.0"
nodejs_version_major: 20
- platform: linux-s390x
base_image: "--platform=linux/s390x s390x/debian:bookworm"
nodejs_arch: s390x
nodejs_hostname: nodejs.org
nodejs_version: "18.17.0"
nodejs_version_major: 18
nodejs_version: "20.9.0"
nodejs_version_major: 20
- platform: linux-ppc64
base_image: "--platform=linux/ppc64le ppc64le/debian:bookworm"
nodejs_arch: ppc64le
nodejs_hostname: nodejs.org
nodejs_version: "18.17.0"
nodejs_version_major: 18
nodejs_version: "20.9.0"
nodejs_version_major: 20
- platform: linux-riscv64
base_image: "--platform=linux/riscv64 riscv64/debian:trixie"
compiler_flags: "-march=rv64gc"
@@ -260,7 +268,7 @@ jobs:
nodejs_version: "20.19.5"
nodejs_version_major: 20
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- uses: uraimo/run-on-arch-action@v3
with:
arch: none
@@ -279,7 +287,7 @@ jobs:
npm run build
node --test test/unit/io.js
npm run package-from-local-build
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v6
with:
name: ${{ matrix.platform }}
path: npm/${{ matrix.platform }}
@@ -291,7 +299,7 @@ jobs:
needs: lint
name: "build-wasm32 [package]"
runs-on: ubuntu-24.04
container: "emscripten/emsdk:4.0.18"
container: "emscripten/emsdk:4.0.21"
steps:
- uses: actions/checkout@v4
- name: Dependencies
@@ -311,7 +319,7 @@ jobs:
test "$EMSCRIPTEN_VERSION_LIBVIPS" = "$EMSCRIPTEN_VERSION_SHARP"
- run: emmake npm run test-unit
- run: emmake npm run package-from-local-build
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v6
with:
name: wasm32
path: npm/wasm32
@@ -329,12 +337,12 @@ jobs:
- build-emscripten
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v7
with:
path: npm
- name: Create npm workspace tarball
run: tar -vcaf npm-workspace.tar.xz --directory npm --exclude=from-local-build.js .
- uses: actions/setup-node@v5
- uses: actions/setup-node@v6
with:
node-version: '24'
- name: Create release notes

View File

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

View File

@@ -8,7 +8,7 @@ smaller, web-friendly JPEG, PNG, WebP, GIF and AVIF images of varying dimensions
It can be used with all JavaScript runtimes
that provide support for Node-API v9, including
Node.js (^18.17.0 or >= 20.3.0), Deno and Bun.
Node.js (>= 20.9.0), Deno and Bun.
Resizing an image is typically 4x-5x faster than using the
quickest ImageMagick and GraphicsMagick settings

View File

@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.4/schema.json",
"$schema": "https://biomejs.dev/schemas/2.3.10/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",

View File

@@ -17,7 +17,7 @@ Dimensions in the response will respect the `page` and `pages` properties of the
A `Promise` is returned when `callback` is not provided.
- `format`: Name of decoder used to decompress image data e.g. `jpeg`, `png`, `webp`, `gif`, `svg`
- `format`: Name of decoder used to parse image e.g. `jpeg`, `png`, `webp`, `gif`, `svg`, `heif`, `tiff`
- `size`: Total size of image in bytes, for Stream and Buffer input only
- `width`: Number of pixels wide (EXIF orientation is not taken into consideration, see example below)
- `height`: Number of pixels high (EXIF orientation is not taken into consideration, see example below)
@@ -50,6 +50,7 @@ A `Promise` is returned when `callback` is not provided.
- `tifftagPhotoshop`: Buffer containing raw TIFFTAG_PHOTOSHOP data, if present
- `formatMagick`: String containing format for images loaded via *magick
- `comments`: Array of keyword/text pairs representing PNG text blocks, if present.
- `gainMap.image`: HDR gain map, if present, as compressed JPEG image.

View File

@@ -250,6 +250,27 @@ const outputWithP3 = await sharp(input)
```
## withGainMap
> withGainMap() ⇒ <code>Sharp</code>
If the input contains gain map metadata, use it to convert the main image to HDR (High Dynamic Range) before further processing.
The input gain map is discarded.
If the output is JPEG, generate and attach a new ISO 21496-1 gain map.
JPEG output options other than `quality` are ignored.
This feature is experimental and the API may change.
**Since**: 0.35.0
**Example**
```js
const outputWithGainMap = await sharp(inputWithGainMap)
.withGainMap()
.toBuffer();
```
## keepXmp
> keepXmp() ⇒ <code>Sharp</code>

View File

@@ -1,5 +1,5 @@
---
title: v0.34.5 - TBD
title: v0.34.5 - 6th November 2025
slug: changelog/v0.34.5
---

View File

@@ -0,0 +1,11 @@
---
title: v0.35.0 - TBC
slug: changelog/v0.35.0
---
* Upgrade to libvips v8.18.0 for upstream bug fixes.
* Drop support for Node.js 18, now requires Node.js >= 20.9.0.
* Add `withGainMap` to process HDR JPEG images with embedded gain maps.
[#4314](https://github.com/lovell/sharp/issues/4314)

View File

@@ -10,7 +10,7 @@ smaller, web-friendly JPEG, PNG, WebP, GIF and AVIF images of varying dimensions
It can be used with all JavaScript runtimes
that provide support for Node-API v9, including
Node.js >= 18.17.0, Deno and Bun.
Node.js >= 20.9.0, Deno and Bun.
Resizing an image is typically 4x-5x faster than using the
quickest ImageMagick and GraphicsMagick settings

View File

@@ -39,7 +39,7 @@ deno run --allow-env --allow-ffi --allow-read --allow-sys ...
## Prerequisites
* Node-API v9 compatible runtime e.g. Node.js ^18.17.0 or >=20.3.0.
* Node-API v9 compatible runtime e.g. Node.js >= 20.9.0.
## Prebuilt binaries

View File

@@ -313,6 +313,7 @@ const Sharp = function (input, options) {
withExif: {},
withExifMerge: true,
withXmp: '',
withGainMap: false,
resolveWithObject: false,
loop: -1,
delay: [],

13
lib/index.d.ts vendored
View File

@@ -1028,11 +1028,11 @@ declare namespace sharp {
openSlide?: OpenSlideInputOptions | undefined;
/** JPEG 2000 specific input options */
jp2?: Jp2InputOptions | undefined;
/** Deprecated: use tiff.subifd instead */
/** @deprecated Use {@link SharpOptions.tiff} instead */
subifd?: number | undefined;
/** Deprecated: use pdf.background instead */
/** @deprecated Use {@link SharpOptions.pdf} instead */
pdfBackground?: Colour | Color | undefined;
/** Deprecated: use openSlide.level instead */
/** @deprecated Use {@link SharpOptions.openSlide} instead */
level?: number | undefined;
/** Set to `true` to read all frames/pages of an animated image (equivalent of setting `pages` to `-1`). (optional, default false) */
animated?: boolean | undefined;
@@ -1277,6 +1277,8 @@ declare namespace sharp {
formatMagick?: string | undefined;
/** Array of keyword/text pairs representing PNG text blocks, if present. */
comments?: CommentsMetadata[] | undefined;
/** HDR gain map, if present */
gainMap?: GainMapMetadata | undefined;
}
interface LevelMetadata {
@@ -1289,6 +1291,11 @@ declare namespace sharp {
text: string;
}
interface GainMapMetadata {
/** JPEG image */
image: Buffer;
}
interface Stats {
/** Array of channel statistics for each channel in the image. */
channels: ChannelStats[];

View File

@@ -574,7 +574,7 @@ function _isStreamInput () {
*
* A `Promise` is returned when `callback` is not provided.
*
* - `format`: Name of decoder used to decompress image data e.g. `jpeg`, `png`, `webp`, `gif`, `svg`
* - `format`: Name of decoder used to parse image e.g. `jpeg`, `png`, `webp`, `gif`, `svg`, `heif`, `tiff`
* - `size`: Total size of image in bytes, for Stream and Buffer input only
* - `width`: Number of pixels wide (EXIF orientation is not taken into consideration, see example below)
* - `height`: Number of pixels high (EXIF orientation is not taken into consideration, see example below)
@@ -607,6 +607,7 @@ function _isStreamInput () {
* - `tifftagPhotoshop`: Buffer containing raw TIFFTAG_PHOTOSHOP data, if present
* - `formatMagick`: String containing format for images loaded via *magick
* - `comments`: Array of keyword/text pairs representing PNG text blocks, if present.
* - `gainMap.image`: HDR gain map, if present, as compressed JPEG image.
*
* @example
* const metadata = await sharp(input).metadata();

View File

@@ -319,6 +319,30 @@ function withIccProfile (icc, options) {
return this;
}
/**
* If the input contains gain map metadata, use it to convert the main image to HDR (High Dynamic Range) before further processing.
* The input gain map is discarded.
*
* If the output is JPEG, generate and attach a new ISO 21496-1 gain map.
* JPEG output options other than `quality` are ignored.
*
* This feature is experimental and the API may change.
*
* @since 0.35.0
*
* @example
* const outputWithGainMap = await sharp(inputWithGainMap)
* .withGainMap()
* .toBuffer();
*
* @returns {Sharp}
*/
function withGainMap() {
this.options.withGainMap = true;
this.options.colourspace = 'scrgb';
return this;
}
/**
* Keep XMP metadata from the input image in the output image.
*
@@ -1640,6 +1664,7 @@ module.exports = (Sharp) => {
withExifMerge,
keepIccProfile,
withIccProfile,
withGainMap,
keepXmp,
withXmp,
keepMetadata,

View File

@@ -7,12 +7,13 @@
const { familySync, versionSync } = require('detect-libc');
const { version } = require('../package.json');
const { runtimePlatformArch, isUnsupportedNodeRuntime, prebuiltPlatforms, minimumLibvipsVersion } = require('./libvips');
const runtimePlatform = runtimePlatformArch();
const paths = [
`../src/build/Release/sharp-${runtimePlatform}.node`,
'../src/build/Release/sharp-wasm32.node',
`../src/build/Release/sharp-${runtimePlatform}-${version}.node`,
`../src/build/Release/sharp-wasm32-${version}.node`,
`@img/sharp-${runtimePlatform}/sharp.node`,
'@img/sharp-wasm32/sharp.node'
];

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-darwin-arm64",
"version": "0.34.5-rc.1",
"version": "0.34.5",
"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.2.4"
"@img/sharp-libvips-darwin-arm64": "1.3.0-rc.1"
},
"files": [
"lib"
@@ -25,11 +25,11 @@
},
"type": "commonjs",
"exports": {
"./sharp.node": "./lib/sharp-darwin-arm64.node",
"./sharp.node": "./index.cjs",
"./package": "./package.json"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
"node": ">=20.9.0"
},
"os": [
"darwin"

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-darwin-x64",
"version": "0.34.5-rc.1",
"version": "0.34.5",
"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.2.4"
"@img/sharp-libvips-darwin-x64": "1.3.0-rc.1"
},
"files": [
"lib"
@@ -25,11 +25,11 @@
},
"type": "commonjs",
"exports": {
"./sharp.node": "./lib/sharp-darwin-x64.node",
"./sharp.node": "./index.cjs",
"./package": "./package.json"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
"node": ">=20.9.0"
},
"os": [
"darwin"

View File

@@ -44,9 +44,10 @@ cpSync(releaseDir, libDir, {
}
});
// Generate README
const { name, description } = require(`./${platform}/package.json`);
// Generate README and index.cjs
const { version, name, description } = require(`./${platform}/package.json`);
writeFileSync(join(destDir, 'README.md'), `# \`${name}\`\n\n${description}.\n${licensing}`);
writeFileSync(join(destDir, 'index.cjs'), `module.exports = require('./lib/sharp-${platform}-${version}.node');`);
// Copy Apache-2.0 LICENSE
copyFileSync(join(__dirname, '..', 'LICENSE'), join(destDir, 'LICENSE'));

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-linux-arm",
"version": "0.34.5-rc.1",
"version": "0.34.5",
"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.2.4"
"@img/sharp-libvips-linux-arm": "1.3.0-rc.1"
},
"files": [
"lib"
@@ -25,11 +25,11 @@
},
"type": "commonjs",
"exports": {
"./sharp.node": "./lib/sharp-linux-arm.node",
"./sharp.node": "./index.cjs",
"./package": "./package.json"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
"node": ">=20.9.0"
},
"config": {
"glibc": ">=2.31"

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-linux-arm64",
"version": "0.34.5-rc.1",
"version": "0.34.5",
"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.2.4"
"@img/sharp-libvips-linux-arm64": "1.3.0-rc.1"
},
"files": [
"lib"
@@ -25,11 +25,11 @@
},
"type": "commonjs",
"exports": {
"./sharp.node": "./lib/sharp-linux-arm64.node",
"./sharp.node": "./index.cjs",
"./package": "./package.json"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
"node": ">=20.9.0"
},
"config": {
"glibc": ">=2.26"

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-linux-ppc64",
"version": "0.34.5-rc.1",
"version": "0.34.5",
"description": "Prebuilt sharp for use with Linux (glibc) ppc64",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://sharp.pixelplumbing.com",
@@ -15,7 +15,7 @@
},
"preferUnplugged": true,
"optionalDependencies": {
"@img/sharp-libvips-linux-ppc64": "1.2.4"
"@img/sharp-libvips-linux-ppc64": "1.3.0-rc.1"
},
"files": [
"lib"
@@ -25,11 +25,11 @@
},
"type": "commonjs",
"exports": {
"./sharp.node": "./lib/sharp-linux-ppc64.node",
"./sharp.node": "./index.cjs",
"./package": "./package.json"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
"node": ">=20.9.0"
},
"config": {
"glibc": ">=2.36"

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-linux-riscv64",
"version": "0.34.5-rc.1",
"version": "0.34.5",
"description": "Prebuilt sharp for use with Linux (glibc) RISC-V 64-bit",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://sharp.pixelplumbing.com",
@@ -15,7 +15,7 @@
},
"preferUnplugged": true,
"optionalDependencies": {
"@img/sharp-libvips-linux-riscv64": "1.2.4"
"@img/sharp-libvips-linux-riscv64": "1.3.0-rc.1"
},
"files": [
"lib"
@@ -25,11 +25,11 @@
},
"type": "commonjs",
"exports": {
"./sharp.node": "./lib/sharp-linux-riscv64.node",
"./sharp.node": "./index.cjs",
"./package": "./package.json"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
"node": ">=20.9.0"
},
"config": {
"glibc": ">=2.41"

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-linux-s390x",
"version": "0.34.5-rc.1",
"version": "0.34.5",
"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.2.4"
"@img/sharp-libvips-linux-s390x": "1.3.0-rc.1"
},
"files": [
"lib"
@@ -25,11 +25,11 @@
},
"type": "commonjs",
"exports": {
"./sharp.node": "./lib/sharp-linux-s390x.node",
"./sharp.node": "./index.cjs",
"./package": "./package.json"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
"node": ">=20.9.0"
},
"config": {
"glibc": ">=2.36"

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-linux-x64",
"version": "0.34.5-rc.1",
"version": "0.34.5",
"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.2.4"
"@img/sharp-libvips-linux-x64": "1.3.0-rc.1"
},
"files": [
"lib"
@@ -25,11 +25,11 @@
},
"type": "commonjs",
"exports": {
"./sharp.node": "./lib/sharp-linux-x64.node",
"./sharp": "./index.cjs",
"./package": "./package.json"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
"node": ">=20.9.0"
},
"config": {
"glibc": ">=2.26"

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-linuxmusl-arm64",
"version": "0.34.5-rc.1",
"version": "0.34.5",
"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.2.4"
"@img/sharp-libvips-linuxmusl-arm64": "1.3.0-rc.1"
},
"files": [
"lib"
@@ -25,11 +25,11 @@
},
"type": "commonjs",
"exports": {
"./sharp.node": "./lib/sharp-linuxmusl-arm64.node",
"./sharp.node": "./index.cjs",
"./package": "./package.json"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
"node": ">=20.9.0"
},
"config": {
"musl": ">=1.2.2"

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-linuxmusl-x64",
"version": "0.34.5-rc.1",
"version": "0.34.5",
"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.2.4"
"@img/sharp-libvips-linuxmusl-x64": "1.3.0-rc.1"
},
"files": [
"lib"
@@ -25,11 +25,11 @@
},
"type": "commonjs",
"exports": {
"./sharp.node": "./lib/sharp-linuxmusl-x64.node",
"./sharp.node": "./index.cjs",
"./package": "./package.json"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
"node": ">=20.9.0"
},
"config": {
"musl": ">=1.2.2"

View File

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

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-wasm32",
"version": "0.34.5-rc.1",
"version": "0.34.5",
"description": "Prebuilt sharp for use with wasm32",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://sharp.pixelplumbing.com",
@@ -23,15 +23,15 @@
},
"type": "commonjs",
"exports": {
"./sharp.node": "./lib/sharp-wasm32.node.js",
"./sharp.node": "./index.cjs",
"./package": "./package.json",
"./versions": "./versions.json"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
"node": ">=20.9.0"
},
"dependencies": {
"@emnapi/runtime": "^1.7.0"
"@emnapi/runtime": "^1.7.1"
},
"cpu": [
"wasm32"

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-win32-arm64",
"version": "0.34.5-rc.1",
"version": "0.34.5",
"description": "Prebuilt sharp for use with Windows 64-bit ARM",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://sharp.pixelplumbing.com",
@@ -23,12 +23,12 @@
},
"type": "commonjs",
"exports": {
"./sharp.node": "./lib/sharp-win32-arm64.node",
"./sharp.node": "./index.cjs",
"./package": "./package.json",
"./versions": "./versions.json"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
"node": ">=20.9.0"
},
"os": [
"win32"

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-win32-ia32",
"version": "0.34.5-rc.1",
"version": "0.34.5",
"description": "Prebuilt sharp for use with Windows x86 (32-bit)",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://sharp.pixelplumbing.com",
@@ -23,12 +23,12 @@
},
"type": "commonjs",
"exports": {
"./sharp.node": "./lib/sharp-win32-ia32.node",
"./sharp.node": "./index.cjs",
"./package": "./package.json",
"./versions": "./versions.json"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
"node": ">=20.9.0"
},
"os": [
"win32"

View File

@@ -1,6 +1,6 @@
{
"name": "@img/sharp-win32-x64",
"version": "0.34.5-rc.1",
"version": "0.34.5",
"description": "Prebuilt sharp for use with Windows x64",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://sharp.pixelplumbing.com",
@@ -23,12 +23,12 @@
},
"type": "commonjs",
"exports": {
"./sharp.node": "./lib/sharp-win32-x64.node",
"./sharp.node": "./index.cjs",
"./package": "./package.json",
"./versions": "./versions.json"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
"node": ">=20.9.0"
},
"os": [
"win32"

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.34.5-rc.1",
"version": "0.34.5",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://sharp.pixelplumbing.com",
"contributors": [
@@ -144,65 +144,59 @@
"semver": "^7.7.3"
},
"optionalDependencies": {
"@img/sharp-darwin-arm64": "0.34.5-rc.1",
"@img/sharp-darwin-x64": "0.34.5-rc.1",
"@img/sharp-libvips-darwin-arm64": "1.2.4",
"@img/sharp-libvips-darwin-x64": "1.2.4",
"@img/sharp-libvips-linux-arm": "1.2.4",
"@img/sharp-libvips-linux-arm64": "1.2.4",
"@img/sharp-libvips-linux-ppc64": "1.2.4",
"@img/sharp-libvips-linux-riscv64": "1.2.4",
"@img/sharp-libvips-linux-s390x": "1.2.4",
"@img/sharp-libvips-linux-x64": "1.2.4",
"@img/sharp-libvips-linuxmusl-arm64": "1.2.4",
"@img/sharp-libvips-linuxmusl-x64": "1.2.4",
"@img/sharp-linux-arm": "0.34.5-rc.1",
"@img/sharp-linux-arm64": "0.34.5-rc.1",
"@img/sharp-linux-ppc64": "0.34.5-rc.1",
"@img/sharp-linux-riscv64": "0.34.5-rc.1",
"@img/sharp-linux-s390x": "0.34.5-rc.1",
"@img/sharp-linux-x64": "0.34.5-rc.1",
"@img/sharp-linuxmusl-arm64": "0.34.5-rc.1",
"@img/sharp-linuxmusl-x64": "0.34.5-rc.1",
"@img/sharp-wasm32": "0.34.5-rc.1",
"@img/sharp-win32-arm64": "0.34.5-rc.1",
"@img/sharp-win32-ia32": "0.34.5-rc.1",
"@img/sharp-win32-x64": "0.34.5-rc.1"
"@img/sharp-darwin-arm64": "0.34.5",
"@img/sharp-darwin-x64": "0.34.5",
"@img/sharp-libvips-darwin-arm64": "1.3.0-rc.1",
"@img/sharp-libvips-darwin-x64": "1.3.0-rc.1",
"@img/sharp-libvips-linux-arm": "1.3.0-rc.1",
"@img/sharp-libvips-linux-arm64": "1.3.0-rc.1",
"@img/sharp-libvips-linux-ppc64": "1.3.0-rc.1",
"@img/sharp-libvips-linux-riscv64": "1.3.0-rc.1",
"@img/sharp-libvips-linux-s390x": "1.3.0-rc.1",
"@img/sharp-libvips-linux-x64": "1.3.0-rc.1",
"@img/sharp-libvips-linuxmusl-arm64": "1.3.0-rc.1",
"@img/sharp-libvips-linuxmusl-x64": "1.3.0-rc.1",
"@img/sharp-linux-arm": "0.34.5",
"@img/sharp-linux-arm64": "0.34.5",
"@img/sharp-linux-ppc64": "0.34.5",
"@img/sharp-linux-riscv64": "0.34.5",
"@img/sharp-linux-s390x": "0.34.5",
"@img/sharp-linux-x64": "0.34.5",
"@img/sharp-linuxmusl-arm64": "0.34.5",
"@img/sharp-linuxmusl-x64": "0.34.5",
"@img/sharp-wasm32": "0.34.5",
"@img/sharp-win32-arm64": "0.34.5",
"@img/sharp-win32-ia32": "0.34.5",
"@img/sharp-win32-x64": "0.34.5"
},
"devDependencies": {
"@biomejs/biome": "^2.3.4",
"@biomejs/biome": "^2.3.10",
"@cpplint/cli": "^0.1.0",
"@emnapi/runtime": "^1.7.0",
"@img/sharp-libvips-dev": "1.2.4",
"@img/sharp-libvips-dev-wasm32": "1.2.4",
"@img/sharp-libvips-win32-arm64": "1.2.4",
"@img/sharp-libvips-win32-ia32": "1.2.4",
"@img/sharp-libvips-win32-x64": "1.2.4",
"@emnapi/runtime": "^1.7.1",
"@img/sharp-libvips-dev": "1.3.0-rc.1",
"@img/sharp-libvips-dev-wasm32": "1.3.0-rc.1",
"@img/sharp-libvips-win32-arm64": "1.3.0-rc.1",
"@img/sharp-libvips-win32-ia32": "1.3.0-rc.1",
"@img/sharp-libvips-win32-x64": "1.3.0-rc.1",
"@types/node": "*",
"emnapi": "^1.7.0",
"exif-reader": "^2.0.2",
"emnapi": "^1.7.1",
"exif-reader": "^2.0.3",
"extract-zip": "^2.0.1",
"icc": "^3.0.0",
"jsdoc-to-markdown": "^9.1.3",
"node-addon-api": "^8.5.0",
"node-gyp": "^11.5.0",
"node-gyp": "^12.1.0",
"tar-fs": "^3.1.1",
"tsd": "^0.33.0"
},
"license": "Apache-2.0",
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
"node": ">=20.9.0"
},
"config": {
"libvips": ">=8.17.3"
"libvips": ">=8.18.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"cc": {
"linelength": "120",
"filter": [
"build/include"
]
}
}

View File

@@ -5,6 +5,7 @@
'variables': {
'vips_version': '<!(node -p "require(\'../lib/libvips\').minimumLibvipsVersion")',
'platform_and_arch': '<!(node -p "require(\'../lib/libvips\').buildPlatformArch()")',
'sharp_version': '<!(node -p "require(\'../package.json\').version")',
'sharp_libvips_version': '<!(node -p "require(\'../package.json\').optionalDependencies[\'@img/sharp-libvips-<(platform_and_arch)\']")',
'sharp_libvips_yarn_locator': '<!(node -p "require(\'../lib/libvips\').yarnLocator()")',
'sharp_libvips_include_dir': '<!(node -p "require(\'../lib/libvips\').buildSharpLibvipsIncludeDir()")',
@@ -81,7 +82,7 @@
}]
]
}, {
'target_name': 'sharp-<(platform_and_arch)',
'target_name': 'sharp-<(platform_and_arch)-<(sharp_version)',
'defines': [
'G_DISABLE_ASSERT',
'G_DISABLE_CAST_CHECKS',
@@ -120,7 +121,7 @@
'conditions': [
['use_global_libvips == "true"', {
# Use pkg-config for include and lib
'include_dirs': ['<!@(PKG_CONFIG_PATH="<(pkg_config_path)" pkg-config --cflags-only-I vips-cpp vips glib-2.0 | sed s\/-I//g)'],
'include_dirs': ['<!@(PKG_CONFIG_PATH="<(pkg_config_path)" pkg-config --cflags-only-I vips-cpp vips glib-2.0 | sed s/-I//g)'],
'libraries': ['<!@(PKG_CONFIG_PATH="<(pkg_config_path)" pkg-config --libs vips-cpp)'],
'defines': [
'SHARP_USE_GLOBAL_LIBVIPS'
@@ -282,7 +283,7 @@
'target_name': 'copy-dll',
'type': 'none',
'dependencies': [
'sharp-<(platform_and_arch)'
'sharp-<(platform_and_arch)-<(sharp_version)'
],
'conditions': [
['OS == "win"', {

View File

@@ -289,6 +289,7 @@ namespace sharp {
case ImageType::JXL: id = "jxl"; break;
case ImageType::RAD: id = "rad"; break;
case ImageType::DCRAW: id = "dcraw"; break;
case ImageType::UHDR: id = "uhdr"; break;
case ImageType::VIPS: id = "vips"; break;
case ImageType::RAW: id = "raw"; break;
case ImageType::UNKNOWN: id = "unknown"; break;
@@ -339,6 +340,9 @@ namespace sharp {
{ "VipsForeignLoadRadBuffer", ImageType::RAD },
{ "VipsForeignLoadDcRawFile", ImageType::DCRAW },
{ "VipsForeignLoadDcRawBuffer", ImageType::DCRAW },
{ "VipsForeignLoadUhdr", ImageType::UHDR },
{ "VipsForeignLoadUhdrFile", ImageType::UHDR },
{ "VipsForeignLoadUhdrBuffer", ImageType::UHDR },
{ "VipsForeignLoadVips", ImageType::VIPS },
{ "VipsForeignLoadVipsFile", ImageType::VIPS },
{ "VipsForeignLoadRaw", ImageType::RAW }
@@ -356,6 +360,9 @@ namespace sharp {
imageType = it->second;
}
}
if (imageType == ImageType::UHDR) {
imageType = ImageType::JPEG;
}
return imageType;
}
@@ -375,6 +382,9 @@ namespace sharp {
imageType = ImageType::MISSING;
}
}
if (imageType == ImageType::UHDR) {
imageType = ImageType::JPEG;
}
return imageType;
}
@@ -1127,4 +1137,20 @@ namespace sharp {
}
return image;
}
/*
Does this image have a gain map?
*/
bool HasGainMap(VImage image) {
return image.get_typeof("gainmap-data") == VIPS_TYPE_BLOB;
}
/*
Removes gain map, if any.
*/
VImage RemoveGainMap(VImage image) {
VImage copy = image.copy();
copy.remove("gainmap-data");
return copy;
}
} // namespace sharp

View File

@@ -18,9 +18,9 @@
// Verify platform and compiler compatibility
#if (VIPS_MAJOR_VERSION < 8) || \
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 17) || \
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 17 && VIPS_MICRO_VERSION < 3)
#error "libvips version 8.17.3+ is required - please see https://sharp.pixelplumbing.com/install"
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 18) || \
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 18 && VIPS_MICRO_VERSION < 0)
#error "libvips version 8.18.0+ is required - please see https://sharp.pixelplumbing.com/install"
#endif
#if defined(__has_include)
@@ -173,6 +173,7 @@ namespace sharp {
JXL,
RAD,
DCRAW,
UHDR,
VIPS,
RAW,
UNKNOWN,
@@ -397,6 +398,16 @@ namespace sharp {
*/
VImage StaySequential(VImage image, bool condition = true);
/*
Does this image have a gain map?
*/
bool HasGainMap(VImage image);
/*
Removes gain map, if any.
*/
VImage RemoveGainMap(VImage image);
} // namespace sharp
#endif // SRC_COMMON_H_

View File

@@ -141,6 +141,14 @@ class MetadataWorker : public Napi::AsyncWorker {
memcpy(baton->tifftagPhotoshop, tifftagPhotoshop, tifftagPhotoshopLength);
baton->tifftagPhotoshopLength = tifftagPhotoshopLength;
}
// Gain Map
if (image.get_typeof("gainmap-data") == VIPS_TYPE_BLOB) {
size_t gainMapLength;
void const *gainMap = image.get_blob("gainmap-data", &gainMapLength);
baton->gainMap = static_cast<char *>(g_malloc(gainMapLength));
memcpy(baton->gainMap, gainMap, gainMapLength);
baton->gainMapLength = gainMapLength;
}
// PNG comments
vips_image_map(image.get_image(), readPNGComment, &baton->comments);
}
@@ -276,6 +284,12 @@ class MetadataWorker : public Napi::AsyncWorker {
Napi::Buffer<char>::NewOrCopy(env, baton->tifftagPhotoshop,
baton->tifftagPhotoshopLength, sharp::FreeCallback));
}
if (baton->gainMapLength > 0) {
Napi::Object gainMap = Napi::Object::New(env);
info.Set("gainMap", gainMap);
gainMap.Set("image",
Napi::Buffer<char>::NewOrCopy(env, baton->gainMap, baton->gainMapLength, sharp::FreeCallback));
}
if (baton->comments.size() > 0) {
int i = 0;
Napi::Array comments = Napi::Array::New(env, baton->comments.size());

View File

@@ -53,6 +53,8 @@ struct MetadataBaton {
size_t xmpLength;
char *tifftagPhotoshop;
size_t tifftagPhotoshopLength;
char *gainMap;
size_t gainMapLength;
MetadataComments comments;
std::string err;
@@ -82,7 +84,9 @@ struct MetadataBaton {
xmp(nullptr),
xmpLength(0),
tifftagPhotoshop(nullptr),
tifftagPhotoshopLength(0) {}
tifftagPhotoshopLength(0),
gainMap(nullptr),
gainMapLength(0) {}
};
Napi::Value metadata(const Napi::CallbackInfo& info);

View File

@@ -296,6 +296,14 @@ class PipelineWorker : public Napi::AsyncWorker {
if (baton->input->autoOrient) {
image = sharp::RemoveExifOrientation(image);
}
if (sharp::HasGainMap(image)) {
if (baton->withGainMap) {
image = image.uhdr2scRGB();
}
image = sharp::RemoveGainMap(image);
} else {
baton->withGainMap = false;
}
// Any pre-shrinking may already have been done
inputWidth = image.width();
@@ -335,7 +343,7 @@ class PipelineWorker : public Napi::AsyncWorker {
image.interpretation() != VIPS_INTERPRETATION_LABS &&
image.interpretation() != VIPS_INTERPRETATION_GREY16 &&
baton->colourspacePipeline != VIPS_INTERPRETATION_CMYK &&
!baton->input->ignoreIcc
!baton->input->ignoreIcc && !baton->withGainMap
) {
// Convert to sRGB/P3 using embedded profile
try {
@@ -1706,6 +1714,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
}
baton->withExifMerge = sharp::AttrAsBool(options, "withExifMerge");
baton->withXmp = sharp::AttrAsStr(options, "withXmp");
baton->withGainMap = sharp::AttrAsBool(options, "withGainMap");
baton->timeoutSeconds = sharp::AttrAsUint32(options, "timeoutSeconds");
baton->loop = sharp::AttrAsUint32(options, "loop");
baton->delay = sharp::AttrAsInt32Vector(options, "delay");

View File

@@ -208,6 +208,7 @@ struct PipelineBaton {
std::unordered_map<std::string, std::string> withExif;
bool withExifMerge;
std::string withXmp;
bool withGainMap;
int timeoutSeconds;
std::vector<double> convKernel;
int convKernelWidth;
@@ -381,6 +382,7 @@ struct PipelineBaton {
withMetadataOrientation(-1),
withMetadataDensity(0.0),
withExifMerge(true),
withGainMap(false),
timeoutSeconds(0),
convKernelWidth(0),
convKernelHeight(0),

BIN
test/fixtures/gain-map.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@@ -70,6 +70,7 @@ module.exports = {
inputJpgRandom: getPath('random.jpg'), // convert -size 200x200 xc: +noise Random random.jpg
inputJpgThRandom: getPath('thRandom.jpg'), // convert random.jpg -channel G -threshold 5% -separate +channel -negate thRandom.jpg
inputJpgLossless: getPath('testimgl.jpg'), // Lossless JPEG from ftp://ftp.fu-berlin.de/unix/X11/graphics/ImageMagick/delegates/ljpeg-6b.tar.gz
inputJpgWithGainMap: getPath('gain-map.jpg'), // https://github.com/libvips/libvips/issues/3799
inputPng: getPath('50020484-00001.png'), // http://c.searspartsdirect.com/lis_png/PLDM/50020484-00001.png
inputPngGradients: getPath('gradients-rgb8.png'),

69
test/unit/gain-map.js Normal file
View File

@@ -0,0 +1,69 @@
/*!
Copyright 2013 Lovell Fuller and others.
SPDX-License-Identifier: Apache-2.0
*/
const { describe, it } = require('node:test');
const sharp = require('../../');
const fixtures = require('../fixtures');
describe('Gain maps', () => {
it('Metadata contains gainMap', async (t) => {
t.plan(4);
const { format, gainMap } = await sharp(
fixtures.inputJpgWithGainMap,
).metadata();
t.assert.strictEqual(format, 'jpeg');
t.assert.strictEqual(typeof gainMap, 'object');
t.assert.ok(Buffer.isBuffer(gainMap.image));
t.assert.strictEqual(gainMap.image.length, 31738);
});
it('Can be regenerated', async (t) => {
t.plan(4);
const data = await sharp(fixtures.inputJpgWithGainMap)
.withGainMap()
.toBuffer();
const metadata = await sharp(data).metadata();
t.assert.strictEqual(metadata.format, 'jpeg');
t.assert.strictEqual(typeof metadata.gainMap, 'object');
t.assert.ok(Buffer.isBuffer(metadata.gainMap.image));
const {
format,
width,
height,
channels,
depth,
space,
hasProfile,
chromaSubsampling,
} = await sharp(metadata.gainMap.image).metadata();
t.assert.deepEqual(
{
format,
width,
height,
channels,
depth,
space,
hasProfile,
chromaSubsampling,
},
{
format: 'jpeg',
width: 1920,
height: 1080,
channels: 1,
depth: 'uchar',
space: 'b-w',
hasProfile: true,
chromaSubsampling: '4:4:4',
},
);
});
});

View File

@@ -45,11 +45,11 @@ describe('JP2 output', () => {
assert.strictEqual('png', info.format);
assert.strictEqual(8, info.width);
assert.strictEqual(15, info.height);
assert.strictEqual(4, info.channels);
assert.strictEqual(3, info.channels);
});
});
it('JP2 quality', (done) => {
it('JP2 quality', (_t, done) => {
sharp(fixtures.inputJp2)
.resize(320, 240)
.jp2({ quality: 70 })
@@ -65,7 +65,7 @@ describe('JP2 output', () => {
});
});
it('Without chroma subsampling generates larger file', (done) => {
it('Without chroma subsampling generates larger file', (_t, done) => {
// First generate with chroma subsampling (default)
sharp(fixtures.inputJp2)
.resize(320, 240)
@@ -111,7 +111,7 @@ describe('JP2 output', () => {
it('Invalid JP2 chromaSubsampling value throws error', () => {
assert.throws(
() => sharp().jp2({ chromaSubsampling: '4:2:2' }),
/Expected one of 4:2:0, 4:4:4 but received 4:2:2 of type string/
/Expected one of: 4:2:0, 4:4:4 for chromaSubsampling but received 4:2:2 of type string/
);
});
}

View File

@@ -180,7 +180,7 @@ describe('libvips binaries', () => {
process.env.npm_config_arch = 's390x';
process.env.npm_config_libc = '';
const locatorHash = libvips.yarnLocator();
assert.strictEqual(locatorHash, '4ab19140fd');
assert.strictEqual(locatorHash, '8cdba194cb');
delete process.env.npm_config_platform;
delete process.env.npm_config_arch;
delete process.env.npm_config_libc;

View File

@@ -226,12 +226,11 @@ describe('PNG', () => {
.png({ colours: 2, palette: false })
.toBuffer();
const { channels, isPalette, bitsPerSample, paletteBitDepth, size, space } = await sharp(data).metadata();
const { channels, isPalette, bitsPerSample, paletteBitDepth, space } = await sharp(data).metadata();
assert.strictEqual(channels, 1);
assert.strictEqual(isPalette, false);
assert.strictEqual(bitsPerSample, 1);
assert.strictEqual(paletteBitDepth, undefined);
assert.strictEqual(size, 89);
assert.strictEqual(space, 'b-w');
});