Browse Source

Fix ImageFrame.Configuration

pull/1055/head
James Jackson-South 6 years ago
parent
commit
516f6df6f5
  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.Buffers;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.Processing
{
/// <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>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <seealso cref="System.IDisposable" />
public abstract class BrushApplicator<TPixel> : IDisposable // disposable will be required if/when there is an ImageBrush
/// <seealso cref="IDisposable" />
public abstract class BrushApplicator<TPixel> : IDisposable
where TPixel : struct, IPixel<TPixel>
{
/// <summary>
/// Initializes a new instance of the <see cref="BrushApplicator{TPixel}"/> class.
/// </summary>
/// <param name="configuration">The configuration instance to use when performing operations.</param>
/// <param name="target">The target.</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.Options = options;
this.Blender = PixelOperations<TPixel>.Instance.GetPixelBlender(options);
}
/// <summary>
/// Gets the blender
/// Gets the configuration instance to use when performing operations.
/// </summary>
protected Configuration Configuration { get; }
/// <summary>
/// Gets the pixel blender.
/// </summary>
internal PixelBlender<TPixel> Blender { get; }
/// <summary>
/// Gets the destination
/// Gets the target image.
/// </summary>
protected ImageFrame<TPixel> Target { get; }
/// <summary>
/// Gets the blend percentage
/// Gets thegraphics options
/// </summary>
protected GraphicsOptions Options { get; }
/// <summary>
/// Gets the color for a single pixel.
/// Gets the overlay pixel at the specified position.
/// </summary>
/// <param name="x">The x coordinate.</param>
/// <param name="y">The y coordinate.</param>
/// <returns>The a <typeparamref name="TPixel"/> that should be applied to the pixel.</returns>
/// <param name="x">The x-coordinate.</param>
/// <param name="y">The y-coordinate.</param>
/// <returns>The <see typeparam="TPixel"/> at the specified position.</returns>
internal abstract TPixel this[int x, int y] { get; }
/// <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>
/// Applies the opacity weighting for each pixel in a scanline to the target based on the pattern contained in the brush.
/// </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="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="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="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>
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);
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.
using System;
@ -47,17 +47,19 @@ namespace SixLabors.ImageSharp.Processing
/// <inheritdoc />
public override BrushApplicator<TPixel> CreateApplicator<TPixel>(
Configuration configuration,
ImageFrame<TPixel> source,
RectangleF region,
GraphicsOptions options) =>
new RadialGradientBrushApplicator<TPixel>(
configuration,
source,
options,
this.center,
this.referenceAxisEnd,
this.axisRatio,
this.ColorStops,
this.RepetitionMode);
this.RepetitionMode,
options);
/// <inheritdoc />
private sealed class RadialGradientBrushApplicator<TPixel> : GradientBrushApplicator<TPixel>
@ -86,24 +88,26 @@ namespace SixLabors.ImageSharp.Processing
/// <summary>
/// Initializes a new instance of the <see cref="RadialGradientBrushApplicator{TPixel}" /> class.
/// </summary>
/// <param name="target">The target image</param>
/// <param name="options">The options</param>
/// <param name="center">Center of the ellipse</param>
/// <param name="configuration">The configuration instance to use when performing operations.</param>
/// <param name="target">The target image.</param>
/// <param name="center">Center of the ellipse.</param>
/// <param name="referenceAxisEnd">Point on one angular points of the ellipse.</param>
/// <param name="axisRatio">
/// 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>
/// <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="options">The graphics options.</param>
public RadialGradientBrushApplicator(
Configuration configuration,
ImageFrame<TPixel> 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);
}
/// <inheritdoc />
public override void Dispose()
{
}
/// <inheritdoc />
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
}
}
}
}
}

