diff --git a/.editorconfig b/.editorconfig
index 2e3045fb1..c28089d72 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -172,6 +172,8 @@ dotnet_diagnostic.IDE0063.severity = suggestion
csharp_using_directive_placement = outside_namespace:warning
# Modifier preferences
csharp_prefer_static_local_function = true:warning
+# Primary constructor preferences
+csharp_style_prefer_primary_constructors = false:none
##########################################
# Unnecessary Code Rules
diff --git a/ImageSharp.sln b/ImageSharp.sln
index 2967acb8f..b8204c47d 100644
--- a/ImageSharp.sln
+++ b/ImageSharp.sln
@@ -38,6 +38,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{815C0625-CD3
src\Directory.Build.props = src\Directory.Build.props
src\Directory.Build.targets = src\Directory.Build.targets
src\README.md = src\README.md
+ src\ImageSharp.ruleset = src\ImageSharp.ruleset
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp", "src\ImageSharp\ImageSharp.csproj", "{2AA31A1F-142C-43F4-8687-09ABCA4B3A26}"
diff --git a/shared-infrastructure b/shared-infrastructure
index 1c526a97e..1dbfb576c 160000
--- a/shared-infrastructure
+++ b/shared-infrastructure
@@ -1 +1 @@
-Subproject commit 1c526a97eea8bcbc7c79de095676f7fb975a9fb1
+Subproject commit 1dbfb576c83507645265c79e03369b66cdc0379f
diff --git a/src/ImageSharp.ruleset b/src/ImageSharp.ruleset
index d7a147df0..b60989020 100644
--- a/src/ImageSharp.ruleset
+++ b/src/ImageSharp.ruleset
@@ -1,7 +1,4 @@
-
-
-
-
+
\ No newline at end of file
diff --git a/src/ImageSharp/Color/Color.Conversions.cs b/src/ImageSharp/Color/Color.Conversions.cs
deleted file mode 100644
index 309ab83ec..000000000
--- a/src/ImageSharp/Color/Color.Conversions.cs
+++ /dev/null
@@ -1,240 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-using System.Numerics;
-using System.Runtime.CompilerServices;
-using SixLabors.ImageSharp.PixelFormats;
-
-namespace SixLabors.ImageSharp;
-
-///
-/// Contains constructors and implicit conversion methods.
-///
-public readonly partial struct Color
-{
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The containing the color information.
- [MethodImpl(InliningOptions.ShortMethod)]
- public Color(Rgba64 pixel)
- {
- this.data = pixel;
- this.boxedHighPrecisionPixel = null;
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The containing the color information.
- [MethodImpl(InliningOptions.ShortMethod)]
- public Color(Rgb48 pixel)
- {
- this.data = new Rgba64(pixel.R, pixel.G, pixel.B, ushort.MaxValue);
- this.boxedHighPrecisionPixel = null;
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The containing the color information.
- [MethodImpl(InliningOptions.ShortMethod)]
- public Color(La32 pixel)
- {
- this.data = new Rgba64(pixel.L, pixel.L, pixel.L, pixel.A);
- this.boxedHighPrecisionPixel = null;
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The containing the color information.
- [MethodImpl(InliningOptions.ShortMethod)]
- public Color(L16 pixel)
- {
- this.data = new Rgba64(pixel.PackedValue, pixel.PackedValue, pixel.PackedValue, ushort.MaxValue);
- this.boxedHighPrecisionPixel = null;
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The containing the color information.
- [MethodImpl(InliningOptions.ShortMethod)]
- public Color(Rgba32 pixel)
- {
- this.data = new Rgba64(pixel);
- this.boxedHighPrecisionPixel = null;
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The containing the color information.
- [MethodImpl(InliningOptions.ShortMethod)]
- public Color(Argb32 pixel)
- {
- this.data = new Rgba64(pixel);
- this.boxedHighPrecisionPixel = null;
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The containing the color information.
- [MethodImpl(InliningOptions.ShortMethod)]
- public Color(Bgra32 pixel)
- {
- this.data = new Rgba64(pixel);
- this.boxedHighPrecisionPixel = null;
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The containing the color information.
- [MethodImpl(InliningOptions.ShortMethod)]
- public Color(Abgr32 pixel)
- {
- this.data = new Rgba64(pixel);
- this.boxedHighPrecisionPixel = null;
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The containing the color information.
- [MethodImpl(InliningOptions.ShortMethod)]
- public Color(Rgb24 pixel)
- {
- this.data = new Rgba64(pixel);
- this.boxedHighPrecisionPixel = null;
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The containing the color information.
- [MethodImpl(InliningOptions.ShortMethod)]
- public Color(Bgr24 pixel)
- {
- this.data = new Rgba64(pixel);
- this.boxedHighPrecisionPixel = null;
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The containing the color information.
- [MethodImpl(InliningOptions.ShortMethod)]
- public Color(Vector4 vector)
- {
- vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One);
- this.boxedHighPrecisionPixel = new RgbaVector(vector.X, vector.Y, vector.Z, vector.W);
- this.data = default;
- }
-
- ///
- /// Converts a to .
- ///
- /// The .
- /// The .
- public static explicit operator Vector4(Color color) => color.ToScaledVector4();
-
- ///
- /// Converts an to .
- ///
- /// The .
- /// The .
- [MethodImpl(InliningOptions.ShortMethod)]
- public static explicit operator Color(Vector4 source) => new(source);
-
- [MethodImpl(InliningOptions.ShortMethod)]
- internal Rgba32 ToRgba32()
- {
- if (this.boxedHighPrecisionPixel is null)
- {
- return this.data.ToRgba32();
- }
-
- Rgba32 value = default;
- this.boxedHighPrecisionPixel.ToRgba32(ref value);
- return value;
- }
-
- [MethodImpl(InliningOptions.ShortMethod)]
- internal Bgra32 ToBgra32()
- {
- if (this.boxedHighPrecisionPixel is null)
- {
- return this.data.ToBgra32();
- }
-
- Bgra32 value = default;
- value.FromScaledVector4(this.boxedHighPrecisionPixel.ToScaledVector4());
- return value;
- }
-
- [MethodImpl(InliningOptions.ShortMethod)]
- internal Argb32 ToArgb32()
- {
- if (this.boxedHighPrecisionPixel is null)
- {
- return this.data.ToArgb32();
- }
-
- Argb32 value = default;
- value.FromScaledVector4(this.boxedHighPrecisionPixel.ToScaledVector4());
- return value;
- }
-
- [MethodImpl(InliningOptions.ShortMethod)]
- internal Abgr32 ToAbgr32()
- {
- if (this.boxedHighPrecisionPixel is null)
- {
- return this.data.ToAbgr32();
- }
-
- Abgr32 value = default;
- value.FromScaledVector4(this.boxedHighPrecisionPixel.ToScaledVector4());
- return value;
- }
-
- [MethodImpl(InliningOptions.ShortMethod)]
- internal Rgb24 ToRgb24()
- {
- if (this.boxedHighPrecisionPixel is null)
- {
- return this.data.ToRgb24();
- }
-
- Rgb24 value = default;
- value.FromScaledVector4(this.boxedHighPrecisionPixel.ToScaledVector4());
- return value;
- }
-
- [MethodImpl(InliningOptions.ShortMethod)]
- internal Bgr24 ToBgr24()
- {
- if (this.boxedHighPrecisionPixel is null)
- {
- return this.data.ToBgr24();
- }
-
- Bgr24 value = default;
- value.FromScaledVector4(this.boxedHighPrecisionPixel.ToScaledVector4());
- return value;
- }
-
- [MethodImpl(InliningOptions.ShortMethod)]
- internal Vector4 ToScaledVector4()
- {
- if (this.boxedHighPrecisionPixel is null)
- {
- return this.data.ToScaledVector4();
- }
-
- return this.boxedHighPrecisionPixel.ToScaledVector4();
- }
-}
diff --git a/src/ImageSharp/Color/Color.NamedColors.cs b/src/ImageSharp/Color/Color.NamedColors.cs
index f8b4c90fd..00130dd90 100644
--- a/src/ImageSharp/Color/Color.NamedColors.cs
+++ b/src/ImageSharp/Color/Color.NamedColors.cs
@@ -1,6 +1,8 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
+using SixLabors.ImageSharp.PixelFormats;
+
namespace SixLabors.ImageSharp;
///
@@ -9,107 +11,107 @@ namespace SixLabors.ImageSharp;
///
public readonly partial struct Color
{
- private static readonly Lazy> NamedColorsLookupLazy = new Lazy>(CreateNamedColorsLookup, true);
+ private static readonly Lazy> NamedColorsLookupLazy = new(CreateNamedColorsLookup, true);
///
/// Represents a matching the W3C definition that has an hex value of #F0F8FF.
///
- public static readonly Color AliceBlue = FromRgba(240, 248, 255, 255);
+ public static readonly Color AliceBlue = FromPixel(new Rgba32(240, 248, 255, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FAEBD7.
///
- public static readonly Color AntiqueWhite = FromRgba(250, 235, 215, 255);
+ public static readonly Color AntiqueWhite = FromPixel(new Rgba32(250, 235, 215, 255));
///
/// Represents a matching the W3C definition that has an hex value of #00FFFF.
///
- public static readonly Color Aqua = FromRgba(0, 255, 255, 255);
+ public static readonly Color Aqua = FromPixel(new Rgba32(0, 255, 255, 255));
///
/// Represents a matching the W3C definition that has an hex value of #7FFFD4.
///
- public static readonly Color Aquamarine = FromRgba(127, 255, 212, 255);
+ public static readonly Color Aquamarine = FromPixel(new Rgba32(127, 255, 212, 255));
///
/// Represents a matching the W3C definition that has an hex value of #F0FFFF.
///
- public static readonly Color Azure = FromRgba(240, 255, 255, 255);
+ public static readonly Color Azure = FromPixel(new Rgba32(240, 255, 255, 255));
///
/// Represents a matching the W3C definition that has an hex value of #F5F5DC.
///
- public static readonly Color Beige = FromRgba(245, 245, 220, 255);
+ public static readonly Color Beige = FromPixel(new Rgba32(245, 245, 220, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FFE4C4.
///
- public static readonly Color Bisque = FromRgba(255, 228, 196, 255);
+ public static readonly Color Bisque = FromPixel(new Rgba32(255, 228, 196, 255));
///
/// Represents a matching the W3C definition that has an hex value of #000000.
///
- public static readonly Color Black = FromRgba(0, 0, 0, 255);
+ public static readonly Color Black = FromPixel(new Rgba32(0, 0, 0, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FFEBCD.
///
- public static readonly Color BlanchedAlmond = FromRgba(255, 235, 205, 255);
+ public static readonly Color BlanchedAlmond = FromPixel(new Rgba32(255, 235, 205, 255));
///
/// Represents a matching the W3C definition that has an hex value of #0000FF.
///
- public static readonly Color Blue = FromRgba(0, 0, 255, 255);
+ public static readonly Color Blue = FromPixel(new Rgba32(0, 0, 255, 255));
///
/// Represents a matching the W3C definition that has an hex value of #8A2BE2.
///
- public static readonly Color BlueViolet = FromRgba(138, 43, 226, 255);
+ public static readonly Color BlueViolet = FromPixel(new Rgba32(138, 43, 226, 255));
///
/// Represents a matching the W3C definition that has an hex value of #A52A2A.
///
- public static readonly Color Brown = FromRgba(165, 42, 42, 255);
+ public static readonly Color Brown = FromPixel(new Rgba32(165, 42, 42, 255));
///
/// Represents a matching the W3C definition that has an hex value of #DEB887.
///
- public static readonly Color BurlyWood = FromRgba(222, 184, 135, 255);
+ public static readonly Color BurlyWood = FromPixel(new Rgba32(222, 184, 135, 255));
///
/// Represents a matching the W3C definition that has an hex value of #5F9EA0.
///
- public static readonly Color CadetBlue = FromRgba(95, 158, 160, 255);
+ public static readonly Color CadetBlue = FromPixel(new Rgba32(95, 158, 160, 255));
///
/// Represents a matching the W3C definition that has an hex value of #7FFF00.
///
- public static readonly Color Chartreuse = FromRgba(127, 255, 0, 255);
+ public static readonly Color Chartreuse = FromPixel(new Rgba32(127, 255, 0, 255));
///
/// Represents a matching the W3C definition that has an hex value of #D2691E.
///
- public static readonly Color Chocolate = FromRgba(210, 105, 30, 255);
+ public static readonly Color Chocolate = FromPixel(new Rgba32(210, 105, 30, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FF7F50.
///
- public static readonly Color Coral = FromRgba(255, 127, 80, 255);
+ public static readonly Color Coral = FromPixel(new Rgba32(255, 127, 80, 255));
///
/// Represents a matching the W3C definition that has an hex value of #6495ED.
///
- public static readonly Color CornflowerBlue = FromRgba(100, 149, 237, 255);
+ public static readonly Color CornflowerBlue = FromPixel(new Rgba32(100, 149, 237, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FFF8DC.
///
- public static readonly Color Cornsilk = FromRgba(255, 248, 220, 255);
+ public static readonly Color Cornsilk = FromPixel(new Rgba32(255, 248, 220, 255));
///
/// Represents a matching the W3C definition that has an hex value of #DC143C.
///
- public static readonly Color Crimson = FromRgba(220, 20, 60, 255);
+ public static readonly Color Crimson = FromPixel(new Rgba32(220, 20, 60, 255));
///
/// Represents a matching the W3C definition that has an hex value of #00FFFF.
@@ -119,27 +121,27 @@ public readonly partial struct Color
///
/// Represents a matching the W3C definition that has an hex value of #00008B.
///
- public static readonly Color DarkBlue = FromRgba(0, 0, 139, 255);
+ public static readonly Color DarkBlue = FromPixel(new Rgba32(0, 0, 139, 255));
///
/// Represents a matching the W3C definition that has an hex value of #008B8B.
///
- public static readonly Color DarkCyan = FromRgba(0, 139, 139, 255);
+ public static readonly Color DarkCyan = FromPixel(new Rgba32(0, 139, 139, 255));
///
/// Represents a matching the W3C definition that has an hex value of #B8860B.
///
- public static readonly Color DarkGoldenrod = FromRgba(184, 134, 11, 255);
+ public static readonly Color DarkGoldenrod = FromPixel(new Rgba32(184, 134, 11, 255));
///
/// Represents a matching the W3C definition that has an hex value of #A9A9A9.
///
- public static readonly Color DarkGray = FromRgba(169, 169, 169, 255);
+ public static readonly Color DarkGray = FromPixel(new Rgba32(169, 169, 169, 255));
///
/// Represents a matching the W3C definition that has an hex value of #006400.
///
- public static readonly Color DarkGreen = FromRgba(0, 100, 0, 255);
+ public static readonly Color DarkGreen = FromPixel(new Rgba32(0, 100, 0, 255));
///
/// Represents a matching the W3C definition that has an hex value of #A9A9A9.
@@ -149,52 +151,52 @@ public readonly partial struct Color
///
/// Represents a matching the W3C definition that has an hex value of #BDB76B.
///
- public static readonly Color DarkKhaki = FromRgba(189, 183, 107, 255);
+ public static readonly Color DarkKhaki = FromPixel(new Rgba32(189, 183, 107, 255));
///
/// Represents a matching the W3C definition that has an hex value of #8B008B.
///
- public static readonly Color DarkMagenta = FromRgba(139, 0, 139, 255);
+ public static readonly Color DarkMagenta = FromPixel(new Rgba32(139, 0, 139, 255));
///
/// Represents a matching the W3C definition that has an hex value of #556B2F.
///
- public static readonly Color DarkOliveGreen = FromRgba(85, 107, 47, 255);
+ public static readonly Color DarkOliveGreen = FromPixel(new Rgba32(85, 107, 47, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FF8C00.
///
- public static readonly Color DarkOrange = FromRgba(255, 140, 0, 255);
+ public static readonly Color DarkOrange = FromPixel(new Rgba32(255, 140, 0, 255));
///
/// Represents a matching the W3C definition that has an hex value of #9932CC.
///
- public static readonly Color DarkOrchid = FromRgba(153, 50, 204, 255);
+ public static readonly Color DarkOrchid = FromPixel(new Rgba32(153, 50, 204, 255));
///
/// Represents a matching the W3C definition that has an hex value of #8B0000.
///
- public static readonly Color DarkRed = FromRgba(139, 0, 0, 255);
+ public static readonly Color DarkRed = FromPixel(new Rgba32(139, 0, 0, 255));
///
/// Represents a matching the W3C definition that has an hex value of #E9967A.
///
- public static readonly Color DarkSalmon = FromRgba(233, 150, 122, 255);
+ public static readonly Color DarkSalmon = FromPixel(new Rgba32(233, 150, 122, 255));
///
/// Represents a matching the W3C definition that has an hex value of #8FBC8F.
///
- public static readonly Color DarkSeaGreen = FromRgba(143, 188, 143, 255);
+ public static readonly Color DarkSeaGreen = FromPixel(new Rgba32(143, 188, 143, 255));
///
/// Represents a matching the W3C definition that has an hex value of #483D8B.
///
- public static readonly Color DarkSlateBlue = FromRgba(72, 61, 139, 255);
+ public static readonly Color DarkSlateBlue = FromPixel(new Rgba32(72, 61, 139, 255));
///
/// Represents a matching the W3C definition that has an hex value of #2F4F4F.
///
- public static readonly Color DarkSlateGray = FromRgba(47, 79, 79, 255);
+ public static readonly Color DarkSlateGray = FromPixel(new Rgba32(47, 79, 79, 255));
///
/// Represents a matching the W3C definition that has an hex value of #2F4F4F.
@@ -204,27 +206,27 @@ public readonly partial struct Color
///
/// Represents a matching the W3C definition that has an hex value of #00CED1.
///
- public static readonly Color DarkTurquoise = FromRgba(0, 206, 209, 255);
+ public static readonly Color DarkTurquoise = FromPixel(new Rgba32(0, 206, 209, 255));
///
/// Represents a matching the W3C definition that has an hex value of #9400D3.
///
- public static readonly Color DarkViolet = FromRgba(148, 0, 211, 255);
+ public static readonly Color DarkViolet = FromPixel(new Rgba32(148, 0, 211, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FF1493.
///
- public static readonly Color DeepPink = FromRgba(255, 20, 147, 255);
+ public static readonly Color DeepPink = FromPixel(new Rgba32(255, 20, 147, 255));
///
/// Represents a matching the W3C definition that has an hex value of #00BFFF.
///
- public static readonly Color DeepSkyBlue = FromRgba(0, 191, 255, 255);
+ public static readonly Color DeepSkyBlue = FromPixel(new Rgba32(0, 191, 255, 255));
///
/// Represents a matching the W3C definition that has an hex value of #696969.
///
- public static readonly Color DimGray = FromRgba(105, 105, 105, 255);
+ public static readonly Color DimGray = FromPixel(new Rgba32(105, 105, 105, 255));
///
/// Represents a matching the W3C definition that has an hex value of #696969.
@@ -234,62 +236,62 @@ public readonly partial struct Color
///
/// Represents a matching the W3C definition that has an hex value of #1E90FF.
///
- public static readonly Color DodgerBlue = FromRgba(30, 144, 255, 255);
+ public static readonly Color DodgerBlue = FromPixel(new Rgba32(30, 144, 255, 255));
///
/// Represents a matching the W3C definition that has an hex value of #B22222.
///
- public static readonly Color Firebrick = FromRgba(178, 34, 34, 255);
+ public static readonly Color Firebrick = FromPixel(new Rgba32(178, 34, 34, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FFFAF0.
///
- public static readonly Color FloralWhite = FromRgba(255, 250, 240, 255);
+ public static readonly Color FloralWhite = FromPixel(new Rgba32(255, 250, 240, 255));
///
/// Represents a matching the W3C definition that has an hex value of #228B22.
///
- public static readonly Color ForestGreen = FromRgba(34, 139, 34, 255);
+ public static readonly Color ForestGreen = FromPixel(new Rgba32(34, 139, 34, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FF00FF.
///
- public static readonly Color Fuchsia = FromRgba(255, 0, 255, 255);
+ public static readonly Color Fuchsia = FromPixel(new Rgba32(255, 0, 255, 255));
///
/// Represents a matching the W3C definition that has an hex value of #DCDCDC.
///
- public static readonly Color Gainsboro = FromRgba(220, 220, 220, 255);
+ public static readonly Color Gainsboro = FromPixel(new Rgba32(220, 220, 220, 255));
///
/// Represents a matching the W3C definition that has an hex value of #F8F8FF.
///
- public static readonly Color GhostWhite = FromRgba(248, 248, 255, 255);
+ public static readonly Color GhostWhite = FromPixel(new Rgba32(248, 248, 255, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FFD700.
///
- public static readonly Color Gold = FromRgba(255, 215, 0, 255);
+ public static readonly Color Gold = FromPixel(new Rgba32(255, 215, 0, 255));
///
/// Represents a matching the W3C definition that has an hex value of #DAA520.
///
- public static readonly Color Goldenrod = FromRgba(218, 165, 32, 255);
+ public static readonly Color Goldenrod = FromPixel(new Rgba32(218, 165, 32, 255));
///
/// Represents a matching the W3C definition that has an hex value of #808080.
///
- public static readonly Color Gray = FromRgba(128, 128, 128, 255);
+ public static readonly Color Gray = FromPixel(new Rgba32(128, 128, 128, 255));
///
/// Represents a matching the W3C definition that has an hex value of #008000.
///
- public static readonly Color Green = FromRgba(0, 128, 0, 255);
+ public static readonly Color Green = FromPixel(new Rgba32(0, 128, 0, 255));
///
/// Represents a matching the W3C definition that has an hex value of #ADFF2F.
///
- public static readonly Color GreenYellow = FromRgba(173, 255, 47, 255);
+ public static readonly Color GreenYellow = FromPixel(new Rgba32(173, 255, 47, 255));
///
/// Represents a matching the W3C definition that has an hex value of #808080.
@@ -299,82 +301,82 @@ public readonly partial struct Color
///
/// Represents a matching the W3C definition that has an hex value of #F0FFF0.
///
- public static readonly Color Honeydew = FromRgba(240, 255, 240, 255);
+ public static readonly Color Honeydew = FromPixel(new Rgba32(240, 255, 240, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FF69B4.
///
- public static readonly Color HotPink = FromRgba(255, 105, 180, 255);
+ public static readonly Color HotPink = FromPixel(new Rgba32(255, 105, 180, 255));
///
/// Represents a matching the W3C definition that has an hex value of #CD5C5C.
///
- public static readonly Color IndianRed = FromRgba(205, 92, 92, 255);
+ public static readonly Color IndianRed = FromPixel(new Rgba32(205, 92, 92, 255));
///
/// Represents a matching the W3C definition that has an hex value of #4B0082.
///
- public static readonly Color Indigo = FromRgba(75, 0, 130, 255);
+ public static readonly Color Indigo = FromPixel(new Rgba32(75, 0, 130, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FFFFF0.
///
- public static readonly Color Ivory = FromRgba(255, 255, 240, 255);
+ public static readonly Color Ivory = FromPixel(new Rgba32(255, 255, 240, 255));
///
/// Represents a matching the W3C definition that has an hex value of #F0E68C.
///
- public static readonly Color Khaki = FromRgba(240, 230, 140, 255);
+ public static readonly Color Khaki = FromPixel(new Rgba32(240, 230, 140, 255));
///
/// Represents a matching the W3C definition that has an hex value of #E6E6FA.
///
- public static readonly Color Lavender = FromRgba(230, 230, 250, 255);
+ public static readonly Color Lavender = FromPixel(new Rgba32(230, 230, 250, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FFF0F5.
///
- public static readonly Color LavenderBlush = FromRgba(255, 240, 245, 255);
+ public static readonly Color LavenderBlush = FromPixel(new Rgba32(255, 240, 245, 255));
///
/// Represents a matching the W3C definition that has an hex value of #7CFC00.
///
- public static readonly Color LawnGreen = FromRgba(124, 252, 0, 255);
+ public static readonly Color LawnGreen = FromPixel(new Rgba32(124, 252, 0, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FFFACD.
///
- public static readonly Color LemonChiffon = FromRgba(255, 250, 205, 255);
+ public static readonly Color LemonChiffon = FromPixel(new Rgba32(255, 250, 205, 255));
///
/// Represents a matching the W3C definition that has an hex value of #ADD8E6.
///
- public static readonly Color LightBlue = FromRgba(173, 216, 230, 255);
+ public static readonly Color LightBlue = FromPixel(new Rgba32(173, 216, 230, 255));
///
/// Represents a matching the W3C definition that has an hex value of #F08080.
///
- public static readonly Color LightCoral = FromRgba(240, 128, 128, 255);
+ public static readonly Color LightCoral = FromPixel(new Rgba32(240, 128, 128, 255));
///
/// Represents a matching the W3C definition that has an hex value of #E0FFFF.
///
- public static readonly Color LightCyan = FromRgba(224, 255, 255, 255);
+ public static readonly Color LightCyan = FromPixel(new Rgba32(224, 255, 255, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FAFAD2.
///
- public static readonly Color LightGoldenrodYellow = FromRgba(250, 250, 210, 255);
+ public static readonly Color LightGoldenrodYellow = FromPixel(new Rgba32(250, 250, 210, 255));
///
/// Represents a matching the W3C definition that has an hex value of #D3D3D3.
///
- public static readonly Color LightGray = FromRgba(211, 211, 211, 255);
+ public static readonly Color LightGray = FromPixel(new Rgba32(211, 211, 211, 255));
///
/// Represents a matching the W3C definition that has an hex value of #90EE90.
///
- public static readonly Color LightGreen = FromRgba(144, 238, 144, 255);
+ public static readonly Color LightGreen = FromPixel(new Rgba32(144, 238, 144, 255));
///
/// Represents a matching the W3C definition that has an hex value of #D3D3D3.
@@ -384,27 +386,27 @@ public readonly partial struct Color
///
/// Represents a matching the W3C definition that has an hex value of #FFB6C1.
///
- public static readonly Color LightPink = FromRgba(255, 182, 193, 255);
+ public static readonly Color LightPink = FromPixel(new Rgba32(255, 182, 193, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FFA07A.
///
- public static readonly Color LightSalmon = FromRgba(255, 160, 122, 255);
+ public static readonly Color LightSalmon = FromPixel(new Rgba32(255, 160, 122, 255));
///
/// Represents a matching the W3C definition that has an hex value of #20B2AA.
///
- public static readonly Color LightSeaGreen = FromRgba(32, 178, 170, 255);
+ public static readonly Color LightSeaGreen = FromPixel(new Rgba32(32, 178, 170, 255));
///
/// Represents a matching the W3C definition that has an hex value of #87CEFA.
///
- public static readonly Color LightSkyBlue = FromRgba(135, 206, 250, 255);
+ public static readonly Color LightSkyBlue = FromPixel(new Rgba32(135, 206, 250, 255));
///
/// Represents a matching the W3C definition that has an hex value of #778899.
///
- public static readonly Color LightSlateGray = FromRgba(119, 136, 153, 255);
+ public static readonly Color LightSlateGray = FromPixel(new Rgba32(119, 136, 153, 255));
///
/// Represents a matching the W3C definition that has an hex value of #778899.
@@ -414,27 +416,27 @@ public readonly partial struct Color
///
/// Represents a matching the W3C definition that has an hex value of #B0C4DE.
///
- public static readonly Color LightSteelBlue = FromRgba(176, 196, 222, 255);
+ public static readonly Color LightSteelBlue = FromPixel(new Rgba32(176, 196, 222, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FFFFE0.
///
- public static readonly Color LightYellow = FromRgba(255, 255, 224, 255);
+ public static readonly Color LightYellow = FromPixel(new Rgba32(255, 255, 224, 255));
///
/// Represents a matching the W3C definition that has an hex value of #00FF00.
///
- public static readonly Color Lime = FromRgba(0, 255, 0, 255);
+ public static readonly Color Lime = FromPixel(new Rgba32(0, 255, 0, 255));
///
/// Represents a matching the W3C definition that has an hex value of #32CD32.
///
- public static readonly Color LimeGreen = FromRgba(50, 205, 50, 255);
+ public static readonly Color LimeGreen = FromPixel(new Rgba32(50, 205, 50, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FAF0E6.
///
- public static readonly Color Linen = FromRgba(250, 240, 230, 255);
+ public static readonly Color Linen = FromPixel(new Rgba32(250, 240, 230, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FF00FF.
@@ -444,237 +446,237 @@ public readonly partial struct Color
///
/// Represents a matching the W3C definition that has an hex value of #800000.
///
- public static readonly Color Maroon = FromRgba(128, 0, 0, 255);
+ public static readonly Color Maroon = FromPixel(new Rgba32(128, 0, 0, 255));
///
/// Represents a matching the W3C definition that has an hex value of #66CDAA.
///
- public static readonly Color MediumAquamarine = FromRgba(102, 205, 170, 255);
+ public static readonly Color MediumAquamarine = FromPixel(new Rgba32(102, 205, 170, 255));
///
/// Represents a matching the W3C definition that has an hex value of #0000CD.
///
- public static readonly Color MediumBlue = FromRgba(0, 0, 205, 255);
+ public static readonly Color MediumBlue = FromPixel(new Rgba32(0, 0, 205, 255));
///
/// Represents a matching the W3C definition that has an hex value of #BA55D3.
///
- public static readonly Color MediumOrchid = FromRgba(186, 85, 211, 255);
+ public static readonly Color MediumOrchid = FromPixel(new Rgba32(186, 85, 211, 255));
///
/// Represents a matching the W3C definition that has an hex value of #9370DB.
///
- public static readonly Color MediumPurple = FromRgba(147, 112, 219, 255);
+ public static readonly Color MediumPurple = FromPixel(new Rgba32(147, 112, 219, 255));
///
/// Represents a matching the W3C definition that has an hex value of #3CB371.
///
- public static readonly Color MediumSeaGreen = FromRgba(60, 179, 113, 255);
+ public static readonly Color MediumSeaGreen = FromPixel(new Rgba32(60, 179, 113, 255));
///
/// Represents a matching the W3C definition that has an hex value of #7B68EE.
///
- public static readonly Color MediumSlateBlue = FromRgba(123, 104, 238, 255);
+ public static readonly Color MediumSlateBlue = FromPixel(new Rgba32(123, 104, 238, 255));
///
/// Represents a matching the W3C definition that has an hex value of #00FA9A.
///
- public static readonly Color MediumSpringGreen = FromRgba(0, 250, 154, 255);
+ public static readonly Color MediumSpringGreen = FromPixel(new Rgba32(0, 250, 154, 255));
///
/// Represents a matching the W3C definition that has an hex value of #48D1CC.
///
- public static readonly Color MediumTurquoise = FromRgba(72, 209, 204, 255);
+ public static readonly Color MediumTurquoise = FromPixel(new Rgba32(72, 209, 204, 255));
///
/// Represents a matching the W3C definition that has an hex value of #C71585.
///
- public static readonly Color MediumVioletRed = FromRgba(199, 21, 133, 255);
+ public static readonly Color MediumVioletRed = FromPixel(new Rgba32(199, 21, 133, 255));
///
/// Represents a matching the W3C definition that has an hex value of #191970.
///
- public static readonly Color MidnightBlue = FromRgba(25, 25, 112, 255);
+ public static readonly Color MidnightBlue = FromPixel(new Rgba32(25, 25, 112, 255));
///
/// Represents a matching the W3C definition that has an hex value of #F5FFFA.
///
- public static readonly Color MintCream = FromRgba(245, 255, 250, 255);
+ public static readonly Color MintCream = FromPixel(new Rgba32(245, 255, 250, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FFE4E1.
///
- public static readonly Color MistyRose = FromRgba(255, 228, 225, 255);
+ public static readonly Color MistyRose = FromPixel(new Rgba32(255, 228, 225, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FFE4B5.
///
- public static readonly Color Moccasin = FromRgba(255, 228, 181, 255);
+ public static readonly Color Moccasin = FromPixel(new Rgba32(255, 228, 181, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FFDEAD.
///
- public static readonly Color NavajoWhite = FromRgba(255, 222, 173, 255);
+ public static readonly Color NavajoWhite = FromPixel(new Rgba32(255, 222, 173, 255));
///
/// Represents a matching the W3C definition that has an hex value of #000080.
///
- public static readonly Color Navy = FromRgba(0, 0, 128, 255);
+ public static readonly Color Navy = FromPixel(new Rgba32(0, 0, 128, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FDF5E6.
///
- public static readonly Color OldLace = FromRgba(253, 245, 230, 255);
+ public static readonly Color OldLace = FromPixel(new Rgba32(253, 245, 230, 255));
///
/// Represents a matching the W3C definition that has an hex value of #808000.
///
- public static readonly Color Olive = FromRgba(128, 128, 0, 255);
+ public static readonly Color Olive = FromPixel(new Rgba32(128, 128, 0, 255));
///
/// Represents a matching the W3C definition that has an hex value of #6B8E23.
///
- public static readonly Color OliveDrab = FromRgba(107, 142, 35, 255);
+ public static readonly Color OliveDrab = FromPixel(new Rgba32(107, 142, 35, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FFA500.
///
- public static readonly Color Orange = FromRgba(255, 165, 0, 255);
+ public static readonly Color Orange = FromPixel(new Rgba32(255, 165, 0, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FF4500.
///
- public static readonly Color OrangeRed = FromRgba(255, 69, 0, 255);
+ public static readonly Color OrangeRed = FromPixel(new Rgba32(255, 69, 0, 255));
///
/// Represents a matching the W3C definition that has an hex value of #DA70D6.
///
- public static readonly Color Orchid = FromRgba(218, 112, 214, 255);
+ public static readonly Color Orchid = FromPixel(new Rgba32(218, 112, 214, 255));
///
/// Represents a matching the W3C definition that has an hex value of #EEE8AA.
///
- public static readonly Color PaleGoldenrod = FromRgba(238, 232, 170, 255);
+ public static readonly Color PaleGoldenrod = FromPixel(new Rgba32(238, 232, 170, 255));
///
/// Represents a matching the W3C definition that has an hex value of #98FB98.
///
- public static readonly Color PaleGreen = FromRgba(152, 251, 152, 255);
+ public static readonly Color PaleGreen = FromPixel(new Rgba32(152, 251, 152, 255));
///
/// Represents a matching the W3C definition that has an hex value of #AFEEEE.
///
- public static readonly Color PaleTurquoise = FromRgba(175, 238, 238, 255);
+ public static readonly Color PaleTurquoise = FromPixel(new Rgba32(175, 238, 238, 255));
///
/// Represents a matching the W3C definition that has an hex value of #DB7093.
///
- public static readonly Color PaleVioletRed = FromRgba(219, 112, 147, 255);
+ public static readonly Color PaleVioletRed = FromPixel(new Rgba32(219, 112, 147, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FFEFD5.
///
- public static readonly Color PapayaWhip = FromRgba(255, 239, 213, 255);
+ public static readonly Color PapayaWhip = FromPixel(new Rgba32(255, 239, 213, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FFDAB9.
///
- public static readonly Color PeachPuff = FromRgba(255, 218, 185, 255);
+ public static readonly Color PeachPuff = FromPixel(new Rgba32(255, 218, 185, 255));
///
/// Represents a matching the W3C definition that has an hex value of #CD853F.
///
- public static readonly Color Peru = FromRgba(205, 133, 63, 255);
+ public static readonly Color Peru = FromPixel(new Rgba32(205, 133, 63, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FFC0CB.
///
- public static readonly Color Pink = FromRgba(255, 192, 203, 255);
+ public static readonly Color Pink = FromPixel(new Rgba32(255, 192, 203, 255));
///
/// Represents a matching the W3C definition that has an hex value of #DDA0DD.
///
- public static readonly Color Plum = FromRgba(221, 160, 221, 255);
+ public static readonly Color Plum = FromPixel(new Rgba32(221, 160, 221, 255));
///
/// Represents a matching the W3C definition that has an hex value of #B0E0E6.
///
- public static readonly Color PowderBlue = FromRgba(176, 224, 230, 255);
+ public static readonly Color PowderBlue = FromPixel(new Rgba32(176, 224, 230, 255));
///
/// Represents a matching the W3C definition that has an hex value of #800080.
///
- public static readonly Color Purple = FromRgba(128, 0, 128, 255);
+ public static readonly Color Purple = FromPixel(new Rgba32(128, 0, 128, 255));
///
/// Represents a matching the W3C definition that has an hex value of #663399.
///
- public static readonly Color RebeccaPurple = FromRgba(102, 51, 153, 255);
+ public static readonly Color RebeccaPurple = FromPixel(new Rgba32(102, 51, 153, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FF0000.
///
- public static readonly Color Red = FromRgba(255, 0, 0, 255);
+ public static readonly Color Red = FromPixel(new Rgba32(255, 0, 0, 255));
///
/// Represents a matching the W3C definition that has an hex value of #BC8F8F.
///
- public static readonly Color RosyBrown = FromRgba(188, 143, 143, 255);
+ public static readonly Color RosyBrown = FromPixel(new Rgba32(188, 143, 143, 255));
///
/// Represents a matching the W3C definition that has an hex value of #4169E1.
///
- public static readonly Color RoyalBlue = FromRgba(65, 105, 225, 255);
+ public static readonly Color RoyalBlue = FromPixel(new Rgba32(65, 105, 225, 255));
///
/// Represents a matching the W3C definition that has an hex value of #8B4513.
///
- public static readonly Color SaddleBrown = FromRgba(139, 69, 19, 255);
+ public static readonly Color SaddleBrown = FromPixel(new Rgba32(139, 69, 19, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FA8072.
///
- public static readonly Color Salmon = FromRgba(250, 128, 114, 255);
+ public static readonly Color Salmon = FromPixel(new Rgba32(250, 128, 114, 255));
///
/// Represents a matching the W3C definition that has an hex value of #F4A460.
///
- public static readonly Color SandyBrown = FromRgba(244, 164, 96, 255);
+ public static readonly Color SandyBrown = FromPixel(new Rgba32(244, 164, 96, 255));
///
/// Represents a matching the W3C definition that has an hex value of #2E8B57.
///
- public static readonly Color SeaGreen = FromRgba(46, 139, 87, 255);
+ public static readonly Color SeaGreen = FromPixel(new Rgba32(46, 139, 87, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FFF5EE.
///
- public static readonly Color SeaShell = FromRgba(255, 245, 238, 255);
+ public static readonly Color SeaShell = FromPixel(new Rgba32(255, 245, 238, 255));
///
/// Represents a matching the W3C definition that has an hex value of #A0522D.
///
- public static readonly Color Sienna = FromRgba(160, 82, 45, 255);
+ public static readonly Color Sienna = FromPixel(new Rgba32(160, 82, 45, 255));
///
/// Represents a matching the W3C definition that has an hex value of #C0C0C0.
///
- public static readonly Color Silver = FromRgba(192, 192, 192, 255);
+ public static readonly Color Silver = FromPixel(new Rgba32(192, 192, 192, 255));
///
/// Represents a matching the W3C definition that has an hex value of #87CEEB.
///
- public static readonly Color SkyBlue = FromRgba(135, 206, 235, 255);
+ public static readonly Color SkyBlue = FromPixel(new Rgba32(135, 206, 235, 255));
///
/// Represents a matching the W3C definition that has an hex value of #6A5ACD.
///
- public static readonly Color SlateBlue = FromRgba(106, 90, 205, 255);
+ public static readonly Color SlateBlue = FromPixel(new Rgba32(106, 90, 205, 255));
///
/// Represents a matching the W3C definition that has an hex value of #708090.
///
- public static readonly Color SlateGray = FromRgba(112, 128, 144, 255);
+ public static readonly Color SlateGray = FromPixel(new Rgba32(112, 128, 144, 255));
///
/// Represents a matching the W3C definition that has an hex value of #708090.
@@ -684,81 +686,80 @@ public readonly partial struct Color
///
/// Represents a matching the W3C definition that has an hex value of #FFFAFA.
///
- public static readonly Color Snow = FromRgba(255, 250, 250, 255);
+ public static readonly Color Snow = FromPixel(new Rgba32(255, 250, 250, 255));
///
/// Represents a matching the W3C definition that has an hex value of #00FF7F.
///
- public static readonly Color SpringGreen = FromRgba(0, 255, 127, 255);
+ public static readonly Color SpringGreen = FromPixel(new Rgba32(0, 255, 127, 255));
///
/// Represents a matching the W3C definition that has an hex value of #4682B4.
///
- public static readonly Color SteelBlue = FromRgba(70, 130, 180, 255);
+ public static readonly Color SteelBlue = FromPixel(new Rgba32(70, 130, 180, 255));
///
/// Represents a matching the W3C definition that has an hex value of #D2B48C.
///
- public static readonly Color Tan = FromRgba(210, 180, 140, 255);
+ public static readonly Color Tan = FromPixel(new Rgba32(210, 180, 140, 255));
///
/// Represents a matching the W3C definition that has an hex value of #008080.
///
- public static readonly Color Teal = FromRgba(0, 128, 128, 255);
+ public static readonly Color Teal = FromPixel(new Rgba32(0, 128, 128, 255));
///
/// Represents a matching the W3C definition that has an hex value of #D8BFD8.
///
- public static readonly Color Thistle = FromRgba(216, 191, 216, 255);
+ public static readonly Color Thistle = FromPixel(new Rgba32(216, 191, 216, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FF6347.
///
- public static readonly Color Tomato = FromRgba(255, 99, 71, 255);
+ public static readonly Color Tomato = FromPixel(new Rgba32(255, 99, 71, 255));
///
/// Represents a matching the W3C definition that has an hex value of #00000000.
///
- public static readonly Color Transparent = FromRgba(0, 0, 0, 0);
+ public static readonly Color Transparent = FromPixel(new Rgba32(0, 0, 0, 0));
///
/// Represents a matching the W3C definition that has an hex value of #40E0D0.
///
- public static readonly Color Turquoise = FromRgba(64, 224, 208, 255);
+ public static readonly Color Turquoise = FromPixel(new Rgba32(64, 224, 208, 255));
///
/// Represents a matching the W3C definition that has an hex value of #EE82EE.
///
- public static readonly Color Violet = FromRgba(238, 130, 238, 255);
+ public static readonly Color Violet = FromPixel(new Rgba32(238, 130, 238, 255));
///
/// Represents a matching the W3C definition that has an hex value of #F5DEB3.
///
- public static readonly Color Wheat = FromRgba(245, 222, 179, 255);
+ public static readonly Color Wheat = FromPixel(new Rgba32(245, 222, 179, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FFFFFF.
///
- public static readonly Color White = FromRgba(255, 255, 255, 255);
+ public static readonly Color White = FromPixel(new Rgba32(255, 255, 255, 255));
///
/// Represents a matching the W3C definition that has an hex value of #F5F5F5.
///
- public static readonly Color WhiteSmoke = FromRgba(245, 245, 245, 255);
+ public static readonly Color WhiteSmoke = FromPixel(new Rgba32(245, 245, 245, 255));
///
/// Represents a matching the W3C definition that has an hex value of #FFFF00.
///
- public static readonly Color Yellow = FromRgba(255, 255, 0, 255);
+ public static readonly Color Yellow = FromPixel(new Rgba32(255, 255, 0, 255));
///
/// Represents a matching the W3C definition that has an hex value of #9ACD32.
///
- public static readonly Color YellowGreen = FromRgba(154, 205, 50, 255);
+ public static readonly Color YellowGreen = FromPixel(new Rgba32(154, 205, 50, 255));
private static Dictionary CreateNamedColorsLookup()
- {
- return new Dictionary(StringComparer.OrdinalIgnoreCase)
+ => new(StringComparer.OrdinalIgnoreCase)
{
{ nameof(AliceBlue), AliceBlue },
{ nameof(AntiqueWhite), AntiqueWhite },
@@ -910,5 +911,4 @@ public readonly partial struct Color
{ nameof(Yellow), Yellow },
{ nameof(YellowGreen), YellowGreen }
};
- }
}
diff --git a/src/ImageSharp/Color/Color.cs b/src/ImageSharp/Color/Color.cs
index cebceabe0..82ecab390 100644
--- a/src/ImageSharp/Color/Color.cs
+++ b/src/ImageSharp/Color/Color.cs
@@ -18,33 +18,24 @@ namespace SixLabors.ImageSharp;
///
public readonly partial struct Color : IEquatable
{
- private readonly Rgba64 data;
+ private readonly Vector4 data;
private readonly IPixel? boxedHighPrecisionPixel;
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// The containing the color information.
[MethodImpl(InliningOptions.ShortMethod)]
- private Color(byte r, byte g, byte b, byte a)
- {
- this.data = new Rgba64(
- ColorNumerics.UpscaleFrom8BitTo16Bit(r),
- ColorNumerics.UpscaleFrom8BitTo16Bit(g),
- ColorNumerics.UpscaleFrom8BitTo16Bit(b),
- ColorNumerics.UpscaleFrom8BitTo16Bit(a));
-
- this.boxedHighPrecisionPixel = null;
- }
-
- [MethodImpl(InliningOptions.ShortMethod)]
- private Color(byte r, byte g, byte b)
+ private Color(Vector4 vector)
{
- this.data = new Rgba64(
- ColorNumerics.UpscaleFrom8BitTo16Bit(r),
- ColorNumerics.UpscaleFrom8BitTo16Bit(g),
- ColorNumerics.UpscaleFrom8BitTo16Bit(b),
- ushort.MaxValue);
-
+ this.data = Numerics.Clamp(vector, Vector4.Zero, Vector4.One);
this.boxedHighPrecisionPixel = null;
}
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// The pixel containing color information.
[MethodImpl(InliningOptions.ShortMethod)]
private Color(IPixel pixel)
{
@@ -52,6 +43,21 @@ public readonly partial struct Color : IEquatable
this.data = default;
}
+ ///
+ /// Converts a to .
+ ///
+ /// The .
+ /// The .
+ public static explicit operator Vector4(Color color) => color.ToScaledVector4();
+
+ ///
+ /// Converts an to .
+ ///
+ /// The .
+ /// The .
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static explicit operator Color(Vector4 source) => new(source);
+
///
/// Checks whether two structures are equal.
///
@@ -76,27 +82,6 @@ public readonly partial struct Color : IEquatable
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(Color left, Color right) => !left.Equals(right);
- ///
- /// Creates a from RGBA bytes.
- ///
- /// The red component (0-255).
- /// The green component (0-255).
- /// The blue component (0-255).
- /// The alpha component (0-255).
- /// The .
- [MethodImpl(InliningOptions.ShortMethod)]
- public static Color FromRgba(byte r, byte g, byte b, byte a) => new(r, g, b, a);
-
- ///
- /// Creates a from RGB bytes.
- ///
- /// The red component (0-255).
- /// The green component (0-255).
- /// The blue component (0-255).
- /// The .
- [MethodImpl(InliningOptions.ShortMethod)]
- public static Color FromRgb(byte r, byte g, byte b) => new(r, g, b);
-
///
/// Creates a from the given .
///
@@ -107,32 +92,43 @@ public readonly partial struct Color : IEquatable
public static Color FromPixel(TPixel pixel)
where TPixel : unmanaged, IPixel
{
- // Avoid boxing in case we can convert to Rgba64 safely and efficently
- if (typeof(TPixel) == typeof(Rgba64))
- {
- return new((Rgba64)(object)pixel);
- }
- else if (typeof(TPixel) == typeof(Rgb48))
- {
- return new((Rgb48)(object)pixel);
- }
- else if (typeof(TPixel) == typeof(La32))
- {
- return new((La32)(object)pixel);
- }
- else if (typeof(TPixel) == typeof(L16))
+ // Avoid boxing in case we can convert to Vector4 safely and efficiently
+ PixelTypeInfo info = TPixel.GetPixelTypeInfo();
+ if (info.ComponentInfo.HasValue && info.ComponentInfo.Value.GetMaximumComponentPrecision() <= (int)PixelComponentBitDepth.Bit32)
{
- return new((L16)(object)pixel);
+ return new(pixel.ToScaledVector4());
}
- else if (Unsafe.SizeOf() <= Unsafe.SizeOf())
+
+ return new(pixel);
+ }
+
+ ///
+ /// Bulk converts a span of a specified type to a span of .
+ ///
+ /// The pixel type to convert to.
+ /// The source pixel span.
+ /// The destination color span.
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static void FromPixel(ReadOnlySpan source, Span destination)
+ where TPixel : unmanaged, IPixel
+ {
+ Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+ // Avoid boxing in case we can convert to Vector4 safely and efficiently
+ PixelTypeInfo info = TPixel.GetPixelTypeInfo();
+ if (info.ComponentInfo.HasValue && info.ComponentInfo.Value.GetMaximumComponentPrecision() <= (int)PixelComponentBitDepth.Bit32)
{
- Rgba32 p = default;
- pixel.ToRgba32(ref p);
- return new(p);
+ for (int i = 0; i < destination.Length; i++)
+ {
+ destination[i] = new(source[i].ToScaledVector4());
+ }
}
else
{
- return new(pixel);
+ for (int i = 0; i < destination.Length; i++)
+ {
+ destination[i] = new(source[i]);
+ }
}
}
@@ -151,8 +147,7 @@ public readonly partial struct Color : IEquatable
public static Color ParseHex(string hex)
{
Rgba32 rgba = Rgba32.ParseHex(hex);
-
- return new Color(rgba);
+ return FromPixel(rgba);
}
///
@@ -174,7 +169,7 @@ public readonly partial struct Color : IEquatable
if (Rgba32.TryParseHex(hex, out Rgba32 rgba))
{
- result = new Color(rgba);
+ result = FromPixel(rgba);
return true;
}
@@ -255,12 +250,10 @@ public readonly partial struct Color : IEquatable
{
if (this.boxedHighPrecisionPixel is not null)
{
- Rgba32 rgba = default;
- this.boxedHighPrecisionPixel.ToRgba32(ref rgba);
- return rgba.ToHex();
+ return this.boxedHighPrecisionPixel.ToRgba32().ToHex();
}
- return this.data.ToRgba32().ToHex();
+ return Rgba32.FromScaledVector4(this.data).ToHex();
}
///
@@ -282,14 +275,10 @@ public readonly partial struct Color : IEquatable
if (this.boxedHighPrecisionPixel is null)
{
- pixel = default;
- pixel.FromRgba64(this.data);
- return pixel;
+ return TPixel.FromScaledVector4(this.data);
}
- pixel = default;
- pixel.FromScaledVector4(this.boxedHighPrecisionPixel.ToScaledVector4());
- return pixel;
+ return TPixel.FromScaledVector4(this.boxedHighPrecisionPixel.ToScaledVector4());
}
///
@@ -302,7 +291,8 @@ public readonly partial struct Color : IEquatable
public static void ToPixel(ReadOnlySpan source, Span destination)
where TPixel : unmanaged, IPixel
{
- // TODO: Investigate bulk operations utilizing configuration parameter here.
+ // We cannot use bulk pixel operations here as there is no guarantee that the source colors are
+ // created from pixel formats which fit into the unboxed vector data.
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
for (int i = 0; i < source.Length; i++)
{
@@ -316,7 +306,7 @@ public readonly partial struct Color : IEquatable
{
if (this.boxedHighPrecisionPixel is null && other.boxedHighPrecisionPixel is null)
{
- return this.data.PackedValue == other.data.PackedValue;
+ return this.data == other.data;
}
return this.boxedHighPrecisionPixel?.Equals(other.boxedHighPrecisionPixel) == true;
@@ -331,9 +321,20 @@ public readonly partial struct Color : IEquatable
{
if (this.boxedHighPrecisionPixel is null)
{
- return this.data.PackedValue.GetHashCode();
+ return this.data.GetHashCode();
}
return this.boxedHighPrecisionPixel.GetHashCode();
}
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ private Vector4 ToScaledVector4()
+ {
+ if (this.boxedHighPrecisionPixel is null)
+ {
+ return this.data;
+ }
+
+ return this.boxedHighPrecisionPixel.ToScaledVector4();
+ }
}
diff --git a/src/ImageSharp/Common/Helpers/ColorNumerics.cs b/src/ImageSharp/Common/Helpers/ColorNumerics.cs
index 553a7c2e8..1c30d857f 100644
--- a/src/ImageSharp/Common/Helpers/ColorNumerics.cs
+++ b/src/ImageSharp/Common/Helpers/ColorNumerics.cs
@@ -41,6 +41,34 @@ internal static class ColorNumerics
public static byte Get8BitBT709Luminance(byte r, byte g, byte b)
=> (byte)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F);
+ ///
+ /// Gets the luminance from the rgb components using the formula
+ /// as specified by ITU-R Recommendation BT.709.
+ ///
+ /// The red component.
+ /// The green component.
+ /// The blue component.
+ /// The .
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static byte Get8BitBT709Luminance(ushort r, ushort g, ushort b)
+ => (byte)((From16BitTo8Bit(r) * .2126F) +
+ (From16BitTo8Bit(g) * .7152F) +
+ (From16BitTo8Bit(b) * .0722F) + 0.5F);
+
+ ///
+ /// Gets the luminance from the rgb components using the formula as
+ /// specified by ITU-R Recommendation BT.709.
+ ///
+ /// The red component.
+ /// The green component.
+ /// The blue component.
+ /// The .
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ushort Get16BitBT709Luminance(byte r, byte g, byte b)
+ => (ushort)((From8BitTo16Bit(r) * .2126F) +
+ (From8BitTo16Bit(g) * .7152F) +
+ (From8BitTo16Bit(b) * .0722F) + 0.5F);
+
///
/// Gets the luminance from the rgb components using the formula as
/// specified by ITU-R Recommendation BT.709.
@@ -72,8 +100,8 @@ internal static class ColorNumerics
/// The 8 bit component value.
/// The
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static byte DownScaleFrom16BitTo8Bit(ushort component)
- {
+ public static byte From16BitTo8Bit(ushort component) =>
+
// To scale to 8 bits From a 16-bit value V the required value (from the PNG specification) is:
//
// (V * 255) / 65535
@@ -102,8 +130,7 @@ internal static class ColorNumerics
// An alternative arithmetic calculation which also gives no errors is:
//
// (V * 255 + 32895) >> 16
- return (byte)(((component * 255) + 32895) >> 16);
- }
+ (byte)(((component * 255) + 32895) >> 16);
///
/// Scales a value from an 8 bit to
@@ -112,7 +139,7 @@ internal static class ColorNumerics
/// The 8 bit component value.
/// The
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ushort UpscaleFrom8BitTo16Bit(byte component)
+ public static ushort From8BitTo16Bit(byte component)
=> (ushort)(component * 257);
///
diff --git a/src/ImageSharp/Common/Helpers/Numerics.cs b/src/ImageSharp/Common/Helpers/Numerics.cs
index 293997c4d..ca28a7aab 100644
--- a/src/ImageSharp/Common/Helpers/Numerics.cs
+++ b/src/ImageSharp/Common/Helpers/Numerics.cs
@@ -5,7 +5,6 @@ using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
-using System.Runtime.Intrinsics.Arm;
using System.Runtime.Intrinsics.X86;
namespace SixLabors.ImageSharp;
@@ -61,6 +60,12 @@ internal static class Numerics
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static nint Modulo4(nint x) => x & 3;
+ ///
+ /// Calculates % 4
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static nuint Modulo4(nuint x) => x & 3;
+
///
/// Calculates % 8
///
diff --git a/src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs b/src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs
index 683ac518b..c856267db 100644
--- a/src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs
+++ b/src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs
@@ -1,12 +1,6 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-using System.Buffers.Binary;
-using System.Numerics;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using static SixLabors.ImageSharp.SimdUtils;
-
// The JIT can detect and optimize rotation idioms ROTL (Rotate Left)
// and ROTR (Rotate Right) emitting efficient CPU instructions:
// https://github.com/dotnet/coreclr/pull/1830
@@ -19,190 +13,24 @@ namespace SixLabors.ImageSharp;
internal interface IComponentShuffle
{
///
- /// Shuffles then slices 8-bit integers within 128-bit lanes in
- /// using the control and store the results in .
+ /// Shuffles then slices 8-bit integers in
+ /// using a byte control and store the results in .
+ /// If successful, this method will reduce the length of length
+ /// by the shuffle amount.
///
/// The source span of bytes.
- /// The destination span of bytes.
- void ShuffleReduce(ref ReadOnlySpan source, ref Span dest);
+ /// The destination span of bytes.
+ void ShuffleReduce(ref ReadOnlySpan source, ref Span destination);
///
- /// Shuffle 8-bit integers within 128-bit lanes in
- /// using the control and store the results in .
+ /// Shuffle 8-bit integers in
+ /// using the control and store the results in .
///
/// The source span of bytes.
- /// The destination span of bytes.
+ /// The destination span of bytes.
///
- /// Implementation can assume that source.Length is less or equal than dest.Length.
+ /// Implementation can assume that source.Length is less or equal than destination.Length.
/// Loops should iterate using source.Length.
///
- void RunFallbackShuffle(ReadOnlySpan source, Span dest);
-}
-
-///
-internal interface IShuffle4 : IComponentShuffle
-{
-}
-
-internal readonly struct DefaultShuffle4 : IShuffle4
-{
- public DefaultShuffle4(byte control)
- => this.Control = control;
-
- public byte Control { get; }
-
- [MethodImpl(InliningOptions.ShortMethod)]
- public void ShuffleReduce(ref ReadOnlySpan source, ref Span dest)
- => HwIntrinsics.Shuffle4Reduce(ref source, ref dest, this.Control);
-
- [MethodImpl(InliningOptions.ShortMethod)]
- public void RunFallbackShuffle(ReadOnlySpan source, Span dest)
- {
- ref byte sBase = ref MemoryMarshal.GetReference(source);
- ref byte dBase = ref MemoryMarshal.GetReference(dest);
-
- Shuffle.InverseMMShuffle(this.Control, out uint p3, out uint p2, out uint p1, out uint p0);
-
- for (nuint i = 0; i < (uint)source.Length; i += 4)
- {
- Unsafe.Add(ref dBase, i + 0) = Unsafe.Add(ref sBase, p0 + i);
- Unsafe.Add(ref dBase, i + 1) = Unsafe.Add(ref sBase, p1 + i);
- Unsafe.Add(ref dBase, i + 2) = Unsafe.Add(ref sBase, p2 + i);
- Unsafe.Add(ref dBase, i + 3) = Unsafe.Add(ref sBase, p3 + i);
- }
- }
-}
-
-internal readonly struct WXYZShuffle4 : IShuffle4
-{
- [MethodImpl(InliningOptions.ShortMethod)]
- public void ShuffleReduce(ref ReadOnlySpan source, ref Span dest)
- => HwIntrinsics.Shuffle4Reduce(ref source, ref dest, Shuffle.MMShuffle2103);
-
- [MethodImpl(InliningOptions.ShortMethod)]
- public void RunFallbackShuffle(ReadOnlySpan source, Span dest)
- {
- ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source));
- ref uint dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest));
- uint n = (uint)source.Length / 4;
-
- for (nuint i = 0; i < n; i++)
- {
- uint packed = Unsafe.Add(ref sBase, i);
-
- // packed = [W Z Y X]
- // ROTL(8, packed) = [Z Y X W]
- Unsafe.Add(ref dBase, i) = (packed << 8) | (packed >> 24);
- }
- }
-}
-
-internal readonly struct WZYXShuffle4 : IShuffle4
-{
- [MethodImpl(InliningOptions.ShortMethod)]
- public void ShuffleReduce(ref ReadOnlySpan source, ref Span dest)
- => HwIntrinsics.Shuffle4Reduce(ref source, ref dest, Shuffle.MMShuffle0123);
-
- [MethodImpl(InliningOptions.ShortMethod)]
- public void RunFallbackShuffle(ReadOnlySpan source, Span dest)
- {
- ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source));
- ref uint dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest));
- uint n = (uint)source.Length / 4;
-
- for (nuint i = 0; i < n; i++)
- {
- uint packed = Unsafe.Add(ref sBase, i);
-
- // packed = [W Z Y X]
- // REVERSE(packedArgb) = [X Y Z W]
- Unsafe.Add(ref dBase, i) = BinaryPrimitives.ReverseEndianness(packed);
- }
- }
-}
-
-internal readonly struct YZWXShuffle4 : IShuffle4
-{
- [MethodImpl(InliningOptions.ShortMethod)]
- public void ShuffleReduce(ref ReadOnlySpan source, ref Span dest)
- => HwIntrinsics.Shuffle4Reduce(ref source, ref dest, Shuffle.MMShuffle0321);
-
- [MethodImpl(InliningOptions.ShortMethod)]
- public void RunFallbackShuffle(ReadOnlySpan source, Span dest)
- {
- ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source));
- ref uint dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest));
- uint n = (uint)source.Length / 4;
-
- for (nuint i = 0; i < n; i++)
- {
- uint packed = Unsafe.Add(ref sBase, i);
-
- // packed = [W Z Y X]
- // ROTR(8, packedArgb) = [Y Z W X]
- Unsafe.Add(ref dBase, i) = BitOperations.RotateRight(packed, 8);
- }
- }
-}
-
-internal readonly struct ZYXWShuffle4 : IShuffle4
-{
- [MethodImpl(InliningOptions.ShortMethod)]
- public void ShuffleReduce(ref ReadOnlySpan source, ref Span dest)
- => HwIntrinsics.Shuffle4Reduce(ref source, ref dest, Shuffle.MMShuffle3012);
-
- [MethodImpl(InliningOptions.ShortMethod)]
- public void RunFallbackShuffle(ReadOnlySpan source, Span dest)
- {
- ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source));
- ref uint dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest));
- uint n = (uint)source.Length / 4;
-
- for (nuint i = 0; i < n; i++)
- {
- uint packed = Unsafe.Add(ref sBase, i);
-
- // packed = [W Z Y X]
- // tmp1 = [W 0 Y 0]
- // tmp2 = [0 Z 0 X]
- // tmp3=ROTL(16, tmp2) = [0 X 0 Z]
- // tmp1 + tmp3 = [W X Y Z]
- uint tmp1 = packed & 0xFF00FF00;
- uint tmp2 = packed & 0x00FF00FF;
- uint tmp3 = BitOperations.RotateLeft(tmp2, 16);
-
- Unsafe.Add(ref dBase, i) = tmp1 + tmp3;
- }
- }
-}
-
-internal readonly struct XWZYShuffle4 : IShuffle4
-{
- [MethodImpl(InliningOptions.ShortMethod)]
- public void ShuffleReduce(ref ReadOnlySpan source, ref Span dest)
- => HwIntrinsics.Shuffle4Reduce(ref source, ref dest, Shuffle.MMShuffle1230);
-
- [MethodImpl(InliningOptions.ShortMethod)]
- public void RunFallbackShuffle(ReadOnlySpan source, Span dest)
- {
- ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source));
- ref uint dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest));
- uint n = (uint)source.Length / 4;
-
- for (nuint i = 0; i < n; i++)
- {
- uint packed = Unsafe.Add(ref sBase, i);
-
- // packed = [W Z Y X]
- // tmp1 = [0 Z 0 X]
- // tmp2 = [W 0 Y 0]
- // tmp3=ROTL(16, tmp2) = [Y 0 W 0]
- // tmp1 + tmp3 = [Y Z W X]
- uint tmp1 = packed & 0x00FF00FF;
- uint tmp2 = packed & 0xFF00FF00;
- uint tmp3 = BitOperations.RotateLeft(tmp2, 16);
-
- Unsafe.Add(ref dBase, i) = tmp1 + tmp3;
- }
- }
+ void Shuffle(ReadOnlySpan source, Span destination);
}
diff --git a/src/ImageSharp/Common/Helpers/Shuffle/IPad3Shuffle4.cs b/src/ImageSharp/Common/Helpers/Shuffle/IPad3Shuffle4.cs
index 6cf6eef08..0f282c7f9 100644
--- a/src/ImageSharp/Common/Helpers/Shuffle/IPad3Shuffle4.cs
+++ b/src/ImageSharp/Common/Helpers/Shuffle/IPad3Shuffle4.cs
@@ -1,6 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
+using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using static SixLabors.ImageSharp.SimdUtils;
@@ -12,24 +13,23 @@ internal interface IPad3Shuffle4 : IComponentShuffle
{
}
-internal readonly struct DefaultPad3Shuffle4 : IPad3Shuffle4
+internal readonly struct DefaultPad3Shuffle4([ConstantExpected] byte control) : IPad3Shuffle4
{
- public DefaultPad3Shuffle4(byte control)
- => this.Control = control;
-
- public byte Control { get; }
+ public byte Control { get; } = control;
[MethodImpl(InliningOptions.ShortMethod)]
- public void ShuffleReduce(ref ReadOnlySpan source, ref Span dest)
- => HwIntrinsics.Pad3Shuffle4Reduce(ref source, ref dest, this.Control);
+ public void ShuffleReduce(ref ReadOnlySpan source, ref Span destination)
+#pragma warning disable CA1857 // A constant is expected for the parameter
+ => HwIntrinsics.Pad3Shuffle4Reduce(ref source, ref destination, this.Control);
+#pragma warning restore CA1857 // A constant is expected for the parameter
[MethodImpl(InliningOptions.ShortMethod)]
- public void RunFallbackShuffle(ReadOnlySpan source, Span dest)
+ public void Shuffle(ReadOnlySpan source, Span destination)
{
ref byte sBase = ref MemoryMarshal.GetReference(source);
- ref byte dBase = ref MemoryMarshal.GetReference(dest);
+ ref byte dBase = ref MemoryMarshal.GetReference(destination);
- Shuffle.InverseMMShuffle(this.Control, out uint p3, out uint p2, out uint p1, out uint p0);
+ SimdUtils.Shuffle.InverseMMShuffle(this.Control, out uint p3, out uint p2, out uint p1, out uint p0);
Span temp = stackalloc byte[4];
ref byte t = ref MemoryMarshal.GetReference(temp);
@@ -51,14 +51,14 @@ internal readonly struct DefaultPad3Shuffle4 : IPad3Shuffle4
internal readonly struct XYZWPad3Shuffle4 : IPad3Shuffle4
{
[MethodImpl(InliningOptions.ShortMethod)]
- public void ShuffleReduce(ref ReadOnlySpan source, ref Span dest)
- => HwIntrinsics.Pad3Shuffle4Reduce(ref source, ref dest, Shuffle.MMShuffle3210);
+ public void ShuffleReduce(ref ReadOnlySpan source, ref Span destination)
+ => HwIntrinsics.Pad3Shuffle4Reduce(ref source, ref destination, SimdUtils.Shuffle.MMShuffle3210);
[MethodImpl(InliningOptions.ShortMethod)]
- public void RunFallbackShuffle(ReadOnlySpan source, Span dest)
+ public void Shuffle(ReadOnlySpan source, Span destination)
{
ref byte sBase = ref MemoryMarshal.GetReference(source);
- ref byte dBase = ref MemoryMarshal.GetReference(dest);
+ ref byte dBase = ref MemoryMarshal.GetReference(destination);
ref byte sEnd = ref Unsafe.Add(ref sBase, (uint)source.Length);
ref byte sLoopEnd = ref Unsafe.Subtract(ref sEnd, 4);
diff --git a/src/ImageSharp/Common/Helpers/Shuffle/IShuffle3.cs b/src/ImageSharp/Common/Helpers/Shuffle/IShuffle3.cs
index 2cd586212..3c0973ad6 100644
--- a/src/ImageSharp/Common/Helpers/Shuffle/IShuffle3.cs
+++ b/src/ImageSharp/Common/Helpers/Shuffle/IShuffle3.cs
@@ -1,6 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
+using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using static SixLabors.ImageSharp.SimdUtils;
@@ -12,24 +13,23 @@ internal interface IShuffle3 : IComponentShuffle
{
}
-internal readonly struct DefaultShuffle3 : IShuffle3
+internal readonly struct DefaultShuffle3([ConstantExpected] byte control) : IShuffle3
{
- public DefaultShuffle3(byte control)
- => this.Control = control;
-
- public byte Control { get; }
+ public byte Control { get; } = control;
[MethodImpl(InliningOptions.ShortMethod)]
- public void ShuffleReduce(ref ReadOnlySpan source, ref Span dest)
- => HwIntrinsics.Shuffle3Reduce(ref source, ref dest, this.Control);
+ public void ShuffleReduce(ref ReadOnlySpan source, ref Span destination)
+#pragma warning disable CA1857 // A constant is expected for the parameter
+ => HwIntrinsics.Shuffle3Reduce(ref source, ref destination, this.Control);
+#pragma warning restore CA1857 // A constant is expected for the parameter
[MethodImpl(InliningOptions.ShortMethod)]
- public void RunFallbackShuffle(ReadOnlySpan source, Span dest)
+ public void Shuffle(ReadOnlySpan source, Span destination)
{
ref byte sBase = ref MemoryMarshal.GetReference(source);
- ref byte dBase = ref MemoryMarshal.GetReference(dest);
+ ref byte dBase = ref MemoryMarshal.GetReference(destination);
- Shuffle.InverseMMShuffle(this.Control, out _, out uint p2, out uint p1, out uint p0);
+ SimdUtils.Shuffle.InverseMMShuffle(this.Control, out _, out uint p2, out uint p1, out uint p0);
for (nuint i = 0; i < (uint)source.Length; i += 3)
{
diff --git a/src/ImageSharp/Common/Helpers/Shuffle/IShuffle4.cs b/src/ImageSharp/Common/Helpers/Shuffle/IShuffle4.cs
new file mode 100644
index 000000000..d5c6df2c8
--- /dev/null
+++ b/src/ImageSharp/Common/Helpers/Shuffle/IShuffle4.cs
@@ -0,0 +1,178 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Buffers.Binary;
+using System.Diagnostics.CodeAnalysis;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using static SixLabors.ImageSharp.SimdUtils;
+
+namespace SixLabors.ImageSharp;
+
+///
+internal interface IShuffle4 : IComponentShuffle
+{
+}
+
+internal readonly struct DefaultShuffle4([ConstantExpected] byte control) : IShuffle4
+{
+ public byte Control { get; } = control;
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void ShuffleReduce(ref ReadOnlySpan source, ref Span destination)
+#pragma warning disable CA1857 // A constant is expected for the parameter
+ => HwIntrinsics.Shuffle4Reduce(ref source, ref destination, this.Control);
+#pragma warning restore CA1857 // A constant is expected for the parameter
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void Shuffle(ReadOnlySpan source, Span destination)
+ {
+ ref byte sBase = ref MemoryMarshal.GetReference(source);
+ ref byte dBase = ref MemoryMarshal.GetReference(destination);
+
+ SimdUtils.Shuffle.InverseMMShuffle(this.Control, out uint p3, out uint p2, out uint p1, out uint p0);
+
+ for (nuint i = 0; i < (uint)source.Length; i += 4)
+ {
+ Unsafe.Add(ref dBase, i + 0) = Unsafe.Add(ref sBase, p0 + i);
+ Unsafe.Add(ref dBase, i + 1) = Unsafe.Add(ref sBase, p1 + i);
+ Unsafe.Add(ref dBase, i + 2) = Unsafe.Add(ref sBase, p2 + i);
+ Unsafe.Add(ref dBase, i + 3) = Unsafe.Add(ref sBase, p3 + i);
+ }
+ }
+}
+
+internal readonly struct WXYZShuffle4 : IShuffle4
+{
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void ShuffleReduce(ref ReadOnlySpan source, ref Span destination)
+ => HwIntrinsics.Shuffle4Reduce(ref source, ref destination, SimdUtils.Shuffle.MMShuffle2103);
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void Shuffle(ReadOnlySpan source, Span destination)
+ {
+ ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source));
+ ref uint dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(destination));
+ uint n = (uint)source.Length / 4;
+
+ for (nuint i = 0; i < n; i++)
+ {
+ uint packed = Unsafe.Add(ref sBase, i);
+
+ // packed = [W Z Y X]
+ // ROTL(8, packed) = [Z Y X W]
+ Unsafe.Add(ref dBase, i) = (packed << 8) | (packed >> 24);
+ }
+ }
+}
+
+internal readonly struct WZYXShuffle4 : IShuffle4
+{
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void ShuffleReduce(ref ReadOnlySpan source, ref Span destination)
+ => HwIntrinsics.Shuffle4Reduce(ref source, ref destination, SimdUtils.Shuffle.MMShuffle0123);
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void Shuffle(ReadOnlySpan source, Span destination)
+ {
+ ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source));
+ ref uint dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(destination));
+ uint n = (uint)source.Length / 4;
+
+ for (nuint i = 0; i < n; i++)
+ {
+ uint packed = Unsafe.Add(ref sBase, i);
+
+ // packed = [W Z Y X]
+ // REVERSE(packedArgb) = [X Y Z W]
+ Unsafe.Add(ref dBase, i) = BinaryPrimitives.ReverseEndianness(packed);
+ }
+ }
+}
+
+internal readonly struct YZWXShuffle4 : IShuffle4
+{
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void ShuffleReduce(ref ReadOnlySpan source, ref Span destination)
+ => HwIntrinsics.Shuffle4Reduce(ref source, ref destination, SimdUtils.Shuffle.MMShuffle0321);
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void Shuffle(ReadOnlySpan source, Span destination)
+ {
+ ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source));
+ ref uint dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(destination));
+ uint n = (uint)source.Length / 4;
+
+ for (nuint i = 0; i < n; i++)
+ {
+ uint packed = Unsafe.Add(ref sBase, i);
+
+ // packed = [W Z Y X]
+ // ROTR(8, packedArgb) = [Y Z W X]
+ Unsafe.Add(ref dBase, i) = BitOperations.RotateRight(packed, 8);
+ }
+ }
+}
+
+internal readonly struct ZYXWShuffle4 : IShuffle4
+{
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void ShuffleReduce(ref ReadOnlySpan source, ref Span destination)
+ => HwIntrinsics.Shuffle4Reduce(ref source, ref destination, SimdUtils.Shuffle.MMShuffle3012);
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void Shuffle(ReadOnlySpan source, Span destination)
+ {
+ ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source));
+ ref uint dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(destination));
+ uint n = (uint)source.Length / 4;
+
+ for (nuint i = 0; i < n; i++)
+ {
+ uint packed = Unsafe.Add(ref sBase, i);
+
+ // packed = [W Z Y X]
+ // tmp1 = [W 0 Y 0]
+ // tmp2 = [0 Z 0 X]
+ // tmp3=ROTL(16, tmp2) = [0 X 0 Z]
+ // tmp1 + tmp3 = [W X Y Z]
+ uint tmp1 = packed & 0xFF00FF00;
+ uint tmp2 = packed & 0x00FF00FF;
+ uint tmp3 = BitOperations.RotateLeft(tmp2, 16);
+
+ Unsafe.Add(ref dBase, i) = tmp1 + tmp3;
+ }
+ }
+}
+
+internal readonly struct XWZYShuffle4 : IShuffle4
+{
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void ShuffleReduce(ref ReadOnlySpan source, ref Span destination)
+ => HwIntrinsics.Shuffle4Reduce(ref source, ref destination, SimdUtils.Shuffle.MMShuffle1230);
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void Shuffle(ReadOnlySpan source, Span destination)
+ {
+ ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source));
+ ref uint dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(destination));
+ uint n = (uint)source.Length / 4;
+
+ for (nuint i = 0; i < n; i++)
+ {
+ uint packed = Unsafe.Add(ref sBase, i);
+
+ // packed = [W Z Y X]
+ // tmp1 = [0 Z 0 X]
+ // tmp2 = [W 0 Y 0]
+ // tmp3=ROTL(16, tmp2) = [Y 0 W 0]
+ // tmp1 + tmp3 = [Y Z W X]
+ uint tmp1 = packed & 0x00FF00FF;
+ uint tmp2 = packed & 0xFF00FF00;
+ uint tmp3 = BitOperations.RotateLeft(tmp2, 16);
+
+ Unsafe.Add(ref dBase, i) = tmp1 + tmp3;
+ }
+ }
+}
diff --git a/src/ImageSharp/Common/Helpers/Shuffle/IShuffle4Slice3.cs b/src/ImageSharp/Common/Helpers/Shuffle/IShuffle4Slice3.cs
index 5e82973e3..3e7e44066 100644
--- a/src/ImageSharp/Common/Helpers/Shuffle/IShuffle4Slice3.cs
+++ b/src/ImageSharp/Common/Helpers/Shuffle/IShuffle4Slice3.cs
@@ -1,6 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
+using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using static SixLabors.ImageSharp.SimdUtils;
@@ -12,26 +13,25 @@ internal interface IShuffle4Slice3 : IComponentShuffle
{
}
-internal readonly struct DefaultShuffle4Slice3 : IShuffle4Slice3
+internal readonly struct DefaultShuffle4Slice3([ConstantExpected] byte control) : IShuffle4Slice3
{
- public DefaultShuffle4Slice3(byte control)
- => this.Control = control;
-
- public byte Control { get; }
+ public byte Control { get; } = control;
[MethodImpl(InliningOptions.ShortMethod)]
- public void ShuffleReduce(ref ReadOnlySpan source, ref Span dest)
- => HwIntrinsics.Shuffle4Slice3Reduce(ref source, ref dest, this.Control);
+ public void ShuffleReduce(ref ReadOnlySpan source, ref Span destination)
+#pragma warning disable CA1857 // A constant is expected for the parameter
+ => HwIntrinsics.Shuffle4Slice3Reduce(ref source, ref destination, this.Control);
+#pragma warning restore CA1857 // A constant is expected for the parameter
[MethodImpl(InliningOptions.ShortMethod)]
- public void RunFallbackShuffle(ReadOnlySpan source, Span dest)
+ public void Shuffle(ReadOnlySpan source, Span destination)
{
ref byte sBase = ref MemoryMarshal.GetReference(source);
- ref byte dBase = ref MemoryMarshal.GetReference(dest);
+ ref byte dBase = ref MemoryMarshal.GetReference(destination);
- Shuffle.InverseMMShuffle(this.Control, out _, out uint p2, out uint p1, out uint p0);
+ SimdUtils.Shuffle.InverseMMShuffle(this.Control, out _, out uint p2, out uint p1, out uint p0);
- for (nuint i = 0, j = 0; i < (uint)dest.Length; i += 3, j += 4)
+ for (nuint i = 0, j = 0; i < (uint)destination.Length; i += 3, j += 4)
{
Unsafe.Add(ref dBase, i + 0) = Unsafe.Add(ref sBase, p0 + j);
Unsafe.Add(ref dBase, i + 1) = Unsafe.Add(ref sBase, p1 + j);
@@ -43,14 +43,14 @@ internal readonly struct DefaultShuffle4Slice3 : IShuffle4Slice3
internal readonly struct XYZWShuffle4Slice3 : IShuffle4Slice3
{
[MethodImpl(InliningOptions.ShortMethod)]
- public void ShuffleReduce(ref ReadOnlySpan source, ref Span dest)
- => HwIntrinsics.Shuffle4Slice3Reduce(ref source, ref dest, Shuffle.MMShuffle3210);
+ public void ShuffleReduce(ref ReadOnlySpan source, ref Span destination)
+ => HwIntrinsics.Shuffle4Slice3Reduce(ref source, ref destination, SimdUtils.Shuffle.MMShuffle3210);
[MethodImpl(InliningOptions.ShortMethod)]
- public void RunFallbackShuffle(ReadOnlySpan source, Span dest)
+ public void Shuffle(ReadOnlySpan source, Span destination)
{
ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source));
- ref Byte3 dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest));
+ ref Byte3 dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(destination));
nint n = (nint)(uint)source.Length / 4;
nint m = Numerics.Modulo4(n);
diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs
index ad079b52e..f27852a82 100644
--- a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs
+++ b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs
@@ -8,6 +8,7 @@ using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.Arm;
using System.Runtime.Intrinsics.X86;
+using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp;
@@ -51,22 +52,34 @@ internal static partial class SimdUtils
///
/// Shuffle single-precision (32-bit) floating-point elements in
- /// using the control and store the results in .
+ /// using the control and store the results in .
///
/// The source span of floats.
- /// The destination span of floats.
+ /// The destination span of floats.
/// The byte control.
[MethodImpl(InliningOptions.ShortMethod)]
public static void Shuffle4Reduce(
ref ReadOnlySpan source,
- ref Span dest,
+ ref Span destination,
[ConstantExpected] byte control)
{
- if (Avx.IsSupported || Sse.IsSupported)
+ if ((Vector512.IsHardwareAccelerated && Vector512Utilities.SupportsShuffleFloat) ||
+ (Vector256.IsHardwareAccelerated && Vector256Utilities.SupportsShuffleFloat) ||
+ (Vector128.IsHardwareAccelerated && Vector128Utilities.SupportsShuffleFloat))
{
- int remainder = Avx.IsSupported
- ? Numerics.ModuloP2(source.Length, Vector256.Count)
- : Numerics.ModuloP2(source.Length, Vector128.Count);
+ int remainder = 0;
+ if (Vector512.IsHardwareAccelerated)
+ {
+ remainder = Numerics.ModuloP2(source.Length, Vector512.Count);
+ }
+ else if (Vector256.IsHardwareAccelerated)
+ {
+ remainder = Numerics.ModuloP2(source.Length, Vector256.Count);
+ }
+ else if (Vector128.IsHardwareAccelerated)
+ {
+ remainder = Numerics.ModuloP2(source.Length, Vector128.Count);
+ }
int adjustedCount = source.Length - remainder;
@@ -74,33 +87,45 @@ internal static partial class SimdUtils
{
Shuffle4(
source[..adjustedCount],
- dest[..adjustedCount],
+ destination[..adjustedCount],
control);
source = source[adjustedCount..];
- dest = dest[adjustedCount..];
+ destination = destination[adjustedCount..];
}
}
}
///
- /// Shuffle 8-bit integers within 128-bit lanes in
- /// using the control and store the results in .
+ /// Shuffle 8-bit integers
+ /// using the control and store the results in .
///
/// The source span of bytes.
- /// The destination span of bytes.
+ /// The destination span of bytes.
/// The byte control.
[MethodImpl(InliningOptions.ShortMethod)]
public static void Shuffle4Reduce(
ref ReadOnlySpan source,
- ref Span dest,
- byte control)
+ ref Span destination,
+ [ConstantExpected] byte control)
{
- if (Avx2.IsSupported || Ssse3.IsSupported)
+ if ((Vector512.IsHardwareAccelerated && Vector512Utilities.SupportsShuffleByte) ||
+ (Vector256.IsHardwareAccelerated && Vector256Utilities.SupportsShuffleByte) ||
+ (Vector128.IsHardwareAccelerated && Vector128Utilities.SupportsShuffleByte))
{
- int remainder = Avx2.IsSupported
- ? Numerics.ModuloP2(source.Length, Vector256.Count)
- : Numerics.ModuloP2(source.Length, Vector128.Count);
+ int remainder = 0;
+ if (Vector512.IsHardwareAccelerated)
+ {
+ remainder = Numerics.ModuloP2(source.Length, Vector512.Count);
+ }
+ else if (Vector256.IsHardwareAccelerated)
+ {
+ remainder = Numerics.ModuloP2(source.Length, Vector256.Count);
+ }
+ else if (Vector128.IsHardwareAccelerated)
+ {
+ remainder = Numerics.ModuloP2(source.Length, Vector128.Count);
+ }
int adjustedCount = source.Length - remainder;
@@ -108,29 +133,29 @@ internal static partial class SimdUtils
{
Shuffle4(
source[..adjustedCount],
- dest[..adjustedCount],
+ destination[..adjustedCount],
control);
source = source[adjustedCount..];
- dest = dest[adjustedCount..];
+ destination = destination[adjustedCount..];
}
}
}
///
- /// Shuffles 8-bit integer triplets within 128-bit lanes in
- /// using the control and store the results in .
+ /// Shuffles 8-bit integer triplets in
+ /// using the control and store the results in .
///
/// The source span of bytes.
- /// The destination span of bytes.
+ /// The destination span of bytes.
/// The byte control.
[MethodImpl(InliningOptions.ShortMethod)]
public static void Shuffle3Reduce(
ref ReadOnlySpan source,
- ref Span dest,
- byte control)
+ ref Span destination,
+ [ConstantExpected] byte control)
{
- if (Ssse3.IsSupported)
+ if (Vector128.IsHardwareAccelerated && Vector128Utilities.SupportsShuffleByte && Vector128Utilities.SupportsRightAlign)
{
int remainder = source.Length % (Vector128.Count * 3);
@@ -140,77 +165,77 @@ internal static partial class SimdUtils
{
Shuffle3(
source[..adjustedCount],
- dest[..adjustedCount],
+ destination[..adjustedCount],
control);
source = source[adjustedCount..];
- dest = dest[adjustedCount..];
+ destination = destination[adjustedCount..];
}
}
}
///
- /// Pads then shuffles 8-bit integers within 128-bit lanes in
- /// using the control and store the results in .
+ /// Pads then shuffles 8-bit integers in
+ /// using the control and store the results in .
///
/// The source span of bytes.
- /// The destination span of bytes.
+ /// The destination span of bytes.
/// The byte control.
[MethodImpl(InliningOptions.ShortMethod)]
public static void Pad3Shuffle4Reduce(
ref ReadOnlySpan source,
- ref Span dest,
- byte control)
+ ref Span destination,
+ [ConstantExpected] byte control)
{
- if (Ssse3.IsSupported)
+ if (Vector128.IsHardwareAccelerated && Vector128Utilities.SupportsShuffleByte && Vector128Utilities.SupportsShiftByte)
{
int remainder = source.Length % (Vector128.Count * 3);
int sourceCount = source.Length - remainder;
- int destCount = (int)((uint)sourceCount * 4 / 3);
+ int destinationCount = (int)((uint)sourceCount * 4 / 3);
if (sourceCount > 0)
{
Pad3Shuffle4(
source[..sourceCount],
- dest[..destCount],
+ destination[..destinationCount],
control);
source = source[sourceCount..];
- dest = dest[destCount..];
+ destination = destination[destinationCount..];
}
}
}
///
- /// Shuffles then slices 8-bit integers within 128-bit lanes in
- /// using the control and store the results in .
+ /// Shuffles then slices 8-bit integers in
+ /// using the control and store the results in .
///
/// The source span of bytes.
- /// The destination span of bytes.
+ /// The destination span of bytes.
/// The byte control.
[MethodImpl(InliningOptions.ShortMethod)]
public static void Shuffle4Slice3Reduce(
ref ReadOnlySpan source,
- ref Span dest,
- byte control)
+ ref Span destination,
+ [ConstantExpected] byte control)
{
- if (Ssse3.IsSupported)
+ if (Vector128.IsHardwareAccelerated && Vector128Utilities.SupportsShuffleByte && Vector128Utilities.SupportsShiftByte)
{
int remainder = source.Length & ((Vector128.Count * 4) - 1); // bit-hack for modulo
int sourceCount = source.Length - remainder;
- int destCount = (int)((uint)sourceCount * 3 / 4);
+ int destinationCount = (int)((uint)sourceCount * 3 / 4);
if (sourceCount > 0)
{
Shuffle4Slice3(
source[..sourceCount],
- dest[..destCount],
+ destination[..destinationCount],
control);
source = source[sourceCount..];
- dest = dest[destCount..];
+ destination = destination[destinationCount..];
}
}
}
@@ -218,76 +243,90 @@ internal static partial class SimdUtils
[MethodImpl(InliningOptions.ShortMethod)]
private static void Shuffle4(
ReadOnlySpan source,
- Span dest,
+ Span destination,
[ConstantExpected] byte control)
{
- if (Avx.IsSupported)
+ if (Vector512.IsHardwareAccelerated && Vector512Utilities.SupportsShuffleFloat)
{
- ref Vector256 sourceBase =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(source));
+ ref Vector512 sourceBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(source));
+ ref Vector512 destinationBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(destination));
- ref Vector256 destBase =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(dest));
+ nuint n = (uint)destination.Length / (uint)Vector512.Count;
+ nuint m = Numerics.Modulo4(n);
+ nuint u = n - m;
- nint n = (nint)dest.Vector256Count();
- nint m = Numerics.Modulo4(n);
- nint u = n - m;
-
- for (nint i = 0; i < u; i += 4)
+ for (nuint i = 0; i < u; i += 4)
{
- ref Vector256 vd0 = ref Unsafe.Add(ref destBase, i);
- ref Vector256 vs0 = ref Unsafe.Add(ref sourceBase, i);
+ ref Vector512 vs0 = ref Unsafe.Add(ref sourceBase, i);
+ ref Vector512 vd0 = ref Unsafe.Add(ref destinationBase, i);
- vd0 = Avx.Permute(vs0, control);
- Unsafe.Add(ref vd0, 1) = Avx.Permute(Unsafe.Add(ref vs0, 1), control);
- Unsafe.Add(ref vd0, 2) = Avx.Permute(Unsafe.Add(ref vs0, 2), control);
- Unsafe.Add(ref vd0, 3) = Avx.Permute(Unsafe.Add(ref vs0, 3), control);
+ vd0 = Vector512Utilities.Shuffle(vs0, control);
+ Unsafe.Add(ref vd0, (nuint)1) = Vector512Utilities.Shuffle(Unsafe.Add(ref vs0, (nuint)1), control);
+ Unsafe.Add(ref vd0, (nuint)2) = Vector512Utilities.Shuffle(Unsafe.Add(ref vs0, (nuint)2), control);
+ Unsafe.Add(ref vd0, (nuint)3) = Vector512Utilities.Shuffle(Unsafe.Add(ref vs0, (nuint)3), control);
}
if (m > 0)
{
- for (nint i = u; i < n; i++)
+ for (nuint i = u; i < n; i++)
{
- Unsafe.Add(ref destBase, i) = Avx.Permute(Unsafe.Add(ref sourceBase, i), control);
+ Unsafe.Add(ref destinationBase, i) = Vector512Utilities.Shuffle(Unsafe.Add(ref sourceBase, i), control);
}
}
}
- else
+ else if (Vector256.IsHardwareAccelerated && Vector256Utilities.SupportsShuffleFloat)
{
- // Sse
- ref Vector128 sourceBase =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(source));
+ ref Vector256 sourceBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(source));
+ ref Vector256 destinationBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(destination));
- ref Vector128 destBase =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(dest));
+ nuint n = (uint)destination.Length / (uint)Vector256.Count;
+ nuint m = Numerics.Modulo4(n);
+ nuint u = n - m;
- nint n = (nint)((uint)dest.Length / (uint)Vector128.Count);
- nint m = Numerics.Modulo4(n);
- nint u = n - m;
-
- for (nint i = 0; i < u; i += 4)
+ for (nuint i = 0; i < u; i += 4)
{
- ref Vector128 vd0 = ref Unsafe.Add(ref destBase, i);
- ref Vector128 vs0 = ref Unsafe.Add(ref sourceBase, i);
+ ref Vector256 vs0 = ref Unsafe.Add(ref sourceBase, i);
+ ref Vector256 vd0 = ref Unsafe.Add(ref destinationBase, i);
+
+ vd0 = Vector256Utilities.Shuffle(vs0, control);
+ Unsafe.Add(ref vd0, (nuint)1) = Vector256Utilities.Shuffle(Unsafe.Add(ref vs0, (nuint)1), control);
+ Unsafe.Add(ref vd0, (nuint)2) = Vector256Utilities.Shuffle(Unsafe.Add(ref vs0, (nuint)2), control);
+ Unsafe.Add(ref vd0, (nuint)3) = Vector256Utilities.Shuffle(Unsafe.Add(ref vs0, (nuint)3), control);
+ }
- vd0 = Sse.Shuffle(vs0, vs0, control);
+ if (m > 0)
+ {
+ for (nuint i = u; i < n; i++)
+ {
+ Unsafe.Add(ref destinationBase, i) = Vector256Utilities.Shuffle(Unsafe.Add(ref sourceBase, i), control);
+ }
+ }
+ }
+ else if (Vector128.IsHardwareAccelerated && Vector128Utilities.SupportsShuffleFloat)
+ {
+ ref Vector128 sourceBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(source));
+ ref Vector128 destinationBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(destination));
- Vector128 vs1 = Unsafe.Add(ref vs0, 1);
- Unsafe.Add(ref vd0, 1) = Sse.Shuffle(vs1, vs1, control);
+ nuint n = (uint)destination.Length / (uint)Vector128.Count;
+ nuint m = Numerics.Modulo4(n);
+ nuint u = n - m;
- Vector128 vs2 = Unsafe.Add(ref vs0, 2);
- Unsafe.Add(ref vd0, 2) = Sse.Shuffle(vs2, vs2, control);
+ for (nuint i = 0; i < u; i += 4)
+ {
+ ref Vector128 vs0 = ref Unsafe.Add(ref sourceBase, i);
+ ref Vector128 vd0 = ref Unsafe.Add(ref destinationBase, i);
- Vector128 vs3 = Unsafe.Add(ref vs0, 3);
- Unsafe.Add(ref vd0, 3) = Sse.Shuffle(vs3, vs3, control);
+ vd0 = Vector128Utilities.Shuffle(vs0, control);
+ Unsafe.Add(ref vd0, (nuint)1) = Vector128Utilities.Shuffle(Unsafe.Add(ref vs0, (nuint)1), control);
+ Unsafe.Add(ref vd0, (nuint)2) = Vector128Utilities.Shuffle(Unsafe.Add(ref vs0, (nuint)2), control);
+ Unsafe.Add(ref vd0, (nuint)3) = Vector128Utilities.Shuffle(Unsafe.Add(ref vs0, (nuint)3), control);
}
if (m > 0)
{
- for (nint i = u; i < n; i++)
+ for (nuint i = u; i < n; i++)
{
- Vector128 vs = Unsafe.Add(ref sourceBase, i);
- Unsafe.Add(ref destBase, i) = Sse.Shuffle(vs, vs, control);
+ Unsafe.Add(ref destinationBase, i) = Vector128Utilities.Shuffle(Unsafe.Add(ref sourceBase, i), control);
}
}
}
@@ -296,80 +335,102 @@ internal static partial class SimdUtils
[MethodImpl(InliningOptions.ShortMethod)]
private static void Shuffle4(
ReadOnlySpan source,
- Span dest,
- byte control)
+ Span destination,
+ [ConstantExpected] byte control)
{
- if (Avx2.IsSupported)
+ if (Vector512.IsHardwareAccelerated && Vector512Utilities.SupportsShuffleByte)
{
- // I've chosen to do this for convenience while we determine what
- // shuffle controls to add to the library.
- // We can add static ROS instances if need be in the future.
- Span bytes = stackalloc byte[Vector256.Count];
- Shuffle.MMShuffleSpan(ref bytes, control);
- Vector256 vshuffle = Unsafe.As>(ref MemoryMarshal.GetReference(bytes));
+ Span temp = stackalloc byte[Vector512.Count];
+ Shuffle.MMShuffleSpan(ref temp, control);
+ Vector512 mask = Unsafe.As>(ref MemoryMarshal.GetReference(temp));
- ref Vector256 sourceBase =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(source));
+ ref Vector512 sourceBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(source));
+ ref Vector512 destinationBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(destination));
- ref Vector256 destBase =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(dest));
+ nuint n = (uint)destination.Length / (uint)Vector512.Count;
+ nuint m = Numerics.Modulo4(n);
+ nuint u = n - m;
+
+ for (nuint i = 0; i < u; i += 4)
+ {
+ ref Vector512 vs0 = ref Unsafe.Add(ref sourceBase, i);
+ ref Vector512 vd0 = ref Unsafe.Add(ref destinationBase, i);
+
+ vd0 = Vector512Utilities.Shuffle(vs0, mask);
+ Unsafe.Add(ref vd0, (nuint)1) = Vector512Utilities.Shuffle(Unsafe.Add(ref vs0, (nuint)1), mask);
+ Unsafe.Add(ref vd0, (nuint)2) = Vector512Utilities.Shuffle(Unsafe.Add(ref vs0, (nuint)2), mask);
+ Unsafe.Add(ref vd0, (nuint)3) = Vector512Utilities.Shuffle(Unsafe.Add(ref vs0, (nuint)3), mask);
+ }
+
+ if (m > 0)
+ {
+ for (nuint i = u; i < n; i++)
+ {
+ Unsafe.Add(ref destinationBase, i) = Vector512Utilities.Shuffle(Unsafe.Add(ref sourceBase, i), mask);
+ }
+ }
+ }
+ else if (Vector256.IsHardwareAccelerated && Vector256Utilities.SupportsShuffleByte)
+ {
+ Span