Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.

using System.Numerics;
using SixLabors.ImageSharp.PixelFormats;

namespace SixLabors.ImageSharp
{
/// <summary>
/// Extensions methods fpor the <see cref="GraphicsOptions"/> class.
/// </summary>
internal static class GraphicsOptionsExtensions
{
/// <summary>
/// Evaluates if a given SOURCE color can completely replace a BACKDROP color given the current blending and composition settings.
/// </summary>
/// <param name="options">The graphics options.</param>
/// <param name="color">The source color.</param>
/// <returns>true if the color can be considered opaque</returns>
/// <remarks>
/// Blending and composition is an expensive operation, in some cases, like
/// filling with a solid color, the blending can be avoided by a plain color replacement.
/// This method can be useful for such processors to select the fast path.
/// </remarks>
public static bool IsOpaqueColorWithoutBlending(this GraphicsOptions options, Color color)
{
if (options.ColorBlendingMode != PixelColorBlendingMode.Normal)
{
return false;
}

if (options.AlphaCompositionMode != PixelAlphaCompositionMode.SrcOver
&& options.AlphaCompositionMode != PixelAlphaCompositionMode.Src)
{
return false;
}

const float Opaque = 1F;

if (options.BlendPercentage != Opaque)
{
return false;
}

if (((Vector4)color).W != Opaque)
{
return false;
}

return true;
}
}
}
6 changes: 3 additions & 3 deletions src/ImageSharp.Drawing/Primitives/ShapeRegion.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -49,7 +49,7 @@ public override int Scan(float y, Span<float> buffer, Configuration configuratio

using (IMemoryOwner<PointF> tempBuffer = configuration.MemoryAllocator.Allocate<PointF>(buffer.Length))
{
Span<PointF> innerBuffer = tempBuffer.GetSpan();
Span<PointF> innerBuffer = tempBuffer.Memory.Span;
int count = this.Shape.FindIntersections(start, end, innerBuffer);

for (int i = 0; i < count; i++)
Expand All @@ -61,4 +61,4 @@ public override int Scan(float y, Span<float> buffer, Configuration configuratio
}
}
}
}
}
6 changes: 3 additions & 3 deletions src/ImageSharp.Drawing/Processing/BrushApplicator.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -71,8 +71,8 @@ internal virtual void Apply(Span<float> scanline, int x, int y)
using (IMemoryOwner<float> amountBuffer = memoryAllocator.Allocate<float>(scanline.Length))
using (IMemoryOwner<TPixel> overlay = memoryAllocator.Allocate<TPixel>(scanline.Length))
{
Span<float> amountSpan = amountBuffer.GetSpan();
Span<TPixel> overlaySpan = overlay.GetSpan();
Span<float> amountSpan = amountBuffer.Memory.Span;
Span<TPixel> overlaySpan = overlay.Memory.Span;

for (int i = 0; i < scanline.Length; i++)
{
Expand Down
21 changes: 7 additions & 14 deletions src/ImageSharp.Drawing/Processing/GradientBrush.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -92,10 +92,10 @@ protected GradientBrushApplicator(
// onLocalGradient = Math.Min(0, Math.Max(1, onLocalGradient));
break;
case GradientRepetitionMode.Repeat:
positionOnCompleteGradient = positionOnCompleteGradient % 1;
positionOnCompleteGradient %= 1;
break;
case GradientRepetitionMode.Reflect:
positionOnCompleteGradient = positionOnCompleteGradient % 2;
positionOnCompleteGradient %= 2;
if (positionOnCompleteGradient > 1)
{
positionOnCompleteGradient = 2 - positionOnCompleteGradient;
Expand All @@ -121,19 +121,12 @@ protected GradientBrushApplicator(
}
else
{
var fromAsVector = from.Color.ToVector4();
var toAsVector = to.Color.ToVector4();
float onLocalGradient = (positionOnCompleteGradient - from.Ratio) / (to.Ratio - from.Ratio);

// TODO: this should be changeble for different gradienting functions
Vector4 result = PorterDuffFunctions.NormalSrcOver(
fromAsVector,
toAsVector,
onLocalGradient);

TPixel resultColor = default;
resultColor.FromVector4(result);
return resultColor;
return PixelOperations<TPixel>
.Instance.GetPixelBlender(PixelColorBlendingMode.Normal, PixelAlphaCompositionMode.SrcOver)
.Blend(from.Color.ToPixel<TPixel>(), to.Color.ToPixel<TPixel>(), onLocalGradient);
}
}
}
Expand Down Expand Up @@ -176,4 +169,4 @@ protected GradientBrushApplicator(
}
}
}
}
}
8 changes: 4 additions & 4 deletions src/ImageSharp.Drawing/Processing/ImageBrush.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -140,8 +140,8 @@ internal override void Apply(Span<float> scanline, int x, int y)
using (IMemoryOwner<float> amountBuffer = this.Target.MemoryAllocator.Allocate<float>(scanline.Length))
using (IMemoryOwner<TPixel> overlay = this.Target.MemoryAllocator.Allocate<TPixel>(scanline.Length))
{
Span<float> amountSpan = amountBuffer.GetSpan();
Span<TPixel> overlaySpan = overlay.GetSpan();
Span<float> amountSpan = amountBuffer.Memory.Span;
Span<TPixel> overlaySpan = overlay.Memory.Span;

int sourceY = (y - this.offsetY) % this.yLength;
int offsetX = x - this.offsetX;
Expand All @@ -167,4 +167,4 @@ internal override void Apply(Span<float> scanline, int x, int y)
}
}
}
}
}
8 changes: 4 additions & 4 deletions src/ImageSharp.Drawing/Processing/PathGradientBrush.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ private static Color CalculateCenterColor(Color[] colors)
"One or more color is needed to construct a path gradient brush.");
}

