镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

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

Closed

Description

@gregbenz

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

Activity

  1. lovell commented on Sep 24, 2026

    @lovell
    Owner

    Thanks for reporting, commit cef3b8c fixes this.

    As an aside, I also noticed the trim operation 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.

  2. added this to the v0.35.5 milestone on Sep 24, 2026
  3. gregbenz commented on Sep 24, 2026

    @gregbenz
    Author

    @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(...)?

  4. lovell commented on Sep 26, 2026

    @lovell
    Owner

    Commit 49f4903 fixes rotate-then-extract, thanks for the suggestion.

  5. lovell commented on Sep 27, 2026

    @lovell
    Owner

    v0.35.5 now available

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions