Trim() cuts portions of the actual image
Hi,
We are using the trim() function to get rid of extra white space around the image.
But there is a recent issue we noticed. Trim() removes the portion of the image. Please find the attached screenshots of the actual image and the image after using Trim().
Note that the dot in the end of the first line gets cut. (after answer, see that portion of 'r' in answer along with the ending fullstop gets cut)

The code that I use is as follows.
sharp(buffer).trim()
Have tried giving threshold for trim with values like 1, 5 12 etc but nothing works. Have tried resize but that does not do the trimming .Please suggest if there is anyother work around to this.
Trying this sample image with vips at the command line, I see:
$ vips find_trim 92702797-3be4ef00-f36f-11ea-9dd3-faf2d2bb91eb.png --threshold 1
14
12
644
205
Using these values (top, left, width, height) to extract the area, also via the command line:
$ vips extract_area 92702797-3be4ef00-f36f-11ea-9dd3-faf2d2bb91eb.png out.png 14 12 644 205
I see the same slightly-over-trimmed result as reported.
@jcupitt Are you able to help here? Could this be something to do with the median filter involved in find_trim?
@lovell Is there any workaround available for this? I saw a lot of similar issues with trim() and workarounds for it, I tried those but nothing worked. Like flattening the image, then trimming etc..
Hello @KrishKayc,
Yes, find_trim was designed for photographic sources, so it includes a median filter. This will remove the single pixel elements in your PNG file. We'd need to add an option (perhaps vector_source, no_fuzz, or no_noise_removal?) for ultra clean vector art like this.
As a workaround, you'd need to make your own find_trim. It's not complex -- just copy paste the existing trimmer and remove the median filter. If you used C++ it'd be very small.
Looking at find_trim again, it could be made quite a bit quicker too. I'll add an enhancement issue to libvips for this.
I had a thought: you could flatten, monochrome, blur and then threshold the image before calling find_trim. That would make single pixels elements large enough to get past the median filter.
What an ugly hack!
@jcupitt Thanks for the workaround. Doing a slight blur() and then trimming worked for this particular use case. So it is a less uglier hack :-)
Did this get anywhere?
I see this issue marked as completed on libvips https://github.com/libvips/libvips/issues/1811 but I am still getting problems with trim on pixelart :(
Attached input and output
input
(it's a tiny green thingy)
output
(it's a tiny black spec above this line)
and the code that ran
const sharp = require("sharp");
const fs = require("fs/promises");
async function test() {
// giving more info about the background doesn't make a difference :(
// const { info, data } = await sharp("./input.png").trim({ background: { r: 0, g: 0, b: 0, alpha: 0 }, threshold: 1 }).png().toBuffer({ resolveWithObject: true });
const { info, data } = await sharp("./input.png").trim().png().toBuffer({ resolveWithObject: true });
console.log(info);
await fs.writeFile("./output.png", data);
}
test();
console log
{
format: 'png',
width: 1,
height: 1,
channels: 4,
premultiplied: false,
trimOffsetLeft: -9,
trimOffsetTop: -8,
size: 89
}
The upstream discussion about a future possible enhancement for this is at https://github.com/libvips/libvips/discussions/2076
The upstream discussion about a future possible enhancement for this is at libvips/libvips#2076
It looks like the functionality to do this has been added: https://github.com/libvips/libvips/pull/3329
Is it possible to add an option in TrimOptions that enables this mode?
This will be dependent on the future libvips 8.15 and we can revisit once available.
Support for the lineArt option added via commit https://github.com/lovell/sharp/commit/0bd1715f362a20207fcd7efbac81adf7b0986ced and will be part of v0.33.0.
Please note this change also mandates that options are passed to trim() as an Object containing the properties you wish to set. Passing a number or string to represent a threshold or colour respectively will no longer be allowed as of v0.33.0
v0.33.0 is now available.