sharp icon indicating copy to clipboard operation
sharp copied to clipboard

Trim() cuts portions of the actual image

Open KrishKayc opened this issue 5 years ago • 5 comments

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)

tux tux_edited

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.

KrishKayc avatar Sep 10 '20 08:09 KrishKayc

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 avatar Sep 10 '20 11:09 lovell

@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..

KrishKayc avatar Sep 10 '20 11:09 KrishKayc

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.

jcupitt avatar Sep 10 '20 11:09 jcupitt

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 avatar Sep 10 '20 11:09 jcupitt

@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 :-)

KrishKayc avatar Sep 10 '20 12:09 KrishKayc

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 input (it's a tiny green thingy)

output 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
}

miltoncandelero avatar Feb 06 '23 15:02 miltoncandelero

The upstream discussion about a future possible enhancement for this is at https://github.com/libvips/libvips/discussions/2076

lovell avatar Feb 06 '23 16:02 lovell

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?

earthiverse avatar Feb 28 '23 08:02 earthiverse

This will be dependent on the future libvips 8.15 and we can revisit once available.

lovell avatar Feb 28 '23 08:02 lovell

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

lovell avatar Nov 04 '23 14:11 lovell

v0.33.0 is now available.

lovell avatar Nov 29 '23 13:11 lovell