This chapter describes SVG's declarative filter effects feature set, which when combined with the 2D power of SVG can describe much of the common artwork on the Web in such a way that client-side generation and alteration can be performed easily. In addition, the ability to apply filter effects to SVG graphics elements and container elements helps to maintain the semantic structure of the document, instead of resorting to images which aside from generally being a fixed resolution tend to obscure the original semantics of the elements they replace. This is especially true for effects applied to text.
A filter effect consists of a series of graphics operations that are applied to a given source graphic to produce a modified graphical result. The result of the filter effect is rendered to the target device instead of the original source graphic. The following illustrates the process:

View this example as SVG (SVG-enabled browsers only)
Filter effects are defined by 'filter' elements. To apply a filter effect to a graphics element or a container element, you set the value of the 'filter' property on the given element such that it references the filter effect.
Each 'filter' element contains a set of filter primitives as its children. Each filter primitive performs a single fundamental graphical operation (e.g., a blur or a lighting effect) on one or more inputs, producing a graphical result. Because most of the filter primitives represent some form of image processing, in most cases the output from a filter primitive is a single RGBA image.
The original source graphic or the result from a filter primitive can be used as input into one or more other filter primitives. A common application is to use the source graphic multiple times. For example, a simple filter could replace one graphic by two by adding a black copy of original source graphic offset to create a drop shadow. In effect, there are now two layers of graphics, both with the same original source graphics.
When applied to container elements such as 'g', the 'filter' property applies to the contents of the group as a whole. The group's children do not render to the screen directly; instead, the graphics commands necessary to render the children are stored temporarily. Typically, the graphics commands are executed as part of the processing of the referenced 'filter' element via use of the keywords SourceGraphic or SourceAlpha. Filter effects can be applied to container elements with no content (e.g., an empty 'g' element), in which case the SourceGraphic or SourceAlpha consist of a transparent black rectangle that is the size of the filter effects region.
Sometimes filter primitives result in undefined pixels. For example, filter primitive 'feOffset' can shift an image down and to the right, leaving undefined pixels at the top and left. In these cases, the undefined pixels are set to transparent black.
The following shows an example of a filter effect.
Example filters01 - introducing filter effects.
<?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="7.5cm" height="5cm" viewBox="0 0 200 120" xmlns="http://www.w3.org/2000/svg" version="1.1"> <title>Example filters01.svg - introducing filter effects</title> <desc>An example which combines multiple filter primitives to produce a 3D lighting effect on a graphic consisting of the string "SVG" sitting on top of oval filled in red and surrounded by an oval outlined in red.</desc> <defs> <filter id="MyFilter" filterUnits="userSpaceOnUse" x="0" y="0" width="200" height="120"> <feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur"/> <feOffset in="blur" dx="4" dy="4" result="offsetBlur"/> <feSpecularLighting in="blur" surfaceScale="5" specularConstant=".75" specularExponent="20" lighting-color="#bbbbbb" result="specOut"> <fePointLight x="-5000" y="-10000" z="20000"/> </feSpecularLighting> <feComposite in="specOut" in2="SourceAlpha" operator="in" result="specOut"/> <feComposite in="SourceGraphic" in2="specOut" operator="arithmetic" k1="0" k2="1" k3="1" k4="0" result="litPaint"/> <feMerge> <feMergeNode in="offsetBlur"/> <feMergeNode in="litPaint"/> </feMerge> </filter> </defs> <rect x="1" y="1" width="198" height="118" fill="#888888" stroke="blue" /> <g filter="url(#MyFilter)" >
<g>
<path fill="none" stroke="#D90000" stroke-width="10"
d="M50,90 C0,90 0,30 50,30 L150,30 C200,30 200,90 150,90 z" />
<path fill="#D90000"
d="M60,80 C30,80 30,40 60,40 L140,40 C170,40 170,80 140,80 z" />
<g fill="#FFFFFF" stroke="black" font-size="45" font-family="Verdana" >
<text x="52" y="76">SVG</text>
</g>
</g>
</g>
</svg>
![]() |
View this example as SVG (SVG-enabled browsers only)
The filter effect used in the example above is repeated here with reference numbers in the left column before each of the six filter primitives:
1 2 3 4 5 6 |
<filter id="MyFilter" filterUnits="userSpaceOnUse" x="0" y="0" width="200" height="120">
<desc>Produces a 3D lighting effect.</desc>
<feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur"/>
<feOffset in="blur" dx="4" dy="4" result="offsetBlur"/>
<feSpecularLighting in="blur" surfaceScale="5" specularConstant=".75"
specularExponent="20" lighting-color="#bbbbbb"
result="specOut">
<fePointLight x="-5000" y="-10000" z="20000"/>
</feSpecularLighting>
<feComposite in="specOut" in2="SourceAlpha" operator="in" result="specOut"/>
<feComposite in="SourceGraphic" in2="specOut" operator="arithmetic"
k1="0" k2="1" k3="1" k4="0" result="litPaint"/>
<feMerge>
<feMergeNode in="offsetBlur"/>
<feMergeNode in="litPaint"/>
</feMerge>
</filter>
|
The following pictures show the intermediate image results from each of the six filter elements:
|
|
|
|
|
|||
|
|
|
|
The description of the 'filter' element follows:
<!ENTITY % SVG.filter.extra.content "" > <!ENTITY % SVG.filter.element "INCLUDE" > <![%SVG.filter.element;[ <!ENTITY % SVG.filter.content "(( %SVG.Description.class; )*, ( %SVG.animate.qname; | %SVG.set.qname; %SVG.FilterPrimitive.class; %SVG.filter.extra.conten\ t; )*)" > <!ELEMENT %SVG.filter.qname; %SVG.filter.content; > <!-- end of SVG.filter.element -->]]> <!ENTITY % SVG.filter.attlist "INCLUDE" > <![%SVG.filter.attlist;[ <!ATTLIST %SVG.filter.qname; %SVG.Core.attrib; %SVG.Style.attrib; %SVG.Presentation.attrib; %SVG.XLink.attrib; %SVG.External.attrib; x %Coordinate.datatype; #IMPLIED y %Coordinate.datatype; #IMPLIED width %Length.datatype; #IMPLIED height %Length.datatype; #IMPLIED filterRes %NumberOptionalNumber.datatype; #IMPLIED filterUnits ( userSpaceOnUse | objectBoundingBox ) #IMPLIED primitiveUnits ( userSpaceOnUse | objectBoundingBox ) #IMPLIED > |
Attribute definitions:
Properties inherit into the 'filter' element from its ancestors; properties do not inherit from the element referencing the 'filter' element.
'filter' elements are never rendered directly; their only usage is as something that can be referenced using the 'filter' property. The 'display' property does not apply to the 'filter' element; thus, 'filter' elements are not directly rendered even if the 'display' property is set to a value other than none, and 'filter' elements are available for referencing even when the 'display' property on the 'filter' element or any of its ancestors is set to none.
The description of the 'filter' property is as follows:
| Value: | <uri> | none | inherit |
| Initial: | none |
| Applies to: | container elements and graphics elements |
| Inherited: | no |
| Percentages: | N/A |
| Media: | visual |
| Animatable: | yes |
A 'filter' element can define a region on the canvas to which a given filter effect applies and can provide a resolution for any intermediate continuous tone images used to process any raster-based filter primitives. The 'filter' element has the following attributes which work together to define the filter effects region:
filterUnits={ userSpaceOnUse | objectBoundingBox }. , ,' and 'height' represent values in the current user coordinate system in place at the time when the 'filter'
is referenced (i.e., the user coordinate system for the element referencing the 'filter'
' and 'height' represent fractions or percentages of the bounding box on the referencing element (see Object bounding box units).
If attribute 'filterUnits' is not specified, then the effect is
if a value of 'objectBoundingBox' were specified.
Animatable: yes.
These attributes define a rectangular region on the canvas to which this filter applies.
The amount of memory and processing time required to apply the filter are related to the size of this rectangle and the 'filterRes' attribute of the filter.
The coordinate system for these attributes depends on the value for attribute 'filterUnits'.
Negative values for 'width' or 'height' are an error (see Error processing). Zero values disable rendering of the element which referenced the filter.
The bounds of this rectangle act as a hard clipping region for each filter primitive included with a given 'filter' element; thus, if the effect of a given filter primitive would extend beyond the bounds of the rectangle (this sometimes happens when using a 'feGaussianBlur' filter primitive with a very large 'stdDeviation'), parts of the effect will get clipped.
If 'x' or 'y' is not specified, the effect is as if a value of
'-10%
'120%
' were specified.
Animatable: yes.
This attribute takes the form x-pixels [y-pixels]
, and indicates the width and height of the intermediate images in pixels. If not provided, then a reasonable default resolution appropriate for the target device will be used. (For displays, an appropriate display resolution, preferably the current display's pixel resolution, is the default. For printing, an appropriate common printer resolution, such as 400dpi, is the default.)
Care should be taken when assigning a non-default value to this attribute. Too small of a value may result in unwanted pixelation in the result. Too large of a value may result in slow processing and large memory usage.
Negative values are an error (see Error processing). Zero values disable rendering of the element which referenced the filter.
Animatable: yes.
Note that both of the two possible value for 'filterUnits' (i.e., 'objectBoundingBox' and 'userSpaceOnUse') result in a filter region whose coordinate system has its X-axis and Y-axis each parallel to the X-axis and Y-axis, respectively, of the user coordinate system for the element to which the filter will be applied.
Sometimes implementers can achieve faster performance when the filter region can be mapped directly to device pixels; thus, for best performance on display devices, it is suggested that authors define their region such that SVG user agent can align the filter region pixel-for-pixel with the background. In particular, for best filter effects performance, avoid rotating or skewing the user coordinate system. Explicit values for attribute 'filterRes' can either help or harm performance. If 'filterRes' is smaller than the automatic (i.e., default) filter resolution, then filter effect might have faster performance (usually at the expense of quality). If 'filterRes' is larger than the automatic (i.e., default) filter resolution, then filter effects performance will usually be slower.
It is often necessary to provide padding space because the filter effect might impact bits slightly outside the tight-fitting bounding box on a given object. For these purposes, it is possible to provide negative percentage values for 'x' and 'y', y and percentages values greater than 100% for 'width, ' and 'height'. This, for example, is why the defaults for the filter effects region are x="-10%" y="-10%" width="120%" height="120%".
Two possible pseudo input images for filter effects are BackgroundImage and BackgroundAlpha, which each represent an image snapshot of the canvas under the filter region at the time that the 'filter' element is invoked. BackgroundImage represents both the color values and alpha channel of the canvas (i.e., RGBA pixel values), whereas BackgroundAlpha represents only the alpha channel.
Implementations of SVG user agents often will need to maintain supplemental background image buffers in order to support the BackgroundImage and BackgroundAlpha pseudo input images. Sometimes, the background image buffers will contain an in-memory copy of the accumulated painting operations on the current canvas.
Because in-memory image buffers can take up significant system resources, SVG content must explicitly indicate to the SVG user agent that the document needs access to the background image before BackgroundImage and BackgroundAlpha pseudo input images can be used. The property which enables access to the background image is 'enable-background', defined below:
| Value: | accumulate | new [ <x> <y> <width> <height> ] | inherit |
| Initial: | accumulate |
| Applies to: | container elements |
| Inherited: | no |
| Percentages: | N/A |
| Media: | visual |
| Animatable: | no |
'enable-background' is only applicable to container elements and specifies how the SVG user agents manages the accumulation of the background image.
A value of new indicates two things:
A meaning of enable-background: accumulate accumulate (the initial/default value) depends on context:
If a filter effect specifies either the BackgroundImage or the BackgroundAlpha pseudo input images and no ancestor container element has a property value of 'enable-background:new', then the background image request is technically in error. Processing will proceed without interruption (i.e., no error message) and a transparent black image shall be provided in response to the request.
The optional <x>,<y>,<width>,<height> parameters on the new value indicate the subregion of the container element's user space where access to the background image is allowed to happen. These parameters enable the SVG user agent potentially to allocate smaller temporary image buffers than the default values, which might require the SVG user agent to allocate buffers as large as the current viewport. Thus, the values <x>,<y>,<width>,<height> act as a clipping rectangle on the background image canvas. Negative values for <width> or <height> are an error (see Error processing). If more than zero but less than four of the values <x>,<y>,<width> and <height> are specified or if zero values are specified for <width> or <height>, BackgroundImage and BackgroundAlpha are processed as if background image processing were not enabled.
Assume you have an element E in the document and that E has a series of ancestors A1 (its immediate parent), A2, etc. (Note: A0 is E.) Each ancestor Ai will have a corresponding temporary background image offscreen buffer BUFi. The contents of the background image available to a 'filter' referenced by E is defined as follows:
Example enable-background-01 illustrates the rules for background image processing.
<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg width="13.5cm" height="2.7cm" viewBox="0 0 1350 270" xmlns="http://www.w3.org/2000/svg" version="1.1"> <title>Example enable-background01</title> <desc>This test case shows five pictures which illustrate the rules for background image processing.</desc> <defs> <filter id="ShiftBGAndBlur" filterUnits="userSpaceOnUse" x="0" y="0" width="1200" height="400"> <desc> This filter discards the SourceGraphic, if any, and just produces a result consisting of the BackgroundImage shifted down 125 units and then blurred. </desc> <feOffset in="BackgroundImage" dx="0" dy="125" /> <feGaussianBlur stdDeviation="8" /> </filter> <filter id="ShiftBGAndBlur_WithSourceGraphic" filterUnits="userSpaceOnUse" x="0" y="0" width="1200" height="400"> <desc> This filter takes the BackgroundImage, shifts it down 125 units, blurs it, and then renders the SourceGraphic on top of the shifted/blurred background. </desc> <feOffset in="BackgroundImage" dx="0" dy="125" /> <feGaussianBlur stdDeviation="8" result="blur" /> <feMerge> <feMergeNode in="blur"/> <feMergeNode in="SourceGraphic"/> </feMerge> </filter> </defs> <g transform="translate(0,0)"> <desc>The first picture is our reference graphic without filters.</desc> <rect x="25" y="25" width="100" height="100" fill="red"/> <g opacity=".5"> <circle cx="125" cy="75" r="45" fill="green"/> <polygon points="160,25 160,125 240,75" fill="blue"/> </g> <rect x="5" y="5" width="260" height="260" fill="none" stroke="blue"/> </g> <g enable-background="new" transform="translate(270,0)"> <desc>The second adds an empty 'g' element which invokes ShiftBGAndBlur.</desc> <rect x="25" y="25" width="100" height="100" fill="red"/> <g opacity=".5"> <circle cx="125" cy="75" r="45" fill="green"/> <polygon points="160,25 160,125 240,75" fill="blue"/> </g> <g filter="url(#ShiftBGAndBlur)"/> <rect x="5" y="5" width="260" height="260" fill="none" stroke="blue"/> </g> <g enable-background="new" transform="translate(540,0)"> <desc>The third invokes ShiftBGAndBlur on the inner group.</desc> <rect x="25" y="25" width="100" height="100" fill="red"/> <g filter="url(#ShiftBGAndBlur)" opacity=".5"> <circle cx="125" cy="75" r="45" fill="green"/> <polygon points="160,25 160,125 240,75" fill="blue"/> </g> <rect x="5" y="5" width="260" height="260" fill="none" stroke="blue"/> </g> <g enable-background="new" transform="translate(810,0)"> <desc>The fourth invokes ShiftBGAndBlur on the triangle.</desc> <rect x="25" y="25" width="100" height="100" fill="red"/> <g opacity=".5"> <circle cx="125" cy="75" r="45" fill="green"/> <polygon points="160,25 160,125 240,75" fill="blue" filter="url(#ShiftBGAndBlur)"/> </g> <rect x="5" y="5" width="260" height="260" fill="none" stroke="blue"/> </g> <g enable-background="new" transform="translate(1080,0)"> <desc>The fifth invokes ShiftBGAndBlur_WithSourceGraphic on the triangle.</desc> <rect x="25" y="25" width="100" height="100" fill="red"/> <g opacity=".5"> <circle cx="125" cy="75" r="45" fill="green"/> <polygon points="160,25 160,125 240,75" fill="blue" filter="url(#ShiftBGAndBlur_WithSourceGraphic)"/> </g> <rect x="5" y="5" width="260" height="260" fill="none" stroke="blue"/> </g> </svg>
![]() |
View this example as SVG (SVG-enabled browsers only)
The example above contains five parts, described as follows:
This section describes the various filter primtives that can be assembled to achieve a particular filter effect.
Unless otherwise stated, all image filters operate on premultiplied RGBA samples. Filters which work more naturally on non-premultiplied data (feColorMatrix and feComponentTransfer) will temporarily undo and redo premultiplication as specified. All raster effect filtering operations take 1 to N input RGBA images, additional attributes as parameters, and produce a single output RGBA image.
The RGBA result from each filter primitive will be clamped into the allowable ranges for colors and opacity values. Thus, for example, the result from a given filter primitive will have any negative color values or opacity values adjusted up to color/opacity of zero.
The color space in which a particular filter primitive performs its operations is determined by the value of property 'color-interpolation-filters' on the given filter primitive. A different property, 'color-interpolation' determines the color space for other color operations. Because these two properties have different initial values ('color-interpolation-filters' has an initial value of linearRGB whereas 'color-interpolation' has an initial value of sRGB), in some cases to achieve certain results (e.g., when coordinating gradient interpolation with a filtering operation) it will be necessary to explicitly set 'color-interpolation' to linearRGB or 'color-interpolation-filters' to sRGB on particular elements. Note that the examples below do not explicitly set either 'color-interpolation' or 'color-interpolation-filters', so the initial values for these properties apply to the examples.
The With the exception of the 'in' attribute, all of the following attributes are available for most of the filter primitives:
<!ENTITY % SVG.FilterPrimitive.extra.attrib "" > <!ENTITY % SVG.FilterPrimitive.attrib "x %Coordinate.datatype; #IMPLIED y %Coordinate.datatype; #IMPLIED width %Length.datatype; #IMPLIED height %Length.datatype; #IMPLIED result CDATA #IMPLIED %SVG.FilterPrimitive.extra.attrib;" > <!-- SVG.FilterPrimitiveWithIn.attrib ..................\ --> <!ENTITY % SVG.FilterPrimitiveWithIn.extra.attrib "" > <!ENTITY % SVG.FilterPrimitiveWithIn.attrib "%SVG.FilterPrimitive.attrib; in CDATA #IMPLIED %SVG.FilterPrimitiveWithIn.extra.attrib;" >
on all filter primitive elements:
Attribute definitions:
The 'in' attribute is available on all filter primitive elements that require an input.
Animatable: yes.All filter primitives have attributes 'x', 'y', 'width' and 'height' which identify a subregion which restricts calculation and rendering of the given filter primitive. These attributes are defined according to the same rules as other filter primitives' coordinate and length attributes and thus represent values in the coordinate system established by attribute 'primitiveUnits' on the 'filter' element.
'x', 'y', 'width' and 'height' default to the union (i.e., tightest fitting bounding box) of the subregions defined for all referenced nodes. If there are no referenced nodes (e.g., for 'feImage' or 'feTurbulence'), or one or more of the referenced nodes is a standard input (one of SourceGraphic, SourceAlpha, BackgroundImage, BackgroundAlpha, FillPaint or StrokePaint), or for 'feTile' (which is special because its principal function is to replicate the referenced node in X and Y and thereby produce a usually larger result), the default subregion is 0%,0%,100%,100%, where percentages are relative to the dimensions of the filter region.
'x', 'y', 'width' and 'height' act as a hard clip clipping rectangle.
All intermediate offscreens are defined to not exceed the intersection of 'x', 'y', 'width' and 'height' with the filter region. The filter region and any of the 'x', 'y', 'width' and 'height' subregions are to be set up such that all offscreens are made big enough to accommodate any pixels which even partly intersect with either the filter region or the x,y,width,height subregions.
'feTile' references a previous filter primitive and then stitches the tiles together based on the 'x', 'y', 'width' and 'height' values of the referenced filter primitive in order to fill its own filter primitive subregion.
The following sections define the elements that define a light source, 'feDistantLight', 'fePointLight' and 'feSpotLight', and property 'lighting-color', which defines the color of the light.
<!ENTITY % SVG.feDistantLight.extra.content "" > <!ENTITY % SVG.feDistantLight.element "INCLUDE" > <![%SVG.feDistantLight.element;[ <!ENTITY % SVG.feDistantLight.content "( %SVG.animate.qname; | %SVG.set.qname; %SVG.feDistantLight.extra.content; )*" > <!ELEMENT %SVG.feDistantLight.qname; %SVG.feDistan\ tLight.content; > <!-- end of SVG.feDistantLight.element -->]]> <!ENTITY % SVG.feDistantLight.attlist "INCLUDE" > <![%SVG.feDistantLight.attlist;[ <!ATTLIST %SVG.feDistantLight.qname; %SVG.Core.attrib; azimuth %Number.datatype; #IMPLIED elevation %Number.datatype; #IMPLIED > |
Attribute definitions:
<!ENTITY % SVG.fePointLight.extra.content "" > <!ENTITY % SVG.fePointLight.element "INCLUDE" > <![%SVG.fePointLight.element;[ <!ENTITY % SVG.fePointLight.content "( %SVG.animate.qname; | %SVG.set.qname; %SVG.fePointLight.extra.content; )*" > <!ELEMENT %SVG.fePointLight.qname; %SVG.fePointLight\ .content; > <!-- end of SVG.fePointLight.element -->]]> <!ENTITY % SVG.fePointLight.attlist "INCLUDE" > <![%SVG.fePointLight.attlist;[ <!ATTLIST %SVG.fePointLight.qname; %SVG.Core.attrib; x %Number.datatype; #IMPLIED y %Number.datatype; #IMPLIED z %Number.datatype; #IMPLIED > |
Attribute definitions:
<!ENTITY % SVG.feSpotLight.extra.content "" > <!ENTITY % SVG.feSpotLight.element "INCLUDE" > <![%SVG.feSpotLight.element;[ <!ENTITY % SVG.feSpotLight.content "( %SVG.animate.qname; | %SVG.set.qname; %SVG.feSpotLight.extra.content; )*" > <!ELEMENT %SVG.feSpotLight.qname; %SVG.feSpotLight.co\ ntent; > <!-- end of SVG.feSpotLight.element -->]]> <!ENTITY % SVG.feSpotLight.attlist "INCLUDE" > <![%SVG.feSpotLight.attlist;[ <!ATTLIST %SVG.feSpotLight.qname; %SVG.Core.attrib; x %Number.datatype; #IMPLIED y %Number.datatype; #IMPLIED z %Number.datatype; #IMPLIED pointsAtX %Number.datatype; #IMPLIED pointsAtY %Number.datatype; #IMPLIED pointsAtZ %Number.datatype; #IMPLIED specularExponent %Number.datatype; #IMPLIED limitingConeAngle %Number.datatype; #IMPLIED > |
Attribute definitions:
The 'lighting-color' property defines the color of the light source for filter primitives 'feDiffuseLighting' and 'feSpecularLighting'.
| Value: | currentColor | <color> [icc-color(<name>[,<icccolorvalue>]*)] | inherit |
| Initial: | white |
| Applies to: | 'feDiffuseLighting' and 'feSpecularLighting' elements |
| Inherited: | no |
| Percentages: | N/A |
| Media: | visual |
| Animatable: | yes |
This filter composites two objects together using commonly used imaging software blending modes. It performs a pixel-wise combination of two input images.
<!ENTITY % SVG.feBlend.extra.content "" > <!ENTITY % SVG.feBlend.element "INCLUDE" > <![%SVG.feBlend.element;[ <!ENTITY % SVG.feBlend.content "( %SVG.animate.qname; | %SVG.set.qname; %SVG.feBlend.extra.content; )*" > <!ELEMENT %SVG.feBlend.qname; %SVG.feBlend.content; > <!-- end of SVG.feBlend.element -->]]> <!ENTITY % SVG.feBlend.attlist "INCLUDE" > <![%SVG.feBlend.attlist;[ <!ATTLIST %SVG.feBlend.qname; %SVG.Core.attrib; %SVG.FilterColor.attrib; %SVG.FilterPrimitiveWithIn.attrib; in2 CDATA #REQUIRED mode ( normal | multiply | screen | darken | lighten ) 'normal' > |
Attribute definitions:
For all feBlend modes, the result opacity is computed as follows:
qr = 1 - (1-qa)*(1-qb)
For the compositing formulas below, the following definitions apply:
cr = Result color (RGB) - premultiplied qa = Opacity value at a given pixel for image A qb = Opacity value at a given pixel for image B ca = Color (RGB) at a given pixel for image A - premultiplied cb = Color (RGB) at a given pixel for image B - premultiplied
The following table provides the list of available image blending modes:
| Image Blending Mode | Formula for computing result color |
| normal | cr = (1 - qa) * cb + ca |
| multiply | cr = (1-qa)*cb + (1-qb)*ca + ca*cb |
| screen | cr = cb + ca - ca * cb |
| darken | cr = Min ((1 - qa) * cb + ca, (1 - qb) * ca + cb) |
| lighten | cr = Max ((1 - qa) * cb + ca, (1 - qb) * ca + cb) |
'normal' blend mode is equivalent to operator="over" on the 'feComposite' filter primitive, matches the blending method used by 'feMerge' and matches the simple alpha compositing technique used in SVG for all compositing outside of filter effects.
Example feBlend shows examples of the five blend modes.
<?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="5cm" viewBox="0 0 500 500"
version="1.1"
xmlns="http://www.w3.org/2000/svg" version="1.1"> <title>Example feBlend - Examples of feBlend modes</title> <desc>Five text strings blended into a gradient, with one text string for each of the five feBlend modes.</desc> <defs> <linearGradient id="MyGradient" gradientUnits="userSpaceOnUse" x1="100" y1="0" x2="300" y2="0"> <stop offset="0" stop-color="#000000" /> <stop offset=".33" stop-color="#ffffff" /> <stop offset=".67" stop-color="#ff0000" /> <stop offset="1" stop-color="#808080" /> </linearGradient> <filter id="Normal"> <feBlend mode="normal" in2="BackgroundImage" in="SourceGraphic"/> </filter> <filter id="Multiply"> <feBlend mode="multiply" in2="BackgroundImage" in="SourceGraphic"/> </filter> <filter id="Screen"> <feBlend mode="screen" in2="BackgroundImage" in="SourceGraphic"/> </filter> <filter id="Darken"> <feBlend mode="darken" in2="BackgroundImage" in="SourceGraphic"/> </filter> <filter id="Lighten"> <feBlend mode="lighten" in2="BackgroundImage" in="SourceGraphic"/> </filter> </defs> <rect fill="none" stroke="blue" x="1" y="1" width="498" height="498"/> <g enable-background="new" > <rect x="100" y="20" width="300" height="460" fill="url(#MyGradient)" /> <g font-family="Verdana" font-size="75" fill="#888888" fill-opacity=".6" > <text x="50" y="90" filter="url(#Normal)" >Normal</text> <text x="50" y="180" filter="url(#Multiply)" >Multiply</text> <text x="50" y="270" filter="url(#Screen)" >Screen</text> <text x="50" y="360" filter="url(#Darken)" >Darken</text> <text x="50" y="450" filter="url(#Lighten)" >Lighten</text> </g> </g> </svg>
![]() |
View this example as SVG (SVG-enabled browsers only)
This filter applies a matrix transformation:
| R' | | a00 a01 a02 a03 a04 | | R | | G' | | a10 a11 a12 a13 a14 | | G | | B' | = | a20 a21 a22 a23 a24 | * | B | | A' | | a30 a31 a32 a33 a34 | | A | | 1 | | 0 0 0 0 1 | | 1 |
on the RGBA color and alpha values of every pixel on the input graphics to produce a result with a new set of RGBA color and alpha values.
The calculations are performed on non-premultiplied color values. If the input graphics consists of premultiplied color values, those values are automatically converted into non-premultiplied color values for this operation.
These matrices often perform an identity mapping in the alpha channel. If that is the case, an implementation can avoid the costly undoing and redoing of the premultiplication for all pixels with A = 1.
<!ENTITY % SVG.feColorMatrix.extra.content "" > <!ENTITY % SVG.feColorMatrix.element "INCLUDE" > <![%SVG.feColorMatrix.element;[ <!ENTITY % SVG.feColorMatrix.content "( %SVG.animate.qname; | %SVG.set.qname; %SVG.feColorMatrix.extra.content; )*" > <!ELEMENT %SVG.feColorMatrix.qname; %SVG.feColorMat\ rix.content; > <!-- end of SVG.feColorMatrix.element -->]]> <!ENTITY % SVG.feColorMatrix.attlist "INCLUDE" > <![%SVG.feColorMatrix.attlist;[ <!ATTLIST %SVG.feColorMatrix.qname; %SVG.Core.attrib; %SVG.FilterColor.attrib; %SVG.FilterPrimitiveWithIn.attrib; type ( matrix | saturate | hueRotate | luminanceToAlpha ) 'matrix' values CDATA #IMPLIED > |
Attribute definitions:
type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"
| R' | |0.213+0.787s 0.715-0.715s 0.072-0.072s 0 0 | | R | | G' | |0.213-0.213s 0.715+0.285s 0.072-0.072s 0 0 | | G | | B' | = |0.213-0.213s 0.715-0.715s 0.072+0.928s 0 0 | * | B | | A' | | 0 0 0 1 0 | | A | | 1 | | 0 0 0 0 1 | | 1 |
| R' | | a00 a01 a02 0 0 | | R | | G' | | a10 a11 a12 0 0 | | G | | B' | = | a20 a21 a22 0 0 | * | B | | A' | | 0 0 0 1 0 | | A | | 1 | | 0 0 0 0 1 | | 1 |where the terms a00, a01, etc. are calculated as follows:
| a00 a01 a02 | [+0.213 +0.715 +0.072]
| a10 a11 a12 | = [+0.213 +0.715 +0.072] +
| a20 a21 a22 | [+0.213 +0.715 +0.072]
[+0.787 -0.715 -0.072]
cos(hueRotate value) * [-0.213 +0.285 -0.072] +
[-0.213 -0.715 +0.928]
[-0.213 -0.715+0.928]
sin(hueRotate value) * [+0.143 +0.140-0.283]
[-0.787 +0.715+0.072]
Thus, the upper left term of the hue matrix turns out to be: .213 + cos(hueRotate value)*.787 - sin(hueRotate value)*.213
| R' | | 0 0 0 0 0 | | R | | G' | | 0 0 0 0 0 | | G | | B' | = | 0 0 0 0 0 | * | B | | A' | | 0.2125 0.7154 0.0721 0 0 | | A | | 1 | | 0 0 0 0 1 | | 1 |
Example feColorMatrix shows examples of the four types of feColorMatrix 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="8cm" height="5cm" viewBox="0 0 800 500"
version="1.1"
xmlns="http://www.w3.org/2000/svg" version="1.1"> <title>Example feColorMatrix - Examples of feColorMatrix operations</title> <desc>Five text strings showing the effects of feColorMatrix: an unfiltered text string acting as a reference, use of the feColorMatrix matrix option to convert to grayscale, use of the feColorMatrix saturate option, use of the feColorMatrix hueRotate option, and use of the feColorMatrix luminanceToAlpha option.</desc> <defs> <linearGradient id="MyGradient" gradientUnits="userSpaceOnUse" x1="100" y1="0" x2="500" y2="0"> <stop offset="0" stop-color="#ff00ff" /> <stop offset=".33" stop-color="#88ff88" /> <stop offset=".67" stop-color="#2020ff" /> <stop offset="1" stop-color="#d00000" /> </linearGradient> <filter id="Matrix" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%"> <feColorMatrix type="matrix" in="SourceGraphic" values=".33 .33 .33 0 0 .33 .33 .33 0 0 .33 .33 .33 0 0 .33 .33 .33 0 0"/> </filter> <filter id="Saturate40" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%"> <feColorMatrix type="saturate" in="SourceGraphic" values="0.4
40%"/> </filter> <filter id="HueRotate90" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%"> <feColorMatrix type="hueRotate" in="SourceGraphic" values="90"/> </filter> <filter id="LuminanceToAlpha" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%"> <feColorMatrix type="luminanceToAlpha" in="SourceGraphic" result="a"/> <feComposite in="SourceGraphic" in2="a" operator="in" /> </filter> </defs> <rect fill="none" stroke="blue" x="1" y="1" width="798" height="498"/> <g font-family="Verdana" font-size="75" font-weight="bold" fill="url(#MyGradient)" > <rect x="100" y="0" width="500" height="20" /> <text x="100" y="90">Unfiltered</text> <text x="100" y="190" filter="url(#Matrix)" >Matrix</text> <text x="100" y="290" filter="url(#Saturate40)" >Saturate</text> <text x="100" y="390" filter="url(#HueRotate90)" >HueRotate</text> <text x="100" y="490" filter="url(#LuminanceToAlpha)" >Luminance</text> </g> </svg>
![]() |
View this example as SVG (SVG-enabled browsers only)
This filter primitive performs component-wise remapping of data as follows:
R' = feFuncR( R ) G' = feFuncG( G ) B' = feFuncB( B ) A' = feFuncA( A )
for every pixel. It allows operations like brightness adjustment, contrast adjustment, color balance or thresholding.
The calculations are performed on non-premultiplied color values. If the input graphics consists of premultiplied color values, those values are automatically converted into non-premultiplied color values for this operation. (Note that the undoing and redoing of the premultiplication can be avoided if feFuncA is the identity transform and all alpha values on the source graphic are set to 1.)
lt;!ENTITY % SVG.feComponentTransfer.extra.content "" > <!ENTITY % SVG.feComponentTransfer.element "INCLUDE" > <![%SVG.feComponentTransfer.element;[ <!ENTITY % SVG.feComponentTransfer.content "( %SVG.feFuncR.qname;?, %SVG.feFuncG.qname;?, %SVG.feFuncB.qname;?, %SVG.feFuncA.qname;? %SVG.feComponentTransfer.e\ xtra.content; )" > <!ELEMENT %SVG.feComponentTransfer.qname; %SV\ G.feComponentTransfer.content; > <!-- end of SVG.feComponentTransfer.element -->]]> <!ENTITY % SVG.feComponentTransfer.attlist "INCLUDE" > <![%SVG.feComponentTransfer.attlist;[ <!ATTLIST %SVG.feComponentTransfer.qname; %SVG.Core.attrib; %SVG.FilterColor.attrib; %SVG.FilterPrimitiveWithIn.attrib; > <!-- feFuncR: Filter Effect Function Red Element ....... --> <!ENTITY % SVG.feFuncR.extra.content "" > <!ENTITY % SVG.feFuncR.element "INCLUDE" > <![%SVG.feFuncR.element;[ <!ENTITY % SVG.feFuncR.content "( %SVG.animate.qname; | %SVG.set.qname; %SVG.feFuncR.extra.content; )*" > <!ELEMENT %SVG.feFuncR.qname; %SVG.feFuncR.content; > <!-- end of SVG.feFuncR.element -->]]> <!ENTITY % SVG.feFuncR.attlist "INCLUDE" > <![%SVG.feFuncR.attlist;[ <!ATTLIST %SVG.feFuncR.qname; %SVG.Core.attrib; type ( identity | table | discrete | linear | gamma ) #REQUIRED tableValues CDATA #IMPLIED slope %Number.datatype; #IMPLIED intercept %Number.datatype; #IMPLIED amplitude %Number.datatype; #IMPLIED exponent %Number.datatype; #IMPLIED offset %Number.datatype; #IMPLIED > <!-- end of SVG.feFuncR.attlist -->]]> <!-- feFuncG: Filter Effect Function Green Element ..... --> <!ENTITY % SVG.feFuncG.extra.content "" > <!ENTITY % SVG.feFuncG.element "INCLUDE" > <![%SVG.feFuncG.element;[ <!ENTITY % SVG.feFuncG.content "( %SVG.animate.qname; | %SVG.set.qname; %SVG.feFuncG.extra.content; )*" > <!ELEMENT %SVG.feFuncG.qname; %SVG.feFuncG.content; > <!-- end of SVG.feFuncG.element -->]]> <!ENTITY % SVG.feFuncG.attlist "INCLUDE" > <![%SVG.feFuncG.attlist;[ <!ATTLIST %SVG.feFuncG.qname; %SVG.Core.attrib; type ( identity | table | discrete | linear | gamma ) #REQUIRED tableValues CDATA #IMPLIED slope %Number.datatype; #IMPLIED intercept %Number.datatype; #IMPLIED amplitude %Number.datatype; #IMPLIED exponent %Number.datatype; #IMPLIED offset %Number.datatype; #IMPLIED > <!-- end of SVG.feFuncG.attlist -->]]> <!-- feFuncB: Filter Effect Function Blue Element ...... --> <!ENTITY % SVG.feFuncB.extra.content "" > <!ENTITY % SVG.feFuncB.element "INCLUDE" > <![%SVG.feFuncB.element;[ <!ENTITY % SVG.feFuncB.content "( %SVG.animate.qname; | %SVG.set.qname; %SVG.feFuncB.extra.content; )*" > <!ELEMENT %SVG.feFuncB.qname; %SVG.feFuncB.content; > <!-- end of SVG.feFuncB.element -->]]> <!ENTITY % SVG.feFuncB.attlist "INCLUDE" > <![%SVG.feFuncB.attlist;[ <!ATTLIST %SVG.feFuncB.qname; %SVG.Core.attrib; type ( identity | table | discrete | linear | gamma ) #REQUIRED tableValues CDATA #IMPLIED slope %Number.datatype; #IMPLIED intercept %Number.datatype; #IMPLIED amplitude %Number.datatype; #IMPLIED exponent %Number.datatype; #IMPLIED offset %Number.datatype; #IMPLIED > <!-- end of SVG.feFuncB.attlist -->]]> <!-- feFuncA: Filter Effect Function Alpha Element ..... --> <!ENTITY % SVG.feFuncA.extra.content "" > <!ENTITY % SVG.feFuncA.element "INCLUDE" > <![%SVG.feFuncA.element;[ <!ENTITY % SVG.feFuncA.content "( %SVG.animate.qname; | %SVG.set.qname; %SVG.feFuncA.extra.content; )*" > <!ELEMENT %SVG.feFuncA.qname; %SVG.feFuncA.content; > <!-- end of SVG.feFuncA.element -->]]> <!ENTITY % SVG.feFuncA.attlist "INCLUDE" > <![%SVG.feFuncA.attlist;[ <!ATTLIST %SVG.feFuncA.qname; %SVG.Core.attrib; type ( identity | table | discrete | linear | gamma ) #REQUIRED tableValues CDATA #IMPLIED slope %Number.datatype; #IMPLIED intercept %Number.datatype; #IMPLIED amplitude %Number.datatype; #IMPLIED exponent %Number.datatype; #IMPLIED offset %Number.datatype; #IMPLIED > |
The child elements of a 'feComponentTransfer' element specify the transfer functions for the four channels:
,The attributes below apply to sub-elements 'feFuncR', 'feFuncG', 'feFuncB' and 'feFuncA' that define the transfer functions.
Attribute definitions:
Indicates the type of component transfer function. The type of function determines the applicability of the other attributes.
C' = C
For a value C pick a k such that:
k/N <= C < (k+1)/N
The result C' is given by:
C' = vk + (C - k/N)*N * (vk+1 - vk)
For a value C pick a k such that:
k/N <= C < (k+1)/N
The result C' is given by:
C' = vk
Example feComponentTransfer shows examples of the four types of feComponentTransfer 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="8cm" height="4cm" viewBox="0 0 800 400"
version="1.1"
xmlns="http://www.w3.org/2000/svg" version="1.1"> <title>Example feComponentTransfer - Examples of feComponentTransfer operations</title> <desc>Four text strings showing the effects of feComponentTransfer: an identity function acting as a reference, use of the feComponentTransfer table option, use of the feComponentTransfer linear option, and use of the feComponentTransfer gamma option.</desc> <defs> <linearGradient id="MyGradient" gradientUnits="userSpaceOnUse" x1="100" y1="0" x2="600" y2="0"> <stop offset="0" stop-color="#ff0000" /> <stop offset=".33" stop-color="#00ff00" /> <stop offset=".67" stop-color="#0000ff" /> <stop offset="1" stop-color="#000000" /> </linearGradient> <filter id="Identity" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%"> <feComponentTransfer> <feFuncR type="identity"/> <feFuncG type="identity"/> <feFuncB type="identity"/> <feFuncA type="identity"/> </feComponentTransfer> </filter> <filter id="Table" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%"> <feComponentTransfer> <feFuncR type="table" tableValues="0 0 1 1"/> <feFuncG type="table" tableValues="1 1 0 0"/> <feFuncB type="table" tableValues="0 1 1 0"/> </feComponentTransfer> </filter> <filter id="Linear" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%"> <feComponentTransfer> <feFuncR type="linear" slope=".5" intercept=".25"/> <feFuncG type="linear" slope=".5" intercept="0"/> <feFuncB type="linear" slope=".5" intercept=".5"/> </feComponentTransfer> </filter> <filter id="Gamma" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%"> <feComponentTransfer> <feFuncR type="gamma" amplitude="2" exponent="5" offset="0"/> <feFuncG type="gamma" amplitude="2" exponent="3" offset="0"/> <feFuncB type="gamma" amplitude="2" exponent="1" offset="0"/> </feComponentTransfer> </filter> </defs> <rect fill="none" stroke="blue" x="1" y="1" width="798" height="398"/> <g font-family="Verdana" font-size="75" font-weight="bold" fill="url(#MyGradient)" > <rect x="100" y="0" width="600" height="20" /> <text x="100" y="90">Identity</text> <text x="100" y="190" filter="url(#Table)" >TableLookup</text> <text x="100" y="290" filter="url(#Linear)" >LinearFunc</text> <text x="100" y="390" filter="url(#Gamma)" >GammaFunc</text> </g> </svg>
![]() |
View this example as SVG (SVG-enabled browsers only)
This filter performs the combination of the two input images pixel-wise in image space using one of the Porter-Duff [PORTERDUFF] compositing operations: over, in, atop, out, xor. Additionally, a component-wise arithmetic operation (with the result clamped between [0..1]) can be applied.
The arithmetic operation is useful for combining the output from the 'feDiffuseLighting' and 'feSpecularLighting' filters with texture data. It is also useful for implementing dissolve. If the arithmetic operation is chosen, each result pixel is computed using the following formula:
result = k1*i1*i2 + k2*i1 + k3*i2 + k4
For this filter primitive, the extent of the resulting image might grow as described in the section that describes the filter primitive subregion.
<!ENTITY % SVG.feComposite.extra.content "" > <!ENTITY % SVG.feComposite.element "INCLUDE" > <![%SVG.feComposite.element;[ <!ENTITY % SVG.feComposite.content "( %SVG.animate.qname; | %SVG.set.qname; %SVG.feComposite.extra.content; )*" > <!ELEMENT %SVG.feComposite.qname; %SVG.feComposite.co\ ntent; > <!-- end of SVG.feComposite.element -->]]> <!ENTITY % SVG.feComposite.attlist "INCLUDE" > <![%SVG.feComposite.attlist;[ <!ATTLIST %SVG.feComposite.qname; %SVG.Core.attrib; %SVG.FilterColor.attrib; %SVG.FilterPrimitiveWithIn.attrib; in2 CDATA #REQUIRED operator ( over | in | out | atop | xor | arithmetic ) 'over' k1 %Number.datatype; #IMPLIED k2 %Number.datatype; #IMPLIED k3 %Number.datatype; #IMPLIED k4 %Number.datatype; #IMPLIED > |
Attribute definitions:
Example feComposite shows examples of the six types of feComposite operations. It also shows two different techniques to using the BackgroundImage as part of the compositing operation.
The first two rows render bluish triangles into the background. A filter is applied which composites reddish triangles into the bluish triangles using one of the compositing operations. The result from compositing is drawn onto an opaque white temporary surface, and then that result is written to the canvas. (The opaque white temporary surface obliterates the original bluish triangle.)
The last two rows apply the same compositing operations of reddish triangles into bluish triangles. However, the compositing result is directly blended into the canvas (the opaque white temporary surface technique is not used). In some cases, the results are different than when a temporary opaque white surface is used. The original bluish triangle from the background shines through wherever the compositing operation results in completely transparent pixel. In other cases, the result from compositing is blended into the bluish triangle, resulting in a different final color value.
<?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="330" height="195" viewBox="0 0 1100 650" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Example feComposite - Examples of feComposite operations</title>
<desc>Four rows of six pairs of overlapping triangles depicting
the six different feComposite operators under different
opacity values and different clearing of the background.</desc>
<defs> <desc>Define two sets of six filters for each of the six compositing operators. The first set wipes out the background image by flooding with opaque white. The second set does not wipe out the background, with the result that the background sometimes shines through and is other cases is blended into itself (i.e., "double-counting").</desc> <filter id="overFlood" filterUnits="objectBoundingBox" x="-5%" y="-5%" width="110%" height="110%"> <feFlood flood-color="#ffffff" flood-opacity="1" result="flood"/> <feComposite in="SourceGraphic" in2="BackgroundImage" operator="over" result="comp"/> <feMerge> <feMergeNode in="flood"/> <feMergeNode in="comp"/> </feMerge> </filter> <filter id="inFlood" filterUnits="objectBoundingBox" x="-5%" y="-5%" width="110%" height="110%"> <feFlood flood-color="#ffffff" flood-opacity="1" result="flood"/> <feComposite in="SourceGraphic" in2="BackgroundImage" operator="in" result="comp"/> <feMerge> <feMergeNode in="flood"/> <feMergeNode in="comp"/> </feMerge> </filter> <filter id="outFlood" filterUnits="objectBoundingBox" x="-5%" y="-5%" width="110%" height="110%"> <feFlood flood-color="#ffffff" flood-opacity="1" result="flood"/> <feComposite in="SourceGraphic" in2="BackgroundImage" operator="out" result="comp"/> <feMerge> <feMergeNode in="flood"/> <feMergeNode in="comp"/> </feMerge> </filter> <filter id="atopFlood" filterUnits="objectBoundingBox" x="-5%" y="-5%" width="110%" height="110%"> <feFlood flood-color="#ffffff" flood-opacity="1" result="flood"/> <feComposite in="SourceGraphic" in2="BackgroundImage" operator="atop" result="comp"/> <feMerge> <feMergeNode in="flood"/> <feMergeNode in="comp"/> </feMerge> </filter> <filter id="xorFlood" filterUnits="objectBoundingBox" x="-5%" y="-5%" width="110%" height="110%"> <feFlood flood-color="#ffffff" flood-opacity="1" result="flood"/> <feComposite in="SourceGraphic" in2="BackgroundImage" operator="xor" result="comp"/> <feMerge> <feMergeNode in="flood"/> <feMergeNode in="comp"/> </feMerge> </filter> <filter id="arithmeticFlood" filterUnits="objectBoundingBox" x="-5%" y="-5%" width="110%" height="110%"> <feFlood flood-color="#ffffff" flood-opacity="1" result="flood"/> <feComposite in="SourceGraphic" in2="BackgroundImage" result="comp" operator="arithmetic" k1=".5" k2=".5" k3=".5" k4=".5"/> <feMerge> <feMergeNode in="flood"/> <feMergeNode in="comp"/> </feMerge> </filter> <filter id="overNoFlood" filterUnits="objectBoundingBox" x="-5%" y="-5%" width="110%" height="110%"> <feComposite in="SourceGraphic" in2="BackgroundImage" operator="over" result="comp"/> </filter> <filter id="inNoFlood" filterUnits="objectBoundingBox" x="-5%" y="-5%" width="110%" height="110%"> <feComposite in="SourceGraphic" in2="BackgroundImage" operator="in" result="comp"/> </filter> <filter id="outNoFlood" filterUnits="objectBoundingBox" x="-5%" y="-5%" width="110%" height="110%"> <feComposite in="SourceGraphic" in2="BackgroundImage" operator="out" result="comp"/> </filter> <filter id="atopNoFlood" filterUnits="objectBoundingBox" x="-5%" y="-5%" width="110%" height="110%"> <feComposite in="SourceGraphic" in2="BackgroundImage" operator="atop" result="comp"/> </filter> <filter id="xorNoFlood" filterUnits="objectBoundingBox" x="-5%" y="-5%" width="110%" height="110%"> <feComposite in="SourceGraphic" in2="BackgroundImage" operator="xor" result="comp"/> </filter> <filter id="arithmeticNoFlood" filterUnits="objectBoundingBox" x="-5%" y="-5%" width="110%" height="110%"> <feComposite in="SourceGraphic" in2="BackgroundImage" result="comp" operator="arithmetic" k1=".5" k2=".5" k3=".5" k4=".5"/> </filter> <path id="Blue100" d="M 0 0 L 100 0 L 100 100 z" fill="#00ffff" /> <path id="Red100" d="M 0 0 L 0 100 L 100 0 z" fill="#ff00ff" /> <path id="Blue50" d="M 0 125 L 100 125 L 100 225 z" fill="#00ffff" fill-opacity=".5" /> <path id="Red50" d="M 0 125 L 0 225 L 100 125 z" fill="#ff00ff" fill-opacity=".5" /> <g id="TwoBlueTriangles"> <use xlink:href="#Blue100"/> <use xlink:href="#Blue50"/> </g> <g id="BlueTriangles"> <use transform="translate(275,25)" xlink:href="#TwoBlueTriangles"/> <use transform="translate(400,25)" xlink:href="#TwoBlueTriangles"/> <use transform="translate(525,25)" xlink:href="#TwoBlueTriangles"/> <use transform="translate(650,25)" xlink:href="#TwoBlueTriangles"/> <use transform="translate(775,25)" xlink:href="#TwoBlueTriangles"/> <use transform="translate(900,25)" xlink:href="#TwoBlueTriangles"/> </g> </defs> <rect fill="none" stroke="blue" x="1" y="1" width="1098" height="648"/> <g font-family="Verdana" font-size="40" shape-rendering="crispEdges"> <desc>Render the examples using the filters that draw on top of an opaque white surface, thus obliterating the background.</desc> <g enable-background="new"> <text x="15" y="75">opacity 1.0</text> <text x="15" y="115" font-size="27">(with feFlood)</text> <text x="15" y="200">opacity 0.5</text> <text x="15" y="240" font-size="27">(with feFlood)</text> <use xlink:href="#BlueTriangles"/> <g transform="translate(275,25)"> <use xlink:href="#Red100" filter="url(#overFlood)" /> <use xlink:href="#Red50" filter="url(#overFlood)" /> <text x="5" y="275">over</text> </g> <g transform="translate(400,25)"> <use xlink:href="#Red100" filter="url(#inFlood)" /> <use xlink:href="#Red50" filter="url(#inFlood)" /> <text x="35" y="275">in</text> </g> <g transform="translate(525,25)"> <use xlink:href="#Red100" filter="url(#outFlood)" /> <use xlink:href="#Red50" filter="url(#outFlood)" /> <text x="15" y="275">out</text> </g> <g transform="translate(650,25)"> <use xlink:href="#Red100" filter="url(#atopFlood)" /> <use xlink:href="#Red50" filter="url(#atopFlood)" /> <text x="10" y="275">atop</text> </g> <g transform="translate(775,25)"> <use xlink:href="#Red100" filter="url(#xorFlood)" /> <use xlink:href="#Red50" filter="url(#xorFlood)" /> <text x="15" y="275">xor</text> </g> <g transform="translate(900,25)"> <use xlink:href="#Red100" filter="url(#arithmeticFlood)" /> <use xlink:href="#Red50" filter="url(#arithmeticFlood)" /> <text x="-25" y="275">arithmetic</text> </g> </g> <g transform="translate(0,325)" enable-background="new"> <desc>Render the examples using the filters that do not obliterate the background, thus sometimes causing the background to continue to appear in some cases, and in other cases the background image blends into itself ("double-counting").</desc> <text x="15" y="75">opacity 1.0</text> <text x="15" y="115" font-size="27">(without feFlood)</text> <text x="15" y="200">opacity 0.5</text> <text x="15" y="240" font-size="27">(without feFlood)</text> <use xlink:href="#BlueTriangles"/> <g transform="translate(275,25)"> <use xlink:href="#Red100" filter="url(#overNoFlood)" /> <use xlink:href="#Red50" filter="url(#overNoFlood)" /> <text x="5" y="275">over</text> </g> <g transform="translate(400,25)"> <use xlink:href="#Red100" filter="url(#inNoFlood)" /> <use xlink:href="#Red50" filter="url(#inNoFlood)" /> <text x="35" y="275">in</text> </g> <g transform="translate(525,25)"> <use xlink:href="#Red100" filter="url(#outNoFlood)" /> <use xlink:href="#Red50" filter="url(#outNoFlood)" /> <text x="15" y="275">out</text> </g> <g transform="translate(650,25)"> <use xlink:href="#Red100" filter="url(#atopNoFlood)" /> <use xlink:href="#Red50" filter="url(#atopNoFlood)" /> <text x="10" y="275">atop</text> </g> <g transform="translate(775,25)"> <use xlink:href="#Red100" filter="url(#xorNoFlood)" /> <use xlink:href="#Red50" filter="url(#xorNoFlood)" /> <text x="15" y="275">xor</text> </g> <g transform="translate(900,25)"> <use xlink:href="#Red100" filter="url(#arithmeticNoFlood)" /> <use xlink:href="#Red50" filter="url(#arithmeticNoFlood)" /> <text x="-25" y="275">arithmetic</text> </g> </g> </g> </svg>
![]() |
View this example as SVG (SVG-enabled browsers only)
feConvolveMatrix applies a matrix convolution filter effect. A convolution combines pixels in the input image with neighboring pixels to produce a resulting image. A wide variety of imaging operations can be achieved through convolutions, including blurring, edge detection, sharpening, embossing and beveling.
A matrix convolution is based on an n-by-m matrix (the convolution kernel) which describes how a given pixel value in the input image is combined with its neighboring pixel values to produce a resulting pixel value. Each result pixel is determined by applying the kernel matrix to the corresponding source pixel and its neighboring pixels. The basic convolution formula which is applied to each color value for a given pixel is:
RESULTX,Y = (
SUM I=0 to [orderY-1] {
SUM J=0 to [orderX-1] {
SOURCE X-targetX+J, Y-targetY+I * kernelMatrixorderX-J-1, orderY-I-1
}
}
) / divisor + bias
where "orderX" and "orderY" represent the X and Y values for the 'order' attribute, "targetX" represents the value of the 'targetX' attribute, "targetY" represents the value of the 'targetY' attribute, "kernelMatrix" represents the value of the 'kernelMatrix' attribute, "divisor" represents the value of the 'divisor' attribute, and "bias" represents the value of the 'bias' attribute.
Note in the above formulas that the values in the kernel matrix are applied such that the kernel matrix is rotated 180 degrees relative to the source and destination images in order to match convolution theory as described in many computer graphics textbooks.
To illustrate, suppose you have a input image which is 5 pixels by 5 pixels, whose color values for one of the color channels are as follows:
0 20 40 235 235
100 120 140 235 235
200 220 240 235 235
225 225 255 255 255
225 225 255 255 255
and you define a 3-by-3 convolution kernel as follows:
1 2 3 4 5 6 7 8 9
Let's focus on the color value at the second row and second column of the image (source pixel value is 120). Assuming the simplest case (where the input image's pixel grid aligns perfectly with the kernel's pixel grid) and assuming default values for attributes 'divisor', 'targetX' and 'targetY', then resulting color value will be:
(9* 0 + 8* 20 + 7* 40 + 6*100 + 5*120 + 4*140 + 3*200 + 2*220 + 1*240) / (9+8+7+6+5+4+3+2+1)
Because they operate on pixels, matrix convolutions are inherently resolution-dependent. To make 'feConvolveMatrix' 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 convolution happens on the resampled image. After applying the convolution, the image is resampled back to the original resolution.
When the image must be resampled to match the coordinate system defined by 'kernelUnitLength' prior to convolution, or resampled to match the device coordinate system after convolution, 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.
<!ENTITY % SVG.feConvolveMatrix.extra.content "" > <!ENTITY % SVG.feConvolveMatrix.element "INCLUDE" > <![%SVG.feConvolveMatrix.element;[ <!ENTITY % SVG.feConvolveMatrix.content "( %SVG.animate.qname; | %SVG.set.qname; %SVG.feConvolveMatrix.extra.content; )*" > <!ELEMENT %SVG.feConvolveMatrix.qname; %SVG.feCo\ nvolveMatrix.content; > <!-- end of SVG.feConvolveMatrix.element -->]]> <!ENTITY % SVG.feConvolveMatrix.attlist "INCLUDE" > <![%SVG.feConvolveMatrix.attlist;[ <!ATTLIST %SVG.feConvolveMatrix.qname; %SVG.Core.attrib; %SVG.FilterColor.attrib; %SVG.FilterPrimitiveWithIn.attrib; order %NumberOptionalNumber.datatype; #REQUIRED kernelMatrix CDATA #REQUIRED divisor %Number.datatype; #IMPLIED bias %Number.datatype; #IMPLIED targetX %Integer.datatype; #IMPLIED targetY %Integer.datatype; #IMPLIED edgeMode ( duplicate | wrap | none ) 'duplicate' kernelUnitLength %NumberOptionalNumber.datatype; #IMPLIED preserveAlpha %Boolean.datatype; #IMPLIED > |
Attribute definitions:
Determines how to extend the input image as necessary with color values so that the matrix operations can be applied when the kernel is positioned at or near the edge of the input image.
"duplicate" indicates that the input image is extended along each of its borders as necessary by duplicating the color values at the given edge of the input image.
Original N-by-M image, where m=M-1 and n=N-1:
11 12 ... 1m 1M
21 22 ... 2m 2M
.. .. ... .. ..
n1 n2 ... nm nM
N1 N2 ... Nm NM
Extended by two pixels using "duplicate":
11 11 11 12 ... 1m 1M 1M 1M
11 11 11 12 ... 1m 1M 1M 1M
11 11 11 12 ... 1m 1M 1M 1M
21 21 21 22 ... 2m 2M 2M 2M
.. .. .. .. ... .. .. .. ..
n1 n1 n1 n2 ... nm nM nM nM
N1 N1 N1 N2 ... Nm NM NM NM
N1 N1 N1 N2 ... Nm NM NM NM
N1 N1 N1 N2 ... Nm NM NM NM
"wrap" indicates that the input image is extended by taking the color values from the opposite edge of the image.
Extended by two pixels using "wrap": nm nM n1 n2 ... nm nM n1 n2 Nm NM N1 N2 ... Nm NM N1 N2 1m 1M 11 12 ... 1m 1M 11 12 2m 2M 21 22 ... 2m 2M 21 22 .. .. .. .. ... .. .. .. .. nm nM n1 n2 ... nm nM n1 n2 Nm NM N1 N2 ... Nm NM N1 N2 1m 1M 11 12 ... 1m 1M 11 12 2m 2M 21 22 ... 2m 2M 21 22
"none" indicates that the input image is extended with pixel values of zero for R, G, B and A.
Animatable: yes.