Repository navigation
Description
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;
});
NODE


Activity
Improve gain map support for extract operation #4606
lovell commentedon Sep 24, 2026
Thanks for reporting, commit cef3b8c fixes this.
As an aside, I also noticed the
trimoperation doesn't work when keeping gain maps. Implementing this will be a bit more involved as it would need to take into consideration (scaled) bounding boxes on the gain map, so I've simply marked it as unsupported for now.gregbenz commentedon Sep 24, 2026
@lovell Thank you for the fix!
I see one potential area to consider: Rotation before cropping: From reading the code, it looks like the base image rotates, but the gain map does not. So the crop can select the wrong map region or exceed its bounds. Ie, does this fix also cover .keepGainMap().rotate(90).extract(...)?
Improve gain map support for rotate-then-extract #4606
lovell commentedon Sep 26, 2026
Commit 49f4903 fixes rotate-then-extract, thanks for the suggestion.
lovell commentedon Sep 27, 2026
v0.35.5 now available
fix(deps): update dependency sharp to v0.35.5 (#1052)
chore(deps): update dependency sharp to ^0.35.5 (#9)
Further improve gain map support for uncached rotate #4606
Update dependency sharp to v0.35.5 (#1785)