Filters
Table of contents
Filters make it possible to apply a number of effects to the image. Depending on the output format and the kind of filter, the filter can be applied directly to the vector image, or it can require the image to be rasterised first. For example, a Gaussian blur filter can be applied directly to an SVG image, but it will require the image to be rasterised if it is being exported as a PDF.
All filters implement the IFilter
interface, but, more importantly, they also implement either the ILocationInvariantFilter
interface, or the IFilterWithLocation
interface.
Filters implementing IlocationInvariantFilter
describe an operation whose effect does not depend on the part of the image where it is applied: for example, a Gaussian blur will have the same blurring effect on any part of the image. Filters implementing IFilterWithLocation
, instead, describe operations that affect different parts of the image differently, such as masking.
Both of these interfaces define two properties, TopLeftMargin
and BottomLeftMargin
, that describe how much the filter extends beyond the boundaries of the image it is applied to (e.g., a Gaussian blur filter extends by about three standard deviations outside the image). They also define a Filter
method, which is used to apply the filter to a raster image. However, unless you are developing new filters, you should not need to worry about these.
VectSharp currently supports a number of filters; you can extend the capabilities of the library by creating new filters that implement one of these two interfaces, and then use them normally. When you apply them, the section of the image to which the filter is applied will be rasterised, and the filter’s Filter
method will be used to transform it.
To apply a filter, you need to invoke the overload of the DrawGraphics
method that takes an IFilter
as a parameter. The filter will be applied to the Graphics
object that is drawn by this call. Filters are defined in the VectSharp.Filters
namespace (included in the VectSharp assembly); thus it is also necessary to add an using
directive.
This section describes the filters that are currently implemented in VectSharp.
Gaussian blur filter
The Gaussian blur filter is implemented by the GaussianBlurFilter
class. The constructor for this class takes a single argument, representing the standard deviation of the Gaussian blur in graphics units. The effect of the filter is to place a 2D Gaussian curve with the specified standard deviation at each pixel, and then compute the filtered colour of the pixel by weighing the original colours of neighbouring pixels with the Gaussian function.
The following example shows the effect of a GaussianBlurFilter
in action.
Gaussian blur filters are supported natively by the SVG format; thus, when a Page
is saved to an SVG file, they are not rasterised. They are instead rasterised if the document is exported in PDF format.
Box blur filter
A Box blur filter blurs the image by replacing each pixel with the average of its neighbours. This filter is implemented by the BoxBlurFilter
class, whose constructor also takes a single argument, which determines the size of the box used for the blurring (i.e., the number of pixels that are averaged).
A box blur filter is always rasterised when the image is exported. Therefore, in order to use it, you will need to install the VectSharp.Raster package or the VectSharp.Raster.ImageSharp package. Adding a using
directive to the namespace in this package can be useful, because it ensures that the assembly is correctly loaded, even though you are not using it directly.
The following example shows the effect of a BoxBlurFilter
.
Convolution filter
A Convolution filter replaces each pixel with a weighted average of its neighbours, using weights defined by a “kernel”. Such a filter is implemented by the ConvolutionFilter
class. The constructor for this class has two main parameters:
kernel
, adouble[,]
matrix, which specifies the kernel of the convolution. Each dimension of the matrix must be an odd number, otherwise an exception will be raised.scale
, adouble
: this parameter determines the relationship between the dimensions of thekernel
and the graphics units. When the filter is rasterised, this parameter is used to create the actual convolution kernel, based on the rasterisation resolution. This ensures that the effect of the filter is independent of the scale at which the image is viewed.
There are also three optional parameters: the bool preserveAlpha
determines whether the alpha channel of the image is subject to the same convolution as the RGB channels, while the double
s normalisation
and bias
are used to modify the result of the convolution.
The following example shows the effect of a ConvolutionFilter
. In order to produce a meaningful effect, the filterSubject
graphics is obtained by importing an SVG image; you can read more about this in the next section. Note that applying a ConvolutionFilter
can be rather slow (especially when the scale is high and on Blazor, as in the example below).
The kernels used in the interactive example above are as follows:
\[\mathrm{Identity} = \begin{bmatrix} 0 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 0 \end{bmatrix}\] \[\mathrm{Edge-detect} = \begin{bmatrix} -1 & -1 & -1 \\ -1 & 8 & -1 \\ -1 & -1 & -1 \end{bmatrix}\] \[\mathrm{Sharpen} = \begin{bmatrix} 0 & -1 & 0 \\ -1 & 5 & -1 \\ 0 & -1 & 0 \end{bmatrix}\]Colour matrix filter
A colour matrix filter transforms the colour of individual pixels using a colour transformation matrix. This filter is implemented by the ColourMatrixFilter
class. The constructor for this class has a single ColourMatrix
parameter, which is a 5x5 matrix describing the transformation. See the description of this filter on the MDN for more details on how the matrix influences the result of the filter.
A ColourMatrix
can be constructed from a double[,]
matrix containing the matrix entries, or using one of the static methods and properties of the ColourMatrix
class:
- The
Identity
static property returns aColourMatrix
that leaves the colours unchanged. - The
GreyScale
static property returns aColourMatrix
that turns the image into greyscale. - The
Pastel
static property returns aColourMatrix
that applies a “pastel” filter to the image, reducing the saturation. - The
Inversion
static property returns aColourMatrix
that inverts each colour in the image. - The
AlphaInversion
static property returns aColourMatrix
that inverts only the alpha channel of the image. -
The
InvertedAlphaShift
static property returns aColourMatrix
that adds to each component the inverted alpha value. This is useful, for example, to turn fully transparent black (RGBA0, 0, 0, 0
) into fully transparent white (RGBA255, 255, 255, 0
). - The
ToColour
static method returns aColourMatrix
that transforms every colour from the original image into the specified colour (i.e., to that exact colour, not to shades of it). If the optional parameteruseAlpha
is set totrue
, the alpha value of the specified colour is also used; otherwise, the original alpha values are preserved. - The
LuminanceToColour
static method returns aColourMatrix
that transforms the colours of the original image into shades of the specified colour (like a “coloured greyscale”). If the optional parameteruseAlpha
is set totrue
, the alpha value of the specified colour is also used; otherwise, the original alpha values are preserved. - The
LuminanceToAlpha
static method returns aColourMatrix
that sets the alpha component of each pixel to a value corresponding to the luminance (greyscale value) of that pixel. If the optional parameterpreserveColour
istrue
, the colour of each pixel is preserved; otherwise, each pixel is set to black.
Furthermore, the WithAlpha
(instance) method of the ColourMatrix
class returns a new ColourMatrix
that produces the same colours as the current instance, but whose alpha values are multiplied by the specified value.
Multiple effects can be combined by multiplying the ColourMatri
ces. For example, the following code produces a ColourMatrix
that, in this order:
- Adds the inverted alpha value to each component of the image (turning transparent black into transparent white).
- Inverts the colours of the image (which turns again transparent white into transparent black).
- Sets the alpha channel to the luminance of the inverted image.
Note that the matrices are specified in reverse order.
The following example shows the effect of a ColourMatrixFilter
. Again, to obtain a meaningful effect, the filterSubject
is obtained by loading an SVG image.
Colour matrix filters are supported natively by the SVG format; thus, when a Page
is saved to an SVG file, they are not rasterised. They are instead rasterised if the document is exported in PDF format.
Composite filter
All the filters described above implement the ILocationInvariantFilter
interface. If you wish to combine the effect of multiple filters, you can do so by using the CompositeLocationInvariantFilter
class (which itself implements the ILocationInvariantFilter
interface). The constructor for this class accepts a collection of filters which are applied to the image in order.
This can be useful, for example, to create a drop shadow: a ColourMatrixFilter
can be used to turn the image to a uniform grey, and then a GaussianBlurFilter
can be used to blur the shadow.
The following example shows how to create a drop shadow by combining a ColourMatrixFilter
and a GaussianBlurFilter
.
As long as all the filters used in the composite filter are supported by the SVG format, the composite filter itself is also supported and will not be rasterised. It will instead be rasterised if the document is exported as a PDF file.
Mask filter
A mask filter uses the luminance information of an image to mask another image. Essentially, the mask image is overlapped on the subject image; then, where the mask image is white, the subject image is preserved, while where the mask image is black the subject image becomes transparent. Intermediate colours apply intermediate alpha values.
A mask is conceptually similar to a clipping path, in that both hide part of the image they are applied to. However, the differences between the two are:
- The clipping path is applied using the
SetClippingPath
method before the drawing calls, while the mask is applied as a filter. - The clipping path operates a “binary” operation (a point is either visible or hidden by the clipping path), while masks allow intermediate values where a point’s alpha is affected.
Mask filters are implemented by the MaskFilter
class. The constructor for this class accepts a single Graphics
parameter, which is used as the mask. Unlike the other filters presented here, the MaskFilter
implements the IFilterWithLocation
interface, because the effect of the mask depends on where the subject image is being drawn.
The following example shows how to use a MaskFilter
. In this case, a linear gradient from white (to the left) to black (to the right) is used to mask the surgeon fish image from the previous examples.
Mask filters are supported natively by the SVG format; thus, when a Page
is saved to an SVG file, they are not rasterised. They are instead rasterised if the document is exported in PDF format.
Exporting documents containing filters
When you use the SaveAsSVG
or SaveAsPDF
methods to create PDF or SVG documents, you can use the optional filterOption
parameter to determine how filters that have been used in the image should be exported.
VectSharp.SVG
For the SaveAsSVG
method, filterOption
should be an instance of SVGContextInterpreter.FilterOption
. The constructor for this class accepts three parameters.
The first parameter is a SVGContextInterpreter.FilterOption.FilterOperations
enumeration, which determines what happens to the filters. This enum
has 6 possible values:
RasteriseAll
means that all filters, even those that would be supported natively by the SVG format, are rasterised.RasteriseIfNecessary
means that only those filters that are not supported by the SVG format are rasterised. This is the default.NeverRasteriseAndIgnore
means that filters will never be rasterised. If a filter that is not supported has been used, the filter is ignored and the subject image is drawn unchanged (as if it had not been filtered).NeverRasteriseAndSkip
also means that the filters will never be rasterised. However, images that have been drawn with a filter that is not supported will not be drawn at all.IgnoreAll
means that no filter will be applied, and those images that have been drawn using a filter will be drawn as if the filter had not been used.SkipAll
means that no filter will be applied, and those image that have been drawn using a filter will not be drawn at all.
The second parameter, rasterisationResolution
, is a double
that determines the scale at which filters that need to be rasterised are rasterised; by default, this is 1
. The third parameter, rasterisationResolutionRelative
, is a bool
determining whether the rasterisationResolution
is relative or absolute. If this is true
(the default), the rasterisationResolution
is multiplied by the size of the image in graphics units to obtain the size in pixel of the image to rasterise. Otherwise, the rasterisationResolution
itself is used as the size in pixels for the rasterised filter.
As a result of the default values, filters are only rasterised when necessary, using a scale corresponding to the size of the image in pixel units. If you wish to produce a higher-quality image, you may wish to specify a filterOption
when exporting the image, increasing the rasterisationResolution
(though this will come at an increased computational cost).
If a filter needs to be rasterised, you need to make sure that there is a way to do this. This can be achieved by installing either the VectSharp.Raster package, or the VectSharp.Raster.ImageSharp package. Alternatively, if you have some other way to rasterise the image, you can set the Graphics.RasterisationMethod
static property to point to a method that does this. The library will choose automatically between the available options.
VectSharp.PDF
As mentioned above, all filters must be rasterised when exporting the image as a PDF document. For the SaveAsPDF
method, filterOption
is an instance of PDFContextInterpreter.FilterOption
; the constructor for this class has three parameters, that correspond to the same parameters of the SVGContextInterpreter.FilterOption
class.
In this case, the PDFContextInterpreter.FilterOption.FilterOperations
enum
only has three options (RasteriseAll
, IgnoreAll
, and SkipAll
), which correspond to the same options as for VectSharp.SVG.
VectSharp.Canvas
The PaintToCanvas
and PaintToSKCanvas
methods also accept a filterOption
parameter, which is an instance of the VectSharp.Canvas.FilterOption
class. In this case, the FilterOption.FilterOperations
enum
has four possible values: IgnoreAll
and SkipAll
, with the same meaning as in VectSharp.SVG, as well as RasteriseAllWithSkia
and RasteriseAllWithVectSharp
.
RasteriseAllWithSkia
(which is the default) does not require any other package to be installed, and uses the SkiaSharp library (which is installed as a dependency of Avalonia anyways) to create the raster images. Using this option is recommended. The RasteriseAllWithVectSharp
option, instead, uses the same approach as the other output layers, requiring VectSharp.Raster or VectSharp.Raster.ImageSharp to be installed.
VectSharp.Raster and VectSharp.Raster.ImageSharp
The SaveAsPNG
and SaveAsImage
methods provided by these packages do not have a filterOption
parameter, because everything needs to be rasterised anyways.