firstDaisy Diff compare report.
Click on the changed parts for a detailed description. Use the left and right arrow keys to walk through the modifications.
last 

15.14 Filter primitive 'feDiffuseLighting'

This filter primitive lights an image using the alpha channel as a bump map. The resulting image is an RGBA opaque image based on the light color with alpha = 1.0 everywhere. The lighting calculation follows the standard diffuse component of the Phong lighting model. The resulting image depends on the light color, light position and surface geometry of the input bump map.

The light map produced by this filter primitive can be combined with a texture image using the multiply term of the arithmetic 'feComposite' compositing method. Multiple light sources can be simulated by adding several of these light maps together before applying it to the texture image.

The formulas below make use of 3x3 filters. Because they operate on pixels, such filters are inherently resolution-dependent. To make 'feDiffuseLighting' produce resolution-independent results, an explicit value should be provided for either the 'filterRes' attribute on the 'filter' element and/or attribute 'kernelUnitLength'.

'kernelUnitLength', in combination with the other attributes, defines an implicit pixel grid in the filter effects coordinate system (i.e., the coordinate system established by the 'primitiveUnits' attribute). If the pixel grid established by 'kernelUnitLength' is not scaled to match the pixel grid established by attribute 'filterRes' (implicitly or explicitly), then the input image will be temporarily rescaled to match its pixels with 'kernelUnitLength'. The 3x3 filters are applied to the resampled image. After applying the filter, the image is resampled back to its original resolution.

When the image must be resampled, it is recommended that high quality viewers make use of appropriate interpolation techniques, for example bilinear or bicubic. Depending on the speed of the available interpolents, this choice may be affected by the 'image-rendering' property setting. Note that implementations might choose approaches that minimize or eliminate resampling when not necessary to produce proper results, such as when the document is zoomed out such that 'kernelUnitLength' is considerably smaller than a device pixel.

For the formulas that follow, the Norm(Ax,Ay,Az) function is defined as:

Norm(Ax,Ay,Az) = sqrt(Ax^2+Ay^2+Az^2)

The resulting RGBA image is computed as follows:

Dr = kd * N.L * Lr
Dg = kd * N.L * Lg
Db = kd * N.L * Lb
Da = 1.0

where

kd = diffuse lighting constant
N = surface normal unit vector, a function of x and y
L = unit vector pointing from surface to light, a function of x and y in the point and spot light cases
Lr,Lg,Lb = RGB components of light, a function of x and y in the spot light case

N is a function of x and y and depends on the surface gradient as follows:

The surface described by the input alpha image Ain (x,y) is:

Z (x,y) = surfaceScale * Ain (x,y)

Surface normal is calculated using the Sobel gradient 3x3 filter. Different filter kernels are used depending on whether the given pixel is on the interior or an edge. For each case, the formula is:

Nx (x,y)= - surfaceScale * FACTORx *
           (K x(0,0)*I(x-dx,y-dy) + Kx(1,0)*I(x,y-dy) + Kx(2,0)*I(x+dx,y-dy) +
            K x(0,1)*I(x-dx,y)   + Kx(1,1)*I(x,y)   + Kx(2,1)*I(x+dx,y)   +
            K x(0,2)*I(x-dx,y+dy) + Kx(1,2)*I(x,y+dy) + Kx(2,2)*I(x+dx,y+dy))
Ny (x,y)= - surfaceScale * FACTORy *
           (K y(0,0)*I(x-dx,y-dy) + Ky(1,0)*I(x,y-dy) + Ky(2,0)*I(x+dx,y-dy) +
            K y(0,1)*I(x-dx,y)   + Ky(1,1)*I(x,y)   + Ky(2,1)*I(x+dx,y)   +
            K y(0,2)*I(x-dx,y+dy) + Ky(1,2)*I(x,y+dy) + Ky(2,2)*I(x+dx,y+dy))
Nz (x,y) = 1.0

N = (Nx, Ny, Nz) / Norm((Nx,Ny,Nz))

In these formulas, the dx and dy values (e.g., I(x-dx,y-dy)), represent deltas relative to a given (x,y) position for the purpose of estimating the slope of the surface at that point. These deltas are determined by the value (explicit or implicit) of attribute 'kernelUnitLength'.

Top/left corner:

FACTORx=2/(3*dx)
Kx =
    |  0  0  0 |
    |  0 -2  2 |
    |  0 -1  1 |

