diff --git a/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor{TPixel}.cs
index 7423fdbfe..a9b91e837 100644
--- a/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor{TPixel}.cs
@@ -3,6 +3,7 @@
using System;
using System.Buffers;
+using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
@@ -27,9 +28,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
/// The source area to process for the current processor instance.
public BackgroundColorProcessor(Configuration configuration, BackgroundColorProcessor definition, Image source, Rectangle sourceRectangle)
: base(configuration, source, sourceRectangle)
- {
- this.definition = definition;
- }
+ => this.definition = definition;
///
protected override void OnFrameApply(ImageFrame source)
@@ -37,65 +36,69 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
TPixel color = this.definition.Color.ToPixel();
GraphicsOptions graphicsOptions = this.definition.GraphicsOptions;
- int startY = this.SourceRectangle.Y;
- int endY = this.SourceRectangle.Bottom;
- int startX = this.SourceRectangle.X;
- int endX = this.SourceRectangle.Right;
+ var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
- // Align start/end positions.
- int minX = Math.Max(0, startX);
- int maxX = Math.Min(source.Width, endX);
- int minY = Math.Max(0, startY);
- int maxY = Math.Min(source.Height, endY);
+ Configuration configuration = this.Configuration;
+ MemoryAllocator memoryAllocator = configuration.MemoryAllocator;
- // Reset offset if necessary.
- if (minX > 0)
- {
- startX = 0;
- }
+ using IMemoryOwner colors = memoryAllocator.Allocate(interest.Width);
+ using IMemoryOwner amount = memoryAllocator.Allocate(interest.Width);
- if (minY > 0)
- {
- startY = 0;
- }
+ colors.GetSpan().Fill(color);
+ amount.GetSpan().Fill(graphicsOptions.BlendPercentage);
- int width = maxX - minX;
+ PixelBlender blender = PixelOperations.Instance.GetPixelBlender(graphicsOptions);
- var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY);
- Configuration configuration = this.Configuration;
- MemoryAllocator memoryAllocator = configuration.MemoryAllocator;
-
- using (IMemoryOwner colors = memoryAllocator.Allocate(width))
- using (IMemoryOwner amount = memoryAllocator.Allocate(width))
- {
- // Be careful! Do not capture colorSpan & amountSpan in the lambda below!
- Span colorSpan = colors.GetSpan();
- Span amountSpan = amount.GetSpan();
+ ParallelRowIterator.IterateRows(
+ interest,
+ configuration,
+ new RowIntervalAction(configuration, interest, blender, amount, colors, source));
+ }
- colorSpan.Fill(color);
- amountSpan.Fill(graphicsOptions.BlendPercentage);
+ private readonly struct RowIntervalAction : IRowIntervalAction
+ {
+ private readonly Configuration configuration;
+ private readonly Rectangle bounds;
+ private readonly PixelBlender blender;
+ private readonly IMemoryOwner amount;
+ private readonly IMemoryOwner colors;
+ private readonly ImageFrame source;
- PixelBlender blender = PixelOperations.Instance.GetPixelBlender(graphicsOptions);
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public RowIntervalAction(
+ Configuration configuration,
+ Rectangle bounds,
+ PixelBlender blender,
+ IMemoryOwner amount,
+ IMemoryOwner colors,
+ ImageFrame source)
+ {
+ this.configuration = configuration;
+ this.bounds = bounds;
+ this.blender = blender;
+ this.amount = amount;
+ this.colors = colors;
+ this.source = source;
+ }
- ParallelRowIterator.IterateRows(
- workingRect,
- configuration,
- rows =>
- {
- for (int y = rows.Min; y < rows.Max; y++)
- {
- Span destination =
- source.GetPixelRowSpan(y - startY).Slice(minX - startX, width);
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void Invoke(in RowInterval rows)
+ {
+ for (int y = rows.Min; y < rows.Max; y++)
+ {
+ Span destination =
+ this.source.GetPixelRowSpan(y)
+ .Slice(this.bounds.X, this.bounds.Width);
- // This switched color & destination in the 2nd and 3rd places because we are applying the target color under the current one
- blender.Blend(
- configuration,
- destination,
- colors.GetSpan(),
- destination,
- amount.GetSpan());
- }
- });
+ // Switch color & destination in the 2nd and 3rd places because we are
+ // applying the target color under the current one.
+ this.blender.Blend(
+ this.configuration,
+ destination,
+ this.colors.GetSpan(),
+ destination,
+ this.amount.GetSpan());
+ }
}
}
}