[Webkit-unassigned] [Bug 111177] feGaussianBlur shows banding under certain circumstances

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Sat Mar 2 18:31:59 PST 2013


https://bugs.webkit.org/show_bug.cgi?id=111177


Florin Malita <fmalita at chromium.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |junov at google.com,
                   |                            |pdr at google.com,
                   |                            |reed at google.com,
                   |                            |schenney at chromium.org,
                   |                            |senorblanco at chromium.org




--- Comment #8 from Florin Malita <fmalita at chromium.org>  2013-03-02 18:34:23 PST ---
(In reply to comment #7)
> (In reply to comment #6)
> > > I expect a smooth gradient without such alternations.
> > 
> > That may be the root of the problem though: this is a Gaussian blur, not a gradient. I'm no feGaussianBlur expert, but your expectation may be unfounded.
> 
> If you have a look at a Gaussian distribution curve it is indeed smooth and not jagged. So my expectation is not unfounded.

If you insist on mathematically correct results, sure. But that may not be practical - see how FF handles the tests while presumably generating an exact blur :)

The current WK implementation uses various approximations for performance reasons:

1) feGausianBlur devolves into a 3-pass box blur for large stdDeviation values. This is explicitly allowed by the spec - see http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement

2) box blur itself is implemented in two one-dimensional passes (horizontal vs. vertical) to keep the runtime in O(n^2) bounds

Even considering the above, I couldn't immediately explain the non-monotonic banding. But after some digging, I found that #2 above is the problem.

It basically boils down to accumulated rounding errors: each box blur pass ends up rounding the components independently. Combine that with loss of precision from using a pre-multiplied format (again required by the spec), and you get enough color-vs-alpha rounding jitter to affect the the composited result.

Here's a trace for a scanline crossing a few of these bands (keep in mind that the blur values are pre-multiplied). Even though the individual components are monotonically increasing, relative red/alpha variations introduced by rounding errors can cause the composited result to be non-monotonic:

>> [153, 250] bg_red: 85, blur_red: 0, blur_alpha: 0, composited_red: 85
>> [154, 250] bg_red: 85, blur_red: 0, blur_alpha: 0, composited_red: 85
>> [155, 250] bg_red: 85, blur_red: 1, blur_alpha: 1, composited_red: 85
>> [156, 250] bg_red: 85, blur_red: 1, blur_alpha: 1, composited_red: 85
>> [157, 250] bg_red: 85, blur_red: 1, blur_alpha: 2, composited_red: 85
>> [158, 250] bg_red: 85, blur_red: 2, blur_alpha: 2, composited_red: 86
>> [159, 250] bg_red: 85, blur_red: 2, blur_alpha: 3, composited_red: 86
>> [160, 250] bg_red: 85, blur_red: 2, blur_alpha: 3, composited_red: 86
>> [161, 250] bg_red: 85, blur_red: 3, blur_alpha: 4, composited_red: 86
>> [162, 250] bg_red: 85, blur_red: 3, blur_alpha: 4, composited_red: 86
>> [163, 250] bg_red: 85, blur_red: 3, blur_alpha: 4, composited_red: 86
>> [164, 250] bg_red: 85, blur_red: 4, blur_alpha: 5, composited_red: 87
>> [165, 250] bg_red: 85, blur_red: 4, blur_alpha: 5, composited_red: 87
>> [166, 250] bg_red: 85, blur_red: 5, blur_alpha: 6, composited_red: 88
>> [167, 250] bg_red: 85, blur_red: 5, blur_alpha: 6, composited_red: 88
>> [168, 250] bg_red: 85, blur_red: 5, blur_alpha: 7, composited_red: 87   <- BZZZZZT!
>> [169, 250] bg_red: 85, blur_red: 6, blur_alpha: 7, composited_red: 88
>> [170, 250] bg_red: 85, blur_red: 6, blur_alpha: 8, composited_red: 88
>> [171, 250] bg_red: 85, blur_red: 6, blur_alpha: 8, composited_red: 88
>> [172, 250] bg_red: 85, blur_red: 7, blur_alpha: 9, composited_red: 89
>> [173, 250] bg_red: 85, blur_red: 7, blur_alpha: 9, composited_red: 89
>> [174, 250] bg_red: 85, blur_red: 8, blur_alpha: 10, composited_red: 89
>> [175, 250] bg_red: 85, blur_red: 8, blur_alpha: 10, composited_red: 89
>> [176, 250] bg_red: 85, blur_red: 8, blur_alpha: 11, composited_red: 89
>> [177, 250] bg_red: 85, blur_red: 9, blur_alpha: 11, composited_red: 90
>> [178, 250] bg_red: 85, blur_red: 9, blur_alpha: 11, composited_red: 90
>> [179, 250] bg_red: 85, blur_red: 9, blur_alpha: 12, composited_red: 90
>> [180, 250] bg_red: 85, blur_red: 10, blur_alpha: 12, composited_red: 91
>> [181, 250] bg_red: 85, blur_red: 10, blur_alpha: 13, composited_red: 90   <- BZZZZZT!
>> [182, 250] bg_red: 85, blur_red: 11, blur_alpha: 13, composited_red: 91
>> [183, 250] bg_red: 85, blur_red: 11, blur_alpha: 14, composited_red: 91
>> [184, 250] bg_red: 85, blur_red: 11, blur_alpha: 14, composited_red: 91
>> [185, 250] bg_red: 85, blur_red: 12, blur_alpha: 15, composited_red: 92
>> [186, 250] bg_red: 85, blur_red: 12, blur_alpha: 15, composited_red: 92
>> [187, 250] bg_red: 85, blur_red: 12, blur_alpha: 16, composited_red: 91   <- BZZZZZT!
>> [188, 250] bg_red: 85, blur_red: 13, blur_alpha: 16, composited_red: 92
...

I agree that this is undesirable, but I can't see a good solution that doesn't obliterate performance. Maybe keeping track of rounding errors across box blur passes and compensating would work?

-- 
Configure bugmail: https://bugs.webkit.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.



More information about the webkit-unassigned mailing list