keepGainMap(): extract() crops the base image but leaves the gain map uncropped
Is this a possible bug in a feature of sharp, unrelated to installation?
- [ x] Running
npm install sharpcompletes without error. - [ x] Running
node -e "import 'sharp'"completes without error.
Are you using the latest version of sharp?
- [ x] I am using the latest version of
sharpas reported bynpm view sharp dist-tags.latest. Running 0.35.4
What is the output of running npx envinfo --binaries --system --npmPackages=sharp --npmGlobalPackages=sharp?
System: OS: macOS 27.0 CPU: (18) arm64 Apple M5 Max Memory: 6.47 GB / 128.00 GB Shell: 3.2.57 - /bin/bash Binaries: Node: 24.18.0 - /Users/redacted/.nvm/versions/node/v24.18.0/bin/node Yarn: 1.22.19 - /usr/local/bin/yarn npm: 11.16.0 - /Users/redacted/.nvm/versions/node/v24.18.0/bin/npm
Does this problem relate to file caching?
- [x ] Adding
sharp.cache(false)does not fix this problem.
Does this problem relate to images appearing to have been rotated by 90 degrees?
- [x ] Using
rotate()orkeepExif()does not fix this problem.
What are the steps to reproduce?
run code below
Tested against sharp main at commit 9dcb3dd (reports version 0.35.4), using libvips 8.18.6 and libultrahdr 2.0.2.
What is the expected behaviour?
The image should be cropped, but show no changes in the cropped area. However, when you view the output on an HDR-capable display, you'll see ghosting because the gain map was not cropped to stay aligned to the base image.
Expected result: both the base image and this source’s full-resolution gain map are cropped to 601 × 499. Actual: the base becomes 601 × 499, but the gain map remains 1080 × 1080.
Please provide a minimal, standalone code sample, without other dependencies, that demonstrates this problem
node - "./ISO JPG - sRGB - transcoding test - Greg Benz.jpg" <<'NODE'
const sharp = require('sharp');
const path = require('node:path');
(async () => {
const output = path.resolve('./crop-gainmap-issue.jpg');
await sharp(process.argv[2])
.keepGainMap()
.extract({ left: 101, top: 153, width: 601, height: 499 }) // Both images should be cropped, but the gain map stays at its original size.
.toFile(output);
const base = await sharp(output).metadata();
const map = await sharp(base.gainMap.image).metadata();
console.log(`Base image: ${base.width} × ${base.height}`);
console.log(`Gain map: ${map.width} × ${map.height}`);
console.log(`Saved: ${output}`);
})().catch(error => {
console.error(error.message);
process.exitCode = 1;
});
NODEPlease provide sample image(s) that help explain this problem
Source to test:
The failed output:
Source: lovell/sharp