diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.cs b/src/ImageSharp/Common/Helpers/SimdUtils.cs
index 0279e57cc..273947272 100644
--- a/src/ImageSharp/Common/Helpers/SimdUtils.cs
+++ b/src/ImageSharp/Common/Helpers/SimdUtils.cs
@@ -1,10 +1,9 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System.Diagnostics;
using System.Numerics;
using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
@@ -36,30 +35,37 @@ internal static partial class SimdUtils
///
/// Rounds all values in 'v' to the nearest integer following semantics.
- /// Source:
- ///
- /// https://github.com/g-truc/glm/blob/master/glm/simd/common.h#L110
- ///
///
/// The vector
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static Vector FastRound(this Vector v)
{
- if (Avx2.IsSupported)
+ if (Avx512F.IsSupported && Vector.Count == Vector512.Count)
+ {
+ ref Vector512 v512 = ref Unsafe.As, Vector512>(ref v);
+
+ // imm8 = 0b1000:
+ // imm8[7:4] = 0b0000 -> preserve 0 fractional bits (round to whole numbers)
+ // imm8[3:0] = 0b1000 -> _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC (round to nearest even, suppress exceptions)
+ Vector512 vRound = Avx512F.RoundScale(v512, 0b0000_1000);
+ return Unsafe.As, Vector>(ref vRound);
+ }
+
+ if (Avx2.IsSupported && Vector.Count == Vector256.Count)
{
ref Vector256 v256 = ref Unsafe.As, Vector256>(ref v);
Vector256 vRound = Avx.RoundToNearestInteger(v256);
return Unsafe.As, Vector>(ref vRound);
}
- else
- {
- var magic0 = new Vector(int.MinValue); // 0x80000000
- var sgn0 = Vector.AsVectorSingle(magic0);
- var and0 = Vector.BitwiseAnd(sgn0, v);
- var or0 = Vector.BitwiseOr(and0, new Vector(8388608.0f));
- var add0 = Vector.Add(v, or0);
- return Vector.Subtract(add0, or0);
- }
+
+ // https://github.com/g-truc/glm/blob/master/glm/simd/common.h#L11
+ Vector magic0 = new(int.MinValue); // 0x80000000
+ Vector sgn0 = Vector.AsVectorSingle(magic0);
+ Vector and0 = Vector.BitwiseAnd(sgn0, v);
+ Vector or0 = Vector.BitwiseOr(and0, new Vector(8388608.0f));
+ Vector add0 = Vector.Add(v, or0);
+
+ return Vector.Subtract(add0, or0);
}
[Conditional("DEBUG")]
diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykArm64.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykArm64.cs
deleted file mode 100644
index 11122d3b8..000000000
--- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykArm64.cs
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Runtime.Intrinsics;
-using System.Runtime.Intrinsics.Arm;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.Components;
-
-internal abstract partial class JpegColorConverterBase
-{
- internal sealed class CmykArm64 : JpegColorConverterArm64
- {
- public CmykArm64(int precision)
- : base(JpegColorSpace.Cmyk, precision)
- {
- }
-
- ///
- public override void ConvertToRgbInplace(in ComponentValues values)
- {
- ref Vector128 c0Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
- ref Vector128 c1Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
- ref Vector128 c2Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
- ref Vector128 c3Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3));
-
- // Used for the color conversion
- var scale = Vector128.Create(1 / (this.MaximumValue * this.MaximumValue));
-
- nint n = (nint)(uint)values.Component0.Length / Vector128.Count;
- for (nint i = 0; i < n; i++)
- {
- ref Vector128 c = ref Unsafe.Add(ref c0Base, i);
- ref Vector128 m = ref Unsafe.Add(ref c1Base, i);
- ref Vector128 y = ref Unsafe.Add(ref c2Base, i);
- Vector128 k = Unsafe.Add(ref c3Base, i);
-
- k = AdvSimd.Multiply(k, scale);
- c = AdvSimd.Multiply(c, k);
- m = AdvSimd.Multiply(m, k);
- y = AdvSimd.Multiply(y, k);
- }
- }
-
- ///
- public override void ConvertFromRgb(in ComponentValues values, Span rLane, Span gLane, Span bLane)
- => ConvertFromRgb(in values, this.MaximumValue, rLane, gLane, bLane);
-
- public static void ConvertFromRgb(in ComponentValues values, float maxValue, Span rLane, Span gLane, Span bLane)
- {
- ref Vector128 destC =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
- ref Vector128 destM =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
- ref Vector128 destY =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
- ref Vector128 destK =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3));
-
- ref Vector128 srcR =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(rLane));
- ref Vector128 srcG =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(gLane));
- ref Vector128 srcB =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(bLane));
-
- var scale = Vector128.Create(maxValue);
-
- nint n = (nint)(uint)values.Component0.Length / Vector128.Count;
- for (nint i = 0; i < n; i++)
- {
- Vector128 ctmp = AdvSimd.Subtract(scale, Unsafe.Add(ref srcR, i));
- Vector128 mtmp = AdvSimd.Subtract(scale, Unsafe.Add(ref srcG, i));
- Vector128 ytmp = AdvSimd.Subtract(scale, Unsafe.Add(ref srcB, i));
- Vector128 ktmp = AdvSimd.Min(ctmp, AdvSimd.Min(mtmp, ytmp));
-
- Vector128 kMask = AdvSimd.Not(AdvSimd.CompareEqual(ktmp, scale));
-
- ctmp = AdvSimd.And(AdvSimd.Arm64.Divide(AdvSimd.Subtract(ctmp, ktmp), AdvSimd.Subtract(scale, ktmp)), kMask);
- mtmp = AdvSimd.And(AdvSimd.Arm64.Divide(AdvSimd.Subtract(mtmp, ktmp), AdvSimd.Subtract(scale, ktmp)), kMask);
- ytmp = AdvSimd.And(AdvSimd.Arm64.Divide(AdvSimd.Subtract(ytmp, ktmp), AdvSimd.Subtract(scale, ktmp)), kMask);
-
- Unsafe.Add(ref destC, i) = AdvSimd.Subtract(scale, AdvSimd.Multiply(ctmp, scale));
- Unsafe.Add(ref destM, i) = AdvSimd.Subtract(scale, AdvSimd.Multiply(mtmp, scale));
- Unsafe.Add(ref destY, i) = AdvSimd.Subtract(scale, AdvSimd.Multiply(ytmp, scale));
- Unsafe.Add(ref destK, i) = AdvSimd.Subtract(scale, ktmp);
- }
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykAvx.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykAvx.cs
deleted file mode 100644
index 76d188f45..000000000
--- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykAvx.cs
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Runtime.Intrinsics;
-using System.Runtime.Intrinsics.X86;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.Components;
-
-internal abstract partial class JpegColorConverterBase
-{
- internal sealed class CmykAvx : JpegColorConverterAvx
- {
- public CmykAvx(int precision)
- : base(JpegColorSpace.Cmyk, precision)
- {
- }
-
- ///
- public override void ConvertToRgbInplace(in ComponentValues values)
- {
- ref Vector256 c0Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
- ref Vector256 c1Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
- ref Vector256 c2Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
- ref Vector256 c3Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3));
-
- // Used for the color conversion
- var scale = Vector256.Create(1 / (this.MaximumValue * this.MaximumValue));
-
- nuint n = values.Component0.Vector256Count();
- for (nuint i = 0; i < n; i++)
- {
- ref Vector256 c = ref Unsafe.Add(ref c0Base, i);
- ref Vector256 m = ref Unsafe.Add(ref c1Base, i);
- ref Vector256 y = ref Unsafe.Add(ref c2Base, i);
- Vector256 k = Unsafe.Add(ref c3Base, i);
-
- k = Avx.Multiply(k, scale);
- c = Avx.Multiply(c, k);
- m = Avx.Multiply(m, k);
- y = Avx.Multiply(y, k);
- }
- }
-
- ///
- public override void ConvertFromRgb(in ComponentValues values, Span rLane, Span gLane, Span bLane)
- => ConvertFromRgb(in values, this.MaximumValue, rLane, gLane, bLane);
-
- public static void ConvertFromRgb(in ComponentValues values, float maxValue, Span rLane, Span gLane, Span bLane)
- {
- ref Vector256 destC =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
- ref Vector256 destM =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
- ref Vector256 destY =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
- ref Vector256 destK =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3));
-
- ref Vector256 srcR =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(rLane));
- ref Vector256 srcG =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(gLane));
- ref Vector256 srcB =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(bLane));
-
- var scale = Vector256.Create(maxValue);
-
- nuint n = values.Component0.Vector256Count();
- for (nuint i = 0; i < n; i++)
- {
- Vector256 ctmp = Avx.Subtract(scale, Unsafe.Add(ref srcR, i));
- Vector256 mtmp = Avx.Subtract(scale, Unsafe.Add(ref srcG, i));
- Vector256 ytmp = Avx.Subtract(scale, Unsafe.Add(ref srcB, i));
- Vector256 ktmp = Avx.Min(ctmp, Avx.Min(mtmp, ytmp));
-
- Vector256 kMask = Avx.CompareNotEqual(ktmp, scale);
-
- ctmp = Avx.And(Avx.Divide(Avx.Subtract(ctmp, ktmp), Avx.Subtract(scale, ktmp)), kMask);
- mtmp = Avx.And(Avx.Divide(Avx.Subtract(mtmp, ktmp), Avx.Subtract(scale, ktmp)), kMask);
- ytmp = Avx.And(Avx.Divide(Avx.Subtract(ytmp, ktmp), Avx.Subtract(scale, ktmp)), kMask);
-
- Unsafe.Add(ref destC, i) = Avx.Subtract(scale, Avx.Multiply(ctmp, scale));
- Unsafe.Add(ref destM, i) = Avx.Subtract(scale, Avx.Multiply(mtmp, scale));
- Unsafe.Add(ref destY, i) = Avx.Subtract(scale, Avx.Multiply(ytmp, scale));
- Unsafe.Add(ref destK, i) = Avx.Subtract(scale, ktmp);
- }
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykScalar.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykScalar.cs
index 6d0013b88..1b3be69fa 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykScalar.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykScalar.cs
@@ -13,7 +13,7 @@ internal abstract partial class JpegColorConverterBase
}
///
- public override void ConvertToRgbInplace(in ComponentValues values) =>
+ public override void ConvertToRgbInPlace(in ComponentValues values) =>
ConvertToRgbInplace(values, this.MaximumValue);
///
diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleArm.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleArm.cs
deleted file mode 100644
index 6bb8fd7aa..000000000
--- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleArm.cs
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Runtime.Intrinsics;
-using System.Runtime.Intrinsics.Arm;
-using static SixLabors.ImageSharp.SimdUtils;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.Components;
-
-internal abstract partial class JpegColorConverterBase
-{
- internal sealed class GrayscaleArm : JpegColorConverterArm
- {
- public GrayscaleArm(int precision)
- : base(JpegColorSpace.Grayscale, precision)
- {
- }
-
- ///
- public override void ConvertToRgbInplace(in ComponentValues values)
- {
- ref Vector128 c0Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
-
- // Used for the color conversion
- var scale = Vector128.Create(1 / this.MaximumValue);
-
- nuint n = values.Component0.Vector128Count();
- for (nuint i = 0; i < n; i++)
- {
- ref Vector128 c0 = ref Unsafe.Add(ref c0Base, i);
- c0 = AdvSimd.Multiply(c0, scale);
- }
- }
-
- ///
- public override void ConvertFromRgb(in ComponentValues values, Span rLane, Span gLane, Span bLane)
- {
- ref Vector128 destLuminance =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
-
- ref Vector128 srcRed =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(rLane));
- ref Vector128 srcGreen =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(gLane));
- ref Vector128 srcBlue =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(bLane));
-
- // Used for the color conversion
- var f0299 = Vector128.Create(0.299f);
- var f0587 = Vector128.Create(0.587f);
- var f0114 = Vector128.Create(0.114f);
-
- nuint n = values.Component0.Vector128Count();
- for (nuint i = 0; i < n; i++)
- {
- ref Vector128 r = ref Unsafe.Add(ref srcRed, i);
- ref Vector128 g = ref Unsafe.Add(ref srcGreen, i);
- ref Vector128 b = ref Unsafe.Add(ref srcBlue, i);
-
- // luminocity = (0.299 * r) + (0.587 * g) + (0.114 * b)
- Unsafe.Add(ref destLuminance, i) = HwIntrinsics.MultiplyAdd(HwIntrinsics.MultiplyAdd(AdvSimd.Multiply(f0114, b), f0587, g), f0299, r);
- }
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleAvx.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleAvx.cs
deleted file mode 100644
index a9e1c5d13..000000000
--- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleAvx.cs
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Runtime.Intrinsics;
-using System.Runtime.Intrinsics.X86;
-using static SixLabors.ImageSharp.SimdUtils;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.Components;
-
-internal abstract partial class JpegColorConverterBase
-{
- internal sealed class GrayscaleAvx : JpegColorConverterAvx
- {
- public GrayscaleAvx(int precision)
- : base(JpegColorSpace.Grayscale, precision)
- {
- }
-
- ///
- public override void ConvertToRgbInplace(in ComponentValues values)
- {
- ref Vector256 c0Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
-
- // Used for the color conversion
- var scale = Vector256.Create(1 / this.MaximumValue);
-
- nuint n = values.Component0.Vector256Count();
- for (nuint i = 0; i < n; i++)
- {
- ref Vector256 c0 = ref Unsafe.Add(ref c0Base, i);
- c0 = Avx.Multiply(c0, scale);
- }
- }
-
- ///
- public override void ConvertFromRgb(in ComponentValues values, Span rLane, Span gLane, Span bLane)
- {
- ref Vector256 destLuminance =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
-
- ref Vector256 srcRed =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(rLane));
- ref Vector256 srcGreen =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(gLane));
- ref Vector256 srcBlue =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(bLane));
-
- // Used for the color conversion
- var f0299 = Vector256.Create(0.299f);
- var f0587 = Vector256.Create(0.587f);
- var f0114 = Vector256.Create(0.114f);
-
- nuint n = values.Component0.Vector256Count();
- for (nuint i = 0; i < n; i++)
- {
- ref Vector256 r = ref Unsafe.Add(ref srcRed, i);
- ref Vector256 g = ref Unsafe.Add(ref srcGreen, i);
- ref Vector256 b = ref Unsafe.Add(ref srcBlue, i);
-
- // luminocity = (0.299 * r) + (0.587 * g) + (0.114 * b)
- Unsafe.Add(ref destLuminance, i) = HwIntrinsics.MultiplyAdd(HwIntrinsics.MultiplyAdd(Avx.Multiply(f0114, b), f0587, g), f0299, r);
- }
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleScalar.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleScalar.cs
index 4d3b5c60b..c01811182 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleScalar.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleScalar.cs
@@ -16,7 +16,7 @@ internal abstract partial class JpegColorConverterBase
}
///
- public override void ConvertToRgbInplace(in ComponentValues values)
+ public override void ConvertToRgbInPlace(in ComponentValues values)
=> ConvertToRgbInplace(values.Component0, this.MaximumValue);
///
diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbArm.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbArm.cs
deleted file mode 100644
index 75eeb17dd..000000000
--- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbArm.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-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.Formats.Jpeg.Components;
-
-internal abstract partial class JpegColorConverterBase
-{
- internal sealed class RgbArm : JpegColorConverterArm
- {
- public RgbArm(int precision)
- : base(JpegColorSpace.RGB, precision)
- {
- }
-
- ///
- public override void ConvertToRgbInplace(in ComponentValues values)
- {
- ref Vector128 rBase =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
- ref Vector128 gBase =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
- ref Vector128 bBase =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
-
- // Used for the color conversion
- var scale = Vector128.Create(1 / this.MaximumValue);
- nuint n = values.Component0.Vector128Count();
- for (nuint i = 0; i < n; i++)
- {
- ref Vector128 r = ref Unsafe.Add(ref rBase, i);
- ref Vector128 g = ref Unsafe.Add(ref gBase, i);
- ref Vector128 b = ref Unsafe.Add(ref bBase, i);
- r = AdvSimd.Multiply(r, scale);
- g = AdvSimd.Multiply(g, scale);
- b = AdvSimd.Multiply(b, scale);
- }
- }
-
- ///
- public override void ConvertFromRgb(in ComponentValues values, Span rLane, Span gLane, Span bLane)
- {
- rLane.CopyTo(values.Component0);
- gLane.CopyTo(values.Component1);
- bLane.CopyTo(values.Component2);
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbAvx.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbAvx.cs
deleted file mode 100644
index b56728fa7..000000000
--- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbAvx.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Runtime.Intrinsics;
-using System.Runtime.Intrinsics.X86;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.Components;
-
-internal abstract partial class JpegColorConverterBase
-{
- internal sealed class RgbAvx : JpegColorConverterAvx
- {
- public RgbAvx(int precision)
- : base(JpegColorSpace.RGB, precision)
- {
- }
-
- ///
- public override void ConvertToRgbInplace(in ComponentValues values)
- {
- ref Vector256 rBase =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
- ref Vector256 gBase =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
- ref Vector256 bBase =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
-
- // Used for the color conversion
- var scale = Vector256.Create(1 / this.MaximumValue);
- nuint n = values.Component0.Vector256Count();
- for (nuint i = 0; i < n; i++)
- {
- ref Vector256 r = ref Unsafe.Add(ref rBase, i);
- ref Vector256 g = ref Unsafe.Add(ref gBase, i);
- ref Vector256 b = ref Unsafe.Add(ref bBase, i);
- r = Avx.Multiply(r, scale);
- g = Avx.Multiply(g, scale);
- b = Avx.Multiply(b, scale);
- }
- }
-
- ///
- public override void ConvertFromRgb(in ComponentValues values, Span rLane, Span gLane, Span bLane)
- {
- rLane.CopyTo(values.Component0);
- gLane.CopyTo(values.Component1);
- bLane.CopyTo(values.Component2);
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbScalar.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbScalar.cs
index a43b7ef84..f62b2c7ff 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbScalar.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbScalar.cs
@@ -13,7 +13,7 @@ internal abstract partial class JpegColorConverterBase
}
///
- public override void ConvertToRgbInplace(in ComponentValues values)
+ public override void ConvertToRgbInPlace(in ComponentValues values)
=> ConvertToRgbInplace(values, this.MaximumValue);
///
diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrArm.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrArm.cs
deleted file mode 100644
index 4f7cf1ed6..000000000
--- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrArm.cs
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Runtime.Intrinsics;
-using System.Runtime.Intrinsics.Arm;
-using System.Runtime.Intrinsics.X86;
-using static SixLabors.ImageSharp.SimdUtils;
-
-// ReSharper disable ImpureMethodCallOnReadonlyValueField
-namespace SixLabors.ImageSharp.Formats.Jpeg.Components;
-
-internal abstract partial class JpegColorConverterBase
-{
- internal sealed class YCbCrArm : JpegColorConverterArm
- {
- public YCbCrArm(int precision)
- : base(JpegColorSpace.YCbCr, precision)
- {
- }
-
- ///
- public override void ConvertToRgbInplace(in ComponentValues values)
- {
- ref Vector128 c0Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
- ref Vector128 c1Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
- ref Vector128 c2Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
-
- // Used for the color conversion
- var chromaOffset = Vector128.Create(-this.HalfValue);
- var scale = Vector128.Create(1 / this.MaximumValue);
- var rCrMult = Vector128.Create(YCbCrScalar.RCrMult);
- var gCbMult = Vector128.Create(-YCbCrScalar.GCbMult);
- var gCrMult = Vector128.Create(-YCbCrScalar.GCrMult);
- var bCbMult = Vector128.Create(YCbCrScalar.BCbMult);
-
- // Walking 8 elements at one step:
- nuint n = (uint)values.Component0.Length / (uint)Vector128.Count;
- for (nuint i = 0; i < n; i++)
- {
- // y = yVals[i];
- // cb = cbVals[i] - 128F;
- // cr = crVals[i] - 128F;
- ref Vector128 c0 = ref Unsafe.Add(ref c0Base, i);
- ref Vector128 c1 = ref Unsafe.Add(ref c1Base, i);
- ref Vector128 c2 = ref Unsafe.Add(ref c2Base, i);
-
- Vector128 y = c0;
- Vector128 cb = AdvSimd.Add(c1, chromaOffset);
- Vector128 cr = AdvSimd.Add(c2, chromaOffset);
-
- // r = y + (1.402F * cr);
- // g = y - (0.344136F * cb) - (0.714136F * cr);
- // b = y + (1.772F * cb);
- Vector128 r = HwIntrinsics.MultiplyAdd(y, cr, rCrMult);
- Vector128 g = HwIntrinsics.MultiplyAdd(HwIntrinsics.MultiplyAdd(y, cb, gCbMult), cr, gCrMult);
- Vector128 b = HwIntrinsics.MultiplyAdd(y, cb, bCbMult);
-
- r = AdvSimd.Multiply(AdvSimd.RoundToNearest(r), scale);
- g = AdvSimd.Multiply(AdvSimd.RoundToNearest(g), scale);
- b = AdvSimd.Multiply(AdvSimd.RoundToNearest(b), scale);
-
- c0 = r;
- c1 = g;
- c2 = b;
- }
- }
-
- ///
- public override void ConvertFromRgb(in ComponentValues values, Span rLane, Span gLane, Span bLane)
- {
- ref Vector128 destY =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
- ref Vector128 destCb =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
- ref Vector128 destCr =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
-
- ref Vector128 srcR =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(rLane));
- ref Vector128 srcG =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(gLane));
- ref Vector128 srcB =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(bLane));
-
- // Used for the color conversion
- var chromaOffset = Vector128.Create(this.HalfValue);
-
- var f0299 = Vector128.Create(0.299f);
- var f0587 = Vector128.Create(0.587f);
- var f0114 = Vector128.Create(0.114f);
- var fn0168736 = Vector128.Create(-0.168736f);
- var fn0331264 = Vector128.Create(-0.331264f);
- var fn0418688 = Vector128.Create(-0.418688f);
- var fn0081312F = Vector128.Create(-0.081312F);
- var f05 = Vector128.Create(0.5f);
-
- nuint n = (uint)values.Component0.Length / (uint)Vector128.Count;
- for (nuint i = 0; i < n; i++)
- {
- Vector128 r = Unsafe.Add(ref srcR, i);
- Vector128 g = Unsafe.Add(ref srcG, i);
- Vector128 b = Unsafe.Add(ref srcB, i);
-
- // y = 0 + (0.299 * r) + (0.587 * g) + (0.114 * b)
- // cb = 128 - (0.168736 * r) - (0.331264 * g) + (0.5 * b)
- // cr = 128 + (0.5 * r) - (0.418688 * g) - (0.081312 * b)
- Vector128 y = HwIntrinsics.MultiplyAdd(HwIntrinsics.MultiplyAdd(AdvSimd.Multiply(f0114, b), f0587, g), f0299, r);
- Vector128 cb = AdvSimd.Add(chromaOffset, HwIntrinsics.MultiplyAdd(HwIntrinsics.MultiplyAdd(AdvSimd.Multiply(f05, b), fn0331264, g), fn0168736, r));
- Vector128 cr = AdvSimd.Add(chromaOffset, HwIntrinsics.MultiplyAdd(HwIntrinsics.MultiplyAdd(AdvSimd.Multiply(fn0081312F, b), fn0418688, g), f05, r));
-
- Unsafe.Add(ref destY, i) = y;
- Unsafe.Add(ref destCb, i) = cb;
- Unsafe.Add(ref destCr, i) = cr;
- }
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrAvx.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrAvx.cs
deleted file mode 100644
index c5fa786e2..000000000
--- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrAvx.cs
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Runtime.Intrinsics;
-using System.Runtime.Intrinsics.X86;
-using static SixLabors.ImageSharp.SimdUtils;
-
-// ReSharper disable ImpureMethodCallOnReadonlyValueField
-namespace SixLabors.ImageSharp.Formats.Jpeg.Components;
-
-internal abstract partial class JpegColorConverterBase
-{
- internal sealed class YCbCrAvx : JpegColorConverterAvx
- {
- public YCbCrAvx(int precision)
- : base(JpegColorSpace.YCbCr, precision)
- {
- }
-
- ///
- public override void ConvertToRgbInplace(in ComponentValues values)
- {
- ref Vector256 c0Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
- ref Vector256 c1Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
- ref Vector256 c2Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
-
- // Used for the color conversion
- var chromaOffset = Vector256.Create(-this.HalfValue);
- var scale = Vector256.Create(1 / this.MaximumValue);
- var rCrMult = Vector256.Create(YCbCrScalar.RCrMult);
- var gCbMult = Vector256.Create(-YCbCrScalar.GCbMult);
- var gCrMult = Vector256.Create(-YCbCrScalar.GCrMult);
- var bCbMult = Vector256.Create(YCbCrScalar.BCbMult);
-
- // Walking 8 elements at one step:
- nuint n = values.Component0.Vector256Count();
- for (nuint i = 0; i < n; i++)
- {
- // y = yVals[i];
- // cb = cbVals[i] - 128F;
- // cr = crVals[i] - 128F;
- ref Vector256 c0 = ref Unsafe.Add(ref c0Base, i);
- ref Vector256 c1 = ref Unsafe.Add(ref c1Base, i);
- ref Vector256 c2 = ref Unsafe.Add(ref c2Base, i);
-
- Vector256 y = c0;
- Vector256 cb = Avx.Add(c1, chromaOffset);
- Vector256 cr = Avx.Add(c2, chromaOffset);
-
- // r = y + (1.402F * cr);
- // g = y - (0.344136F * cb) - (0.714136F * cr);
- // b = y + (1.772F * cb);
- Vector256 r = HwIntrinsics.MultiplyAdd(y, cr, rCrMult);
- Vector256 g = HwIntrinsics.MultiplyAdd(HwIntrinsics.MultiplyAdd(y, cb, gCbMult), cr, gCrMult);
- Vector256 b = HwIntrinsics.MultiplyAdd(y, cb, bCbMult);
-
- r = Avx.Multiply(Avx.RoundToNearestInteger(r), scale);
- g = Avx.Multiply(Avx.RoundToNearestInteger(g), scale);
- b = Avx.Multiply(Avx.RoundToNearestInteger(b), scale);
-
- c0 = r;
- c1 = g;
- c2 = b;
- }
- }
-
- ///
- public override void ConvertFromRgb(in ComponentValues values, Span rLane, Span gLane, Span bLane)
- {
- ref Vector256 destY =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
- ref Vector256 destCb =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
- ref Vector256 destCr =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
-
- ref Vector256 srcR =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(rLane));
- ref Vector256 srcG =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(gLane));
- ref Vector256 srcB =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(bLane));
-
- // Used for the color conversion
- var chromaOffset = Vector256.Create(this.HalfValue);
-
- var f0299 = Vector256.Create(0.299f);
- var f0587 = Vector256.Create(0.587f);
- var f0114 = Vector256.Create(0.114f);
- var fn0168736 = Vector256.Create(-0.168736f);
- var fn0331264 = Vector256.Create(-0.331264f);
- var fn0418688 = Vector256.Create(-0.418688f);
- var fn0081312F = Vector256.Create(-0.081312F);
- var f05 = Vector256.Create(0.5f);
-
- nuint n = values.Component0.Vector256Count();
- for (nuint i = 0; i < n; i++)
- {
- Vector256 r = Unsafe.Add(ref srcR, i);
- Vector256 g = Unsafe.Add(ref srcG, i);
- Vector256 b = Unsafe.Add(ref srcB, i);
-
- // y = 0 + (0.299 * r) + (0.587 * g) + (0.114 * b)
- // cb = 128 - (0.168736 * r) - (0.331264 * g) + (0.5 * b)
- // cr = 128 + (0.5 * r) - (0.418688 * g) - (0.081312 * b)
- Vector256 y = HwIntrinsics.MultiplyAdd(HwIntrinsics.MultiplyAdd(Avx.Multiply(f0114, b), f0587, g), f0299, r);
- Vector256 cb = Avx.Add(chromaOffset, HwIntrinsics.MultiplyAdd(HwIntrinsics.MultiplyAdd(Avx.Multiply(f05, b), fn0331264, g), fn0168736, r));
- Vector256 cr = Avx.Add(chromaOffset, HwIntrinsics.MultiplyAdd(HwIntrinsics.MultiplyAdd(Avx.Multiply(fn0081312F, b), fn0418688, g), f05, r));
-
- Unsafe.Add(ref destY, i) = y;
- Unsafe.Add(ref destCb, i) = cb;
- Unsafe.Add(ref destCr, i) = cr;
- }
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrScalar.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrScalar.cs
index e3e5a452a..e7e29a87a 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrScalar.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrScalar.cs
@@ -19,7 +19,7 @@ internal abstract partial class JpegColorConverterBase
}
///
- public override void ConvertToRgbInplace(in ComponentValues values)
+ public override void ConvertToRgbInPlace(in ComponentValues values)
=> ConvertToRgbInplace(values, this.MaximumValue, this.HalfValue);
///
diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrVector.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrVector.cs
index a5d0c889e..2591ae310 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrVector.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrVector.cs
@@ -27,13 +27,13 @@ internal abstract partial class JpegColorConverterBase
ref Vector c2Base =
ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
- var chromaOffset = new Vector(-this.HalfValue);
+ Vector chromaOffset = new(-this.HalfValue);
- var scale = new Vector(1 / this.MaximumValue);
- var rCrMult = new Vector(YCbCrScalar.RCrMult);
- var gCbMult = new Vector(-YCbCrScalar.GCbMult);
- var gCrMult = new Vector(-YCbCrScalar.GCrMult);
- var bCbMult = new Vector(YCbCrScalar.BCbMult);
+ Vector scale = new(1 / this.MaximumValue);
+ Vector