diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs
index 7ec359220..dc55112c9 100644
--- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs
+++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.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;
@@ -59,10 +59,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
public float Opacity { get; }
///
- public IImageProcessor CreatePixelSpecificProcessor()
+ public IImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle)
where TPixelBg : struct, IPixel
{
- var visitor = new ProcessorFactoryVisitor(this);
+ var visitor = new ProcessorFactoryVisitor(this, source, sourceRectangle);
this.Image.AcceptVisitor(visitor);
return visitor.Result;
}
@@ -71,10 +71,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
where TPixelBg : struct, IPixel
{
private readonly DrawImageProcessor definition;
+ private readonly Image source;
+ private readonly Rectangle sourceRectangle;
- public ProcessorFactoryVisitor(DrawImageProcessor definition)
+ public ProcessorFactoryVisitor(DrawImageProcessor definition, Image source, Rectangle sourceRectangle)
{
this.definition = definition;
+ this.source = source;
+ this.sourceRectangle = sourceRectangle;
}
public IImageProcessor Result { get; private set; }
@@ -84,6 +88,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
{
this.Result = new DrawImageProcessor(
image,
+ this.source,
+ this.sourceRectangle,
this.definition.Location,
this.definition.ColorBlendingMode,
this.definition.AlphaCompositionMode,
@@ -91,4 +97,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs
index 21599bf78..6cfa23cce 100644
--- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs
+++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs
@@ -20,19 +20,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
where TPixelFg : struct, IPixel
{
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
- /// The image to blend with the currently processing image.
+ /// The foreground to blend with the currently processing image.
+ /// The source for the current processor instance.
+ /// The source area to process for the current processor instance.
/// The location to draw the blended image.
/// The blending mode to use when drawing the image.
/// The Alpha blending mode to use when drawing the image.
/// The opacity of the image to blend. Must be between 0 and 1.
public DrawImageProcessor(
Image image,
+ Image source,
+ Rectangle sourceRectangle,
Point location,
PixelColorBlendingMode colorBlendingMode,
PixelAlphaCompositionMode alphaCompositionMode,
float opacity)
+ : base(source, sourceRectangle)
{
Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity));
@@ -63,11 +68,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
public Point Location { get; }
///
- protected override void OnFrameApply(
- ImageFrame source,
- Rectangle sourceRectangle,
- Configuration configuration)
+ protected override void OnFrameApply(ImageFrame source)
{
+ Rectangle sourceRectangle = this.SourceRectangle;
+ Configuration configuration = this.Configuration;
+
Image targetImage = this.Image;
PixelBlender blender = this.Blender;
int locationY = this.Location.Y;
@@ -101,11 +106,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
for (int y = rows.Min; y < rows.Max; y++)
{
Span background = source.GetPixelRowSpan(y).Slice(minX, width);
- Span foreground =
- targetImage.GetPixelRowSpan(y - locationY).Slice(targetX, width);
+ Span foreground = targetImage.GetPixelRowSpan(y - locationY).Slice(targetX, width);
blender.Blend(configuration, background, background, foreground, this.Opacity);
}
});
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs
index 81880308c..1d3cf3557 100644
--- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs
+++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs
@@ -1,7 +1,8 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Drawing
{
@@ -33,10 +34,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
public GraphicsOptions Options { get; }
///
- public IImageProcessor CreatePixelSpecificProcessor()
+ public IImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle)
where TPixel : struct, IPixel
{
- return new FillProcessor(this);
+ return new FillProcessor(this, source, sourceRectangle);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs
index 68aef82e2..a7c22f6d7 100644
--- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs
@@ -21,14 +21,17 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
{
private readonly FillProcessor definition;
- public FillProcessor(FillProcessor definition)
+ public FillProcessor(FillProcessor definition, Image source, Rectangle sourceRectangle)
+ : base(source, sourceRectangle)
{
this.definition = definition;
}
///
- protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration)
+ protected override void OnFrameApply(ImageFrame source)
{
+ Rectangle sourceRectangle = this.SourceRectangle;
+ Configuration configuration = this.Configuration;
int startX = sourceRectangle.X;
int endX = sourceRectangle.Right;
int startY = sourceRectangle.Y;
@@ -115,4 +118,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
return this.definition.Options.IsOpaqueColorWithoutBlending(solidBrush.Color);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs
index 000fa260a..2318f3168 100644
--- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs
+++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs
@@ -1,8 +1,9 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
+using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Drawing
{
@@ -41,10 +42,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
public GraphicsOptions Options { get; }
///
- public IImageProcessor CreatePixelSpecificProcessor()
+ public IImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle)
where TPixel : struct, IPixel
{
- return new FillRegionProcessor(this);
+ return new FillRegionProcessor(this, source, sourceRectangle);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs
index 347d243ae..45d5015ae 100644
--- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs
@@ -23,14 +23,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
{
private readonly FillRegionProcessor definition;
- public FillRegionProcessor(FillRegionProcessor definition)
+ public FillRegionProcessor(FillRegionProcessor definition, Image source, Rectangle sourceRectangle)
+ : base(source, sourceRectangle)
{
this.definition = definition;
}
///
- protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration)
+ protected override void OnFrameApply(ImageFrame source)
{
+ Configuration configuration = this.Configuration;
GraphicsOptions options = this.definition.Options;
IBrush brush = this.definition.Brush;
Region region = this.definition.Region;
diff --git a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs
index 40621ce99..775cf55ab 100644
--- a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs
+++ b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.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;
@@ -72,10 +72,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text
public PointF Location { get; }
///
- public IImageProcessor CreatePixelSpecificProcessor()
+ public IImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle)
where TPixel : struct, IPixel
{
- return new DrawTextProcessor(this);
+ return new DrawTextProcessor(this, source, sourceRectangle);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs
index b3c336c88..3809200d5 100644
--- a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs
@@ -27,7 +27,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text
private readonly DrawTextProcessor definition;
- public DrawTextProcessor(DrawTextProcessor definition)
+ public DrawTextProcessor(DrawTextProcessor definition, Image source, Rectangle sourceRectangle)
+ : base(source, sourceRectangle)
{
this.definition = definition;
}
@@ -44,35 +45,35 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text
private IBrush Brush => this.definition.Brush;
- protected override void BeforeImageApply(Image source, Rectangle sourceRectangle)
+ protected override void BeforeImageApply()
{
- base.BeforeImageApply(source, sourceRectangle);
+ base.BeforeImageApply();
// do everything at the image level as we are delegating the processing down to other processors
var style = new RendererOptions(this.Font, this.Options.DpiX, this.Options.DpiY, this.Location)
- {
- ApplyKerning = this.Options.ApplyKerning,
- TabWidth = this.Options.TabWidth,
- WrappingWidth = this.Options.WrapTextWidth,
- HorizontalAlignment = this.Options.HorizontalAlignment,
- VerticalAlignment = this.Options.VerticalAlignment
- };
-
- this.textRenderer = new CachingGlyphRenderer(source.GetMemoryAllocator(), this.Text.Length, this.Pen, this.Brush != null);
+ {
+ ApplyKerning = this.Options.ApplyKerning,
+ TabWidth = this.Options.TabWidth,
+ WrappingWidth = this.Options.WrapTextWidth,
+ HorizontalAlignment = this.Options.HorizontalAlignment,
+ VerticalAlignment = this.Options.VerticalAlignment
+ };
+
+ this.textRenderer = new CachingGlyphRenderer(this.Source.GetMemoryAllocator(), this.Text.Length, this.Pen, this.Brush != null);
this.textRenderer.Options = (GraphicsOptions)this.Options;
var renderer = new TextRenderer(this.textRenderer);
renderer.RenderText(this.Text, style);
}
- protected override void AfterImageApply(Image source, Rectangle sourceRectangle)
+ protected override void AfterImageApply()
{
- base.AfterImageApply(source, sourceRectangle);
+ base.AfterImageApply();
this.textRenderer?.Dispose();
this.textRenderer = null;
}
///
- protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration)
+ protected override void OnFrameApply(ImageFrame source)
{
// this is a no-op as we have processes all as an image, we should be able to pass out of before email apply a skip frames outcome
Draw(this.textRenderer.FillOperations, this.Brush);
@@ -82,7 +83,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text
{
if (operations?.Count > 0)
{
- using (BrushApplicator app = brush.CreateApplicator(source, sourceRectangle, this.textRenderer.Options))
+ using (BrushApplicator app = brush.CreateApplicator(source, this.SourceRectangle, this.textRenderer.Options))
{
foreach (DrawingOperation operation in operations)
{
@@ -279,19 +280,19 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text
if (this.renderFill)
{
this.FillOperations.Add(new DrawingOperation
- {
- Location = this.currentRenderPosition,
- Map = renderData.FillMap
- });
+ {
+ Location = this.currentRenderPosition,
+ Map = renderData.FillMap
+ });
}
if (this.renderOutline)
{
this.OutlineOperations.Add(new DrawingOperation
- {
- Location = this.currentRenderPosition,
- Map = renderData.OutlineMap
- });
+ {
+ Location = this.currentRenderPosition,
+ Map = renderData.OutlineMap
+ });
}
}
diff --git a/src/ImageSharp/Advanced/AotCompilerTools.cs b/src/ImageSharp/Advanced/AotCompilerTools.cs
index 439ea6de0..8d3a074b5 100644
--- a/src/ImageSharp/Advanced/AotCompilerTools.cs
+++ b/src/ImageSharp/Advanced/AotCompilerTools.cs
@@ -179,9 +179,8 @@ namespace SixLabors.ImageSharp.Advanced
private static void AotCompileResizeOperations()
where TPixel : struct, IPixel
{
- var resizeProcessor = new ResizeProcessor(new ResizeOptions(), default);
- var genericResizeProcessor = new ResizeProcessor((ResizeProcessor)resizeProcessor.CreatePixelSpecificProcessor());
- genericResizeProcessor.AotCreateDestination(new Image(0, 0), default);
+ var genericResizeProcessor = (ResizeProcessor)new ResizeProcessor(new ResizeOptions(), default).CreatePixelSpecificProcessor(new Image(0, 0), default);
+ genericResizeProcessor.AotCreateDestination();
}
}
}
diff --git a/src/ImageSharp/Processing/DefaultImageProcessorContext.cs b/src/ImageSharp/Processing/DefaultImageProcessorContext.cs
index d0c4c076f..7b6fbebd1 100644
--- a/src/ImageSharp/Processing/DefaultImageProcessorContext.cs
+++ b/src/ImageSharp/Processing/DefaultImageProcessorContext.cs
@@ -53,43 +53,33 @@ namespace SixLabors.ImageSharp.Processing
///
public Size GetCurrentSize() => this.GetCurrentBounds().Size;
- public IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectangle rectangle)
- {
- var processorImplementation = processor.CreatePixelSpecificProcessor();
- return this.ApplyProcessor(processorImplementation, rectangle);
- }
-
+ ///
public IImageProcessingContext ApplyProcessor(IImageProcessor processor)
{
- var processorImplementation = processor.CreatePixelSpecificProcessor();
- return this.ApplyProcessor(processorImplementation);
+ return this.ApplyProcessor(processor, this.GetCurrentBounds());
}
- private IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectangle rectangle)
+ ///
+ public IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectangle rectangle)
{
if (!this.mutate && this.destination is null)
{
// This will only work if the first processor applied is the cloning one thus
// realistically for this optimization to work the resize must the first processor
// applied any only up processors will take the double data path.
- if (processor is ICloningImageProcessor cloningImageProcessor)
+ if (processor.CreatePixelSpecificProcessor(this.source, rectangle) is ICloningImageProcessor cloningImageProcessor)
{
- this.destination = cloningImageProcessor.CloneAndApply(this.source, rectangle);
+ this.destination = cloningImageProcessor.CloneAndApply();
return this;
}
this.destination = this.source.Clone();
}
- processor.Apply(this.destination, rectangle);
+ processor.CreatePixelSpecificProcessor(this.destination, rectangle).Apply();
return this;
}
- private IImageProcessingContext ApplyProcessor(IImageProcessor processor)
- {
- return this.ApplyProcessor(processor, this.GetCurrentBounds());
- }
-
private Rectangle GetCurrentBounds() => this.destination?.Bounds() ?? this.source.Bounds();
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Extensions/GrayscaleExtensions.cs b/src/ImageSharp/Processing/Extensions/GrayscaleExtensions.cs
index a4bfaa516..d87c40226 100644
--- a/src/ImageSharp/Processing/Extensions/GrayscaleExtensions.cs
+++ b/src/ImageSharp/Processing/Extensions/GrayscaleExtensions.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.Processing.Processors;
@@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.Processing
{
IImageProcessor processor = mode == GrayscaleMode.Bt709
? (IImageProcessor)new GrayscaleBt709Processor(amount)
- : new GrayscaleBt601Processor(1F);
+ : new GrayscaleBt601Processor(amount);
source.ApplyProcessor(processor);
return source;
@@ -111,4 +111,4 @@ namespace SixLabors.ImageSharp.Processing
return source;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryErrorDiffusionProcessor.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryErrorDiffusionProcessor.cs
index 840d1c1f4..80164793b 100644
--- a/src/ImageSharp/Processing/Processors/Binarization/BinaryErrorDiffusionProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryErrorDiffusionProcessor.cs
@@ -1,8 +1,9 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Processors.Dithering;
+using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Binarization
{
@@ -69,10 +70,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
public Color LowerColor { get; }
///
- public IImageProcessor CreatePixelSpecificProcessor()
+ public IImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle)
where TPixel : struct, IPixel
- {
- return new BinaryErrorDiffusionProcessor(this);
- }
+ => new BinaryErrorDiffusionProcessor(this, source, sourceRectangle);
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryErrorDiffusionProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryErrorDiffusionProcessor{TPixel}.cs
index e3828aeb6..7e3458ae3 100644
--- a/src/ImageSharp/Processing/Processors/Binarization/BinaryErrorDiffusionProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryErrorDiffusionProcessor{TPixel}.cs
@@ -19,13 +19,20 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
{
private readonly BinaryErrorDiffusionProcessor definition;
- public BinaryErrorDiffusionProcessor(BinaryErrorDiffusionProcessor definition)
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The defining the processor parameters.
+ /// The source for the current processor instance.
+ /// The source area to process for the current processor instance.
+ public BinaryErrorDiffusionProcessor(BinaryErrorDiffusionProcessor definition, Image source, Rectangle sourceRectangle)
+ : base(source, sourceRectangle)
{
this.definition = definition;
}
///
- protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration)
+ protected override void OnFrameApply(ImageFrame source)
{
TPixel upperColor = this.definition.UpperColor.ToPixel();
TPixel lowerColor = this.definition.LowerColor.ToPixel();
@@ -34,7 +41,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
byte threshold = (byte)MathF.Round(this.definition.Threshold * 255F);
bool isAlphaOnly = typeof(TPixel) == typeof(Alpha8);
- var interest = Rectangle.Intersect(sourceRectangle, source.Bounds());
+ var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
int startY = interest.Y;
int endY = interest.Bottom;
int startX = interest.X;
@@ -74,4 +81,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor.cs
index 6cf1a9526..0a426c893 100644
--- a/src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor.cs
@@ -1,10 +1,11 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Processors.Dithering;
+using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Binarization
{
@@ -51,10 +52,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
public Color LowerColor { get; }
///
- public IImageProcessor CreatePixelSpecificProcessor()
+ public IImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle)
where TPixel : struct, IPixel
- {
- return new BinaryOrderedDitherProcessor(this);
- }
+ => new BinaryOrderedDitherProcessor(this, source, sourceRectangle);
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor{TPixel}.cs
index b3d174dfb..e0aae0279 100644
--- a/src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor{TPixel}.cs
@@ -19,13 +19,20 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
{
private readonly BinaryOrderedDitherProcessor definition;
- public BinaryOrderedDitherProcessor(BinaryOrderedDitherProcessor definition)
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The defining the processor parameters.
+ /// The source for the current processor instance.
+ /// The source area to process for the current processor instance.
+ public BinaryOrderedDitherProcessor(BinaryOrderedDitherProcessor definition, Image source, Rectangle sourceRectangle)
+ : base(source, sourceRectangle)
{
this.definition = definition;
}
///
- protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration)
+ protected override void OnFrameApply(ImageFrame source)
{
IOrderedDither dither = this.definition.Dither;
TPixel upperColor = this.definition.UpperColor.ToPixel();
@@ -33,7 +40,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
bool isAlphaOnly = typeof(TPixel) == typeof(Alpha8);
- var interest = Rectangle.Intersect(sourceRectangle, source.Bounds());
+ var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
int startY = interest.Y;
int endY = interest.Bottom;
int startX = interest.X;
@@ -72,4 +79,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs
index 7f00d0219..a33c46469 100644
--- a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs
@@ -1,7 +1,8 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Binarization
{
@@ -49,10 +50,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
public Color LowerColor { get; }
///
- public IImageProcessor CreatePixelSpecificProcessor()
+ public IImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle)
where TPixel : struct, IPixel
- {
- return new BinaryThresholdProcessor(this);
- }
+ => new BinaryThresholdProcessor(this, source, sourceRectangle);
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs
index 0d90d3647..7234955ed 100644
--- a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs
@@ -19,21 +19,28 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
{
private readonly BinaryThresholdProcessor definition;
- public BinaryThresholdProcessor(BinaryThresholdProcessor definition)
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The defining the processor parameters.
+ /// The source for the current processor instance.
+ /// The source area to process for the current processor instance.
+ public BinaryThresholdProcessor(BinaryThresholdProcessor definition, Image source, Rectangle sourceRectangle)
+ : base(source, sourceRectangle)
{
this.definition = definition;
}
///
- protected override void OnFrameApply(
- ImageFrame source,
- Rectangle sourceRectangle,
- Configuration configuration)
+ protected override void OnFrameApply(ImageFrame source)
{
byte threshold = (byte)MathF.Round(this.definition.Threshold * 255F);
TPixel upper = this.definition.UpperColor.ToPixel();
TPixel lower = this.definition.LowerColor.ToPixel();
+ Rectangle sourceRectangle = this.SourceRectangle;
+ Configuration configuration = this.Configuration;
+
var interest = Rectangle.Intersect(sourceRectangle, source.Bounds());
int startY = interest.Y;
int endY = interest.Bottom;
@@ -67,4 +74,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
});
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/CloningImageProcessor.cs b/src/ImageSharp/Processing/Processors/CloningImageProcessor.cs
index 8150d5921..518fdf0cb 100644
--- a/src/ImageSharp/Processing/Processors/CloningImageProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/CloningImageProcessor.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;
@@ -15,32 +15,58 @@ namespace SixLabors.ImageSharp.Processing.Processors
internal abstract class CloningImageProcessor : ICloningImageProcessor
where TPixel : struct, IPixel
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The source for the current processor instance.
+ /// The source area to process for the current processor instance.
+ protected CloningImageProcessor(Image source, Rectangle sourceRectangle)
+ {
+ this.Source = source;
+ this.SourceRectangle = sourceRectangle;
+ this.Configuration = this.Source.GetConfiguration();
+ }
+
+ ///
+ /// Gets The source for the current processor instance.
+ ///
+ protected Image Source { get; }
+
+ ///
+ /// Gets The source area to process for the current processor instance.
+ ///
+ protected Rectangle SourceRectangle { get; }
+
+ ///
+ /// Gets the instance to use when performing operations.
+ ///
+ protected Configuration Configuration { get; }
+
///
- public Image CloneAndApply(Image source, Rectangle sourceRectangle)
+ public Image CloneAndApply()
{
try
{
- Image clone = this.CreateDestination(source, sourceRectangle);
+ Image clone = this.CreateDestination();
- if (clone.Frames.Count != source.Frames.Count)
+ if (clone.Frames.Count != this.Source.Frames.Count)
{
throw new ImageProcessingException($"An error occurred when processing the image using {this.GetType().Name}. The processor changed the number of frames.");
}
- Configuration configuration = source.GetConfiguration();
- this.BeforeImageApply(source, clone, sourceRectangle);
+ this.BeforeImageApply(clone);
- for (int i = 0; i < source.Frames.Count; i++)
+ for (int i = 0; i < this.Source.Frames.Count; i++)
{
- ImageFrame sourceFrame = source.Frames[i];
+ ImageFrame sourceFrame = this.Source.Frames[i];
ImageFrame clonedFrame = clone.Frames[i];
- this.BeforeFrameApply(sourceFrame, clonedFrame, sourceRectangle, configuration);
- this.OnFrameApply(sourceFrame, clonedFrame, sourceRectangle, configuration);
- this.AfterFrameApply(sourceFrame, clonedFrame, sourceRectangle, configuration);
+ this.BeforeFrameApply(sourceFrame, clonedFrame);
+ this.OnFrameApply(sourceFrame, clonedFrame);
+ this.AfterFrameApply(sourceFrame, clonedFrame);
}
- this.AfterImageApply(source, clone, sourceRectangle);
+ this.AfterImageApply(clone);
return clone;
}
@@ -57,40 +83,31 @@ namespace SixLabors.ImageSharp.Processing.Processors
}
///
- public void Apply(Image source, Rectangle sourceRectangle)
+ public void Apply()
{
- using (Image cloned = this.CloneAndApply(source, sourceRectangle))
+ using (Image cloned = this.CloneAndApply())
{
// we now need to move the pixel data/size data from one image base to another
- if (cloned.Frames.Count != source.Frames.Count)
+ if (cloned.Frames.Count != this.Source.Frames.Count)
{
throw new ImageProcessingException($"An error occurred when processing the image using {this.GetType().Name}. The processor changed the number of frames.");
}
- source.SwapOrCopyPixelsBuffersFrom(cloned);
+ this.Source.SwapOrCopyPixelsBuffersFrom(cloned);
}
}
///
/// Generates a deep clone of the source image that operations should be applied to.
///
- /// The source image. Cannot be null.
- /// The source rectangle.
/// The cloned image.
- protected virtual Image CreateDestination(Image source, Rectangle sourceRectangle)
- {
- return source.Clone();
- }
+ protected virtual Image CreateDestination() => this.Source.Clone();
///
/// This method is called before the process is applied to prepare the processor.
///
- /// The source image. Cannot be null.
/// The cloned/destination image. Cannot be null.
- ///
- /// The structure that specifies the portion of the image object to draw.
- ///
- protected virtual void BeforeImageApply(Image source, Image destination, Rectangle sourceRectangle)
+ protected virtual void BeforeImageApply(Image destination)
{
}
@@ -99,9 +116,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
///
/// The source image. Cannot be null.
/// The cloned/destination image. Cannot be null.
- /// The structure that specifies the portion of the image object to draw.
- /// The configuration.
- protected virtual void BeforeFrameApply(ImageFrame source, ImageFrame destination, Rectangle sourceRectangle, Configuration configuration)
+ protected virtual void BeforeFrameApply(ImageFrame source, ImageFrame destination)
{
}
@@ -111,31 +126,23 @@ namespace SixLabors.ImageSharp.Processing.Processors
///
/// The source image. Cannot be null.
/// The cloned/destination image. Cannot be null.
- /// The structure that specifies the portion of the image object to draw.
- /// The configuration.
- protected abstract void OnFrameApply(ImageFrame source, ImageFrame destination, Rectangle sourceRectangle, Configuration configuration);
+ protected abstract void OnFrameApply(ImageFrame source, ImageFrame destination);
///
/// This method is called after the process is applied to prepare the processor.
///
/// The source image. Cannot be null.
/// The cloned/destination image. Cannot be null.
- /// The structure that specifies the portion of the image object to draw.
- /// The configuration.
- protected virtual void AfterFrameApply(ImageFrame source, ImageFrame destination, Rectangle sourceRectangle, Configuration configuration)
+ protected virtual void AfterFrameApply(ImageFrame source, ImageFrame destination)
{
}
///
/// This method is called after the process is applied to prepare the processor.
///
- /// The source image. Cannot be null.
/// The cloned/destination image. Cannot be null.
- ///
- /// The structure that specifies the portion of the image object to draw.
- ///
- protected virtual void AfterImageApply(Image source, Image destination, Rectangle sourceRectangle)
+ protected virtual void AfterImageApply(Image destination)
{
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor.cs
index ede68e319..b7e102deb 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Convolution
{
@@ -112,10 +113,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
public BokehBlurExecutionMode ExecutionMode { get; }
///
- public IImageProcessor CreatePixelSpecificProcessor()
+ public IImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle)
where TPixel : struct, IPixel
{
- return new BokehBlurProcessor(this);
+ return new BokehBlurProcessor(this, source, sourceRectangle);
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs
index a083026c3..9339c8fe4 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs
@@ -75,7 +75,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// Initializes a new instance of the class.
///
/// The defining the processor parameters.
- public BokehBlurProcessor(BokehBlurProcessor definition)
+ /// The source for the current processor instance.
+ /// The source area to process for the current processor instance.
+ public BokehBlurProcessor(BokehBlurProcessor definition, Image source, Rectangle sourceRectangle)
+ : base(source, sourceRectangle)
{
this.radius = definition.Radius;
this.kernelSize = (this.radius * 2) + 1;
@@ -271,36 +274,36 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
}
///
- protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration)
+ protected override void OnFrameApply(ImageFrame source)
{
// Preliminary gamma highlight pass
- this.ApplyGammaExposure(source.PixelBuffer, sourceRectangle, configuration);
+ this.ApplyGammaExposure(source.PixelBuffer, this.SourceRectangle, this.Configuration);
// Create a 0-filled buffer to use to store the result of the component convolutions
- using (Buffer2D processing = configuration.MemoryAllocator.Allocate2D(source.Size(), AllocationOptions.Clean))
+ using (Buffer2D processing = this.Configuration.MemoryAllocator.Allocate2D(source.Size(), AllocationOptions.Clean))
{
if (this.executionMode == BokehBlurExecutionMode.PreferLowMemoryUsage)
{
// Memory usage priority: allocate a shared buffer and execute the second convolution in sequential mode
- using (Buffer2D buffer = configuration.MemoryAllocator.Allocate2D(source.Width, source.Height + this.radius))
+ using (Buffer2D buffer = this.Configuration.MemoryAllocator.Allocate2D(source.Width, source.Height + this.radius))
using (Buffer2D firstPassBuffer = buffer.Slice(this.radius, source.Height))
using (Buffer2D secondPassBuffer = buffer.Slice(0, source.Height))
{
- this.OnFrameApplyCore(source, sourceRectangle, configuration, processing, firstPassBuffer, secondPassBuffer);
+ this.OnFrameApplyCore(source, this.SourceRectangle, this.Configuration, processing, firstPassBuffer, secondPassBuffer);
}
}
else
{
// Performance priority: allocate two independent buffers and execute both convolutions in parallel mode
- using (Buffer2D firstPassValues = configuration.MemoryAllocator.Allocate2D(source.Size()))
- using (Buffer2D secondPassBuffer = configuration.MemoryAllocator.Allocate2D(source.Size()))
+ using (Buffer2D firstPassValues = this.Configuration.MemoryAllocator.Allocate2D(source.Size()))
+ using (Buffer2D secondPassBuffer = this.Configuration.MemoryAllocator.Allocate2D(source.Size()))
{
- this.OnFrameApplyCore(source, sourceRectangle, configuration, processing, firstPassValues, secondPassBuffer);
+ this.OnFrameApplyCore(source, this.SourceRectangle, this.Configuration, processing, firstPassValues, secondPassBuffer);
}
}
// Apply the inverse gamma exposure pass, and write the final pixel data
- this.ApplyInverseGammaExposure(source.PixelBuffer, processing, sourceRectangle, configuration);
+ this.ApplyInverseGammaExposure(source.PixelBuffer, processing, this.SourceRectangle, this.Configuration);
}
}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs
index 726947ac9..a5368c463 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Convolution
{
@@ -40,10 +41,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
public int Radius { get; }
///
- public IImageProcessor CreatePixelSpecificProcessor()
+ public IImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle)
where TPixel : struct, IPixel
{
- return new BoxBlurProcessor(this);
+ return new BoxBlurProcessor(this, source, sourceRectangle);
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor{TPixel}.cs
index f4252e840..b9ca2df0b 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor{TPixel}.cs
@@ -20,7 +20,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// Initializes a new instance of the class.
///
/// The defining the processor parameters.
- public BoxBlurProcessor(BoxBlurProcessor definition)
+ /// The source for the current processor instance.
+ /// The source area to process for the current processor instance.
+ public BoxBlurProcessor(BoxBlurProcessor definition, Image source, Rectangle sourceRectangle)
+ : base(source, sourceRectangle)
{
this.definition = definition;
int kernelSize = (definition.Radius * 2) + 1;
@@ -39,14 +42,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
public DenseMatrix KernelY { get; }
///
- protected override void OnFrameApply(
- ImageFrame source,
- Rectangle sourceRectangle,
- Configuration configuration) =>
- new Convolution2PassProcessor(this.KernelX, this.KernelY, false).Apply(
- source,
- sourceRectangle,
- configuration);
+ protected override void OnFrameApply(ImageFrame source) =>
+ new Convolution2PassProcessor(this.KernelX, this.KernelY, false, this.Source, this.SourceRectangle).Apply(source);
///
/// Create a 1 dimensional Box kernel.
@@ -60,4 +57,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
return kernel;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs
index 299b1d41c..b38d87cd4 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs
@@ -26,7 +26,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// The horizontal gradient operator.
/// The vertical gradient operator.
/// Whether the convolution filter is applied to alpha as well as the color channels.
- public Convolution2DProcessor(in DenseMatrix kernelX, in DenseMatrix kernelY, bool preserveAlpha)
+ /// The source for the current processor instance.
+ /// The source area to process for the current processor instance.
+ public Convolution2DProcessor(
+ in DenseMatrix kernelX,
+ in DenseMatrix kernelY,
+ bool preserveAlpha,
+ Image source,
+ Rectangle sourceRectangle)
+ : base(source, sourceRectangle)
{
Guard.IsTrue(kernelX.Size.Equals(kernelY.Size), $"{nameof(kernelX)} {nameof(kernelY)}", "Kernel sizes must be the same.");
this.KernelX = kernelX;
@@ -50,16 +58,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
public bool PreserveAlpha { get; }
///
- protected override void OnFrameApply(
- ImageFrame source,
- Rectangle sourceRectangle,
- Configuration configuration)
+ protected override void OnFrameApply(ImageFrame source)
{
DenseMatrix matrixY = this.KernelY;
DenseMatrix matrixX = this.KernelX;
bool preserveAlpha = this.PreserveAlpha;
- var interest = Rectangle.Intersect(sourceRectangle, source.Bounds());
+ var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
int startY = interest.Y;
int endY = interest.Bottom;
int startX = interest.X;
@@ -67,7 +72,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
int maxY = endY - 1;
int maxX = endX - 1;
- using (Buffer2D targetPixels = configuration.MemoryAllocator.Allocate2D(source.Width, source.Height))
+ using (Buffer2D targetPixels = this.Configuration.MemoryAllocator.Allocate2D(source.Width, source.Height))
{
source.CopyTo(targetPixels);
@@ -76,7 +81,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
ParallelHelper.IterateRowsWithTempBuffer(
workingRectangle,
- configuration,
+ this.Configuration,
(rows, vectorBuffer) =>
{
Span vectorSpan = vectorBuffer.Span;
@@ -86,7 +91,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
for (int y = rows.Min; y < rows.Max; y++)
{
Span targetRowSpan = targetPixels.GetRowSpan(y).Slice(startX);
- PixelOperations.Instance.ToVector4(configuration, targetRowSpan.Slice(0, length), vectorSpan);
+ PixelOperations.Instance.ToVector4(this.Configuration, targetRowSpan.Slice(0, length), vectorSpan);
if (preserveAlpha)
{
@@ -123,7 +128,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
}
}
- PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan, targetRowSpan);
+ PixelOperations.Instance.FromVector4Destructive(this.Configuration, vectorSpan, targetRowSpan);
}
});
@@ -131,4 +136,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs
index 03268c9dd..a523f7c22 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.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;
@@ -25,10 +25,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// The horizontal gradient operator.
/// The vertical gradient operator.
/// Whether the convolution filter is applied to alpha as well as the color channels.
+ /// The source for the current processor instance.
+ /// The source area to process for the current processor instance.
public Convolution2PassProcessor(
in DenseMatrix kernelX,
in DenseMatrix kernelY,
- bool preserveAlpha)
+ bool preserveAlpha,
+ Image source,
+ Rectangle sourceRectangle)
+ : base(source, sourceRectangle)
{
this.KernelX = kernelX;
this.KernelY = kernelY;
@@ -51,13 +56,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
public bool PreserveAlpha { get; }
///
- protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration)
+ protected override void OnFrameApply(ImageFrame source)
{
- using (Buffer2D firstPassPixels = configuration.MemoryAllocator.Allocate2D(source.Size()))
+ using (Buffer2D firstPassPixels = this.Configuration.MemoryAllocator.Allocate2D(source.Size()))
{
- var interest = Rectangle.Intersect(sourceRectangle, source.Bounds());
- this.ApplyConvolution(firstPassPixels, source.PixelBuffer, interest, this.KernelX, configuration);
- this.ApplyConvolution(source.PixelBuffer, firstPassPixels, interest, this.KernelY, configuration);
+ var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
+ this.ApplyConvolution(firstPassPixels, source.PixelBuffer, interest, this.KernelX, this.Configuration);
+ this.ApplyConvolution(source.PixelBuffer, firstPassPixels, interest, this.KernelY, this.Configuration);
}
}
@@ -144,4 +149,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
});
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs
index 6c3b9a46f..5bdec738d 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.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;
@@ -24,7 +24,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// The 2d gradient operator.
/// Whether the convolution filter is applied to alpha as well as the color channels.
- public ConvolutionProcessor(in DenseMatrix kernelXY, bool preserveAlpha)
+ /// The source for the current processor instance.
+ /// The source area to process for the current processor instance.
+ public ConvolutionProcessor(
+ in DenseMatrix kernelXY,
+ bool preserveAlpha,
+ Image source,
+ Rectangle sourceRectangle)
+ : base(source, sourceRectangle)
{
this.KernelXY = kernelXY;
this.PreserveAlpha = preserveAlpha;
@@ -41,12 +48,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
public bool PreserveAlpha { get; }
///
- protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration)
+ protected override void OnFrameApply(ImageFrame source)
{
DenseMatrix matrix = this.KernelXY;
bool preserveAlpha = this.PreserveAlpha;
- var interest = Rectangle.Intersect(sourceRectangle, source.Bounds());
+ var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
int startY = interest.Y;
int endY = interest.Bottom;
int startX = interest.X;
@@ -54,7 +61,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
int maxY = endY - 1;
int maxX = endX - 1;
- using (Buffer2D targetPixels = configuration.MemoryAllocator.Allocate2D(source.Size()))
+ using (Buffer2D targetPixels = this.Configuration.MemoryAllocator.Allocate2D(source.Size()))
{
source.CopyTo(targetPixels);
@@ -63,7 +70,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
ParallelHelper.IterateRowsWithTempBuffer(
workingRectangle,
- configuration,
+ this.Configuration,
(rows, vectorBuffer) =>
{
Span vectorSpan = vectorBuffer.Span;
@@ -73,7 +80,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
for (int y = rows.Min; y < rows.Max; y++)
{
Span targetRowSpan = targetPixels.GetRowSpan(y).Slice(startX);
- PixelOperations.Instance.ToVector4(configuration, targetRowSpan.Slice(0, length), vectorSpan);
+ PixelOperations.Instance.ToVector4(this.Configuration, targetRowSpan.Slice(0, length), vectorSpan);
if (preserveAlpha)
{
@@ -108,7 +115,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
}
}
- PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan, targetRowSpan);
+ PixelOperations.Instance.FromVector4Destructive(this.Configuration, vectorSpan, targetRowSpan);
}
});
@@ -116,4 +123,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs
index f6771288f..26a789cfc 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.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;
@@ -21,7 +21,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// The horizontal gradient operator.
/// The vertical gradient operator.
/// Whether to convert the image to grayscale before performing edge detection.
- internal EdgeDetector2DProcessor(in DenseMatrix kernelX, in DenseMatrix kernelY, bool grayscale)
+ /// The source for the current processor instance.
+ /// The source area to process for the current processor instance.
+ internal EdgeDetector2DProcessor(
+ in DenseMatrix kernelX,
+ in DenseMatrix kernelY,
+ bool grayscale,
+ Image source,
+ Rectangle sourceRectangle)
+ : base(source, sourceRectangle)
{
Guard.IsTrue(kernelX.Size.Equals(kernelY.Size), $"{nameof(kernelX)} {nameof(kernelY)}", "Kernel sizes must be the same.");
this.KernelX = kernelX;
@@ -41,17 +49,17 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
public bool Grayscale { get; }
- ///
- protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration)
- => new Convolution2DProcessor(this.KernelX, this.KernelY, true).Apply(source, sourceRectangle, configuration);
-
///
- protected override void BeforeFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration)
+ protected override void BeforeImageApply()
{
if (this.Grayscale)
{
- new GrayscaleBt709Processor(1F).Apply(source, sourceRectangle, configuration);
+ new GrayscaleBt709Processor(1F).Apply(this.Source, this.SourceRectangle);
}
}
+
+ ///
+ protected override void OnFrameApply(ImageFrame source)
+ => new Convolution2DProcessor(this.KernelX, this.KernelY, true, this.Source, this.SourceRectangle).Apply(source);
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs
index 5995ac844..543014f6f 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.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;
@@ -27,7 +27,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// Gets the kernels to use.
/// Whether to convert the image to grayscale before performing edge detection.
- internal EdgeDetectorCompassProcessor(CompassKernels kernels, bool grayscale)
+ /// The source for the current processor instance.
+ /// The source area to process for the current processor instance.
+ internal EdgeDetectorCompassProcessor(CompassKernels kernels, bool grayscale, Image source, Rectangle sourceRectangle)
+ : base(source, sourceRectangle)
{
this.Grayscale = grayscale;
this.Kernels = kernels;
@@ -38,23 +41,23 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private bool Grayscale { get; }
///
- protected override void BeforeFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration)
+ protected override void BeforeImageApply()
{
if (this.Grayscale)
{
- new GrayscaleBt709Processor(1F).Apply(source, sourceRectangle, configuration);
+ new GrayscaleBt709Processor(1F).Apply(this.Source, this.SourceRectangle);
}
}
///
- protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration)
+ protected override void OnFrameApply(ImageFrame source)
{
DenseMatrix[] kernels = this.Kernels.Flatten();
- int startY = sourceRectangle.Y;
- int endY = sourceRectangle.Bottom;
- int startX = sourceRectangle.X;
- int endX = sourceRectangle.Right;
+ int startY = this.SourceRectangle.Y;
+ int endY = this.SourceRectangle.Bottom;
+ int startX = this.SourceRectangle.X;
+ int endX = this.SourceRectangle.Right;
// Align start/end positions.
int minX = Math.Max(0, startX);
@@ -65,7 +68,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
// we need a clean copy for each pass to start from
using (ImageFrame cleanCopy = source.Clone())
{
- new ConvolutionProcessor(kernels[0], true).Apply(source, sourceRectangle, configuration);
+ new ConvolutionProcessor(kernels[0], true, this.Source, this.SourceRectangle).Apply(source);
if (kernels.Length == 1)
{
@@ -94,14 +97,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
{
using (ImageFrame pass = cleanCopy.Clone())
{
- new ConvolutionProcessor(kernels[i], true).Apply(pass, sourceRectangle, configuration);
+ new ConvolutionProcessor(kernels[i], true, this.Source, this.SourceRectangle).Apply(pass);
Buffer2D passPixels = pass.PixelBuffer;
Buffer2D targetPixels = source.PixelBuffer;
ParallelHelper.IterateRows(
workingRect,
- configuration,
+ this.Configuration,
rows =>
{
for (int y = rows.Min; y < rows.Max; y++)
@@ -132,4 +135,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs
index 75be15bcc..24b95da69 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs
@@ -1,7 +1,8 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Convolution
{
@@ -25,7 +26,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
public bool Grayscale { get; }
///
- public abstract IImageProcessor CreatePixelSpecificProcessor()
+ public abstract IImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle)
where TPixel : struct, IPixel;
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs
index 041c54803..7ee9d6829 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs
@@ -20,7 +20,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// The 2d gradient operator.
/// Whether to convert the image to grayscale before performing edge detection.
- public EdgeDetectorProcessor(in DenseMatrix kernelXY, bool grayscale)
+ /// The source for the current processor instance.
+ /// The target area to process for the current processor instance.
+ public EdgeDetectorProcessor(in DenseMatrix kernelXY, bool grayscale, Image source, Rectangle sourceRectangle)
+ : base(source, sourceRectangle)
{
this.KernelXY = kernelXY;
this.Grayscale = grayscale;
@@ -34,16 +37,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
public DenseMatrix KernelXY { get; }
///
- protected override void BeforeFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration)
+ protected override void BeforeImageApply()
{
if (this.Grayscale)
{
- new GrayscaleBt709Processor(1F).Apply(source, sourceRectangle, configuration);
+ new GrayscaleBt709Processor(1F).Apply(this.Source, this.SourceRectangle);
}
}
///
- protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration)
- => new ConvolutionProcessor(this.KernelXY, true).Apply(source, sourceRectangle, configuration);
+ protected override void OnFrameApply(ImageFrame source)
+ => new ConvolutionProcessor(this.KernelXY, true, this.Source, this.SourceRectangle).Apply(source);
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs
index 8504db161..aabc8041d 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs
@@ -1,7 +1,8 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Convolution
{
@@ -70,10 +71,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
public int Radius { get; }
///
- public IImageProcessor CreatePixelSpecificProcessor()
+ public IImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle)
where TPixel : struct, IPixel
{
- return new GaussianBlurProcessor(this);
+ return new GaussianBlurProcessor