29
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
/// <inheritdoc />
public abstract BrushApplicator<TPixel> CreateApplicator<TPixel>(
Configuration configuration,
ImageFrame<TPixel> source,
RectangleF region,
GraphicsOptions options)
@ -58,27 +57,24 @@ namespace SixLabors.ImageSharp.Processing
/// <summary>
/// Initializes a new instance of the <see cref="GradientBrushApplicator{TPixel}"/> class.
/// </summary>
/// <param name="target">The target.</param>
/// <param name="options">The options.</param>
/// <param name="configuration">The configuration instance to use when performing operations.</param>
/// <param name="target">The target image.</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="options">The graphics options.</param>
protected GradientBrushApplicator(
Configuration configuration,
ImageFrame<TPixel> 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;
}
/// <summary>
/// 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>
/// <inheritdoc/>
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<TPixel>
.Instance.GetPixelBlender(PixelColorBlendingMode.Normal, PixelAlphaCompositionMode.SrcOver)
.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.
/// This method is abstract as it's content depends on the shape of the gradient.
/// </summary>
/// <param name="x">The x coordinate of the point</param>
/// <param name="y">The y 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>
/// <returns>
/// The position the given point has on the gradient.
/// 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.
using SixLabors.ImageSharp.PixelFormats;
@ -19,20 +19,22 @@ namespace SixLabors.ImageSharp.Processing
/// Creates the applicator for this brush.
/// </summary>
/// <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="region">The region the brush will be applied to.</param>
/// <param name="options">The graphic options</param>
/// <returns>
/// The brush applicator for this brush
/// The <see cref="BrushApplicator{TPixel}"/> for this brush.
/// </returns>
/// <remarks>
/// 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>
BrushApplicator<TPixel> CreateApplicator<TPixel>(
Configuration configuration,
ImageFrame<TPixel> source,
RectangleF region,
GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>;
}
}
}

47
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
/// <inheritdoc />
public BrushApplicator<TPixel> CreateApplicator<TPixel>(
Configuration configuration,
ImageFrame<TPixel> source,
RectangleF region,
GraphicsOptions options)
@ -39,12 +39,12 @@ namespace SixLabors.ImageSharp.Processing
{
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>();
return new ImageBrushApplicator<TPixel>(source, specificImage, region, options, true);
return new ImageBrushApplicator<TPixel>(configuration, source, specificImage, region, true, options);
}
/// <summary>
@ -79,21 +79,25 @@ namespace SixLabors.ImageSharp.Processing
/// </summary>
private readonly int offsetX;
private bool isDisposed;
/// <summary>
/// Initializes a new instance of the <see cref="ImageBrushApplicator{TPixel}"/> class.
/// </summary>
/// <param name="configuration">The configuration instance to use when performing operations.</param>
/// <param name="target">The target image.</param>
/// <param name="image">The image.</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="options">The graphics options.</param>
public ImageBrushApplicator(
Configuration configuration,
ImageFrame<TPixel> target,
Image<TPixel> 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);
}
/// <summary>
/// Gets the color for a single pixel.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>
/// The color
/// </returns>
/// <inheritdoc/>
internal override TPixel this[int x, int y]
{
get
@ -123,14 +120,21 @@ namespace SixLabors.ImageSharp.Processing
}
/// <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 = null;
this.sourceFrame = null;
}
this.sourceImage = null;
this.sourceFrame = null;
this.isDisposed = true;
}
/// <inheritdoc />
@ -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<TPixel> destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length);
this.Blender.Blend(
this.sourceFrame.Configuration,
this.Configuration,
destinationRow,
destinationRow,
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.
using System;
@ -39,10 +39,12 @@ namespace SixLabors.ImageSharp.Processing
/// <inheritdoc />
public override BrushApplicator<TPixel> CreateApplicator<TPixel>(
Configuration configuration,
ImageFrame<TPixel> source,
RectangleF region,
GraphicsOptions options) =>
new LinearGradientBrushApplicator<TPixel>(
configuration,
source,
this.p1,
this.p2,
@ -93,20 +95,22 @@ namespace SixLabors.ImageSharp.Processing
/// <summary>
/// Initializes a new instance of the <see cref="LinearGradientBrushApplicator{TPixel}" /> class.
/// </summary>
/// <param name="source">The source</param>
/// <param name="start">start point of the gradient</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="configuration">The configuration instance to use when performing operations.</param>
/// <param name="source">The source image.</param>
/// <param name="start">start point of the gradient.</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="options">the graphics options</param>
/// <param name="options">the graphics options.</param>
public LinearGradientBrushApplicator(
Configuration configuration,
ImageFrame<TPixel> 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()
{
}
}
}
}
}

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

@ -83,12 +83,13 @@ namespace SixLabors.ImageSharp.Processing
/// <inheritdoc />
public BrushApplicator<TPixel> CreateApplicator<TPixel>(
Configuration configuration,
ImageFrame<TPixel> source,
RectangleF region,
GraphicsOptions options)
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)
@ -199,16 +200,18 @@ namespace SixLabors.ImageSharp.Processing
/// <summary>
/// Initializes a new instance of the <see cref="PathGradientBrushApplicator{TPixel}"/> class.
/// </summary>
/// <param name="configuration">The configuration instance to use when performing operations.</param>
/// <param name="source">The source image.</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="options">The options.</param>
/// <param name="options">The graphics options.</param>
public PathGradientBrushApplicator(
Configuration configuration,
ImageFrame<TPixel> source,
IList<Edge> 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<TPixel>();
}
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<TPixel>();
}
@ -277,11 +280,6 @@ namespace SixLabors.ImageSharp.Processing
return closest;
}
/// <inheritdoc />
public override void Dispose()
{
}
}
}
}

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

