Browse Source

Fix ImageFrame.Configuration

af/merge-core
James Jackson-South 7 years ago
parent
commit
d7b0a322ab
  1. 53
      src/ImageSharp.Drawing/Processing/BrushApplicator.cs
  2. 41
      src/ImageSharp.Drawing/Processing/EllipticGradientBrush.cs
  3. 29
      src/ImageSharp.Drawing/Processing/GradientBrush.cs
  4. 10
      src/ImageSharp.Drawing/Processing/IBrush.cs
  5. 47
      src/ImageSharp.Drawing/Processing/ImageBrush.cs
  6. 27
      src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs
  7. 18
      src/ImageSharp.Drawing/Processing/PathGradientBrush.cs
  8. 36
      src/ImageSharp.Drawing/Processing/PatternBrush.cs
  9. 5
      src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs
  10. 2
      src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs
  11. 2
      src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs
  12. 30
      src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs
  13. 39
      src/ImageSharp.Drawing/Processing/RecolorBrush.cs
  14. 62
      src/ImageSharp.Drawing/Processing/SolidBrush.cs
  15. 2
      src/ImageSharp.Drawing/Utils/QuickSort.cs

53
src/ImageSharp.Drawing/Processing/BrushApplicator.cs

@ -3,66 +3,83 @@
using System; using System;
using System.Buffers; using System.Buffers;
using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory; using SixLabors.Memory;
namespace SixLabors.ImageSharp.Processing namespace SixLabors.ImageSharp.Processing
{ {
/// <summary> /// <summary>
/// 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.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
/// <seealso cref="System.IDisposable" /> /// <seealso cref="IDisposable" />
public abstract class BrushApplicator<TPixel> : IDisposable // disposable will be required if/when there is an ImageBrush public abstract class BrushApplicator<TPixel> : IDisposable
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="BrushApplicator{TPixel}"/> class. /// Initializes a new instance of the <see cref="BrushApplicator{TPixel}"/> class.
/// </summary> /// </summary>
/// <param name="configuration">The configuration instance to use when performing operations.</param>
/// <param name="target">The target.</param> /// <param name="target">The target.</param>
/// <param name="options">The options.</param> /// <param name="options">The options.</param>
internal BrushApplicator(ImageFrame<TPixel> target, GraphicsOptions options) internal BrushApplicator(Configuration configuration, ImageFrame<TPixel> target, GraphicsOptions options)
{ {
this.Configuration = configuration;
this.Target = target; this.Target = target;
this.Options = options; this.Options = options;
this.Blender = PixelOperations<TPixel>.Instance.GetPixelBlender(options); this.Blender = PixelOperations<TPixel>.Instance.GetPixelBlender(options);
} }
/// <summary> /// <summary>
/// Gets the blender /// Gets the configuration instance to use when performing operations.
/// </summary>
protected Configuration Configuration { get; }
/// <summary>
/// Gets the pixel blender.
/// </summary> /// </summary>
internal PixelBlender<TPixel> Blender { get; } internal PixelBlender<TPixel> Blender { get; }
/// <summary> /// <summary>
/// Gets the destination /// Gets the target image.
/// </summary> /// </summary>
protected ImageFrame<TPixel> Target { get; } protected ImageFrame<TPixel> Target { get; }
/// <summary> /// <summary>
/// Gets the blend percentage /// Gets thegraphics options
/// </summary> /// </summary>
protected GraphicsOptions Options { get; } protected GraphicsOptions Options { get; }
/// <summary> /// <summary>
/// Gets the color for a single pixel. /// Gets the overlay pixel at the specified position.
/// </summary> /// </summary>
/// <param name="x">The x coordinate.</param> /// <param name="x">The x-coordinate.</param>
/// <param name="y">The y coordinate.</param> /// <param name="y">The y-coordinate.</param>
/// <returns>The a <typeparamref name="TPixel"/> that should be applied to the pixel.</returns> /// <returns>The <see typeparam="TPixel"/> at the specified position.</returns>
internal abstract TPixel this[int x, int y] { get; } internal abstract TPixel this[int x, int y] { get; }
/// <inheritdoc/> /// <inheritdoc/>
public abstract void Dispose(); public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Disposes the object and frees resources for the Garbage Collector.
/// </summary>
/// <param name="disposing">Whether to dispose managed and unmanaged objects.</param>
protected virtual void Dispose(bool disposing)
{
}
/// <summary> /// <summary>
/// Applies the opacity weighting for each pixel in a scanline to the target based on the pattern contained in the brush. /// Applies the opacity weighting for each pixel in a scanline to the target based on the pattern contained in the brush.
/// </summary> /// </summary>
/// <param name="scanline">The a collection of opacity values between 0 and 1 to be merged with the brushed color value before being applied to the target.</param> /// <param name="scanline">A collection of opacity values between 0 and 1 to be merged with the brushed color value before being applied to the target.</param>
/// <param name="x">The x position in the target pixel space that the start of the scanline data corresponds to.</param> /// <param name="x">The x-position in the target pixel space that the start of the scanline data corresponds to.</param>
/// <param name="y">The y position in the target pixel space that whole scanline corresponds to.</param> /// <param name="y">The y-position in the target pixel space that whole scanline corresponds to.</param>
/// <remarks>scanlineBuffer will be > scanlineWidth but provide and offset in case we want to share a larger buffer across runs.</remarks> /// <remarks>scanlineBuffer will be > scanlineWidth but provide and offset in case we want to share a larger buffer across runs.</remarks>
internal virtual void Apply(Span<float> scanline, int x, int y) internal virtual void Apply(Span<float> scanline, int x, int y)
{ {
@ -89,7 +106,7 @@ namespace SixLabors.ImageSharp.Processing
} }
Span<TPixel> destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); Span<TPixel> 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);
} }
} }
} }

