Donner 0.5.1
Embeddable browser-grade SVG2 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).

A critical gotcha: always set divisor explicitly

If you omit the divisor attribute, the default is the sum of the kernel values. For a Laplacian-style edge-detect kernel like 0 -1 0 / -1 4 -1 / 0 -1 0, that sum is 0, and dividing by zero produces an undefined / broken render (in many implementations the output is simply white or all opaque).

Always set divisor explicitly when your kernel sums to zero, and set a bias of 0.5 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. Note that we set divisor="1" explicitly (the default would be 0 → division by zero → broken render) and 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. Again divisor="1" and bias="0.5" are required for correct output because the kernel sums to zero:

-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 of kernel values Final sum is divided by this. Always set explicitly if the kernel sums to zero, otherwise you get a division by zero.
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).
kernelUnitLength 1 1 Physical size of one kernel cell in the user coordinate system. Allows resolution-independent kernels.
preserveAlpha false If true, the alpha channel is copied through unchanged and convolution only affects RGB.

Inherits standard filter primitive attributes (in, result, x, y, width, height) from donner::svg::SVGFilterPrimitiveStandardAttributes.