blur
Mojo module đźˇ
blur
Gaussian blur, approximated by three successive box blurs, and draw_shadowed, the drop-shadow / glow composite built on it.
blur() modifies the entire pixel buffer and ignores the active clip
and transform. draw_shadowed applies the destination’s clip and blend
mode when compositing the shadow and source layer.
The three-box approximation
Three successive box blurs approximate a Gaussian.
The box widths are derived from the desired standard deviation sigma
by P. Kovesi, “Fast Almost-Gaussian Filtering”, DICTA 2010: for n
boxes,
w_ideal = sqrt(12 * sigma^2 / n + 1)
wl = w_ideal rounded down to the nearest odd number
wu = wl + 2
m = round((12*sigma^2 - n*wl^2 - 4*n*wl - 3*n) / (-4*wl - 4))
and m boxes use width wl, with the remaining n - m using wu.
Odd widths keep every box centered on its output pixel.
Following CSS blur(), sigma is half of radius.
Premultiplied alpha and edge handling
Blur operates on premultiplied color (channel * alpha / 255) so
transparent pixels do not contribute hidden color.
Each 1-D box average clamps samples outside the buffer to its nearest edge pixel.
Box blurs commute, so the three horizontal sweeps run back to back and
then the three vertical ones, rather than alternating. Away from the
edges the result is the same as alternating; at an edge the clamp
meets an intermediate rather than the original, a difference of at
most a few levels within the outermost _shadow_pad pixels
(draw_shadowed pads by that much, so its shadows are unaffected).
Each row band begins r0 + r1 + r2 rows above its output range so the
vertical sliding windows are populated before its first output row.