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

Add experimental withoutGaussianBlur API #211

Closed
wants to merge 1 commit into from

Conversation

gasi
Copy link

@gasi gasi commented May 6, 2015

Applying a Gaussian blur for large reductions of transparent images can cause dark ‘fringing’ around bright parts of the image.

This API helps us work around the issue, but I’d love to hear more about the cause of this issue and if there is a way to apply the Gaussian blur safely. We originally assumed this was caused by a missing alpha channel premultiplication before the affine transform but this turned out not to be the case.

See gasi#3 for details.

/cc @julianwa

Applying a Gaussian blur for large reductions of transparent images can cause
dark ‘fringing’ around bright parts of the image.

See: #3
@coveralls
Copy link

Coverage Status

Coverage increased (+0.04%) to 95.87% when pulling eba84af on gasi:alpha-reduction-gaussian-blur into acc6059 on lovell:knife.

@lovell
Copy link
Owner

lovell commented May 6, 2015

I wonder if using floating point arithmetic will help here.

vips_gaussmat and vips_convsep have a precision parameter you can set to VIPS_PRECISION_FLOAT instead of the default VIPS_PRECISION_INTEGER.

(I notice the existing code sets a non-existent integer parameter of vips_gaussmat - not sure where that came from - can probably be removed.)

@gasi
Copy link
Author

gasi commented May 6, 2015

Thanks for the tip, @lovell, but I just tried that and the black fringing got even worse (compared visually). Luckily, I can work around the reduction fringes by disabling the Gaussian blur, but to my dismay, I realized that even upscaling transparent images with straight VIPS CLI causes dark fringes when using non-nearest interpolation. See: https://github.com/jcupitt/libvips/issues/291

It’s after 3am here, so I will catch some sleep and come back to this tomorrow with a fresh mind 😄 Happy to discuss best long-term solution to this. For now, we’ll use withoutGaussianBlur as a workaround for image reductions. We’ll still have to find a solution for upscaling though. Please let me know if you have any ideas 😄 If you’re ever in Seattle or NYC, please let us know and you’ll get a tour of the office + dinner 👍

@coveralls
Copy link

Coverage Status

Coverage increased (+0.04%) to 95.87% when pulling 6f2715b on gasi:alpha-reduction-gaussian-blur into acc6059 on lovell:knife.

@julianwa
Copy link

julianwa commented May 6, 2015

@gasi There’s actually good reasons why they are applying the gaussian blur before downsampling; you can filter the high-frequency noise and therefore avoid moiré patterns. Does this mean that they were doing that blur before your were converting to pre-multiplied alpha? If we convert to pre-multiplied as early as possible (before the blur), it just might fix things, possibly in both upsampling and downsampling cases.

The issue is that you can’t interpolate two semi-transparent colors non-pre-multiplied colors. You’ll get the wrong result. For example: lerp(color(255, 0, 0, 255), color(0, 0, 0, 0), 0.5) = color(128, 0, 0, 128), which is a 50% transparent gray pixel, not a 50% transparent white pixel. On the other hand, lerp(color(255 * 1, 0 * 1, 0 * 1, 255), color(0 * 0, 0 * 0, 0 * 0, 0), 0.5) = pre-mulitiplied-color(128, 0, 0, 128) = color(128 / 0.5, 0 / 0.5, 0 / 0.5, 128) = color(255, 0, 0, 128), which is what you’d expect.

So anything that does interpolation of colors, including gaussian blur or resampling, needs to be done in pre-multiplied space. Being a scientific image processing library, not a general purpose one, vips may not be taking this into account because it has to do with color perception and the treatment of alpha, rather than the raw math.

@lovell
Copy link
Owner

lovell commented May 6, 2015

@gasi Thanks for testing the use of floats to remove rounding/truncate errors as a possible source.

@julianwa Yes, the blur is to reduce aliasing on diagonal edges, a similar method to *magick's Lanczos filter.

In case you missed it, the related improvement to libvips is being discussed over at https://github.com/jcupitt/libvips/issues/291

@gasi
Copy link
Author

gasi commented May 7, 2015

Thanks for your feedback, @lovell, and apologies for this misguided attempt at solving the problem (although it did visually make an improvement). This is superceded by #211 and I will hence close this.

@gasi gasi closed this May 7, 2015
@gasi gasi deleted the alpha-reduction-gaussian-blur branch May 7, 2015 04:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants