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

Black border on right and bottom of resized image #1185

Closed
davidwood opened this issue Apr 9, 2018 · 9 comments
Closed

Black border on right and bottom of resized image #1185

davidwood opened this issue Apr 9, 2018 · 9 comments

Comments

@davidwood
Copy link

I've experience an issue where the resized image has a black border on the right and bottom of the image. This issue appears to be isolated to certain images and changing the resize kernel and / or sharpening the image do not remove the artifacts.

Sharp: 0.20.1

Source:
source

Result:
output

Code:

sharp(source)
  .resize(200)
  .withoutEnlargement()
  .min()
  .jpeg()
  .toBuffer();
@lovell
Copy link
Owner

lovell commented Apr 9, 2018

Hello, switching off the (on-by-default) fastShrinkOnLoad feature will improve things a little:

  .resize(200, null, { fastShrinkOnLoad: false })

However the underlying libvips resize operation is creating a small dark border, presumably as a result of rounding/averaging for these specific input and output dimensions.

Running:

vipsthumbnail --size=200 38505630-46e30d48-3bdd-11e8-856f-48555a5d713f.jpg

produces:

The scaling factor is 200/1801 = 0.111, which will result in libvips performing an integral shrink of 4x.

To avoid exactly the kind of problem seen here, libvips extends an image by copying the pixels from the edges before shrinking but it doesn't seem to be working in this case. @jcupitt may be able to provide more information about what is happening.

@lovell lovell added the question label Apr 9, 2018
@jcupitt
Copy link
Contributor

jcupitt commented Apr 10, 2018

Hello, that looks bad. I tried with git master and I see:

$ vipsthumbnail pill.jpg -s 200

tn_pill

So it seems fixed, in master anyway. I'll try with some older versions.

(edit: oh heh maybe not, hang on)

@jcupitt
Copy link
Contributor

jcupitt commented Apr 10, 2018

It's the jpg loader. Try:

$ vips jpegload pill.jpg x.png --shrink 4

x

But all libvips does is use the dimensions that libjpeg gives it. Has libjpg always rounded up and generated black edges? It seems strange we've not noticed before. I'll look a bit deeper.

@jcupitt
Copy link
Contributor

jcupitt commented Apr 10, 2018

It seems to be a standard part of libjpeg. For example, in IJG jpeg9:

$ djpeg -scale 1/4 pill.jpg >x.pnm

will also make the extra column and row. The black pixels are not 0, they are 64, which of course is 1/4 of 255, for 1/4 of a pixel.

The libvips jpeg load operation should probably repeat the shrink calculation and do strict round down. I hope this doesn't cause too much breakage.

jcupitt added a commit to libvips/libvips that referenced this issue Apr 10, 2018
libjpeg rounds up on shrink-on-load. In some cases this can leave a dark
line along the right and bottom edge, since it only contains (for
example) 1/4 of a pixel of data.

This change adds a crop after jpeg load so that only complete pixels are
output.

See lovell/sharp#1185
@jcupitt
Copy link
Contributor

jcupitt commented Apr 10, 2018

8.6 HEAD should address this. I now see:

$ vipsthumbnail pill.jpg -s 200

tn_pill

It's very embarrassing that this has gone undetected so long. Thank you for reporting this dumbness.

This changes the behaviour of shrink-on-load in a minor release, which is very bad. However I can't think of a simple way for sharp to be able to work around this problem, so unfortunately I think this does have to be classed as a bugfix. @lovell, does that seem OK?

@lovell
Copy link
Owner

lovell commented Apr 10, 2018

Thank you @jcupitt, that looks much better.

The relatively big change in behaviour makes me think this should wait until libvips v8.7.0, but I don't mind either way.

The latest v0.20.x versions of sharp currently ship with (and, for testing purposes, rely on) a prebuilt libvips v8.6.1 but people can use more recent versions if installed globally.

@jcupitt
Copy link
Contributor

jcupitt commented Apr 10, 2018

I agree, I'm very uncomfortable pushing a big change out like this, but it's a serious problem and I cant think of a workaround. I'll make 8.6.4 in a few days with this thing in.

@davidwood
Copy link
Author

Thanks to both of you for the quick diagnosis and fix!

@lovell
Copy link
Owner

lovell commented Oct 4, 2018

sharp v0.21.0 is now available with a prebuilt libvips v8.7.0 that contains the upstream fix.

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

3 participants