Donner SVG 0.8.0-pre
SVG editor and embeddable C⁠+⁠+⁠20 engine.
Loading...
Searching...
No Matches
<feConvolveMatrix>

<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.

How convolution works

Imagine sliding the kernel grid over every pixel of the input image. For each position:

  1. Multiply each kernel number by the corresponding neighbour pixel's value.
  2. Sum all of those products.
  3. Divide by divisor.
  4. Add bias.
  5. Write the result to the output pixel.

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).

Default divisor

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.

Example 1: box blur

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:

111 111 111 divisor=9 Text original Text box blur

<feConvolveMatrix order="3" divisor="9"
kernelMatrix="1 1 1
1 1 1
1 1 1" />

Example 2: sharpen

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":

0-10 -15-1 0-10 divisor=1 Text original Text sharpened

<feConvolveMatrix order="3" divisor="1"
kernelMatrix="0 -1 0
-1 5 -1
0 -1 0" />

Example 3: edge detect (Laplacian)

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:

0-10 -14-1 0-10 divisor=1, bias=0.5 Text original Text edges

<feConvolveMatrix order="3" divisor="1" bias="0.5"
kernelMatrix="0 -1 0
-1 4 -1
0 -1 0" />

Example 4: emboss

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:

-2-10 -111 012 divisor=1, bias=0.5 Text original Text embossed

<feConvolveMatrix order="3" divisor="1" bias="0.5"
kernelMatrix="-2 -1 0
-1 1 1
0 1 2" />

Attributes

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.