|
|
Donner SVG 0.8.0-pre
SVG editor and embeddable C++20 engine.
|
<feConvolveMatrix> applies a convolution kernel to the input image.
It's the general-purpose primitive behind blur, sharpen, edge detection, emboss, and countless other image-processing effects. You give it a small grid of numbers (the kernel), and each output pixel is computed as a weighted sum of the input pixel and its neighbours using those numbers.
If you've used an image editor's "custom filter" or "convolution" dialog, this is the same math. Changing the kernel changes the effect - the same primitive produces wildly different results depending on the numbers you feed it.
Imagine sliding the kernel grid over every pixel of the input image. For each position:
That's it. The art is in choosing the kernel: a 3×3 kernel of all 1/9 averages a neighbourhood (blur); a kernel with a large positive centre and small negative neighbours amplifies local differences (sharpen); a kernel that subtracts opposite neighbours highlights intensity gradients (edge detect).
If you omit the divisor attribute, the effective divisor is the sum of the kernel values, or 1 when that sum is zero. A Laplacian-style edge-detect kernel like 0 -1 0 / -1 4 -1 / 0 -1 0 therefore works without an explicit divisor.
Setting divisor="1" explicitly can make the intended normalization clear. A bias of 0.5 is useful for edge-detect / emboss kernels so negative results are remapped into the visible [0, 1] range instead of being clamped to black.
All nine cells are 1, and divisor="9" turns the sum back into an average. Each output pixel becomes the average of its 3×3 neighbourhood, producing a mild uniform blur:
The centre weight is 5 and the four neighbours are -1, summing to 1. Because the centre outweighs the (negative) average of the neighbours, the pixel is pulled further from the local average, exaggerating edges. Set divisor="1":
The kernel sums to 0, so flat regions produce zero and only rapid changes in intensity (edges) produce non-zero output. The omitted-divisor fallback would also use 1; this example sets divisor="1" explicitly and uses bias="0.5" to re-centre negative responses into the visible range:
An asymmetric kernel lights one diagonal and darkens the other, simulating a raised surface lit from the upper-left. This zero-sum kernel defaults to an effective divisor of 1; the example states it explicitly and uses bias="0.5" to keep negative responses visible:
| Attribute | Default | Description |
|---|---|---|
| order | 3 | Size of the kernel matrix. One or two integers (N or cols rows). A 3 means a 3×3 kernel. |
| kernelMatrix | (required) | order.x * order.y numbers, row-major. Whitespace- or comma-separated. |
| divisor | sum, or 1 if sum is 0 | Final sum is divided by this value. |
| bias | 0 | Added to the result after division. Use 0.5 for edge-detect / emboss kernels so negative responses map into the visible range. |
| targetX | floor(order.x / 2) | Which column of the kernel aligns with the output pixel. |
| targetY | floor(order.y / 2) | Which row of the kernel aligns with the output pixel. |
| edgeMode | duplicate | How pixels outside the input are sampled: duplicate (extend edge pixels), wrap (tile), or none (treat as transparent black). |
| preserveAlpha | false | If true, the alpha channel is copied through unchanged and convolution only affects RGB. |
kernelUnitLength is not implemented; kernel cells are evaluated at the renderer's filter sample spacing.
Inherits standard filter primitive attributes (in, result, x, y, width, height) from donner::svg::SVGFilterPrimitiveStandardAttributes.