|
|
|
@ -7,6 +7,7 @@ using System.Numerics; |
|
|
|
using System.Threading.Tasks; |
|
|
|
using SixLabors.ImageSharp.Advanced; |
|
|
|
using SixLabors.ImageSharp.Memory; |
|
|
|
using SixLabors.ImageSharp.ParallelUtils; |
|
|
|
using SixLabors.ImageSharp.PixelFormats; |
|
|
|
using SixLabors.ImageSharp.Primitives; |
|
|
|
using SixLabors.Memory; |
|
|
|
@ -84,6 +85,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays |
|
|
|
/// <inheritdoc/>
|
|
|
|
protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration) |
|
|
|
{ |
|
|
|
// TODO: can we simplify the rectangle calculation?
|
|
|
|
|
|
|
|
int startY = sourceRectangle.Y; |
|
|
|
int endY = sourceRectangle.Bottom; |
|
|
|
int startX = sourceRectangle.X; |
|
|
|
@ -113,36 +116,43 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays |
|
|
|
} |
|
|
|
|
|
|
|
int width = maxX - minX; |
|
|
|
int offsetX = minX - startX; |
|
|
|
|
|
|
|
var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); |
|
|
|
|
|
|
|
using (IMemoryOwner<TPixel> rowColors = source.MemoryAllocator.Allocate<TPixel>(width)) |
|
|
|
{ |
|
|
|
// Be careful! Do not capture rowColorsSpan in the lambda below!
|
|
|
|
Span<TPixel> rowColorsSpan = rowColors.GetSpan(); |
|
|
|
rowColors.GetSpan().Fill(glowColor); |
|
|
|
|
|
|
|
for (int i = 0; i < width; i++) |
|
|
|
{ |
|
|
|
rowColorsSpan[i] = glowColor; |
|
|
|
} |
|
|
|
|
|
|
|
ParallelFor.WithTemporaryBuffer<float>( |
|
|
|
minY, |
|
|
|
maxY, |
|
|
|
ParallelHelper.IterateRowsWithTempBuffer<float>( |
|
|
|
workingRect, |
|
|
|
configuration, |
|
|
|
width, |
|
|
|
(y, amounts) => |
|
|
|
{ |
|
|
|
Span<float> amountsSpan = amounts.GetSpan(); |
|
|
|
int offsetY = y - startY; |
|
|
|
int offsetX = minX - startX; |
|
|
|
for (int i = 0; i < width; i++) |
|
|
|
(rows, amounts) => |
|
|
|
{ |
|
|
|
float distance = Vector2.Distance(center, new Vector2(i + offsetX, offsetY)); |
|
|
|
amountsSpan[i] = (this.GraphicsOptions.BlendPercentage * (1 - (.95F * (distance / maxDistance)))).Clamp(0, 1); |
|
|
|
} |
|
|
|
|
|
|
|
Span<TPixel> destination = source.GetPixelRowSpan(offsetY).Slice(offsetX, width); |
|
|
|
|
|
|
|
this.blender.Blend(source.MemoryAllocator, destination, destination, rowColors.GetSpan(), amountsSpan); |
|
|
|
}); |
|
|
|
Span<float> 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] = |
|
|
|
(this.GraphicsOptions.BlendPercentage * (1 - (.95F * (distance / maxDistance)))) |
|
|
|
.Clamp(0, 1); |
|
|
|
} |
|
|
|
|
|
|
|
Span<TPixel> destination = source.GetPixelRowSpan(offsetY).Slice(offsetX, width); |
|
|
|
|
|
|
|
this.blender.Blend( |
|
|
|
source.MemoryAllocator, |
|
|
|
destination, |
|
|
|
destination, |
|
|
|
rowColors.GetSpan(), |
|
|
|
amountsSpan); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|