sharp icon indicating copy to clipboard operation
sharp copied to clipboard

.trim() removes 1 too many pixels

Open Zirafnik opened this issue 2 months ago • 5 comments

Possible bug: .trim() removes 1 pixel too many

When using .trim() Sharp.js will remove 1 too many pixels. I first noticed it in the metadata returned by .trim(): trimOffsetLeft and trimOffsetTop.

I also confirmed it is not just an error in the data returned, by testing it on a PNG.

Instead of only removing the border up-to (and excluding) the first pixel of color change, it also removes that first pixel of different color.

I noticed this difference, as I am porting from ImageMagick to Sharp.js. (ImageMagick willl remove the correct amount: only up-to the first changed pixel.)

Possible fix: Make .trim() remove all the border only up-to the new color.

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 "require('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.

Zirafnik avatar Apr 25 '24 15:04 Zirafnik

You've not provided an example image but the lineArt property may be more appropriate for your input images.

https://sharp.pixelplumbing.com/api-resize#trim

.trim({ lineArt: true })

lovell avatar Apr 25 '24 16:04 lovell

My image was a PNG of some document with typed text.

What is the impact on performance of lineArt: true? Additionally, what happens if there are alternating types of PNGs (document with text VS. photograph)?

Zirafnik avatar Apr 25 '24 16:04 Zirafnik

What is the impact on performance of lineArt: true

I would expect minimal, it might be very slightly faster, you'll need to profile using samples of the type of image you're likely to have to process.

what happens if there are alternating types of PNGs

You'll need to determine which setting is most appropriate for the type of image you're likely to have to process.

lovell avatar Apr 25 '24 19:04 lovell

Thank you for the answer, however, I am still confused about this setting. Could you explain a bit more what the lineArt: true setting does? Why should I use it and when?

Docs description:

Does the input more closely resemble line art (e.g. vector) rather than being photographic?

Maybe... What does this even really mean?

Zirafnik avatar Apr 26 '24 08:04 Zirafnik

If the input is best represented as in a vector format such as SVG or uses a lossless compression such as PNG then lineArt would be more suitable as there is unlikely to be "noise" around the edges between background and non-background areas.

If the input is more photographic and/or uses a lossy format such as JPEG then some smoothing of the noise is required to ensure trim() is more accurate around the edges.

The underlying libvips operation is vips_find_trim.

lovell avatar Apr 26 '24 09:04 lovell

I hope this information helped. Please feel free to re-open with more details if further assistance is required.

lovell avatar May 16 '24 12:05 lovell