41
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. // Licensed under the Apache License, Version 2.0.
using System; using System;
@ -47,17 +47,19 @@ namespace SixLabors.ImageSharp.Processing
/// <inheritdoc /> /// <inheritdoc />
public override BrushApplicator<TPixel> CreateApplicator<TPixel>( public override BrushApplicator<TPixel> CreateApplicator<TPixel>(
Configuration configuration,
ImageFrame<TPixel> source, ImageFrame<TPixel> source,
RectangleF region, RectangleF region,
GraphicsOptions options) => GraphicsOptions options) =>
new RadialGradientBrushApplicator<TPixel>( new RadialGradientBrushApplicator<TPixel>(
configuration,
source, source,
options,
this.center, this.center,
this.referenceAxisEnd, this.referenceAxisEnd,
this.axisRatio, this.axisRatio,
this.ColorStops, this.ColorStops,
this.RepetitionMode); this.RepetitionMode,
options);
/// <inheritdoc /> /// <inheritdoc />
private sealed class RadialGradientBrushApplicator<TPixel> : GradientBrushApplicator<TPixel> private sealed class RadialGradientBrushApplicator<TPixel> : GradientBrushApplicator<TPixel>
@ -86,24 +88,26 @@ namespace SixLabors.ImageSharp.Processing
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RadialGradientBrushApplicator{TPixel}" /> class. /// Initializes a new instance of the <see cref="RadialGradientBrushApplicator{TPixel}" /> class.
/// </summary> /// </summary>
/// <param name="target">The target image</param> /// <param name="configuration">The configuration instance to use when performing operations.</param>
/// <param name="options">The options</param> /// <param name="target">The target image.</param>
/// <param name="center">Center of the ellipse</param> /// <param name="center">Center of the ellipse.</param>
/// <param name="referenceAxisEnd">Point on one angular points of the ellipse.</param> /// <param name="referenceAxisEnd">Point on one angular points of the ellipse.</param>
/// <param name="axisRatio"> /// <param name="axisRatio">
/// Ratio of the axis length's. Used to determine the length of the second axis, /// Ratio of the axis length's. Used to determine the length of the second axis,
/// the first is defined by <see cref="center"/> and <see cref="referenceAxisEnd"/>.</param> /// the first is defined by <see cref="center"/> and <see cref="referenceAxisEnd"/>.</param>
/// <param name="colorStops">Definition of colors</param> /// <param name="colorStops">Definition of colors.</param>
/// <param name="repetitionMode">Defines how the gradient colors are repeated.</param> /// <param name="repetitionMode">Defines how the gradient colors are repeated.</param>
/// <param name="options">The graphics options.</param>
public RadialGradientBrushApplicator( public RadialGradientBrushApplicator(
Configuration configuration,
ImageFrame<TPixel> target, ImageFrame<TPixel> target,
GraphicsOptions options,
PointF center, PointF center,
PointF referenceAxisEnd, PointF referenceAxisEnd,
float axisRatio, float axisRatio,
ColorStop[] colorStops, ColorStop[] colorStops,
GradientRepetitionMode repetitionMode) GradientRepetitionMode repetitionMode,
: base(target, options, colorStops, repetitionMode) GraphicsOptions options)
: base(configuration, target, colorStops, repetitionMode, options)
{ {
this.center = center; this.center = center;
this.referenceAxisEnd = referenceAxisEnd; this.referenceAxisEnd = referenceAxisEnd;
@ -122,11 +126,6 @@ namespace SixLabors.ImageSharp.Processing
this.cosRotation = (float)Math.Cos(this.rotation); this.cosRotation = (float)Math.Cos(this.rotation);
} }
/// <inheritdoc />
public override void Dispose()
{
}
/// <inheritdoc /> /// <inheritdoc />
protected override float PositionOnGradient(float xt, float yt) protected override float PositionOnGradient(float xt, float yt)
{ {
@ -139,16 +138,13 @@ namespace SixLabors.ImageSharp.Processing
float xSquared = x * x; float xSquared = x * x;
float ySquared = y * y; float ySquared = y * y;
var inBoundaryChecker = (xSquared / this.referenceRadiusSquared) return (xSquared / this.referenceRadiusSquared) + (ySquared / this.secondRadiusSquared);
+ (ySquared / this.secondRadiusSquared);
return inBoundaryChecker;
} }
private float AngleBetween(PointF junction, PointF a, PointF b) private float AngleBetween(PointF junction, PointF a, PointF b)
{ {
var vA = a - junction; PointF vA = a - junction;
var vB = b - junction; PointF vB = b - junction;
return MathF.Atan2(vB.Y, vB.X) - MathF.Atan2(vA.Y, vA.X); return MathF.Atan2(vB.Y, vB.X) - MathF.Atan2(vA.Y, vA.X);
} }
@ -156,6 +152,7 @@ namespace SixLabors.ImageSharp.Processing
PointF p1, PointF p1,
PointF p2) PointF p2)
{ {
// TODO: Can we not just use Vector2 distance here?
float dX = p1.X - p2.X; float dX = p1.X - p2.X;
float dXsquared = dX * dX; float dXsquared = dX * dX;
@ -165,4 +162,4 @@ namespace SixLabors.ImageSharp.Processing
} }
} }
} }
} }

29
src/ImageSharp.Drawing/Processing/GradientBrush.cs