FACTORy=2/(3*dy)
Ky =  
    |  0  0  0 |
    |  0 -2 -1 |
    |  0  2  1 |

Top row:

FACTORx=1/(3*dx)
Kx =
    |  0  0  0 |
    | -2  0  2 |
    | -1  0  1 |

FACTORy=1/(2*dy)
Ky =  
    |  0  0  0 |
    | -1 -2 -1 |
    |  1  2  1 |

Top/right corner:

FACTORx=2/(3*dx)
Kx =
    |  0  0  0 |
    | -2  2  0 |
    | -1  1  0 |

FACTORy=2/(3*dy)
Ky =  
    |  0  0  0 |
    | -1 -2  0 |
    |  1  2  0 |

Left column:

FACTORx=1/(2*dx)
Kx =
    | 0 -1  1 |
    | 0 -2  2 |
    | 0 -1  1 |

FACTORy=1/(3*dy)
Ky =  
    |  0 -2 -1 |
    |  0  0  0 |
    |  0  2  1 |

Interior pixels:

FACTORx=1/(4*dx)
Kx =
    | -1  0  1 |
    | -2  0  2 |
    | -1  0  1 |

FACTORy=1/(4*dy)
Ky =  
    | -1 -2 -1 |
    |  0  0  0 |
    |  1  2  1 |

Right column:

FACTORx=1/(2*dx)
Kx =
    | -1  1  0|
    | -2  2  0|
    | -1  1  0|

FACTORy=1/(3*dy)
Ky =  
    | -1 -2  0 |
    |  0  0  0 |
    |  1  2  0 |

Bottom/left corner:

FACTORx=2/(3*dx)
Kx =
    | 0 -1  1 |
    | 0 -2  2 |
    | 0  0  0 |

FACTORy=2/(3*dy)
Ky =  
    |  0 -2 -1 |
    |  0  2  1 |
    |  0  0  0 |

Bottom row:

FACTORx=1/(3*dx)
Kx =
    | -1  0  1 |
    | -2  0  2 |
    |  0  0  0 |

FACTORy=1/(2*dy)
Ky =  
    | -1 -2 -1 |
    |  1  2  1 |
    |  0  0  0 |

Bottom/right corner:

FACTORx=2/(3*dx)
Kx =
    | -1  1  0 |
    | -2  2  0 |
    |  0  0  0 |

FACTORy=2/(3*dy)
Ky =  
    | -1 -2  0 |
    |  1  2  0 |
    |  0  0  0 |

L, the unit vector from the image sample to the light, is calculated as follows:

For Infinite light sources it is constant:

Lx = cos(azimuth)*cos(elevation)
Ly = sin(azimuth)*cos(elevation)
Lz = sin(elevation)

For Point and spot lights it is a function of position:

Lx = Lightx - x
Ly = Lighty - y
Lz = Lightz - Z(x,y)

L = (Lx, Ly, Lz) / Norm(Lx, Ly, Lz)

where Lightx, Lighty, and Lightz are the input light position.

Lr,Lg,Lb, the light color vector, is a function of position in the spot light case only:

Lr = Lightr*pow((-L.S),specularExponent)
Lg = Lightg*pow((-L.S),specularExponent)
Lb = Lightb*pow((-L.S),specularExponent)

where S is the unit vector pointing from the light to the point (pointsAtX, pointsAtY, pointsAtZ) in the x-y plane:

Sx = pointsAtX - Lightx
Sy = pointsAtY - Lighty
Sz = pointsAtZ - Lightz

S = (Sx, Sy, Sz) / Norm(Sx, Sy, Sz)

If L.S is positive, no light is present. (Lr = Lg = Lb = 0)


