Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Operations that introduce non-opaque background make unnecessary, implicit cast to double #3465

Closed
3 tasks done
stefanpieper opened this issue Nov 22, 2022 · 3 comments
Closed
3 tasks done

Comments

@stefanpieper
Copy link

stefanpieper commented Nov 22, 2022

Possible bug

Is this a possible bug in a feature of sharp, unrelated to installation?

  • Running npm install sharp completes without error.
  • Running node -e "require('sharp')" completes without error.

Are you using the latest version of sharp?

  • I am using the latest version of sharp as reported by npm view sharp dist-tags.latest.

What is the output of running npx envinfo --binaries --system --npmPackages=sharp --npmGlobalPackages=sharp?

  System:
    OS: macOS 12.6.1
    CPU: (10) arm64 Apple M1 Max
    Memory: 3.44 GB / 32.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 16.16.0 - ~/.nvm/versions/node/v16.16.0/bin/node
    npm: 8.11.0 - ~/.nvm/versions/node/v16.16.0/bin/npm
  npmPackages:
    sharp: ^0.31.2 => 0.31.2 

What are the steps to reproduce?

Hi Lovell,

while using your excellent library, we hit a problem of which I hope you can give some hints on the cause.

We try to do image manipulation in several steps, converting a sharp to a buffer and re-reading it, since we need to apply transformations in arbitrary order. To speed up converting to a buffer, we want to use uncompressed TIFF format. As soon as we add an alpha channel to the image, however, conversion of a previously written buffer back to a sharp fails.

Please provide a minimal, standalone code sample, without other dependencies, that demonstrates this problem

This is a simplified code snippet to illustrate the issue:

    let buffer = await fs.readFileSync("random-small.jpeg"));
    buffer = await sharp(buffer)
      .tiff({compression: 'none'})
      .extend({left: 10, background: {r: 255, g: 255, b: 255, alpha: 0.5}})
      .toBuffer();
    await sharp(buffer)
      .toBuffer();

What is the expected behaviour?

With the second sharp(buffer), an error is thrown by libvips:

Error: Input buffer has corrupt header: tiff2vips: samples out of range

It seems that all components (R, G, B, and Alpha) are represented as 8-byte floats each. If no alpha is included, the conversion and re-reading works just fine with R, G, and B being represented by uchar. The issue does not appear with raw format but that one cannot handle animated images, unfortunately (#3189).

random-small

Knowing too little about JavaScript and C++, I failed to find my way through the code to see the root cause of the issue.

Do you have a hint maybe or know a way around it?

Thanks,
Stefan

@lovell
Copy link
Owner

lovell commented Dec 5, 2022

This is a bit niche, but when introducing a non-opaque background colour via extend, the image was being cast to double-precision. It just so happens that the tiff saver supports this, so the output of the first step was also double precision, however the tiff loader can't open these, hence the error you saw.

Commit 9d760f3 ensures the addition of a background colour always casts to the same precision as the input image, which prevents an unnecessary cast to slower double precision, thereby improving performance.

Thanks for reporting this.

@lovell lovell changed the title Image with alpha converted to uncompressed TIFF cannot be re-read Operations that introduce non-opaque background make unnecessary, implicit cast to double Dec 5, 2022
@stefanpieper
Copy link
Author

Absolutely perfect, thanks a lot!

@lovell lovell added this to the v0.31.3 milestone Jan 17, 2023
@lovell
Copy link
Owner

lovell commented Jan 17, 2023

This was included as part of v0.31.3

@lovell lovell closed this as completed Jan 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants