diff --git a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs
index 0271caa5d..ce677c515 100644
--- a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs
@@ -4,6 +4,7 @@
using System;
using System.Buffers;
using System.Numerics;
+using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
@@ -37,78 +38,83 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
///
protected override void OnFrameApply(ImageFrame source)
{
- // TODO: can we simplify the rectangle calculation?
- int startY = this.SourceRectangle.Y;
- int endY = this.SourceRectangle.Bottom;
- int startX = this.SourceRectangle.X;
- int endX = this.SourceRectangle.Right;
TPixel glowColor = this.definition.GlowColor.ToPixel();
- Vector2 center = Rectangle.Center(this.SourceRectangle);
+ float blendPercent = this.definition.GraphicsOptions.BlendPercentage;
- float finalRadius = this.definition.Radius.Calculate(source.Size());
+ var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
+ Vector2 center = Rectangle.Center(interest);
+ float finalRadius = this.definition.Radius.Calculate(interest.Size);
float maxDistance = finalRadius > 0
- ? MathF.Min(finalRadius, this.SourceRectangle.Width * .5F)
- : this.SourceRectangle.Width * .5F;
+ ? MathF.Min(finalRadius, interest.Width * .5F)
+ : interest.Width * .5F;
- // 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 allocator = configuration.MemoryAllocator;
- // Reset offset if necessary.
- if (minX > 0)
- {
- startX = 0;
- }
+ using IMemoryOwner rowColors = allocator.Allocate(interest.Width);
+ rowColors.GetSpan().Fill(glowColor);
+
+ ParallelRowIterator.IterateRows(
+ interest,
+ configuration,
+ new RowIntervalAction(configuration, interest, rowColors, this.blender, center, maxDistance, blendPercent, source));
+ }
- if (minY > 0)
+ private readonly struct RowIntervalAction : IRowIntervalAction
+ {
+ private readonly Configuration configuration;
+ private readonly Rectangle bounds;
+ private readonly PixelBlender blender;
+ private readonly Vector2 center;
+ private readonly float maxDistance;
+ private readonly float blendPercent;
+ private readonly IMemoryOwner colors;
+ private readonly ImageFrame source;
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public RowIntervalAction(
+ Configuration configuration,
+ Rectangle bounds,
+ IMemoryOwner colors,
+ PixelBlender blender,
+ Vector2 center,
+ float maxDistance,
+ float blendPercent,
+ ImageFrame source)
{
- startY = 0;
+ this.configuration = configuration;
+ this.bounds = bounds;
+ this.colors = colors;
+ this.blender = blender;
+ this.center = center;
+ this.maxDistance = maxDistance;
+ this.blendPercent = blendPercent;
+ this.source = source;
}
- int width = maxX - minX;
- int offsetX = minX - startX;
-
- var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY);
-
- float blendPercentage = this.definition.GraphicsOptions.BlendPercentage;
- Configuration configuration = this.Configuration;
- MemoryAllocator memoryAllocator = configuration.MemoryAllocator;
-
- using (IMemoryOwner rowColors = memoryAllocator.Allocate(width))
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void Invoke(in RowInterval rows, Memory memory)
{
- rowColors.GetSpan().Fill(glowColor);
-
- ParallelRowIterator.IterateRows(
- workingRect,
- configuration,
- (rows, amounts) =>
- {
- Span amountsSpan = amounts.Span;
-
- for (int y = rows.Min; y < rows.Max; y++)
- {
- int offsetY = y - startY;
-
- for (int i = 0; i < width; i++)
- {
- float distance = Vector2.Distance(center, new Vector2(i + offsetX, offsetY));
- amountsSpan[i] =
- (blendPercentage * (1 - (.95F * (distance / maxDistance)))).Clamp(0, 1);
- }
-
- Span destination = source.GetPixelRowSpan(offsetY).Slice(offsetX, width);
-
- this.blender.Blend(
- configuration,
- destination,
- destination,
- rowColors.GetSpan(),
- amountsSpan);
- }
- });
+ Span amountsSpan = memory.Span;
+
+ for (int y = rows.Min; y < rows.Max; y++)
+ {
+ for (int i = 0; i < this.bounds.Width; i++)
+ {
+ float distance = Vector2.Distance(this.center, new Vector2(i + this.bounds.X, y));
+ amountsSpan[i] = (this.blendPercent * (1 - (.95F * (distance / this.maxDistance)))).Clamp(0, 1);
+ }
+
+ Span destination = this.source.GetPixelRowSpan(y).Slice(this.bounds.X, this.bounds.Width);
+
+ this.blender.Blend(
+ this.configuration,
+ destination,
+ destination,
+ this.colors.GetSpan(),
+ amountsSpan);
+ }
}
}
}