@ -2,10 +2,8 @@
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System; using System;
using System.Numerics;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.PixelFormats.PixelBlenders;
using SixLabors.Primitives; using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing namespace SixLabors.ImageSharp.Processing
@ -38,6 +36,7 @@ namespace SixLabors.ImageSharp.Processing
/// <inheritdoc /> /// <inheritdoc />
public abstract BrushApplicator<TPixel> CreateApplicator<TPixel>( public abstract BrushApplicator<TPixel> CreateApplicator<TPixel>(
Configuration configuration,
ImageFrame<TPixel> source, ImageFrame<TPixel> source,
RectangleF region, RectangleF region,
GraphicsOptions options) GraphicsOptions options)
@ -58,27 +57,24 @@ namespace SixLabors.ImageSharp.Processing
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="GradientBrushApplicator{TPixel}"/> class. /// Initializes a new instance of the <see cref="GradientBrushApplicator{TPixel}"/> class.
/// </summary> /// </summary>
/// <param name="target">The target.</param> /// <param name="configuration">The configuration instance to use when performing operations.</param>
/// <param name="options">The options.</param> /// <param name="target">The target image.</param>
/// <param name="colorStops">An array of color stops sorted by their position.</param> /// <param name="colorStops">An array of color stops sorted by their position.</param>
/// <param name="repetitionMode">Defines if and how the gradient should be repeated.</param> /// <param name="repetitionMode">Defines if and how the gradient should be repeated.</param>
/// <param name="options">The graphics options.</param>
protected GradientBrushApplicator( protected GradientBrushApplicator(
Configuration configuration,
ImageFrame<TPixel> target, ImageFrame<TPixel> target,
GraphicsOptions options,
ColorStop[] colorStops, ColorStop[] colorStops,
GradientRepetitionMode repetitionMode) GradientRepetitionMode repetitionMode,
: base(target, options) GraphicsOptions options)
: base(configuration, target, options)
{ {
this.colorStops = colorStops; // TODO: requires colorStops to be sorted by position - should that be checked? this.colorStops = colorStops; // TODO: requires colorStops to be sorted by position - should that be checked?
this.repetitionMode = repetitionMode; this.repetitionMode = repetitionMode;
} }
/// <summary> /// <inheritdoc/>
/// Base implementation of the indexer for gradients
/// (follows the facade pattern, using abstract methods)
/// </summary>
/// <param name="x">X coordinate of the Pixel.</param>
/// <param name="y">Y coordinate of the Pixel.</param>
internal override TPixel this[int x, int y] internal override TPixel this[int x, int y]
{ {
get get
@ -123,7 +119,8 @@ namespace SixLabors.ImageSharp.Processing
{ {
float onLocalGradient = (positionOnCompleteGradient - from.Ratio) / (to.Ratio - from.Ratio); 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<TPixel> return PixelOperations<TPixel>
.Instance.GetPixelBlender(PixelColorBlendingMode.Normal, PixelAlphaCompositionMode.SrcOver) .Instance.GetPixelBlender(PixelColorBlendingMode.Normal, PixelAlphaCompositionMode.SrcOver)
.Blend(from.Color.ToPixel<TPixel>(), to.Color.ToPixel<TPixel>(), onLocalGradient); .Blend(from.Color.ToPixel<TPixel>(), to.Color.ToPixel<TPixel>(), onLocalGradient);
@ -135,8 +132,8 @@ namespace SixLabors.ImageSharp.Processing
/// calculates the position on the gradient for a given point. /// 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. /// This method is abstract as it's content depends on the shape of the gradient.
/// </summary> /// </summary>
/// <param name="x">The x coordinate of the point</param> /// <param name="x">The x-coordinate of the point.</param>
/// <param name="y">The y coordinate of the point</param> /// <param name="y">The y-coordinate of the point.</param>
/// <returns> /// <returns>
/// The position the given point has on the gradient. /// The position the given point has on the gradient.
/// The position is not bound to the [0..1] interval. /// The position is not bound to the [0..1] interval.

10
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. // Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
@ -19,20 +19,22 @@ namespace SixLabors.ImageSharp.Processing
/// Creates the applicator for this brush. /// Creates the applicator for this brush.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel type.</typeparam> /// <typeparam name="TPixel">The pixel type.</typeparam>
/// <param name="configuration">The configuration instance to use when performing operations.</param>
/// <param name="source">The source image.</param> /// <param name="source">The source image.</param>
/// <param name="region">The region the brush will be applied to.</param> /// <param name="region">The region the brush will be applied to.</param>
/// <param name="options">The graphic options</param> /// <param name="options">The graphic options</param>
/// <returns> /// <returns>
/// The brush applicator for this brush /// The <see cref="BrushApplicator{TPixel}"/> for this brush.
/// </returns> /// </returns>
/// <remarks> /// <remarks>
/// The <paramref name="region" /> when being applied to things like shapes would usually be the /// The <paramref name="region" /> 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.
/// </remarks> /// </remarks>
BrushApplicator<TPixel> CreateApplicator<TPixel>( BrushApplicator<TPixel> CreateApplicator<TPixel>(
Configuration configuration,
ImageFrame<TPixel> source, ImageFrame<TPixel> source,
RectangleF region, RectangleF region,
GraphicsOptions options) GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>; where TPixel : struct, IPixel<TPixel>;
} }
} }

47
src/ImageSharp.Drawing/Processing/ImageBrush.cs

@ -5,7 +5,6 @@ using System;
using System.Buffers; using System.Buffers;
using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives; using SixLabors.Primitives;
@ -32,6 +31,7 @@ namespace SixLabors.ImageSharp.Processing
/// <inheritdoc /> /// <inheritdoc />
public BrushApplicator<TPixel> CreateApplicator<TPixel>( public BrushApplicator<TPixel> CreateApplicator<TPixel>(
Configuration configuration,
ImageFrame<TPixel> source, ImageFrame<TPixel> source,
RectangleF region, RectangleF region,
GraphicsOptions options) GraphicsOptions options)
@ -39,12 +39,12 @@ namespace SixLabors.ImageSharp.Processing
{ {
if (this.image is Image<TPixel> specificImage) if (this.image is Image<TPixel> specificImage)
{ {
return new ImageBrushApplicator<TPixel>(source, specificImage, region, options, false); return new ImageBrushApplicator<TPixel>(configuration, source, specificImage, region, false, options);
} }
specificImage = this.image.CloneAs<TPixel>(); specificImage = this.image.CloneAs<TPixel>();
return new ImageBrushApplicator<TPixel>(source, specificImage, region, options, true); return new ImageBrushApplicator<TPixel>(configuration, source, specificImage, region, true, options);
} }
/// <summary> /// <summary>
@ -79,21 +79,25 @@ namespace SixLabors.ImageSharp.Processing
/// </summary> /// </summary>
private readonly int offsetX; private readonly int offsetX;
private bool isDisposed;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ImageBrushApplicator{TPixel}"/> class. /// Initializes a new instance of the <see cref="ImageBrushApplicator{TPixel}"/> class.
/// </summary> /// </summary>
/// <param name="configuration">The configuration instance to use when performing operations.</param>
/// <param name="target">The target image.</param> /// <param name="target">The target image.</param>
/// <param name="image">The image.</param> /// <param name="image">The image.</param>
/// <param name="region">The region.</param> /// <param name="region">The region.</param>
/// <param name="options">The options</param>
/// <param name="shouldDisposeImage">Whether to dispose the image on disposal of the applicator.</param> /// <param name="shouldDisposeImage">Whether to dispose the image on disposal of the applicator.</param>
/// <param name="options">The graphics options.</param>
public ImageBrushApplicator( public ImageBrushApplicator(
Configuration configuration,
ImageFrame<TPixel> target, ImageFrame<TPixel> target,
Image<TPixel> image, Image<TPixel> image,
RectangleF region, RectangleF region,
GraphicsOptions options, bool shouldDisposeImage,
bool shouldDisposeImage) GraphicsOptions options)
: base(target, options) : base(configuration, target, options)
{ {
this.sourceImage = image; this.sourceImage = image;
this.sourceFrame = image.Frames.RootFrame; this.sourceFrame = image.Frames.RootFrame;
@ -104,14 +108,7 @@ namespace SixLabors.ImageSharp.Processing
this.offsetX = (int)MathF.Max(MathF.Floor(region.Left), 0); this.offsetX = (int)MathF.Max(MathF.Floor(region.Left), 0);
} }
/// <summary> /// <inheritdoc/>
/// Gets the color for a single pixel.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>
/// The color
/// </returns>
internal override TPixel this[int x, int y] internal override TPixel this[int x, int y]
{ {
get get
@ -123,14 +120,21 @@ namespace SixLabors.ImageSharp.Processing
} }
/// <inheritdoc /> /// <inheritdoc />
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?.Dispose();
this.sourceImage = null;
this.sourceFrame = null;
} }
this.sourceImage = null;
this.sourceFrame = null;
this.isDisposed = true;
} }
/// <inheritdoc /> /// <inheritdoc />
@ -152,13 +156,12 @@ namespace SixLabors.ImageSharp.Processing
amountSpan[i] = scanline[i] * this.Options.BlendPercentage; amountSpan[i] = scanline[i] * this.Options.BlendPercentage;
int sourceX = (i + offsetX) % this.xLength; int sourceX = (i + offsetX) % this.xLength;
TPixel pixel = sourceRow[sourceX]; overlaySpan[i] = sourceRow[sourceX];
overlaySpan[i] = pixel;
} }
Span<TPixel> destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); Span<TPixel> destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length);
this.Blender.Blend( this.Blender.Blend(
this.sourceFrame.Configuration, this.Configuration,
destinationRow, destinationRow,
destinationRow, destinationRow,
overlaySpan, overlaySpan,

27
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. // Licensed under the Apache License, Version 2.0.
using System; using System;
@ -39,10 +39,12 @@ namespace SixLabors.ImageSharp.Processing
/// <inheritdoc /> /// <inheritdoc />
public override BrushApplicator<TPixel> CreateApplicator<TPixel>( public override BrushApplicator<TPixel> CreateApplicator<TPixel>(
Configuration configuration,
ImageFrame<TPixel> source, ImageFrame<TPixel> source,
RectangleF region, RectangleF region,
GraphicsOptions options) => GraphicsOptions options) =>
new LinearGradientBrushApplicator<TPixel>( new LinearGradientBrushApplicator<TPixel>(
configuration,
source, source,
this.p1, this.p1,
this.p2, this.p2,
@ -93,20 +95,22 @@ namespace SixLabors.ImageSharp.Processing
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="LinearGradientBrushApplicator{TPixel}" /> class. /// Initializes a new instance of the <see cref="LinearGradientBrushApplicator{TPixel}" /> class.
/// </summary> /// </summary>
/// <param name="source">The source</param> /// <param name="configuration">The configuration instance to use when performing operations.</param>
/// <param name="start">start point of the gradient</param> /// <param name="source">The source image.</param>
/// <param name="end">end point of the gradient</param> /// <param name="start">start point of the gradient.</param>
/// <param name="colorStops">tuple list of colors and their respective position between 0 and 1 on the line</param> /// <param name="end">end point of the gradient.</param>
/// <param name="colorStops">tuple list of colors and their respective position between 0 and 1 on the line.</param>
/// <param name="repetitionMode">defines how the gradient colors are repeated.</param> /// <param name="repetitionMode">defines how the gradient colors are repeated.</param>
/// <param name="options">the graphics options</param> /// <param name="options">the graphics options.</param>
public LinearGradientBrushApplicator( public LinearGradientBrushApplicator(
Configuration configuration,
ImageFrame<TPixel> source, ImageFrame<TPixel> source,
PointF start, PointF start,
PointF end, PointF end,
ColorStop[] colorStops, ColorStop[] colorStops,
GradientRepetitionMode repetitionMode, GradientRepetitionMode repetitionMode,
GraphicsOptions options) GraphicsOptions options)
: base(source, options, colorStops, repetitionMode) : base(configuration, source, colorStops, repetitionMode, options)
{ {
this.start = start; this.start = start;
this.end = end; 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)); float distance = MathF.Sqrt(MathF.Pow(x4 - this.start.X, 2) + MathF.Pow(y4 - this.start.Y, 2));
// get and return ratio // get and return ratio
float ratio = distance / this.length; return distance / this.length;
return ratio;
} }
} }
public override void Dispose()
{
}
} }
} }
} }

18
src/ImageSharp.Drawing/Processing/PathGradientBrush.cs

@ -83,12 +83,13 @@ namespace SixLabors.ImageSharp.Processing
/// <inheritdoc /> /// <inheritdoc />
public BrushApplicator<TPixel> CreateApplicator<TPixel>( public BrushApplicator<TPixel> CreateApplicator<TPixel>(
Configuration configuration,
ImageFrame<TPixel> source, ImageFrame<TPixel> source,
RectangleF region, RectangleF region,
GraphicsOptions options) GraphicsOptions options)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
return new PathGradientBrushApplicator<TPixel>(source, this.edges, this.centerColor, options); return new PathGradientBrushApplicator<TPixel>(configuration, source, this.edges, this.centerColor, options);
} }
private static Color CalculateCenterColor(Color[] colors) private static Color CalculateCenterColor(Color[] colors)
@ -199,16 +200,18 @@ namespace SixLabors.ImageSharp.Processing
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="PathGradientBrushApplicator{TPixel}"/> class. /// Initializes a new instance of the <see cref="PathGradientBrushApplicator{TPixel}"/> class.
/// </summary> /// </summary>
/// <param name="configuration">The configuration instance to use when performing operations.</param>
/// <param name="source">The source image.</param> /// <param name="source">The source image.</param>
/// <param name="edges">Edges of the polygon.</param> /// <param name="edges">Edges of the polygon.</param>
/// <param name="centerColor">Color at the center of the gradient area to which the other colors converge.</param> /// <param name="centerColor">Color at the center of the gradient area to which the other colors converge.</param>
/// <param name="options">The options.</param> /// <param name="options">The graphics options.</param>
public PathGradientBrushApplicator( public PathGradientBrushApplicator(
Configuration configuration,
ImageFrame<TPixel> source, ImageFrame<TPixel> source,
IList<Edge> edges, IList<Edge> edges,
Color centerColor, Color centerColor,
GraphicsOptions options) GraphicsOptions options)
: base(source, options) : base(configuration, source, options)
{ {
this.edges = edges; this.edges = edges;
@ -232,7 +235,7 @@ namespace SixLabors.ImageSharp.Processing
return new Color(this.centerColor).ToPixel<TPixel>(); return new Color(this.centerColor).ToPixel<TPixel>();
} }
Vector2 direction = Vector2.Normalize(point - this.center); var direction = Vector2.Normalize(point - this.center);
PointF end = point + (PointF)(direction * this.maxDistance); PointF end = point + (PointF)(direction * this.maxDistance);
@ -250,7 +253,7 @@ namespace SixLabors.ImageSharp.Processing
float length = DistanceBetween(intersection, this.center); float length = DistanceBetween(intersection, this.center);
float ratio = length > 0 ? DistanceBetween(intersection, point) / length : 0; 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<TPixel>(); return new Color(color).ToPixel<TPixel>();
} }
@ -277,11 +280,6 @@ namespace SixLabors.ImageSharp.Processing
return closest; return closest;
} }
/// <inheritdoc />
public override void Dispose()
{
}
} }
} }
} }

