VectSharp  2.2.1
A light library for C# vector graphics
Filters.cs
1 /*
2  VectSharp - A light library for C# vector graphics.
3  Copyright (C) 2020-2022 Giorgio Bianchini
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, version 3.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU Lesser General Public License for more details.
13 
14  You should have received a copy of the GNU Lesser General Public License
15  along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17 
18 using System;
19 
20 namespace VectSharp.Filters
21 {
22  /// <summary>
23  /// Represents a filter. Do not implement this interface directly; instead, implement <see cref="ILocationInvariantFilter"/> or <see cref="IFilterWithLocation"/>.
24  /// </summary>
25  public interface IFilter
26  {
27  /// <summary>
28  /// Determines how much the area of the filter's subject should be expanded on the top-left to accommodate the results of the filter.
29  /// </summary>
31 
32  /// <summary>
33  /// Determines how much the area of the filter's subject should be expanded on the bottom-right to accommodate the results of the filter.
34  /// </summary>
36  }
37 
38  /// <summary>
39  /// Represents a filter that can be applied to an image regardless of its location on the graphics surface.
40  /// </summary>
41  public interface ILocationInvariantFilter : IFilter
42  {
43  /// <summary>
44  /// Applies the filter to a <see cref="RasterImage"/>.
45  /// </summary>
46  /// <param name="image">The <see cref="RasterImage"/> to which the filter will be applied.</param>
47  /// <param name="scale">The scale of the image with respect to the filter.</param>
48  /// <returns>A new <see cref="RasterImage"/> containing the filtered image. The source <paramref name="image"/> is left unaltered.</returns>
49  RasterImage Filter(RasterImage image, double scale);
50  }
51 
52  /// <summary>
53  /// Represents a filter whose results depend on the position of the subject image on the graphics surface.
54  /// </summary>
55  public interface IFilterWithLocation : IFilter
56  {
57  /// <summary>
58  /// Applies the filter to a <see cref="RasterImage"/>.
59  /// </summary>
60  /// <param name="image">The <see cref="RasterImage"/> to which the filter will be applied.</param>
61  /// <param name="bounds">The region on the graphics surface where the image will be drawn.</param>
62  /// <param name="scale">The scale of the image with respect to the filter.</param>
63  /// <returns>A new <see cref="RasterImage"/> containing the filtered image. The source <paramref name="image"/> is left unaltered.</returns>
64  RasterImage Filter(RasterImage image, Rectangle bounds, double scale);
65  }
66 
67  /// <summary>
68  /// Represents a filter with a parameter that needs to be rasterised at the same resolution as the subject image prior to applying the filter.
69  /// The <see cref="FilterWithRasterisableParameter"/> abstract class provides a default implementation of this interface.
70  /// </summary>
72  {
73  /// <summary>
74  /// Rasterises the filter's parameter at the specified scale, using the specified rasterisation method.
75  /// </summary>
76  /// <param name="rasterisationMethod">The method used to rasterise the image. The first argument of this method is the <see cref="Graphics"/> to be rasterised,
77  /// the second is a <see cref="Rectangle"/> representing the region to rasterise, the third is a <see cref="double"/> representing the scale, and the third is
78  /// a boolean value indicating whether the resulting <see cref="RasterImage"/> should be interpolated.</param>
79  /// <param name="scale">The scale factor at which the parameter is rasterised.</param>
80  void RasteriseParameter(Func<Graphics, Rectangle, double, bool, RasterImage> rasterisationMethod, double scale);
81  }
82 
83  /// <summary>
84  /// Represents a filter with a parameter that needs to be rasterised at the same resolution as the subject image prior to applying the filter.
85  /// </summary>
87  {
88  /// <summary>
89  /// The parameter that needs to be rasterised.
90  /// </summary>
91  protected virtual Graphics RasterisableParameter { get; }
92 
93  /// <summary>
94  /// The result of the last rasterisation of the <see cref="RasterisableParameter"/>.
95  /// </summary>
96  protected RasterImage cachedRasterisation;
97  private bool disposedValue;
98 
99  /// <summary>
100  /// Get a rasterised version of the <see cref="RasterisableParameter"/> at the specified scale. If this has already been computed, the cached result is returned.
101  /// Otherwise, the image is rasterised using the default rasterisation method.
102  /// </summary>
103  /// <param name="scale">The scale at which the <see cref="RasterisableParameter"/> will be rasterised.</param>
104  /// <returns>A rasterised version of the <see cref="RasterisableParameter"/> at the specified scale.</returns>
105  protected virtual RasterImage GetCachedRasterisation(double scale)
106  {
107  if (this.cachedRasterisation == null || CachedResolution != scale)
108  {
109  this.RasteriseParameter(scale);
110  }
111 
112  return this.cachedRasterisation;
113  }
114 
115  /// <summary>
116  /// The bounds of the last cached rendering of the <see cref="RasterisableParameter"/> on the graphics surface.
117  /// </summary>
118  protected virtual Rectangle CachedBounds { get; set; }
119 
120  /// <summary>
121  /// The resolution using which the cached rendering of the <see cref="RasterisableParameter"/> has been computed.
122  /// </summary>
123  protected virtual double CachedResolution { get; set; } = double.NaN;
124 
125  /// <summary>
126  /// Create a new <see cref="FilterWithRasterisableParameter"/> with the specified parameter.
127  /// </summary>
128  /// <param name="rasterisableParameter">The parameter that needs to be rasterised at the same resolution as the subject image prior to applying the filter.</param>
129  protected FilterWithRasterisableParameter(Graphics rasterisableParameter)
130  {
131  this.RasterisableParameter = rasterisableParameter;
132  }
133 
134  /// <inheritdoc />
135  public virtual void RasteriseParameter(Func<Graphics, Rectangle, double, bool, RasterImage> rasterisationMethod, double scale)
136  {
137  Rectangle bounds = RasterisableParameter.GetBounds();
138 
139  this.cachedRasterisation?.Dispose();
140 
141  this.cachedRasterisation = rasterisationMethod(this.RasterisableParameter, bounds, scale, true);
142  this.CachedResolution = scale;
143  this.CachedBounds = bounds;
144  }
145 
146  /// <summary>
147  /// Rasterises the filter's parameter at the specified scale, using the default rasterisation method.
148  /// </summary>
149  /// <param name="scale">The scale factor at which the parameter is rasterised.</param>
150  /// <exception cref="NotImplementedException">This exception is thrown when there is no default rasterisation method. This occurs because neither the VectSharp.Raster
151  /// assembly, nor the VectSharp.Raster.ImageSharp assembly have been loaded, and no custom implementation of <see cref="Graphics.RasterisationMethod"/> has been provided.</exception>
152  protected virtual void RasteriseParameter(double scale)
153  {
154  Rectangle bounds = this.RasterisableParameter.GetBounds();
155 
156  this.cachedRasterisation?.Dispose();
157 
158  if (this.RasterisableParameter.TryRasterise(bounds, scale, true, out RasterImage raster))
159  {
160  this.cachedRasterisation = raster;
161  this.CachedResolution = scale;
162  this.CachedBounds = bounds;
163  }
164  else
165  {
166  throw new NotImplementedException(@"The filter could not be rasterised! You can avoid this error by doing one of the following:
167  • Add a reference to VectSharp.Raster or VectSharp.Raster.ImageSharp (you may also need to add a using directive somewhere to force the assembly to be loaded).
168  • Provide your own implementation of Graphics.RasterisationMethod.");
169  }
170  }
171 
172  /// <inheritdoc/>
173  protected virtual void Dispose(bool disposing)
174  {
175  if (!disposedValue)
176  {
177  if (disposing)
178  {
179  this.cachedRasterisation?.Dispose();
180  }
181 
182  disposedValue = true;
183  }
184  }
185 
186  /// <inheritdoc/>
187  public void Dispose()
188  {
189  Dispose(disposing: true);
190  GC.SuppressFinalize(this);
191  }
192  }
193 
194 
195 }
VectSharp.Rectangle
Represents a rectangle.
Definition: Point.cs:173
VectSharp.Filters.IFilter.TopLeftMargin
Point TopLeftMargin
Determines how much the area of the filter's subject should be expanded on the top-left to accommodat...
Definition: Filters.cs:30
VectSharp.RasterImage
Represents a raster image, created from raw pixel data. Consider using the derived classes included i...
Definition: RasterImage.cs:99
VectSharp.Filters.IFilter
Represents a filter. Do not implement this interface directly; instead, implement ILocationInvariantF...
Definition: Filters.cs:26
VectSharp.Filters.IFilterWithLocation.Filter
RasterImage Filter(RasterImage image, Rectangle bounds, double scale)
Applies the filter to a RasterImage.
VectSharp.Graphics
Represents an abstract drawing surface.
Definition: Graphics.cs:262
VectSharp.Filters.FilterWithRasterisableParameter
Represents a filter with a parameter that needs to be rasterised at the same resolution as the subjec...
Definition: Filters.cs:87
VectSharp.Graphics.TryRasterise
bool TryRasterise(Rectangle region, double scale, bool interpolate, out RasterImage output)
Tries to rasterise specified region of this Graphics object using the default rasterisation method.
Definition: Graphics.cs:1404
VectSharp.Rectangle.NaN
static readonly Rectangle NaN
A rectangle whose dimensions are all double.NaN.
Definition: Point.cs:177
VectSharp.Filters.IFilterWithRasterisableParameter.RasteriseParameter
void RasteriseParameter(Func< Graphics, Rectangle, double, bool, RasterImage > rasterisationMethod, double scale)
Rasterises the filter's parameter at the specified scale, using the specified rasterisation method.
VectSharp.Filters.IFilterWithRasterisableParameter
Represents a filter with a parameter that needs to be rasterised at the same resolution as the subjec...
Definition: Filters.cs:72
VectSharp.Filters.FilterWithRasterisableParameter.Dispose
void Dispose()
Definition: Filters.cs:187
VectSharp.Filters.ILocationInvariantFilter.Filter
RasterImage Filter(RasterImage image, double scale)
Applies the filter to a RasterImage.
VectSharp.Filters
Definition: BoxBlurFilter.cs:22
VectSharp.Filters.IFilter.BottomRightMargin
Point BottomRightMargin
Determines how much the area of the filter's subject should be expanded on the bottom-right to accomm...
Definition: Filters.cs:35
VectSharp.Filters.IFilterWithLocation
Represents a filter whose results depend on the position of the subject image on the graphics surface...
Definition: Filters.cs:56
VectSharp.Filters.ILocationInvariantFilter
Represents a filter that can be applied to an image regardless of its location on the graphics surfac...
Definition: Filters.cs:42
VectSharp.Filters.FilterWithRasterisableParameter.RasteriseParameter
virtual void RasteriseParameter(Func< Graphics, Rectangle, double, bool, RasterImage > rasterisationMethod, double scale)
Rasterises the filter's parameter at the specified scale, using the specified rasterisation method.
Definition: Filters.cs:135
VectSharp.Point
Represents a point relative to an origin in the top-left corner.
Definition: Point.cs:28
VectSharp.Graphics.GetBounds
Rectangle GetBounds()
Computes the rectangular bounds of the region affected by the drawing operations performed on the Gra...
Definition: Graphics.cs:1313