return new Color(colors.Select(c => c.ToVector4()).Aggregate((p1, p2) => p1 + p2) / colors.Length);
return new Color(colors.Select(c => (Vector4)c).Aggregate((p1, p2) => p1 + p2) / colors.Length);
}

private static float DistanceBetween(PointF p1, PointF p2) => ((Vector2)(p2 - p1)).Length();
Expand Down Expand Up @@ -141,10 +141,10 @@ public Edge(Path path, Color startColor, Color endColor)
Vector2[] points = path.LineSegments.SelectMany(s => s.Flatten()).Select(p => (Vector2)p).ToArray();

this.Start = points.First();
this.StartColor = startColor.ToVector4();
this.StartColor = (Vector4)startColor;

this.End = points.Last();
this.EndColor = endColor.ToVector4();
this.EndColor = (Vector4)endColor;

this.length = DistanceBetween(this.End, this.Start);
this.buffer = new PointF[this.path.MaxIntersections];
Expand Down Expand Up @@ -215,7 +215,7 @@ public PathGradientBrushApplicator(
PointF[] points = edges.Select(s => s.Start).ToArray();

this.center = points.Aggregate((p1, p2) => p1 + p2) / edges.Count;
this.centerColor = centerColor.ToVector4();
this.centerColor = (Vector4)centerColor;

this.maxDistance = points.Select(p => (Vector2)(p - this.center)).Select(d => d.Length()).Max();
}
Expand Down
12 changes: 6 additions & 6 deletions src/ImageSharp.Drawing/Processing/PatternBrush.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -61,8 +61,8 @@ public PatternBrush(Color foreColor, Color backColor, bool[,] pattern)
/// <param name="pattern">The pattern.</param>
internal PatternBrush(Color foreColor, Color backColor, in DenseMatrix<bool> pattern)
{
var foreColorVector = foreColor.ToVector4();
var backColorVector = backColor.ToVector4();
var foreColorVector = (Vector4)foreColor;
var backColorVector = (Vector4)backColor;
this.pattern = new DenseMatrix<Color>(pattern.Columns, pattern.Rows);
this.patternVector = new DenseMatrix<Vector4>(pattern.Columns, pattern.Rows);
for (int i = 0; i < pattern.Data.Length; i++)
Expand Down Expand Up @@ -159,8 +159,8 @@ internal override void Apply(Span<float> scanline, int x, int y)
using (IMemoryOwner<float> amountBuffer = memoryAllocator.Allocate<float>(scanline.Length))
using (IMemoryOwner<TPixel> overlay = memoryAllocator.Allocate<TPixel>(scanline.Length))
{
Span<float> amountSpan = amountBuffer.GetSpan();
Span<TPixel> overlaySpan = overlay.GetSpan();
Span<float> amountSpan = amountBuffer.Memory.Span;
Span<TPixel> overlaySpan = overlay.Memory.Span;

for (int i = 0; i < scanline.Length; i++)
{
Expand All @@ -181,4 +181,4 @@ internal override void Apply(Span<float> scanline, int x, int y)
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ protected override void OnFrameApply(ImageFrame<TPixel> source)
sourceRectangle,
options))
{
amount.GetSpan().Fill(1f);
amount.Memory.Span.Fill(1f);

ParallelHelper.IterateRows(
workingRect,
Expand All @@ -100,7 +100,7 @@ protected override void OnFrameApply(ImageFrame<TPixel> source)
int offsetY = y - startY;
int offsetX = minX - startX;

applicator.Apply(amount.GetSpan(), offsetX, offsetY);
applicator.Apply(amount.Memory.Span, offsetX, offsetY);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ protected override void OnFrameApply(ImageFrame<TPixel> source)
float subpixelFraction = 1f / subpixelCount;
float subpixelFractionPoint = subpixelFraction / subpixelCount;

Span<float> buffer = bBuffer.GetSpan();
Span<float> scanline = bScanline.GetSpan();
Span<float> buffer = bBuffer.Memory.Span;
Span<float> scanline = bScanline.Memory.Span;

bool isSolidBrushWithoutBlending = this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush);
TPixel solidBrushColor = isSolidBrushWithoutBlending ? solidBrush.Color.ToPixel<TPixel>() : default;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ private Buffer2D<float> Render(IPath path)
{
float subpixelFraction = 1f / subpixelCount;
float subpixelFractionPoint = subpixelFraction / subpixelCount;
Span<PointF> intersectionSpan = rowIntersectionBuffer.Memory.Span;
Span<float> buffer = bufferBacking.Memory.Span;

for (int y = 0; y <= size.Height; y++)
{
Expand All @@ -337,8 +339,6 @@ private Buffer2D<float> Render(IPath path)
{
var start = new PointF(path.Bounds.Left - 1, subPixel);
var end = new PointF(path.Bounds.Right + 1, subPixel);
Span<PointF> intersectionSpan = rowIntersectionBuffer.GetSpan();
Span<float> buffer = bufferBacking.GetSpan();
int pointsFound = path.FindIntersections(start, end, intersectionSpan);

if (pointsFound == 0)
Expand Down
8 changes: 4 additions & 4 deletions src/ImageSharp.Drawing/Processing/RecolorBrush.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -151,8 +151,8 @@ internal override void Apply(Span<float> scanline, int x, int y)
using (IMemoryOwner<float> amountBuffer = memoryAllocator.Allocate<float>(scanline.Length))
using (IMemoryOwner<TPixel> overlay = memoryAllocator.Allocate<TPixel>(scanline.Length))
{
Span<float> amountSpan = amountBuffer.GetSpan();
Span<TPixel> overlaySpan = overlay.GetSpan();
Span<float> amountSpan = amountBuffer.Memory.Span;
Span<TPixel> overlaySpan = overlay.Memory.Span;

for (int i = 0; i < scanline.Length; i++)
{
Expand All @@ -176,4 +176,4 @@ internal override void Apply(Span<float> scanline, int x, int y)
}
}
}
}
}
14 changes: 7 additions & 7 deletions src/ImageSharp.Drawing/Processing/SolidBrush.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -62,7 +62,7 @@ public SolidBrushApplicator(ImageFrame<TPixel> source, TPixel color, GraphicsOpt
: base(source, options)
{
this.Colors = source.MemoryAllocator.Allocate<TPixel>(source.Width);
this.Colors.GetSpan().Fill(color);
this.Colors.Memory.Span.Fill(color);
}

/// <summary>
Expand All @@ -78,7 +78,7 @@ public SolidBrushApplicator(ImageFrame<TPixel> source, TPixel color, GraphicsOpt
/// <returns>
/// The color
/// </returns>
internal override TPixel this[int x, int y] => this.Colors.GetSpan()[x];
internal override TPixel this[int x, int y] => this.Colors.Memory.Span[x];

/// <inheritdoc />
public override void Dispose()
Expand Down Expand Up @@ -106,13 +106,13 @@ internal override void Apply(Span<float> scanline, int x, int y)

if (this.Options.BlendPercentage == 1f)
{
this.Blender.Blend(configuration, destinationRow, destinationRow, this.Colors.GetSpan(), scanline);
this.Blender.Blend(configuration, destinationRow, destinationRow, this.Colors.Memory.Span, scanline);
}
else
{
using (IMemoryOwner<float> amountBuffer = memoryAllocator.Allocate<float>(scanline.Length))
{
Span<float> amountSpan = amountBuffer.GetSpan();
Span<float> amountSpan = amountBuffer.Memory.Span;

for (int i = 0; i < scanline.Length; i++)
{
Expand All @@ -123,11 +123,11 @@ internal override void Apply(Span<float> scanline, int x, int y)
configuration,
destinationRow,
destinationRow,
this.Colors.GetSpan(),
this.Colors.Memory.Span,
amountSpan);
}
}
}
}
}
}
}
Loading