36
src/ImageSharp.Drawing/Processing/PatternBrush.cs

@ -92,13 +92,15 @@ namespace SixLabors.ImageSharp.Processing
/// <inheritdoc /> /// <inheritdoc />
public BrushApplicator<TPixel> CreateApplicator<TPixel>( public BrushApplicator<TPixel> CreateApplicator<TPixel>(
Configuration configuration,
ImageFrame<TPixel> source, ImageFrame<TPixel> source,
RectangleF region, RectangleF region,
GraphicsOptions options) GraphicsOptions options)
where TPixel : struct, IPixel<TPixel> => where TPixel : struct, IPixel<TPixel> =>
new PatternBrushApplicator<TPixel>( new PatternBrushApplicator<TPixel>(
configuration,
source, source,
this.pattern.ToPixelMatrix<TPixel>(source.Configuration), this.pattern.ToPixelMatrix<TPixel>(configuration),
options); options);
/// <summary> /// <summary>
@ -115,41 +117,33 @@ namespace SixLabors.ImageSharp.Processing
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="PatternBrushApplicator{TPixel}" /> class. /// Initializes a new instance of the <see cref="PatternBrushApplicator{TPixel}" /> class.
/// </summary> /// </summary>
/// <param name="configuration">The configuration instance to use when performing operations.</param>
/// <param name="source">The source image.</param> /// <param name="source">The source image.</param>
/// <param name="pattern">The pattern.</param> /// <param name="pattern">The pattern.</param>
/// <param name="options">The options</param> /// <param name="options">The graphics options.</param>
public PatternBrushApplicator(ImageFrame<TPixel> source, in DenseMatrix<TPixel> pattern, GraphicsOptions options) public PatternBrushApplicator(
: base(source, options) Configuration configuration,
ImageFrame<TPixel> source,
in DenseMatrix<TPixel> pattern,
GraphicsOptions options)
: base(configuration, source, options)
{ {
this.pattern = pattern; this.pattern = pattern;
} }
/// <summary> /// <inheritdoc/>
/// Gets the color for a single pixel.
/// </summary>#
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>
/// The Color.
/// </returns>
internal override TPixel this[int x, int y] internal override TPixel this[int x, int y]
{ {
get get
{ {
x = x % this.pattern.Columns; x %= this.pattern.Columns;
y = y % this.pattern.Rows; y %= this.pattern.Rows;
// 2d array index at row/column // 2d array index at row/column
return this.pattern[y, x]; return this.pattern[y, x];
} }
} }
/// <inheritdoc />
public override void Dispose()
{
// noop
}
/// <inheritdoc /> /// <inheritdoc />
internal override void Apply(Span<float> scanline, int x, int y) internal override void Apply(Span<float> scanline, int x, int y)
{ {
@ -172,7 +166,7 @@ namespace SixLabors.ImageSharp.Processing
Span<TPixel> destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); Span<TPixel> destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length);
this.Blender.Blend( this.Blender.Blend(
this.Target.Configuration, this.Configuration,
destinationRow, destinationRow,
destinationRow, destinationRow,
overlaySpan, overlaySpan,

5
src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs

@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
int width = maxX - minX; 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; IBrush brush = this.definition.Brush;
GraphicsOptions options = this.definition.Options; GraphicsOptions options = this.definition.Options;
@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
ParallelExecutionSettings parallelSettings = ParallelExecutionSettings.FromConfiguration(configuration) ParallelExecutionSettings parallelSettings = ParallelExecutionSettings.FromConfiguration(configuration)
.MultiplyMinimumPixelsPerTask(4); .MultiplyMinimumPixelsPerTask(4);
var colorPixel = solidBrush.Color.ToPixel<TPixel>(); TPixel colorPixel = solidBrush.Color.ToPixel<TPixel>();
ParallelHelper.IterateRows( ParallelHelper.IterateRows(
workingRect, workingRect,
@ -84,6 +84,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
using (IMemoryOwner<float> amount = source.MemoryAllocator.Allocate<float>(width)) using (IMemoryOwner<float> amount = source.MemoryAllocator.Allocate<float>(width))
using (BrushApplicator<TPixel> applicator = brush.CreateApplicator( using (BrushApplicator<TPixel> applicator = brush.CreateApplicator(
configuration,
source, source,
sourceRectangle, sourceRectangle,
options)) options))

2
src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs

@ -71,7 +71,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
} }
} }
using (BrushApplicator<TPixel> applicator = brush.CreateApplicator(source, rect, options)) using (BrushApplicator<TPixel> applicator = brush.CreateApplicator(configuration, source, rect, options))
{ {
int scanlineWidth = maxX - minX; int scanlineWidth = maxX - minX;
using (IMemoryOwner<float> bBuffer = source.MemoryAllocator.Allocate<float>(maxIntersections)) using (IMemoryOwner<float> bBuffer = source.MemoryAllocator.Allocate<float>(maxIntersections))

2
src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs

@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text
{ {
if (operations?.Count > 0) if (operations?.Count > 0)
{ {
using (BrushApplicator<TPixel> app = brush.CreateApplicator(source, this.SourceRectangle, this.textRenderer.Options)) using (BrushApplicator<TPixel> app = brush.CreateApplicator(this.Configuration, source, this.SourceRectangle, this.textRenderer.Options))
{ {
foreach (DrawingOperation operation in operations) foreach (DrawingOperation operation in operations)
{ {

30
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. // Licensed under the Apache License, Version 2.0.
using System; using System;
@ -9,7 +9,7 @@ using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing namespace SixLabors.ImageSharp.Processing
{ {
/// <summary> /// <summary>
/// A Circular Gradient Brush, defined by center point and radius. /// A radial gradient brush, defined by center point and radius.
/// </summary> /// </summary>
public sealed class RadialGradientBrush : GradientBrush public sealed class RadialGradientBrush : GradientBrush
{ {
@ -35,16 +35,18 @@ namespace SixLabors.ImageSharp.Processing
/// <inheritdoc /> /// <inheritdoc />
public override BrushApplicator<TPixel> CreateApplicator<TPixel>( public override BrushApplicator<TPixel> CreateApplicator<TPixel>(
Configuration configuration,
ImageFrame<TPixel> source, ImageFrame<TPixel> source,
RectangleF region, RectangleF region,
GraphicsOptions options) => GraphicsOptions options) =>
new RadialGradientBrushApplicator<TPixel>( new RadialGradientBrushApplicator<TPixel>(
configuration,
source, source,
options,
this.center, this.center,
this.radius, this.radius,
this.ColorStops, this.ColorStops,
this.RepetitionMode); this.RepetitionMode,
options);
/// <inheritdoc /> /// <inheritdoc />
private sealed class RadialGradientBrushApplicator<TPixel> : GradientBrushApplicator<TPixel> private sealed class RadialGradientBrushApplicator<TPixel> : GradientBrushApplicator<TPixel>
@ -57,30 +59,27 @@ namespace SixLabors.ImageSharp.Processing
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RadialGradientBrushApplicator{TPixel}" /> class. /// Initializes a new instance of the <see cref="RadialGradientBrushApplicator{TPixel}" /> class.
/// </summary> /// </summary>
/// <param name="target">The target image</param> /// <param name="configuration">The configuration instance to use when performing operations.</param>
/// <param name="options">The options.</param> /// <param name="target">The target image.</param>
/// <param name="center">Center point of the gradient.</param> /// <param name="center">Center point of the gradient.</param>
/// <param name="radius">Radius of the gradient.</param> /// <param name="radius">Radius of the gradient.</param>
/// <param name="colorStops">Definition of colors.</param> /// <param name="colorStops">Definition of colors.</param>
/// <param name="repetitionMode">How the colors are repeated beyond the first gradient.</param> /// <param name="repetitionMode">How the colors are repeated beyond the first gradient.</param>
/// <param name="options">The graphics options.</param>
public RadialGradientBrushApplicator( public RadialGradientBrushApplicator(
Configuration configuration,
ImageFrame<TPixel> target, ImageFrame<TPixel> target,
GraphicsOptions options,
PointF center, PointF center,
float radius, float radius,
ColorStop[] colorStops, ColorStop[] colorStops,
GradientRepetitionMode repetitionMode) GradientRepetitionMode repetitionMode,
: base(target, options, colorStops, repetitionMode) GraphicsOptions options)
: base(configuration, target, colorStops, repetitionMode, options)
{ {
this.center = center; this.center = center;
this.radius = radius; this.radius = radius;
} }
/// <inheritdoc cref="Dispose" />
public override void Dispose()
{
}
/// <summary> /// <summary>
/// As this is a circular gradient, the position on the gradient is based on /// As this is a circular gradient, the position on the gradient is based on
/// the distance of the point to the center. /// the distance of the point to the center.
@ -90,6 +89,7 @@ namespace SixLabors.ImageSharp.Processing
/// <returns>the position on the color gradient.</returns> /// <returns>the position on the color gradient.</returns>
protected override float PositionOnGradient(float x, float y) 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)); float distance = MathF.Sqrt(MathF.Pow(this.center.X - x, 2) + MathF.Pow(this.center.Y - y, 2));
return distance / this.radius; return distance / this.radius;
} }
@ -101,4 +101,4 @@ namespace SixLabors.ImageSharp.Processing
} }
} }
} }
} }

39
src/ImageSharp.Drawing/Processing/RecolorBrush.cs

@ -5,7 +5,6 @@ using System;
using System.Buffers; using System.Buffers;
using System.Numerics; using System.Numerics;
using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory; using SixLabors.Memory;
using SixLabors.Primitives; using SixLabors.Primitives;
@ -38,9 +37,6 @@ namespace SixLabors.ImageSharp.Processing
/// <summary> /// <summary>
/// Gets the source color. /// Gets the source color.
/// </summary> /// </summary>
/// <value>
/// The color of the source.
/// </value>
public Color SourceColor { get; } public Color SourceColor { get; }
/// <summary> /// <summary>
@ -50,12 +46,14 @@ namespace SixLabors.ImageSharp.Processing
/// <inheritdoc /> /// <inheritdoc />
public BrushApplicator<TPixel> CreateApplicator<TPixel>( public BrushApplicator<TPixel> CreateApplicator<TPixel>(
Configuration configuration,
ImageFrame<TPixel> source, ImageFrame<TPixel> source,
RectangleF region, RectangleF region,
GraphicsOptions options) GraphicsOptions options)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
return new RecolorBrushApplicator<TPixel>( return new RecolorBrushApplicator<TPixel>(
configuration,
source, source,
this.SourceColor.ToPixel<TPixel>(), this.SourceColor.ToPixel<TPixel>(),
this.TargetColor.ToPixel<TPixel>(), this.TargetColor.ToPixel<TPixel>(),
@ -74,11 +72,6 @@ namespace SixLabors.ImageSharp.Processing
/// </summary> /// </summary>
private readonly Vector4 sourceColor; private readonly Vector4 sourceColor;
/// <summary>
/// The target color.
/// </summary>
private readonly Vector4 targetColor;
/// <summary> /// <summary>
/// The threshold. /// The threshold.
/// </summary> /// </summary>
@ -89,16 +82,22 @@ namespace SixLabors.ImageSharp.Processing
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RecolorBrushApplicator{TPixel}" /> class. /// Initializes a new instance of the <see cref="RecolorBrushApplicator{TPixel}" /> class.
/// </summary> /// </summary>
/// <param name="configuration">The configuration instance to use when performing operations.</param>
/// <param name="source">The source image.</param> /// <param name="source">The source image.</param>
/// <param name="sourceColor">Color of the source.</param> /// <param name="sourceColor">Color of the source.</param>
/// <param name="targetColor">Color of the target.</param> /// <param name="targetColor">Color of the target.</param>
/// <param name="threshold">The threshold .</param> /// <param name="threshold">The threshold .</param>
/// <param name="options">The options</param> /// <param name="options">The options</param>
public RecolorBrushApplicator(ImageFrame<TPixel> source, TPixel sourceColor, TPixel targetColor, float threshold, GraphicsOptions options) public RecolorBrushApplicator(
: base(source, options) Configuration configuration,
ImageFrame<TPixel> source,
TPixel sourceColor,
TPixel targetColor,
float threshold,
GraphicsOptions options)
: base(configuration, source, options)
{ {
this.sourceColor = sourceColor.ToVector4(); this.sourceColor = sourceColor.ToVector4();
this.targetColor = targetColor.ToVector4();
this.targetColorPixel = targetColor; 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 :) // 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; this.threshold = Vector4.DistanceSquared(maxColor.ToVector4(), minColor.ToVector4()) * threshold;
} }
/// <summary> /// <inheritdoc />
/// Gets the color for a single pixel.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>
/// The color
/// </returns>
internal override TPixel this[int x, int y] internal override TPixel this[int x, int y]
{ {
get get
@ -138,11 +130,6 @@ namespace SixLabors.ImageSharp.Processing
} }
} }
/// <inheritdoc />
public override void Dispose()
{
}
/// <inheritdoc /> /// <inheritdoc />
internal override void Apply(Span<float> scanline, int x, int y) internal override void Apply(Span<float> scanline, int x, int y)
{ {
@ -167,7 +154,7 @@ namespace SixLabors.ImageSharp.Processing
Span<TPixel> destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); Span<TPixel> destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length);
this.Blender.Blend( this.Blender.Blend(
this.Target.Configuration, this.Configuration,
destinationRow, destinationRow,
destinationRow, destinationRow,
overlaySpan, overlaySpan,

62
src/ImageSharp.Drawing/Processing/SolidBrush.cs

@ -5,7 +5,6 @@ using System;
using System.Buffers; using System.Buffers;
using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory; using SixLabors.Memory;
using SixLabors.Primitives; using SixLabors.Primitives;
@ -17,33 +16,29 @@ namespace SixLabors.ImageSharp.Processing
/// </summary> /// </summary>
public class SolidBrush : IBrush public class SolidBrush : IBrush
{ {
/// <summary>
/// The color to paint.
/// </summary>
private readonly Color color;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SolidBrush"/> class. /// Initializes a new instance of the <see cref="SolidBrush"/> class.
/// </summary> /// </summary>
/// <param name="color">The color.</param> /// <param name="color">The color.</param>
public SolidBrush(Color color) public SolidBrush(Color color)
{ {
this.color = color; this.Color = color;
} }
/// <summary> /// <summary>
/// Gets the color. /// Gets the color.
/// </summary> /// </summary>
/// <value> public Color Color { get; }
/// The color.
/// </value>
public Color Color => this.color;
/// <inheritdoc /> /// <inheritdoc />
public BrushApplicator<TPixel> CreateApplicator<TPixel>(ImageFrame<TPixel> source, RectangleF region, GraphicsOptions options) public BrushApplicator<TPixel> CreateApplicator<TPixel>(
Configuration configuration,
ImageFrame<TPixel> source,
RectangleF region,
GraphicsOptions options)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
return new SolidBrushApplicator<TPixel>(source, this.color.ToPixel<TPixel>(), options); return new SolidBrushApplicator<TPixel>(configuration, source, this.Color.ToPixel<TPixel>(), options);
} }
/// <summary> /// <summary>
@ -52,14 +47,21 @@ namespace SixLabors.ImageSharp.Processing
private class SolidBrushApplicator<TPixel> : BrushApplicator<TPixel> private class SolidBrushApplicator<TPixel> : BrushApplicator<TPixel>
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
private bool isDisposed;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SolidBrushApplicator{TPixel}"/> class. /// Initializes a new instance of the <see cref="SolidBrushApplicator{TPixel}"/> class.
/// </summary> /// </summary>
/// <param name="configuration">The configuration instance to use when performing operations.</param>
/// <param name="source">The source image.</param> /// <param name="source">The source image.</param>
/// <param name="color">The color.</param> /// <param name="color">The color.</param>
/// <param name="options">The options</param> /// <param name="options">The graphics options.</param>
public SolidBrushApplicator(ImageFrame<TPixel> source, TPixel color, GraphicsOptions options) public SolidBrushApplicator(
: base(source, options) Configuration configuration,
ImageFrame<TPixel> source,
TPixel color,
GraphicsOptions options)
: base(configuration, source, options)
{ {
this.Colors = source.MemoryAllocator.Allocate<TPixel>(source.Width); this.Colors = source.MemoryAllocator.Allocate<TPixel>(source.Width);
this.Colors.Memory.Span.Fill(color); this.Colors.Memory.Span.Fill(color);
@ -68,22 +70,26 @@ namespace SixLabors.ImageSharp.Processing
/// <summary> /// <summary>
/// Gets the colors. /// Gets the colors.
/// </summary> /// </summary>
protected IMemoryOwner<TPixel> Colors { get; } protected IMemoryOwner<TPixel> Colors { get; private set; }
/// <summary> /// <inheritdoc/>
/// Gets the color for a single pixel.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>
/// The color
/// </returns>
internal override TPixel this[int x, int y] => this.Colors.Memory.Span[x]; internal override TPixel this[int x, int y] => this.Colors.Memory.Span[x];
/// <inheritdoc /> /// <inheritdoc />
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;
} }
/// <inheritdoc /> /// <inheritdoc />
@ -102,7 +108,7 @@ namespace SixLabors.ImageSharp.Processing
} }
MemoryAllocator memoryAllocator = this.Target.MemoryAllocator; MemoryAllocator memoryAllocator = this.Target.MemoryAllocator;
Configuration configuration = this.Target.Configuration; Configuration configuration = this.Configuration;
if (this.Options.BlendPercentage == 1f) if (this.Options.BlendPercentage == 1f)
{ {

2
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. // Licensed under the Apache License, Version 2.0.
using System; using System;

Loading…
Cancel
Save