diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj
index d4caadce7..9a766c559 100644
--- a/src/Artemis.Core/Artemis.Core.csproj
+++ b/src/Artemis.Core/Artemis.Core.csproj
@@ -12,7 +12,6 @@
ArtemisRGB.Core
1
enable
- true
diff --git a/src/Artemis.Core/ColorScience/Quantization/ColorCube.cs b/src/Artemis.Core/ColorScience/Quantization/ColorCube.cs
index 0bfc2fe59..5b7b353a0 100644
--- a/src/Artemis.Core/ColorScience/Quantization/ColorCube.cs
+++ b/src/Artemis.Core/ColorScience/Quantization/ColorCube.cs
@@ -1,6 +1,7 @@
using SkiaSharp;
using System;
using System.Numerics;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Artemis.Core.ColorScience;
@@ -19,7 +20,7 @@ internal readonly struct ColorRanges
}
}
-internal class ColorCube
+internal readonly struct ColorCube
{
private const int BYTES_PER_COLOR = 4;
private static readonly int ELEMENTS_PER_VECTOR = Vector.Count / BYTES_PER_COLOR;
@@ -27,19 +28,16 @@ internal class ColorCube
private readonly int _from;
private readonly int _length;
- private SortTarget _currentOrder = SortTarget.None;
+ private readonly SortTarget _currentOrder = SortTarget.None;
public ColorCube(in Span fullColorList, int from, int length, SortTarget preOrdered)
{
this._from = from;
this._length = length;
- OrderColors(fullColorList.Slice(from, length), preOrdered);
- }
+ if (length < 2) return;
- private void OrderColors(in Span colors, SortTarget preOrdered)
- {
- if (colors.Length < 2) return;
+ Span colors = fullColorList.Slice(from, length);
ColorRanges colorRanges = GetColorRanges(colors);
if ((colorRanges.RedRange > colorRanges.GreenRange) && (colorRanges.RedRange > colorRanges.BlueRange))
@@ -65,29 +63,21 @@ internal class ColorCube
}
}
- private unsafe ColorRanges GetColorRanges(in ReadOnlySpan colors)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private ColorRanges GetColorRanges(in ReadOnlySpan colors)
{
if (Vector.IsHardwareAccelerated && (colors.Length >= Vector.Count))
{
int chunks = colors.Length / ELEMENTS_PER_VECTOR;
- int missingElements = colors.Length - (chunks * ELEMENTS_PER_VECTOR);
+ int vectorElements = (chunks * ELEMENTS_PER_VECTOR);
+ int missingElements = colors.Length - vectorElements;
Vector max = Vector.Zero;
Vector min = new(byte.MaxValue);
-
- ReadOnlySpan colorBytes = MemoryMarshal.AsBytes(colors);
- fixed (byte* colorPtr = &MemoryMarshal.GetReference(colorBytes))
+ foreach (Vector currentVector in MemoryMarshal.Cast>(colors[..vectorElements]))
{
- byte* current = colorPtr;
- for (int i = 0; i < chunks; i++)
- {
- Vector currentVector = *(Vector*)current;
-
- max = Vector.Max(max, currentVector);
- min = Vector.Min(min, currentVector);
-
- current += BYTES_PER_VECTOR;
- }
+ max = Vector.Max(max, currentVector);
+ min = Vector.Min(min, currentVector);
}
byte redMin = byte.MaxValue;
@@ -144,7 +134,7 @@ internal class ColorCube
}
}
-
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void Split(in Span fullColorList, out ColorCube a, out ColorCube b)
{
Span colors = fullColorList.Slice(_from, _length);
@@ -155,6 +145,7 @@ internal class ColorCube
b = new ColorCube(fullColorList, _from + median, colors.Length - median, _currentOrder);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal SKColor GetAverageColor(in ReadOnlySpan fullColorList)
{
ReadOnlySpan colors = fullColorList.Slice(_from, _length);
diff --git a/src/Artemis.Core/ColorScience/Quantization/QuantizerSort.cs b/src/Artemis.Core/ColorScience/Quantization/QuantizerSort.cs
index 3126a9b7c..46b593ece 100644
--- a/src/Artemis.Core/ColorScience/Quantization/QuantizerSort.cs
+++ b/src/Artemis.Core/ColorScience/Quantization/QuantizerSort.cs
@@ -9,94 +9,112 @@ internal static class QuantizerSort
{
#region Methods
- public static void SortRed(in Span span)
+ public static void SortRed(in Span colors)
{
Span counts = stackalloc int[256];
- foreach (SKColor t in span)
+ foreach (SKColor t in colors)
counts[t.Red]++;
- SKColor[] bucketsArray = ArrayPool.Shared.Rent(span.Length);
- Span buckets = bucketsArray.AsSpan().Slice(0, span.Length);
- Span currentBucketIndex = stackalloc int[256];
+ SKColor[] bucketsArray = ArrayPool.Shared.Rent(colors.Length);
- int offset = 0;
- for (int i = 0; i < counts.Length; i++)
+ try
{
- currentBucketIndex[i] = offset;
- offset += counts[i];
- }
+ Span buckets = bucketsArray.AsSpan().Slice(0, colors.Length);
+ Span currentBucketIndex = stackalloc int[256];
- foreach (SKColor color in span)
+ int offset = 0;
+ for (int i = 0; i < counts.Length; i++)
+ {
+ currentBucketIndex[i] = offset;
+ offset += counts[i];
+ }
+
+ foreach (SKColor color in colors)
+ {
+ int index = color.Red;
+ int bucketIndex = currentBucketIndex[index];
+ currentBucketIndex[index]++;
+ buckets[bucketIndex] = color;
+ }
+
+ buckets.CopyTo(colors);
+ }
+ finally
{
- int index = color.Red;
- int bucketIndex = currentBucketIndex[index];
- currentBucketIndex[index]++;
- buckets[bucketIndex] = color;
+ ArrayPool.Shared.Return(bucketsArray);
}
-
- buckets.CopyTo(span);
-
- ArrayPool.Shared.Return(bucketsArray);
}
- public static void SortGreen(in Span span)
+ public static void SortGreen(in Span colors)
{
Span counts = stackalloc int[256];
- foreach (SKColor t in span)
+ foreach (SKColor t in colors)
counts[t.Green]++;
- SKColor[] bucketsArray = ArrayPool.Shared.Rent(span.Length);
- Span buckets = bucketsArray.AsSpan().Slice(0, span.Length);
- Span currentBucketIndex = stackalloc int[256];
+ SKColor[] bucketsArray = ArrayPool.Shared.Rent(colors.Length);
- int offset = 0;
- for (int i = 0; i < counts.Length; i++)
+ try
{
- currentBucketIndex[i] = offset;
- offset += counts[i];
- }
+ Span buckets = bucketsArray.AsSpan().Slice(0, colors.Length);
+ Span currentBucketIndex = stackalloc int[256];
- foreach (SKColor color in span)
+ int offset = 0;
+ for (int i = 0; i < counts.Length; i++)
+ {
+ currentBucketIndex[i] = offset;
+ offset += counts[i];
+ }
+
+ foreach (SKColor color in colors)
+ {
+ int index = color.Green;
+ int bucketIndex = currentBucketIndex[index];
+ currentBucketIndex[index]++;
+ buckets[bucketIndex] = color;
+ }
+
+ buckets.CopyTo(colors);
+ }
+ finally
{
- int index = color.Green;
- int bucketIndex = currentBucketIndex[index];
- currentBucketIndex[index]++;
- buckets[bucketIndex] = color;
+ ArrayPool.Shared.Return(bucketsArray);
}
-
- buckets.CopyTo(span);
-
- ArrayPool.Shared.Return(bucketsArray);
}
- public static void SortBlue(in Span span)
+ public static void SortBlue(in Span colors)
{
Span counts = stackalloc int[256];
- foreach (SKColor t in span)
+ foreach (SKColor t in colors)
counts[t.Blue]++;
- SKColor[] bucketsArray = ArrayPool.Shared.Rent(span.Length);
- Span buckets = bucketsArray.AsSpan().Slice(0, span.Length);
- Span currentBucketIndex = stackalloc int[256];
+ SKColor[] bucketsArray = ArrayPool.Shared.Rent(colors.Length);
- int offset = 0;
- for (int i = 0; i < counts.Length; i++)
+ try
{
- currentBucketIndex[i] = offset;
- offset += counts[i];
- }
+ Span buckets = bucketsArray.AsSpan().Slice(0, colors.Length);
+ Span currentBucketIndex = stackalloc int[256];
- foreach (SKColor color in span)
+ int offset = 0;
+ for (int i = 0; i < counts.Length; i++)
+ {
+ currentBucketIndex[i] = offset;
+ offset += counts[i];
+ }
+
+ foreach (SKColor color in colors)
+ {
+ int index = color.Blue;
+ int bucketIndex = currentBucketIndex[index];
+ currentBucketIndex[index]++;
+ buckets[bucketIndex] = color;
+ }
+
+ buckets.CopyTo(colors);
+ }
+ finally
{
- int index = color.Blue;
- int bucketIndex = currentBucketIndex[index];
- currentBucketIndex[index]++;
- buckets[bucketIndex] = color;
+ ArrayPool.Shared.Return(bucketsArray);
}
-
- buckets.CopyTo(span);
-
- ArrayPool.Shared.Return(bucketsArray);
}
#endregion
diff --git a/src/Artemis.Core/ColorScience/Sorting/ColorSorter.cs b/src/Artemis.Core/ColorScience/Sorting/ColorSorter.cs
index 63f3f04d9..0ff7c5d6f 100644
--- a/src/Artemis.Core/ColorScience/Sorting/ColorSorter.cs
+++ b/src/Artemis.Core/ColorScience/Sorting/ColorSorter.cs
@@ -66,9 +66,15 @@ namespace Artemis.Core.ColorScience
else
{
SortColor[] sortColorArray = ArrayPool.Shared.Rent(colors.Length);
- Span sortColors = sortColorArray.AsSpan(0, colors.Length);
- Sort(colors, sortColors, referenceColor);
- ArrayPool.Shared.Return(sortColorArray);
+ try
+ {
+ Span sortColors = sortColorArray.AsSpan(0, colors.Length);
+ Sort(colors, sortColors, referenceColor);
+ }
+ finally
+ {
+ ArrayPool.Shared.Return(sortColorArray);
+ }
}
}