lovell / lovell/sharp

keepGainMap(): extract() crops the base image but leaves the gain map uncropped

Open
#4,606 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

triage
Dominant language
JavaScript
Stars
32.7k
Forks
1.4k
Avg merge
1d 14h
Merged PRs (30d)
5

Description

### Is this a possible bug in a feature of sharp, unrelated to installation?
- [ x] Running `npm install sharp` completes 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 `sharp` as reported by `npm 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()` or `keepExif()` 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
```

### Please provide sample image(s) that help explain this problem
Source to test:
Image

The failed output:
Image

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Run the provided Node.js reproduction with keepGainMap(), extract(), and toFile(), then inspect the resulting metadata through base.gainMap.image. Trace the keepGainMap/extract interaction in the sharp entry points and confirm the behavior against the supplied 601 × 499 base and 1080 × 1080 gain-map dimensions. Done means the gain map remains aligned with the cropped base image.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, nodejs
Domain
computer-graphics
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.