@ -92,13 +92,15 @@ namespace SixLabors.ImageSharp.Processing
/// <inheritdoc />
public BrushApplicator<TPixel> CreateApplicator<TPixel>(
Configuration configuration,
ImageFrame<TPixel> source,
RectangleF region,
GraphicsOptions options)
where TPixel : struct, IPixel<TPixel> =>
new PatternBrushApplicator<TPixel>(
configuration,
source,
this.pattern.ToPixelMatrix<TPixel>(source.Configuration),
this.pattern.ToPixelMatrix<TPixel>(configuration),
options);
/// <summary>
@ -115,41 +117,33 @@ namespace SixLabors.ImageSharp.Processing
/// <summary>
/// Initializes a new instance of the <see cref="PatternBrushApplicator{TPixel}" /> class.
/// </summary>
/// <param name="configuration">The configuration instance to use when performing operations.</param>
/// <param name="source">The source image.</param>
/// <param name="pattern">The pattern.</param>
/// <param name="options">The options</param>
public PatternBrushApplicator(ImageFrame<TPixel> source, in DenseMatrix<TPixel> pattern, GraphicsOptions options)
: base(source, options)
/// <param name="options">The graphics options.</param>
public PatternBrushApplicator(
Configuration configuration,
ImageFrame<TPixel> source,
in DenseMatrix<TPixel> pattern,
GraphicsOptions options)
: base(configuration, source, options)
{
this.pattern = pattern;
}
/// <summary>
/// Gets the color for a single pixel.
/// </summary>#
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>
/// The Color.
/// </returns>
/// <inheritdoc/>
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];
}
}
/// <inheritdoc />
public override void Dispose()
{
// noop
}
/// <inheritdoc />
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);
this.Blender.Blend(
this.Target.Configuration,
this.Configuration,
destinationRow,
destinationRow,
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;
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>();
TPixel colorPixel = solidBrush.Color.ToPixel<TPixel>();
ParallelHelper.IterateRows(
workingRect,
@ -84,6 +84,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
using (IMemoryOwner<float> amount = source.MemoryAllocator.Allocate<float>(width))
using (BrushApplicator<TPixel> applicator = brush.CreateApplicator(
configuration,
source,
sourceRectangle,
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;
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)
{
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)
{

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.
using System;
@ -9,7 +9,7 @@ using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing
{
/// <summary>
/// A Circular Gradient Brush, defined by center point and radius.
/// A radial gradient brush, defined by center point and radius.
/// </summary>
public sealed class RadialGradientBrush : GradientBrush
{
@ -35,16 +35,18 @@ namespace SixLabors.ImageSharp.Processing
/// <inheritdoc />
public override BrushApplicator<TPixel> CreateApplicator<TPixel>(
Configuration configuration,
ImageFrame<TPixel> source,
RectangleF region,
GraphicsOptions options) =>
new RadialGradientBrushApplicator<TPixel>(
configuration,
source,
options,
this.center,
this.radius,
this.ColorStops,
this.RepetitionMode);
this.RepetitionMode,
options);
/// <inheritdoc />
private sealed class RadialGradientBrushApplicator<TPixel> : GradientBrushApplicator<TPixel>
@ -57,30 +59,27 @@ namespace SixLabors.ImageSharp.Processing
/// <summary>
/// Initializes a new instance of the <see cref="RadialGradientBrushApplicator{TPixel}" /> class.
/// </summary>
/// <param name="target">The target image</param>
/// <param name="options">The options.</param>
/// <param name="configuration">The configuration instance to use when performing operations.</param>
/// <param name="target">The target image.</param>
/// <param name="center">Center point of the gradient.</param>
/// <param name="radius">Radius of the gradient.</param>
/// <param name="colorStops">Definition of colors.</param>
/// <param name="repetitionMode">How the colors are repeated beyond the first gradient.</param>
/// <param name="options">The graphics options.</param>
public RadialGradientBrushApplicator(
Configuration configuration,
ImageFrame<TPixel> 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;
}
/// <inheritdoc cref="Dispose" />
public override void Dispose()
{
}
/// <summary>
/// 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
/// <returns>the position on the color gradient.</returns>
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
}
}
}
}
}

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

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

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.
using System;

Loading…
Cancel
Save