<!ENTITY % SVG.feDiffuseLighting.extra.content "" >
<!ENTITY % SVG.feDiffuseLighting.element "INCLUDE" >
<![%SVG.feDiffuseLighting.element;[
<!ENTITY % SVG.feDiffuseLighting.content
    "(( %SVG.feDistantLight.qname; | %SVG.fePointLight.qname;
      | %SVG.feSpotLight.qname; ), ( %SVG.animate.qname; | %SVG.set.qname;
      | %SVG.animateColor.qname; %SVG.feDiffuseLig\
hting.extra.content; )*)"
>
<!ELEMENT %SVG.feDiffuseLighting.qname; %SVG.fe\
DiffuseLighting.content; >
<!-- end of SVG.feDiffuseLighting.element -->]]>
<!ENTITY % SVG.feDiffuseLighting.attlist "INCLUDE" >
<![%SVG.feDiffuseLighting.attlist;[
<!ATTLIST %SVG.feDiffuseLighting.qname;
    %SVG.Core.attrib;
    %SVG.Style.attrib;
    %SVG.Color.attrib;
    %SVG.FilterColor.attrib;
    %SVG.FilterPrimitiveWithIn.attrib;
    lighting-color %SVGColor.datatype; #IMPLIED
    surfaceScale %Number.datatype; #IMPLIED
    diffuseConstant %Number.datatype; #IMPLIED
    kernelUnitLength %NumberOptionalNumber.datatype; #IMPLIED
>

'feDiffuseLighting'
Categories:
Filter primitive element
Content model:
Any number of the following elements, in any order:
Attributes:
DOM Interfaces:

Attribute definitions:

surfaceScale = "<number>"
height of surface when Ain = 1.
If the attribute is not specified, then the effect is as if a value of 1 were specified.
Animatable: yes.
diffuseConstant = "<number>"
kd in Phong lighting model. In SVG, this can be any non-negative number.
If the attribute is not specified, then the effect is as if a value of 1 were specified.
Animatable: yes.
kernelUnitLength = "<number-optional-number>"
The first number is the <dx> value. The second number is the <dy> value. If the <dy> value is not specified, it defaults to the same value as <dx>. Indicates the intended distance in current filter units (i.e., units as determined by the value of attribute 'primitiveUnits') for dx and dy, respectively, in the surface normal calculation formulas. By specifying value(s) for 'kernelUnitLength', the kernel becomes defined in a scalable, abstract coordinate system. If 'kernelUnitLength' is not specified, the dx and dy values should represent very small deltas relative to a given (x,y) position, which might be implemented in some cases as one pixel in the intermediate image offscreen bitmap, which is a pixel-based coordinate system, and thus potentially not scalable. For some level of consistency across display media and user agents, it is necessary that a value be provided for at least one of 'filterRes' and 'kernelUnitLength'. Discussion of intermediate images are in the Introduction and in the description of attribute 'filterRes'.
A negative or zero value is an error (see Error processing).
Animatable: yes.

The light source is defined by one of the child elements 'feDistantLight', 'fePointLight' or 'feSpotLight'. The light color is specified by property 'lighting-color'.

15.15 Filter primitive 'feDisplacementMap'

This filter primitive uses the pixels values from the image from 'in2' to spatially displace the image from 'in'. This is the transformation to be performed:

P'(x,y) <- P( x + scale * (XC(x,y) - .5), y + scale * (YC(x,y) - .5))

where P(x,y) is the input image, 'in', and P'(x,y) is the destination. XC(x,y) and YC(x,y) are the component values of the designated by the xChannelSelector and yChannelSelector. For example, to use the R component of 'in2' to control displacement in x and the G component of Image2 to control displacement in y, set xChannelSelector to "R" and yChannelSelector to "G".

The displacement map defines the inverse of the mapping performed.

The calculations using the pixel values from 'in2' are performed using non-premultiplied color values. If the image from 'in2' consists of premultiplied color values, those values are automatically converted into non-premultiplied color values before performing this operation.

This filter can have arbitrary non-localized effect on the input which might require substantial buffering in the processing pipeline. However with this formulation, any intermediate buffering needs can be determined by scale which represents the maximum range of displacement in either x or y.

When applying this filter, the source pixel location will often lie between several source pixels. In this case it is recommended that high quality viewers apply an interpolent on the surrounding pixels, for example bilinear or bicubic, rather than simply selecting the nearest source pixel. Depending on the speed of the available interpolents, this choice may be affected by the 'image-rendering' property setting.

The 'color-interpolation-filters' property only applies to the 'in2' source image and does not apply to the 'in' source image.


<!ENTITY % SVG.feDisplacementMap.extra.content "" >
<!ENTITY % SVG.feDisplacementMap.element "INCLUDE" >
<![%SVG.feDisplacementMap.element;[
<!ENTITY % SVG.feDisplacementMap.content
    "( %SVG.animate.qname; | %SVG.set.qname;
       %SVG.feDisplacementMap.extra.content; )*"
>
<!ELEMENT %SVG.feDisplacementMap.qname; %SVG.fe\
DisplacementMap.content; >
<!-- end of SVG.feDisplacementMap.element -->]]>
<!ENTITY % SVG.feDisplacementMap.attlist "INCLUDE" >
<![%SVG.feDisplacementMap.attlist;[
<!ATTLIST %SVG.feDisplacementMap.qname;
    %SVG.Core.attrib;
    %SVG.FilterColor.attrib;
    %SVG.FilterPrimitiveWithIn.attrib;
    in2 CDATA #REQUIRED
    scale %Number.datatype; #IMPLIED
    xChannelSelector ( R | G | B | A ) 'A'
    yChannelSelector ( R | G | B | A ) 'A'
>

'feDisplacementMap'
Categories:
Filter primitive element
Content model:
Any number of the following elements, in any order:
Attributes:
DOM Interfaces:

Attribute definitions:

scale = "<number>"
Displacement scale factor. The amount is expressed in the coordinate system established by attribute 'primitiveUnits' on the 'filter' element.
When the value of this attribute is 0, this operation has no effect on the source image.
If the attribute is not specified, then the effect is as if a value of 0 were specified.
Animatable: yes.
xChannelSelector = "R | G | B | A"
Indicates which channel from 'in2' to use to displace the pixels in 'in' along the x-axis.
Animatable: yes.
yChannelSelector = "R | G | B | A"
Indicates which channel from 'in2' to use to displace the pixels in 'in' along the y-axis.
Animatable: yes.
in2 = "(see 'in' attribute)"
The second input image, which is used to displace the pixels in the image from attribute 'in'. This attribute can take on the same values as the 'in' attribute.
Animatable: yes.

15.16 Filter primitive 'feFlood'

This filter primitive creates a rectangle filled with the color and opacity values from properties 'flood-color' and 'flood-opacity'. The rectangle is as large as the filter primitive subregion established by the 'x', 'y', 'width' and 'height' attributes on the 'feFlood' element.


<!ENTITY % SVG.feFlood.extra.content "" >
<!ENTITY % SVG.feFlood.element "INCLUDE" >
<![%SVG.feFlood.element;[
<!ENTITY % SVG.feFlood.content
    "( %SVG.animate.qname; | %SVG.set.qname; | %SVG.animateColor.qname;
       %SVG.feFlood.extra.content; )*"
>
<!ELEMENT %SVG.feFlood.qname; %SVG.feFlood.content; >
<!-- end of SVG.feFlood.element -->]]>
<!ENTITY % SVG.feFlood.attlist "INCLUDE" >
<![%SVG.feFlood.attlist;[
<!ATTLIST %SVG.feFlood.qname;
    %SVG.Core.attrib;
    %SVG.Style.attrib;
    %SVG.Color.attrib;
    %SVG.FilterColor.attrib;
    %SVG.FilterPrimitiveWithIn.attrib;
    flood-color %SVGColor.datatype; #IMPLIED
    flood-opacity %OpacityValue.datatype; #IMPLIED
>

 
'feFlood'
Categories:
Filter primitive element
Content model:
Any number of the following elements, in any order:
Attributes:
DOM Interfaces:

The 'flood-color' property indicates what color to use to flood the current filter primitive subregion. The keyword currentColor and ICC colors can be specified in the same manner as within a <paint> specification for the 'fill' and 'stroke' properties.

'flood-color'
Value:  currentColor |
<color> [icc-color(<name>[,<icccolorvalue>]*)] |
inherit
Initial:  black
Applies to:  'feFlood' elements
Inherited:  no
Percentages:  N/A
Media:  visual
Animatable:  yes

The 'flood-opacity' property defines the opacity value to use across the entire filter primitive subregion.

'flood-opacity'
Value:  <opacity-value> | inherit
Initial:  1
Applies to:  'feFlood' elements
Inherited:  no
Percentages:  N/A
Media:  visual
Animatable:  yes

15.17 Filter primitive 'feGaussianBlur'

This filter primitive performs a Gaussian blur on the input image.

The Gaussian blur kernel is an approximation of the normalized convolution:

H(x) = exp(-x2/ (2s2)) / sqrt(2* pi*s2)

where 's' is the standard deviation specified by 'stdDeviation'.

The value of 'stdDeviation' can be either one or two numbers. If two numbers are provided, the first number represents a standard deviation value along the x-axis of the current coordinate system and the second value represents a standard deviation in Y. If one number is provided, then that value is used for both X and Y.

Even if only one value is provided for 'stdDeviation', this can be implemented as a separable convolution.

For larger values of 's' (s >= 2.0), an approximation can be used: Three successive box-blurs build a piece-wise quadratic convolution kernel, which approximates the Gaussian kernel to within roughly 3%.

let d = floor(s * 3*sqrt(2*pi)/4 + 0.5)

... if d is odd, use three box-blurs of size 'd', centered on the output pixel.

... if d is even, two box-blurs of size 'd' (the first one centered on the pixel boundary between the output pixel and the one to the left, the second one centered on the pixel boundary between the output pixel and the one to the right) and one box blur of size 'd+1' centered on the output pixel.

Frequently this operation will take place on alpha-only images, such as that produced by the built-in input, SourceAlpha. The implementation may notice this and optimize the single channel case. If the input has infinite extent and is constant, this operation has no effect. If the input has infinite extent and is a tile, the filter is evaluated with periodic boundary conditions.


<!ENTITY % SVG.feGaussianBlur.extra.content "" >
<!ENTITY % SVG.feGaussianBlur.element "INCLUDE" >
<![%SVG.feGaussianBlur.element;[
<!ENTITY % SVG.feGaussianBlur.content
    "( %SVG.animate.qname; | %SVG.set.qname;
       %SVG.feGaussianBlur.extra.content; )*"
>
<!ELEMENT %SVG.feGaussianBlur.qname; %SVG.feGaussi\
anBlur.content; >
<!-- end of SVG.feGaussianBlur.element -->]]>
<!ENTITY % SVG.feGaussianBlur.attlist "INCLUDE" >
<![%SVG.feGaussianBlur.attlist;[
<!ATTLIST %SVG.feGaussianBlur.qname;
    %SVG.Core.attrib;
    %SVG.FilterColor.attrib;
    %SVG.FilterPrimitiveWithIn.attrib;
    stdDeviation %NumberOptionalNumber.datatype; #IMPLIED
>

'feGaussianBlur'
Categories:
Filter primitive element
Content model:
Any number of the following elements, in any order:
Attributes:
DOM Interfaces:

Attribute definitions:

stdDeviation = "<number-optional-number>"
The standard deviation for the blur operation. If two <number>s are provided, the first number represents a standard deviation value along the x-axis of the coordinate system established by attribute 'primitiveUnits' on the 'filter' element. The second value represents a standard deviation in Y. If one number is provided, then that value is used for both X and Y.
A negative value is an error (see Error processing). A value of zero disables the effect of the given filter primitive (i.e., the result is a transparent black image).
If the attribute is not specified, then the effect is as if a value of 0 were specified.
Animatable: yes.

The example at the start of this chapter makes use of the 'feGaussianBlur' filter primitive to create a drop shadow effect.

15.18 Filter primitive 'feImage'

This filter primitive refers to a graphic external to this filter element, which is loaded or rendered into an RGBA raster and becomes the result of the filter primitive.

This filter primitive can refer to an external image or can be a reference to another piece of SVG. It produces an image similar to the built-in image source SourceGraphic except that the graphic comes from an external source.

If the 'xlink:href' references a stand-alone image resource such as a JPEG, PNG or SVG file, then the image resource is rendered according to the behavior of the 'image' element; otherwise, the referenced resource is rendered according to the behavior of the 'use' element. In either case, the current user coordinate system depends on the value of attribute 'primitiveUnits' on the 'filter' element. The processing of the 'preserveAspectRatio' attribute on the 'feImage' element is identical to that of the 'image' element.

When the referenced image must be resampled to match the device coordinate system, it is recommended that high quality viewers make use of appropriate interpolation techniques, for example bilinear or bicubic. Depending on the speed of the available interpolents, this choice may be affected by the 'image-rendering' property setting.


<!ENTITY % SVG.feImage.extra.content "" >
<!ENTITY % SVG.feImage.element "INCLUDE" >
<![%SVG.feImage.element;[
<!ENTITY % SVG.feImage.content
    "( %SVG.animate.qname; | %SVG.set.qname; | %SVG.animateTransform.qname;
       %SVG.feImage.extra.content; )*"
>
<!ELEMENT %SVG.feImage.qname; %SVG.feImage.content; >
<!-- end of SVG.feImage.element -->]]>
<!ENTITY % SVG.feImage.attlist "INCLUDE" >
<![%SVG.feImage.attlist;[
<!ATTLIST %SVG.feImage.qname;
    %SVG.Core.attrib;
    %SVG.Style.attrib;
    %SVG.Presentation.attrib;
    %SVG.FilterPrimitive.attrib;
    %SVG.XLinkEmbed.attrib;
    %SVG.External.attrib;
    preserveAspectRatio %PreserveAspectRatioSpec.datatype; 'xMidYMid meet'
>

 
'feImage'
Categories:
Filter primitive element
Content model:
Any number of the following elements, in any order:
Attributes:
DOM Interfaces:

Attribute definitions:

xlink:href = "<uri>"

A URI reference to the image source.

Animatable: yes.

15.19 Filter primitive 'feMerge'

This filter primitive composites input image layers on top of each other using the over operator with Input1 (corresponding to the first 'feMergeNode' child element) on the bottom and the last specified input, InputN (corresponding to the last 'feMergeNode' child element), on top.

Many effects produce a number of intermediate layers in order to create the final output image. This filter allows us to collapse those into a single image. Although this could be done by using n-1 Composite-filters, it is more convenient to have this common operation available in this form, and offers the implementation some additional flexibility.

Each 'feMerge' element can have any number of 'feMergeNode' subelements, each of which has an 'in' attribute.

The canonical implementation of feMerge is to render the entire effect into one RGBA layer, and then render the resulting layer on the output device. In certain cases (in particular if the output device itself is a continuous tone device), and since merging is associative, it might be a sufficient approximation to evaluate the effect one layer at a time and render each layer individually onto the output device bottom to top.

If the topmost image input is SourceGraphic and this 'feMerge' is the last filter primitive in the filter, the implementation is encouraged to render the layers up to that point, and then render the SourceGraphic directly from its vector description on top.


<!ENTITY % SVG.feMerge.extra.content "" >
<!ENTITY % SVG.feMerge.element "INCLUDE" >
<![%SVG.feMerge.element;[
<!ENTITY % SVG.feMerge.content
    "( %SVG.feMergeNode.qname; %SVG.feMerge.extra.\
content; )*"
>
<!ELEMENT %SVG.feMerge.qname; %SVG.feMerge.content; >
<!-- end of SVG.feMerge.element -->]]>
<!ENTITY % SVG.feMerge.attlist "INCLUDE" >
<![%SVG.feMerge.attlist;[
<!ATTLIST %SVG.feMerge.qname;
    %SVG.Core.attrib;
    %SVG.FilterColor.attrib;
    %SVG.FilterPrimitive.attrib;
>
<!-- end of SVG.feMerge.attlist -->]]>
<!-- feMergeNode: Filter Effect Merge Node Element ..... -->
<!ENTITY % SVG.feMergeNode.extra.content "" >
<!ENTITY % SVG.feMergeNode.element "INCLUDE" >
<![%SVG.feMergeNode.element;[
<!ENTITY % SVG.feMergeNode.content
    "( %SVG.animate.qname; | %SVG.set.qname; %SVG.feMergeNode.extra.content; )*"
>
<!ELEMENT %SVG.feMergeNode.qname; %SVG.feMergeNode.co\
ntent; >
<!-- end of SVG.feMergeNode.element -->]]>
<!ENTITY % SVG.feMergeNode.attlist "INCLUDE" >
<![%SVG.feMergeNode.attlist;[
<!ATTLIST %SVG.feMergeNode.qname;
    %SVG.Core.attrib;
    in CDATA #IMPLIED
>

 
'feMerge'
Categories:
Filter primitive element
Content model:
Any number of the following elements, in any order:
Attributes:
DOM Interfaces:
'feMergeNode'
Categories:
None
Content model:
Any number of the following elements, in any order:
Attributes:
DOM Interfaces:

The example at the start of this chapter makes use of the 'feMerge' filter primitive to composite two intermediate filter results together.

15.20 Filter primitive 'feMorphology'

This filter primitive performs "fattening" or "thinning" of artwork. It is particularly useful for fattening or thinning an alpha channel.

The dilation (or erosion) kernel is a rectangle with a width of 2*x-radius and a height of 2*y-radius. In dilation, the output pixel is the individual component-wise maximum of the corresponding R,G,B,A values in the input image's kernel rectangle. In erosion, the output pixel is the individual component-wise minimum of the corresponding R,G,B,A values in the input image's kernel rectangle.

Frequently this operation will take place on alpha-only images, such as that produced by the built-in input, SourceAlpha. In that case, the implementation might want to optimize the single channel case.

If the input has infinite extent and is constant, this operation has no effect. If the input has infinite extent and is a tile, the filter is evaluated with periodic boundary conditions.

Because 'feMorphology' operates on premultipied color values, it will always result in color values less than or equal to the alpha channel.


<!ENTITY % SVG.feMorphology.extra.content "" >
<!ENTITY % SVG.feMorphology.element "INCLUDE" >
<![%SVG.feMorphology.element;[
<!ENTITY % SVG.feMorphology.content
    "( %SVG.animate.qname; | %SVG.set.qname;
       %SVG.feMorphology.extra.content; )*"
>
<!ELEMENT %SVG.feMorphology.qname; %SVG.feMorphology\
.content; >
<!-- end of SVG.feMorphology.element -->]]>
<!ENTITY % SVG.feMorphology.attlist "INCLUDE" >
<![%SVG.feMorphology.attlist;[
<!ATTLIST %SVG.feMorphology.qname;
    %SVG.Core.attrib;
    %SVG.FilterColor.attrib;
    %SVG.FilterPrimitiveWithIn.attrib;
    operator ( erode | dilate ) 'erode'
    radius %NumberOptionalNumber.datatype; #IMPLIED
>

'feMorphology'
Categories:
Filter primitive element
Content model:
Any number of the following elements, in any order:
Attributes:
DOM Interfaces:

Attribute definitions:

operator = "erode | dilate"
A keyword indicating whether to erode (i.e., thin) or dilate (fatten) the source graphic.
Animatable: yes.
radius = "<number-optional-number>"
The radius (or radii) for the operation. If two <number>s are provided, the first number represents a x-radius and the second value represents a y-radius. If one number is provided, then that value is used for both X and Y. The values are in the coordinate system established by attribute 'primitiveUnits' on the 'filter' element.
A negative value is an error (see Error processing). A value of zero disables the effect of the given filter primitive (i.e., the result is a transparent black image).
If the attribute is not specified, then the effect is as if a value of 0 were specified.
Animatable: yes.

Example feMorphology shows examples of the four types of feMorphology operations.

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
          "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="5cm" height="7cm" viewBox="0 0 700 500"

version="1.1"
     
xmlns="http://www.w3.org/2000/svg" version="1.1">
  <title>Example feMorphology - Examples of erode and dilate</title>
  <desc>Five text strings drawn as outlines.
        The first is unfiltered. The second and third use 'erode'.
        The fourth and fifth use 'dilate'.</desc>
  <defs>
    <filter id="Erode3">
      <feMorphology operator="erode" in="SourceGraphic" radius="3" />
    </filter>
    <filter id="Erode6">
      <feMorphology operator="erode" in="SourceGraphic" radius="6" />
    </filter>
    <filter id="Dilate3">
      <feMorphology operator="dilate" in="SourceGraphic" radius="3" />
    </filter>
    <filter id="Dilate6">
      <feMorphology operator="dilate" in="SourceGraphic" radius="6" />
    </filter>
  </defs>
  <rect fill="none" stroke="blue" stroke-width="2"  
        x="1" y="1" width="698" height="498"/>
  <g enable-background="new" >
    <g font-family="Verdana" font-size="75" 
              fill="none" stroke="black" stroke-width="6" >
      <text x="50" y="90">Unfiltered</text>
      <text x="50" y="180" filter="url(#Erode3)" >Erode radius 3</text>
      <text x="50" y="270" filter="url(#Erode6)" >Erode radius 6</text>
      <text x="50" y="360" filter="url(#Dilate3)" >Dilate radius 3</text>
      <text x="50" y="450" filter="url(#Dilate6)" >Dilate radius 6</text>
    </g>
  </g>
</svg>
Example feMorphology
Example feMorphology — Examples of erode and dilate

View this example as SVG (SVG-enabled browsers only)