From 516f6df6f5ce1c3fe12657a488b436fe738d7bbb Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 6 Nov 2019 20:48:05 +1100 Subject: [PATCH] Fix ImageFrame.Configuration --- .../Processing/BrushApplicator.cs | 53 ++++++++++------ .../Processing/EllipticGradientBrush.cs | 41 ++++++------ .../Processing/GradientBrush.cs | 29 ++++----- src/ImageSharp.Drawing/Processing/IBrush.cs | 10 +-- .../Processing/ImageBrush.cs | 47 +++++++------- .../Processing/LinearGradientBrush.cs | 27 ++++---- .../Processing/PathGradientBrush.cs | 18 +++--- .../Processing/PatternBrush.cs | 36 +++++------ .../Drawing/FillProcessor{TPixel}.cs | 5 +- .../Drawing/FillRegionProcessor{TPixel}.cs | 2 +- .../Text/DrawTextProcessor{TPixel}.cs | 2 +- .../Processing/RadialGradientBrush.cs | 30 ++++----- .../Processing/RecolorBrush.cs | 39 ++++-------- .../Processing/SolidBrush.cs | 62 ++++++++++--------- src/ImageSharp.Drawing/Utils/QuickSort.cs | 2 +- 15 files changed, 202 insertions(+), 201 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/BrushApplicator.cs b/src/ImageSharp.Drawing/Processing/BrushApplicator.cs index ab601bb8b..2b02c14fe 100644 --- a/src/ImageSharp.Drawing/Processing/BrushApplicator.cs +++ b/src/ImageSharp.Drawing/Processing/BrushApplicator.cs @@ -3,66 +3,83 @@ using System; using System.Buffers; - using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Memory; namespace SixLabors.ImageSharp.Processing { /// - /// primitive that converts a point in to a color for discovering the fill color based on an implementation + /// A primitive that converts a point into a color for discovering the fill color based on an implementation. /// /// The pixel format. - /// - public abstract class BrushApplicator : IDisposable // disposable will be required if/when there is an ImageBrush + /// + public abstract class BrushApplicator : IDisposable where TPixel : struct, IPixel { /// /// Initializes a new instance of the class. /// + /// The configuration instance to use when performing operations. /// The target. /// The options. - internal BrushApplicator(ImageFrame target, GraphicsOptions options) + internal BrushApplicator(Configuration configuration, ImageFrame target, GraphicsOptions options) { + this.Configuration = configuration; this.Target = target; this.Options = options; this.Blender = PixelOperations.Instance.GetPixelBlender(options); } /// - /// Gets the blender + /// Gets the configuration instance to use when performing operations. + /// + protected Configuration Configuration { get; } + + /// + /// Gets the pixel blender. /// internal PixelBlender Blender { get; } /// - /// Gets the destination + /// Gets the target image. /// protected ImageFrame Target { get; } /// - /// Gets the blend percentage + /// Gets thegraphics options /// protected GraphicsOptions Options { get; } /// - /// Gets the color for a single pixel. + /// Gets the overlay pixel at the specified position. /// - /// The x coordinate. - /// The y coordinate. - /// The a that should be applied to the pixel. + /// The x-coordinate. + /// The y-coordinate. + /// The at the specified position. internal abstract TPixel this[int x, int y] { get; } /// - public abstract void Dispose(); + public void Dispose() + { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Disposes the object and frees resources for the Garbage Collector. + /// + /// Whether to dispose managed and unmanaged objects. + protected virtual void Dispose(bool disposing) + { + } /// /// Applies the opacity weighting for each pixel in a scanline to the target based on the pattern contained in the brush. /// - /// The a collection of opacity values between 0 and 1 to be merged with the brushed color value before being applied to the target. - /// The x position in the target pixel space that the start of the scanline data corresponds to. - /// The y position in the target pixel space that whole scanline corresponds to. + /// A collection of opacity values between 0 and 1 to be merged with the brushed color value before being applied to the target. + /// The x-position in the target pixel space that the start of the scanline data corresponds to. + /// The y-position in the target pixel space that whole scanline corresponds to. /// scanlineBuffer will be > scanlineWidth but provide and offset in case we want to share a larger buffer across runs. internal virtual void Apply(Span scanline, int x, int y) { @@ -89,7 +106,7 @@ namespace SixLabors.ImageSharp.Processing } Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); - this.Blender.Blend(this.Target.Configuration, destinationRow, destinationRow, overlaySpan, amountSpan); + this.Blender.Blend(this.Configuration, destinationRow, destinationRow, overlaySpan, amountSpan); } } } diff --git a/src/ImageSharp.Drawing/Processing/EllipticGradientBrush.cs b/src/ImageSharp.Drawing/Processing/EllipticGradientBrush.cs index 91da332a1..7810c3c6d 100644 --- a/src/ImageSharp.Drawing/Processing/EllipticGradientBrush.cs +++ b/src/ImageSharp.Drawing/Processing/EllipticGradientBrush.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; @@ -47,17 +47,19 @@ namespace SixLabors.ImageSharp.Processing /// public override BrushApplicator CreateApplicator( + Configuration configuration, ImageFrame source, RectangleF region, GraphicsOptions options) => new RadialGradientBrushApplicator( + configuration, source, - options, this.center, this.referenceAxisEnd, this.axisRatio, this.ColorStops, - this.RepetitionMode); + this.RepetitionMode, + options); /// private sealed class RadialGradientBrushApplicator : GradientBrushApplicator @@ -86,24 +88,26 @@ namespace SixLabors.ImageSharp.Processing /// /// Initializes a new instance of the class. /// - /// The target image - /// The options - /// Center of the ellipse + /// The configuration instance to use when performing operations. + /// The target image. + /// Center of the ellipse. /// Point on one angular points of the ellipse. /// /// Ratio of the axis length's. Used to determine the length of the second axis, /// the first is defined by and . - /// Definition of colors + /// Definition of colors. /// Defines how the gradient colors are repeated. + /// The graphics options. public RadialGradientBrushApplicator( + Configuration configuration, ImageFrame target, - GraphicsOptions options, PointF center, PointF referenceAxisEnd, float axisRatio, ColorStop[] colorStops, - GradientRepetitionMode repetitionMode) - : base(target, options, colorStops, repetitionMode) + GradientRepetitionMode repetitionMode, + GraphicsOptions options) + : base(configuration, target, colorStops, repetitionMode, options) { this.center = center; this.referenceAxisEnd = referenceAxisEnd; @@ -122,11 +126,6 @@ namespace SixLabors.ImageSharp.Processing this.cosRotation = (float)Math.Cos(this.rotation); } - /// - public override void Dispose() - { - } - /// protected override float PositionOnGradient(float xt, float yt) { @@ -139,16 +138,13 @@ namespace SixLabors.ImageSharp.Processing float xSquared = x * x; float ySquared = y * y; - var inBoundaryChecker = (xSquared / this.referenceRadiusSquared) - + (ySquared / this.secondRadiusSquared); - - return inBoundaryChecker; + return (xSquared / this.referenceRadiusSquared) + (ySquared / this.secondRadiusSquared); } private float AngleBetween(PointF junction, PointF a, PointF b) { - var vA = a - junction; - var vB = b - junction; + PointF vA = a - junction; + PointF vB = b - junction; return MathF.Atan2(vB.Y, vB.X) - MathF.Atan2(vA.Y, vA.X); } @@ -156,6 +152,7 @@ namespace SixLabors.ImageSharp.Processing PointF p1, PointF p2) { + // TODO: Can we not just use Vector2 distance here? float dX = p1.X - p2.X; float dXsquared = dX * dX; @@ -165,4 +162,4 @@ namespace SixLabors.ImageSharp.Processing } } } -} \ No newline at end of file +} diff --git a/src/ImageSharp.Drawing/Processing/GradientBrush.cs b/src/ImageSharp.Drawing/Processing/GradientBrush.cs index bc87a26f3..044f4e2ee 100644 --- a/src/ImageSharp.Drawing/Processing/GradientBrush.cs +++ b/src/ImageSharp.Drawing/Processing/GradientBrush.cs @@ -2,10 +2,8 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Numerics; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.PixelFormats.PixelBlenders; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing @@ -38,6 +36,7 @@ namespace SixLabors.ImageSharp.Processing /// public abstract BrushApplicator CreateApplicator( + Configuration configuration, ImageFrame source, RectangleF region, GraphicsOptions options) @@ -58,27 +57,24 @@ namespace SixLabors.ImageSharp.Processing /// /// Initializes a new instance of the class. /// - /// The target. - /// The options. + /// The configuration instance to use when performing operations. + /// The target image. /// An array of color stops sorted by their position. /// Defines if and how the gradient should be repeated. + /// The graphics options. protected GradientBrushApplicator( + Configuration configuration, ImageFrame target, - GraphicsOptions options, ColorStop[] colorStops, - GradientRepetitionMode repetitionMode) - : base(target, options) + GradientRepetitionMode repetitionMode, + GraphicsOptions options) + : base(configuration, target, options) { this.colorStops = colorStops; // TODO: requires colorStops to be sorted by position - should that be checked? this.repetitionMode = repetitionMode; } - /// - /// Base implementation of the indexer for gradients - /// (follows the facade pattern, using abstract methods) - /// - /// X coordinate of the Pixel. - /// Y coordinate of the Pixel. + /// internal override TPixel this[int x, int y] { get @@ -123,7 +119,8 @@ namespace SixLabors.ImageSharp.Processing { float onLocalGradient = (positionOnCompleteGradient - from.Ratio) / (to.Ratio - from.Ratio); - // TODO: this should be changeble for different gradienting functions + // TODO: this should be changeble for different gradienting functions. + // TODO: Why not use Blender property? return PixelOperations .Instance.GetPixelBlender(PixelColorBlendingMode.Normal, PixelAlphaCompositionMode.SrcOver) .Blend(from.Color.ToPixel(), to.Color.ToPixel(), onLocalGradient); @@ -135,8 +132,8 @@ namespace SixLabors.ImageSharp.Processing /// calculates the position on the gradient for a given point. /// This method is abstract as it's content depends on the shape of the gradient. /// - /// The x coordinate of the point - /// The y coordinate of the point + /// The x-coordinate of the point. + /// The y-coordinate of the point. /// /// The position the given point has on the gradient. /// The position is not bound to the [0..1] interval. diff --git a/src/ImageSharp.Drawing/Processing/IBrush.cs b/src/ImageSharp.Drawing/Processing/IBrush.cs index 0cd2e20fd..f2fdc32f0 100644 --- a/src/ImageSharp.Drawing/Processing/IBrush.cs +++ b/src/ImageSharp.Drawing/Processing/IBrush.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.PixelFormats; @@ -19,20 +19,22 @@ namespace SixLabors.ImageSharp.Processing /// Creates the applicator for this brush. /// /// The pixel type. + /// The configuration instance to use when performing operations. /// The source image. /// The region the brush will be applied to. /// The graphic options /// - /// The brush applicator for this brush + /// The for this brush. /// /// /// The when being applied to things like shapes would usually be the - /// bounding box of the shape not necessarily the bounds of the whole image + /// bounding box of the shape not necessarily the bounds of the whole image. /// BrushApplicator CreateApplicator( + Configuration configuration, ImageFrame source, RectangleF region, GraphicsOptions options) where TPixel : struct, IPixel; } -} \ No newline at end of file +} diff --git a/src/ImageSharp.Drawing/Processing/ImageBrush.cs b/src/ImageSharp.Drawing/Processing/ImageBrush.cs index ebcc2c067..f23fb1f18 100644 --- a/src/ImageSharp.Drawing/Processing/ImageBrush.cs +++ b/src/ImageSharp.Drawing/Processing/ImageBrush.cs @@ -5,7 +5,6 @@ using System; using System.Buffers; using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; @@ -32,6 +31,7 @@ namespace SixLabors.ImageSharp.Processing /// public BrushApplicator CreateApplicator( + Configuration configuration, ImageFrame source, RectangleF region, GraphicsOptions options) @@ -39,12 +39,12 @@ namespace SixLabors.ImageSharp.Processing { if (this.image is Image specificImage) { - return new ImageBrushApplicator(source, specificImage, region, options, false); + return new ImageBrushApplicator(configuration, source, specificImage, region, false, options); } specificImage = this.image.CloneAs(); - return new ImageBrushApplicator(source, specificImage, region, options, true); + return new ImageBrushApplicator(configuration, source, specificImage, region, true, options); } /// @@ -79,21 +79,25 @@ namespace SixLabors.ImageSharp.Processing /// private readonly int offsetX; + private bool isDisposed; + /// /// Initializes a new instance of the class. /// + /// The configuration instance to use when performing operations. /// The target image. /// The image. /// The region. - /// The options /// Whether to dispose the image on disposal of the applicator. + /// The graphics options. public ImageBrushApplicator( + Configuration configuration, ImageFrame target, Image image, RectangleF region, - GraphicsOptions options, - bool shouldDisposeImage) - : base(target, options) + bool shouldDisposeImage, + GraphicsOptions options) + : base(configuration, target, options) { this.sourceImage = image; this.sourceFrame = image.Frames.RootFrame; @@ -104,14 +108,7 @@ namespace SixLabors.ImageSharp.Processing this.offsetX = (int)MathF.Max(MathF.Floor(region.Left), 0); } - /// - /// Gets the color for a single pixel. - /// - /// The x. - /// The y. - /// - /// The color - /// + /// internal override TPixel this[int x, int y] { get @@ -123,14 +120,21 @@ namespace SixLabors.ImageSharp.Processing } /// - public override void Dispose() + protected override void Dispose(bool disposing) { - if (this.shouldDisposeImage) + if (this.isDisposed) + { + return; + } + + if (disposing && this.shouldDisposeImage) { this.sourceImage?.Dispose(); - this.sourceImage = null; - this.sourceFrame = null; } + + this.sourceImage = null; + this.sourceFrame = null; + this.isDisposed = true; } /// @@ -152,13 +156,12 @@ namespace SixLabors.ImageSharp.Processing amountSpan[i] = scanline[i] * this.Options.BlendPercentage; int sourceX = (i + offsetX) % this.xLength; - TPixel pixel = sourceRow[sourceX]; - overlaySpan[i] = pixel; + overlaySpan[i] = sourceRow[sourceX]; } Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); this.Blender.Blend( - this.sourceFrame.Configuration, + this.Configuration, destinationRow, destinationRow, overlaySpan, diff --git a/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs b/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs index bb99eeb26..bf6a6356a 100644 --- a/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs +++ b/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; @@ -39,10 +39,12 @@ namespace SixLabors.ImageSharp.Processing /// public override BrushApplicator CreateApplicator( + Configuration configuration, ImageFrame source, RectangleF region, GraphicsOptions options) => new LinearGradientBrushApplicator( + configuration, source, this.p1, this.p2, @@ -93,20 +95,22 @@ namespace SixLabors.ImageSharp.Processing /// /// Initializes a new instance of the class. /// - /// The source - /// start point of the gradient - /// end point of the gradient - /// tuple list of colors and their respective position between 0 and 1 on the line + /// The configuration instance to use when performing operations. + /// The source image. + /// start point of the gradient. + /// end point of the gradient. + /// tuple list of colors and their respective position between 0 and 1 on the line. /// defines how the gradient colors are repeated. - /// the graphics options + /// the graphics options. public LinearGradientBrushApplicator( + Configuration configuration, ImageFrame source, PointF start, PointF end, ColorStop[] colorStops, GradientRepetitionMode repetitionMode, GraphicsOptions options) - : base(source, options, colorStops, repetitionMode) + : base(configuration, source, colorStops, repetitionMode, options) { this.start = start; this.end = end; @@ -148,14 +152,9 @@ namespace SixLabors.ImageSharp.Processing float distance = MathF.Sqrt(MathF.Pow(x4 - this.start.X, 2) + MathF.Pow(y4 - this.start.Y, 2)); // get and return ratio - float ratio = distance / this.length; - return ratio; + return distance / this.length; } } - - public override void Dispose() - { - } } } -} \ No newline at end of file +} diff --git a/src/ImageSharp.Drawing/Processing/PathGradientBrush.cs b/src/ImageSharp.Drawing/Processing/PathGradientBrush.cs index d2ad23a0d..be1af5011 100644 --- a/src/ImageSharp.Drawing/Processing/PathGradientBrush.cs +++ b/src/ImageSharp.Drawing/Processing/PathGradientBrush.cs @@ -83,12 +83,13 @@ namespace SixLabors.ImageSharp.Processing /// public BrushApplicator CreateApplicator( + Configuration configuration, ImageFrame source, RectangleF region, GraphicsOptions options) where TPixel : struct, IPixel { - return new PathGradientBrushApplicator(source, this.edges, this.centerColor, options); + return new PathGradientBrushApplicator(configuration, source, this.edges, this.centerColor, options); } private static Color CalculateCenterColor(Color[] colors) @@ -199,16 +200,18 @@ namespace SixLabors.ImageSharp.Processing /// /// Initializes a new instance of the class. /// + /// The configuration instance to use when performing operations. /// The source image. /// Edges of the polygon. /// Color at the center of the gradient area to which the other colors converge. - /// The options. + /// The graphics options. public PathGradientBrushApplicator( + Configuration configuration, ImageFrame source, IList edges, Color centerColor, GraphicsOptions options) - : base(source, options) + : base(configuration, source, options) { this.edges = edges; @@ -232,7 +235,7 @@ namespace SixLabors.ImageSharp.Processing return new Color(this.centerColor).ToPixel(); } - Vector2 direction = Vector2.Normalize(point - this.center); + var direction = Vector2.Normalize(point - this.center); PointF end = point + (PointF)(direction * this.maxDistance); @@ -250,7 +253,7 @@ namespace SixLabors.ImageSharp.Processing float length = DistanceBetween(intersection, this.center); float ratio = length > 0 ? DistanceBetween(intersection, point) / length : 0; - Vector4 color = Vector4.Lerp(edgeColor, this.centerColor, ratio); + var color = Vector4.Lerp(edgeColor, this.centerColor, ratio); return new Color(color).ToPixel(); } @@ -277,11 +280,6 @@ namespace SixLabors.ImageSharp.Processing return closest; } - - /// - public override void Dispose() - { - } } } } diff --git a/src/ImageSharp.Drawing/Processing/PatternBrush.cs b/src/ImageSharp.Drawing/Processing/PatternBrush.cs index 1b7db970a..37bb9b0fc 100644 --- a/src/ImageSharp.Drawing/Processing/PatternBrush.cs +++ b/src/ImageSharp.Drawing/Processing/PatternBrush.cs @@ -92,13 +92,15 @@ namespace SixLabors.ImageSharp.Processing /// public BrushApplicator CreateApplicator( + Configuration configuration, ImageFrame source, RectangleF region, GraphicsOptions options) where TPixel : struct, IPixel => new PatternBrushApplicator( + configuration, source, - this.pattern.ToPixelMatrix(source.Configuration), + this.pattern.ToPixelMatrix(configuration), options); /// @@ -115,41 +117,33 @@ namespace SixLabors.ImageSharp.Processing /// /// Initializes a new instance of the class. /// + /// The configuration instance to use when performing operations. /// The source image. /// The pattern. - /// The options - public PatternBrushApplicator(ImageFrame source, in DenseMatrix pattern, GraphicsOptions options) - : base(source, options) + /// The graphics options. + public PatternBrushApplicator( + Configuration configuration, + ImageFrame source, + in DenseMatrix pattern, + GraphicsOptions options) + : base(configuration, source, options) { this.pattern = pattern; } - /// - /// Gets the color for a single pixel. - /// # - /// The x. - /// The y. - /// - /// The Color. - /// + /// internal override TPixel this[int x, int y] { get { - x = x % this.pattern.Columns; - y = y % this.pattern.Rows; + x %= this.pattern.Columns; + y %= this.pattern.Rows; // 2d array index at row/column return this.pattern[y, x]; } } - /// - public override void Dispose() - { - // noop - } - /// internal override void Apply(Span scanline, int x, int y) { @@ -172,7 +166,7 @@ namespace SixLabors.ImageSharp.Processing Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); this.Blender.Blend( - this.Target.Configuration, + this.Configuration, destinationRow, destinationRow, overlaySpan, diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs index 1dd4be135..0309c561a 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs @@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing int width = maxX - minX; - Rectangle workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); + var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); IBrush brush = this.definition.Brush; GraphicsOptions options = this.definition.Options; @@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing ParallelExecutionSettings parallelSettings = ParallelExecutionSettings.FromConfiguration(configuration) .MultiplyMinimumPixelsPerTask(4); - var colorPixel = solidBrush.Color.ToPixel(); + TPixel colorPixel = solidBrush.Color.ToPixel(); ParallelHelper.IterateRows( workingRect, @@ -84,6 +84,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing using (IMemoryOwner amount = source.MemoryAllocator.Allocate(width)) using (BrushApplicator applicator = brush.CreateApplicator( + configuration, source, sourceRectangle, options)) diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs index 69f97ce75..8c665826f 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs @@ -71,7 +71,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing } } - using (BrushApplicator applicator = brush.CreateApplicator(source, rect, options)) + using (BrushApplicator applicator = brush.CreateApplicator(configuration, source, rect, options)) { int scanlineWidth = maxX - minX; using (IMemoryOwner bBuffer = source.MemoryAllocator.Allocate(maxIntersections)) diff --git a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs index c2e38f67b..8ae6ee491 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs @@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text { if (operations?.Count > 0) { - using (BrushApplicator app = brush.CreateApplicator(source, this.SourceRectangle, this.textRenderer.Options)) + using (BrushApplicator app = brush.CreateApplicator(this.Configuration, source, this.SourceRectangle, this.textRenderer.Options)) { foreach (DrawingOperation operation in operations) { diff --git a/src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs b/src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs index f4d2dd81f..7f1fa818e 100644 --- a/src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs +++ b/src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; @@ -9,7 +9,7 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// A Circular Gradient Brush, defined by center point and radius. + /// A radial gradient brush, defined by center point and radius. /// public sealed class RadialGradientBrush : GradientBrush { @@ -35,16 +35,18 @@ namespace SixLabors.ImageSharp.Processing /// public override BrushApplicator CreateApplicator( + Configuration configuration, ImageFrame source, RectangleF region, GraphicsOptions options) => new RadialGradientBrushApplicator( + configuration, source, - options, this.center, this.radius, this.ColorStops, - this.RepetitionMode); + this.RepetitionMode, + options); /// private sealed class RadialGradientBrushApplicator : GradientBrushApplicator @@ -57,30 +59,27 @@ namespace SixLabors.ImageSharp.Processing /// /// Initializes a new instance of the class. /// - /// The target image - /// The options. + /// The configuration instance to use when performing operations. + /// The target image. /// Center point of the gradient. /// Radius of the gradient. /// Definition of colors. /// How the colors are repeated beyond the first gradient. + /// The graphics options. public RadialGradientBrushApplicator( + Configuration configuration, ImageFrame target, - GraphicsOptions options, PointF center, float radius, ColorStop[] colorStops, - GradientRepetitionMode repetitionMode) - : base(target, options, colorStops, repetitionMode) + GradientRepetitionMode repetitionMode, + GraphicsOptions options) + : base(configuration, target, colorStops, repetitionMode, options) { this.center = center; this.radius = radius; } - /// - public override void Dispose() - { - } - /// /// As this is a circular gradient, the position on the gradient is based on /// the distance of the point to the center. @@ -90,6 +89,7 @@ namespace SixLabors.ImageSharp.Processing /// the position on the color gradient. protected override float PositionOnGradient(float x, float y) { + // TODO: Can this not use Vector2 distance? float distance = MathF.Sqrt(MathF.Pow(this.center.X - x, 2) + MathF.Pow(this.center.Y - y, 2)); return distance / this.radius; } @@ -101,4 +101,4 @@ namespace SixLabors.ImageSharp.Processing } } } -} \ No newline at end of file +} diff --git a/src/ImageSharp.Drawing/Processing/RecolorBrush.cs b/src/ImageSharp.Drawing/Processing/RecolorBrush.cs index d93110972..1ad613bf8 100644 --- a/src/ImageSharp.Drawing/Processing/RecolorBrush.cs +++ b/src/ImageSharp.Drawing/Processing/RecolorBrush.cs @@ -5,7 +5,6 @@ using System; using System.Buffers; using System.Numerics; using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Memory; using SixLabors.Primitives; @@ -38,9 +37,6 @@ namespace SixLabors.ImageSharp.Processing /// /// Gets the source color. /// - /// - /// The color of the source. - /// public Color SourceColor { get; } /// @@ -50,12 +46,14 @@ namespace SixLabors.ImageSharp.Processing /// public BrushApplicator CreateApplicator( + Configuration configuration, ImageFrame source, RectangleF region, GraphicsOptions options) where TPixel : struct, IPixel { return new RecolorBrushApplicator( + configuration, source, this.SourceColor.ToPixel(), this.TargetColor.ToPixel(), @@ -74,11 +72,6 @@ namespace SixLabors.ImageSharp.Processing /// private readonly Vector4 sourceColor; - /// - /// The target color. - /// - private readonly Vector4 targetColor; - /// /// The threshold. /// @@ -89,16 +82,22 @@ namespace SixLabors.ImageSharp.Processing /// /// Initializes a new instance of the class. /// + /// The configuration instance to use when performing operations. /// The source image. /// Color of the source. /// Color of the target. /// The threshold . /// The options - public RecolorBrushApplicator(ImageFrame source, TPixel sourceColor, TPixel targetColor, float threshold, GraphicsOptions options) - : base(source, options) + public RecolorBrushApplicator( + Configuration configuration, + ImageFrame source, + TPixel sourceColor, + TPixel targetColor, + float threshold, + GraphicsOptions options) + : base(configuration, source, options) { this.sourceColor = sourceColor.ToVector4(); - this.targetColor = targetColor.ToVector4(); this.targetColorPixel = targetColor; // Lets hack a min max extremes for a color space by letting the IPackedPixel clamp our values to something in the correct spaces :) @@ -109,14 +108,7 @@ namespace SixLabors.ImageSharp.Processing this.threshold = Vector4.DistanceSquared(maxColor.ToVector4(), minColor.ToVector4()) * threshold; } - /// - /// Gets the color for a single pixel. - /// - /// The x. - /// The y. - /// - /// The color - /// + /// internal override TPixel this[int x, int y] { get @@ -138,11 +130,6 @@ namespace SixLabors.ImageSharp.Processing } } - /// - public override void Dispose() - { - } - /// internal override void Apply(Span scanline, int x, int y) { @@ -167,7 +154,7 @@ namespace SixLabors.ImageSharp.Processing Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); this.Blender.Blend( - this.Target.Configuration, + this.Configuration, destinationRow, destinationRow, overlaySpan, diff --git a/src/ImageSharp.Drawing/Processing/SolidBrush.cs b/src/ImageSharp.Drawing/Processing/SolidBrush.cs index 71738de52..a2be775da 100644 --- a/src/ImageSharp.Drawing/Processing/SolidBrush.cs +++ b/src/ImageSharp.Drawing/Processing/SolidBrush.cs @@ -5,7 +5,6 @@ using System; using System.Buffers; using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Memory; using SixLabors.Primitives; @@ -17,33 +16,29 @@ namespace SixLabors.ImageSharp.Processing /// public class SolidBrush : IBrush { - /// - /// The color to paint. - /// - private readonly Color color; - /// /// Initializes a new instance of the class. /// /// The color. public SolidBrush(Color color) { - this.color = color; + this.Color = color; } /// /// Gets the color. /// - /// - /// The color. - /// - public Color Color => this.color; + public Color Color { get; } /// - public BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options) + public BrushApplicator CreateApplicator( + Configuration configuration, + ImageFrame source, + RectangleF region, + GraphicsOptions options) where TPixel : struct, IPixel { - return new SolidBrushApplicator(source, this.color.ToPixel(), options); + return new SolidBrushApplicator(configuration, source, this.Color.ToPixel(), options); } /// @@ -52,14 +47,21 @@ namespace SixLabors.ImageSharp.Processing private class SolidBrushApplicator : BrushApplicator where TPixel : struct, IPixel { + private bool isDisposed; + /// /// Initializes a new instance of the class. /// + /// The configuration instance to use when performing operations. /// The source image. /// The color. - /// The options - public SolidBrushApplicator(ImageFrame source, TPixel color, GraphicsOptions options) - : base(source, options) + /// The graphics options. + public SolidBrushApplicator( + Configuration configuration, + ImageFrame source, + TPixel color, + GraphicsOptions options) + : base(configuration, source, options) { this.Colors = source.MemoryAllocator.Allocate(source.Width); this.Colors.Memory.Span.Fill(color); @@ -68,22 +70,26 @@ namespace SixLabors.ImageSharp.Processing /// /// Gets the colors. /// - protected IMemoryOwner Colors { get; } + protected IMemoryOwner Colors { get; private set; } - /// - /// Gets the color for a single pixel. - /// - /// The x. - /// The y. - /// - /// The color - /// + /// internal override TPixel this[int x, int y] => this.Colors.Memory.Span[x]; /// - public override void Dispose() + protected override void Dispose(bool disposing) { - this.Colors.Dispose(); + if (this.isDisposed) + { + return; + } + + if (disposing) + { + this.Colors.Dispose(); + } + + this.Colors = null; + this.isDisposed = true; } /// @@ -102,7 +108,7 @@ namespace SixLabors.ImageSharp.Processing } MemoryAllocator memoryAllocator = this.Target.MemoryAllocator; - Configuration configuration = this.Target.Configuration; + Configuration configuration = this.Configuration; if (this.Options.BlendPercentage == 1f) { diff --git a/src/ImageSharp.Drawing/Utils/QuickSort.cs b/src/ImageSharp.Drawing/Utils/QuickSort.cs index ca1da5505..14e3146a0 100644 --- a/src/ImageSharp.Drawing/Utils/QuickSort.cs +++ b/src/ImageSharp.Drawing/Utils/QuickSort.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System;