From 87438a3a11ddf18909de942449bd91c60451ef07 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 5 May 2025 13:17:22 +1000 Subject: [PATCH] Port Grayscale converter --- .../JpegColorConverter.CmykScalar.cs | 12 +-- .../JpegColorConverter.GrayScaleScalar.cs | 19 ++-- .../JpegColorConverter.GrayScaleVector.cs | 4 +- .../JpegColorConverter.GrayScaleVector128.cs | 67 ++++++++++++++ .../JpegColorConverter.GrayScaleVector256.cs | 67 ++++++++++++++ .../JpegColorConverter.GrayScaleVector512.cs | 75 ++++++++++++++++ .../JpegColorConverter.RgbScalar.cs | 22 ++--- .../JpegColorConverter.RgbVector.cs | 2 +- .../JpegColorConverter.YCbCrScalar.cs | 8 +- .../JpegColorConverter.YCbCrVector512.cs | 2 +- .../ColorConverters/JpegColorConverterBase.cs | 16 +++- .../GrayscaleColorConversion.cs | 30 +++++-- .../Formats/Jpg/JpegColorConverterTests.cs | 89 +++++++++++++------ 13 files changed, 339 insertions(+), 74 deletions(-) create mode 100644 src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleVector128.cs create mode 100644 src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleVector256.cs create mode 100644 src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleVector512.cs diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykScalar.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykScalar.cs index 1b3be69fa5..60078db38f 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykScalar.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykScalar.cs @@ -17,8 +17,8 @@ internal abstract partial class JpegColorConverterBase ConvertToRgbInplace(values, this.MaximumValue); /// - public override void ConvertFromRgb(in ComponentValues values, Span r, Span g, Span b) - => ConvertFromRgb(values, this.MaximumValue, r, g, b); + public override void ConvertFromRgb(in ComponentValues values, Span rLane, Span gLane, Span bLane) + => ConvertFromRgb(values, this.MaximumValue, rLane, gLane, bLane); public static void ConvertToRgbInplace(in ComponentValues values, float maxValue) { @@ -42,7 +42,7 @@ internal abstract partial class JpegColorConverterBase } } - public static void ConvertFromRgb(in ComponentValues values, float maxValue, Span r, Span g, Span b) + public static void ConvertFromRgb(in ComponentValues values, float maxValue, Span rLane, Span gLane, Span bLane) { Span c = values.Component0; Span m = values.Component1; @@ -51,9 +51,9 @@ internal abstract partial class JpegColorConverterBase for (int i = 0; i < c.Length; i++) { - float ctmp = 255f - r[i]; - float mtmp = 255f - g[i]; - float ytmp = 255f - b[i]; + float ctmp = 255f - rLane[i]; + float mtmp = 255f - gLane[i]; + float ytmp = 255f - bLane[i]; float ktmp = MathF.Min(MathF.Min(ctmp, mtmp), ytmp); if (ktmp >= 255f) diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleScalar.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleScalar.cs index c018111824..f710b73650 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleScalar.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleScalar.cs @@ -8,22 +8,22 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components; internal abstract partial class JpegColorConverterBase { - internal sealed class GrayscaleScalar : JpegColorConverterScalar + internal sealed class GrayScaleScalar : JpegColorConverterScalar { - public GrayscaleScalar(int precision) + public GrayScaleScalar(int precision) : base(JpegColorSpace.Grayscale, precision) { } /// public override void ConvertToRgbInPlace(in ComponentValues values) - => ConvertToRgbInplace(values.Component0, this.MaximumValue); + => ConvertToRgbInPlace(values.Component0, this.MaximumValue); /// - public override void ConvertFromRgb(in ComponentValues values, Span r, Span g, Span b) - => ConvertCoreInplaceFromRgb(values, r, g, b); + public override void ConvertFromRgb(in ComponentValues values, Span rLane, Span gLane, Span bLane) + => ConvertFromRgbScalar(values, rLane, gLane, bLane); - internal static void ConvertToRgbInplace(Span values, float maxValue) + internal static void ConvertToRgbInPlace(Span values, float maxValue) { ref float valuesRef = ref MemoryMarshal.GetReference(values); float scale = 1 / maxValue; @@ -34,15 +34,14 @@ internal abstract partial class JpegColorConverterBase } } - internal static void ConvertCoreInplaceFromRgb(in ComponentValues values, Span rLane, Span gLane, Span bLane) + internal static void ConvertFromRgbScalar(in ComponentValues values, Span rLane, Span gLane, Span bLane) { Span c0 = values.Component0; for (int i = 0; i < c0.Length; i++) { - // luminocity = (0.299 * r) + (0.587 * g) + (0.114 * b) - float luma = (0.299f * rLane[i]) + (0.587f * gLane[i]) + (0.114f * bLane[i]); - c0[i] = luma; + // luminosity = (0.299 * r) + (0.587 * g) + (0.114 * b) + c0[i] = (float)((0.299f * rLane[i]) + (0.587f * gLane[i]) + (0.114f * bLane[i])); } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleVector.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleVector.cs index b6283084f9..c9e1a34992 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleVector.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleVector.cs @@ -34,7 +34,7 @@ internal abstract partial class JpegColorConverterBase /// protected override void ConvertToRgbInPlaceScalarRemainder(in ComponentValues values) - => GrayscaleScalar.ConvertToRgbInplace(values.Component0, this.MaximumValue); + => GrayScaleScalar.ConvertToRgbInPlace(values.Component0, this.MaximumValue); /// protected override void ConvertFromRgbVectorized(in ComponentValues values, Span rLane, Span gLane, Span bLane) @@ -67,6 +67,6 @@ internal abstract partial class JpegColorConverterBase /// protected override void ConvertFromRgbScalarRemainder(in ComponentValues values, Span r, Span g, Span b) - => GrayscaleScalar.ConvertCoreInplaceFromRgb(values, r, g, b); + => GrayScaleScalar.ConvertFromRgbScalar(values, r, g, b); } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleVector128.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleVector128.cs new file mode 100644 index 0000000000..f3a6f7d372 --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleVector128.cs @@ -0,0 +1,67 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using SixLabors.ImageSharp.Common.Helpers; + +namespace SixLabors.ImageSharp.Formats.Jpeg.Components; + +internal abstract partial class JpegColorConverterBase +{ + internal sealed class GrayScaleVector128 : JpegColorConverterVector128 + { + public GrayScaleVector128(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 + Vector128 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 *= 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 + Vector128 f0299 = Vector128.Create(0.299f); + Vector128 f0587 = Vector128.Create(0.587f); + Vector128 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); + + // luminosity = (0.299 * r) + (0.587 * g) + (0.114 * b) + Unsafe.Add(ref destLuminance, i) = Vector128Utilities.MultiplyAdd(Vector128Utilities.MultiplyAdd(f0114 * b, f0587, g), f0299, r); + } + } + } +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleVector256.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleVector256.cs new file mode 100644 index 0000000000..12ced3dcd9 --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleVector256.cs @@ -0,0 +1,67 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using SixLabors.ImageSharp.Common.Helpers; + +namespace SixLabors.ImageSharp.Formats.Jpeg.Components; + +internal abstract partial class JpegColorConverterBase +{ + internal sealed class GrayScaleVector256 : JpegColorConverterVector256 + { + public GrayScaleVector256(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 + Vector256 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 *= 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 + Vector256 f0299 = Vector256.Create(0.299f); + Vector256 f0587 = Vector256.Create(0.587f); + Vector256 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); + + // luminosity = (0.299 * r) + (0.587 * g) + (0.114 * b) + Unsafe.Add(ref destLuminance, i) = Vector256Utilities.MultiplyAdd(Vector256Utilities.MultiplyAdd(f0114 * b, f0587, g), f0299, r); + } + } + } +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleVector512.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleVector512.cs new file mode 100644 index 0000000000..163cb6656a --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleVector512.cs @@ -0,0 +1,75 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using SixLabors.ImageSharp.Common.Helpers; + +namespace SixLabors.ImageSharp.Formats.Jpeg.Components; + +internal abstract partial class JpegColorConverterBase +{ + internal sealed class GrayScaleVector512 : JpegColorConverterVector512 + { + public GrayScaleVector512(int precision) + : base(JpegColorSpace.Grayscale, precision) + { + } + + /// + protected override void ConvertToRgbInPlaceVectorized(in ComponentValues values) + { + ref Vector512 c0Base = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); + + // Used for the color conversion + Vector512 scale = Vector512.Create(1 / this.MaximumValue); + + nuint n = values.Component0.Vector512Count(); + for (nuint i = 0; i < n; i++) + { + ref Vector512 c0 = ref Unsafe.Add(ref c0Base, i); + c0 *= scale; + } + } + + /// + protected override void ConvertFromRgbVectorized(in ComponentValues values, Span rLane, Span gLane, Span bLane) + { + ref Vector512 destLuminance = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); + + ref Vector512 srcRed = + ref Unsafe.As>(ref MemoryMarshal.GetReference(rLane)); + ref Vector512 srcGreen = + ref Unsafe.As>(ref MemoryMarshal.GetReference(gLane)); + ref Vector512 srcBlue = + ref Unsafe.As>(ref MemoryMarshal.GetReference(bLane)); + + // Used for the color conversion + Vector512 f0299 = Vector512.Create(0.299f); + Vector512 f0587 = Vector512.Create(0.587f); + Vector512 f0114 = Vector512.Create(0.114f); + + nuint n = values.Component0.Vector512Count(); + for (nuint i = 0; i < n; i++) + { + ref Vector512 r = ref Unsafe.Add(ref srcRed, i); + ref Vector512 g = ref Unsafe.Add(ref srcGreen, i); + ref Vector512 b = ref Unsafe.Add(ref srcBlue, i); + + // luminosity = (0.299 * r) + (0.587 * g) + (0.114 * b) + Unsafe.Add(ref destLuminance, i) = Vector512Utilities.MultiplyAdd(Vector512Utilities.MultiplyAdd(f0114 * b, f0587, g), f0299, r); + } + } + + /// + protected override void ConvertToRgbInPlaceScalarRemainder(in ComponentValues values) + => GrayScaleScalar.ConvertToRgbInPlace(values.Component0, this.MaximumValue); + + /// + protected override void ConvertFromRgbScalarRemainder(in ComponentValues values, Span r, Span g, Span b) + => GrayScaleScalar.ConvertFromRgbScalar(values, r, g, b); + } +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbScalar.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbScalar.cs index f62b2c7fff..23825b06e3 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbScalar.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbScalar.cs @@ -14,24 +14,24 @@ internal abstract partial class JpegColorConverterBase /// public override void ConvertToRgbInPlace(in ComponentValues values) - => ConvertToRgbInplace(values, this.MaximumValue); + => ConvertToRgbInPlace(values, this.MaximumValue); /// - public override void ConvertFromRgb(in ComponentValues values, Span r, Span g, Span b) - => ConvertFromRgb(values, r, g, b); + public override void ConvertFromRgb(in ComponentValues values, Span rLane, Span gLane, Span bLane) + => ConvertFromRgb(values, rLane, gLane, bLane); - internal static void ConvertToRgbInplace(ComponentValues values, float maxValue) + internal static void ConvertToRgbInPlace(ComponentValues values, float maxValue) { - GrayscaleScalar.ConvertToRgbInplace(values.Component0, maxValue); - GrayscaleScalar.ConvertToRgbInplace(values.Component1, maxValue); - GrayscaleScalar.ConvertToRgbInplace(values.Component2, maxValue); + GrayScaleScalar.ConvertToRgbInPlace(values.Component0, maxValue); + GrayScaleScalar.ConvertToRgbInPlace(values.Component1, maxValue); + GrayScaleScalar.ConvertToRgbInPlace(values.Component2, maxValue); } - internal static void ConvertFromRgb(ComponentValues values, Span r, Span g, Span b) + internal static void ConvertFromRgb(ComponentValues values, Span rLane, Span gLane, Span bLane) { - r.CopyTo(values.Component0); - g.CopyTo(values.Component1); - b.CopyTo(values.Component2); + rLane.CopyTo(values.Component0); + gLane.CopyTo(values.Component1); + bLane.CopyTo(values.Component2); } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbVector.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbVector.cs index 5fabc80c78..2b4ae2af12 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbVector.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbVector.cs @@ -42,7 +42,7 @@ internal abstract partial class JpegColorConverterBase /// protected override void ConvertToRgbInPlaceScalarRemainder(in ComponentValues values) - => RgbScalar.ConvertToRgbInplace(values, this.MaximumValue); + => RgbScalar.ConvertToRgbInPlace(values, this.MaximumValue); /// protected override void ConvertFromRgbVectorized(in ComponentValues values, Span r, Span g, Span b) diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrScalar.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrScalar.cs index e7e29a87a6..e514a01663 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrScalar.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrScalar.cs @@ -20,13 +20,13 @@ internal abstract partial class JpegColorConverterBase /// public override void ConvertToRgbInPlace(in ComponentValues values) - => ConvertToRgbInplace(values, this.MaximumValue, this.HalfValue); + => ConvertToRgbInPlace(values, this.MaximumValue, this.HalfValue); /// - public override void ConvertFromRgb(in ComponentValues values, Span r, Span g, Span b) - => ConvertFromRgb(values, this.HalfValue, r, g, b); + public override void ConvertFromRgb(in ComponentValues values, Span rLane, Span gLane, Span bLane) + => ConvertFromRgb(values, this.HalfValue, rLane, gLane, bLane); - public static void ConvertToRgbInplace(in ComponentValues values, float maxValue, float halfValue) + public static void ConvertToRgbInPlace(in ComponentValues values, float maxValue, float halfValue) { Span c0 = values.Component0; Span c1 = values.Component1; diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrVector512.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrVector512.cs index 79ad03512a..def65b4a7e 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrVector512.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrVector512.cs @@ -114,7 +114,7 @@ internal abstract partial class JpegColorConverterBase /// protected override void ConvertToRgbInPlaceScalarRemainder(in ComponentValues values) - => YCbCrScalar.ConvertToRgbInplace(values, this.MaximumValue, this.HalfValue); + => YCbCrScalar.ConvertToRgbInPlace(values, this.MaximumValue, this.HalfValue); /// protected override void ConvertFromRgbScalarRemainder(in ComponentValues values, Span rLane, Span gLane, Span bLane) diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs index 6ad62b682f..96eb927d0b 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs @@ -178,12 +178,22 @@ internal abstract partial class JpegColorConverterBase /// The precision in bits. private static JpegColorConverterBase GetGrayScaleConverter(int precision) { - if (JpegColorConverterVector.IsSupported) + if (JpegColorConverterVector512.IsSupported) + { + return new GrayScaleVector512(precision); + } + + if (JpegColorConverterVector256.IsSupported) + { + return new GrayScaleVector256(precision); + } + + if (JpegColorConverterVector128.IsSupported) { - return new GrayScaleVector(precision); + return new GrayScaleVector128(precision); } - return new GrayscaleScalar(precision); + return new GrayScaleScalar(precision); } /// diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/GrayscaleColorConversion.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/GrayscaleColorConversion.cs index a63a97152f..3ade4279fd 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/GrayscaleColorConversion.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/GrayscaleColorConversion.cs @@ -7,9 +7,9 @@ using SixLabors.ImageSharp.Formats.Jpeg.Components; namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg; [Config(typeof(Config.Short))] -public class GrayscaleColorConversion : ColorConversionBenchmark +public class GrayScaleColorConversion : ColorConversionBenchmark { - public GrayscaleColorConversion() + public GrayScaleColorConversion() : base(1) { } @@ -17,16 +17,32 @@ public class GrayscaleColorConversion : ColorConversionBenchmark [Benchmark(Baseline = true)] public void Scalar() { - var values = new JpegColorConverterBase.ComponentValues(this.Input, 0); + JpegColorConverterBase.ComponentValues values = new(this.Input, 0); - new JpegColorConverterBase.GrayscaleScalar(8).ConvertToRgbInPlace(values); + new JpegColorConverterBase.GrayScaleScalar(8).ConvertToRgbInPlace(values); } [Benchmark] - public void SimdVector8() + public void SimdVector128() { - var values = new JpegColorConverterBase.ComponentValues(this.Input, 0); + JpegColorConverterBase.ComponentValues values = new(this.Input, 0); - new JpegColorConverterBase.GrayScaleVector(8).ConvertToRgbInPlace(values); + new JpegColorConverterBase.GrayScaleVector128(8).ConvertToRgbInPlace(values); + } + + [Benchmark] + public void SimdVector256() + { + JpegColorConverterBase.ComponentValues values = new(this.Input, 0); + + new JpegColorConverterBase.GrayScaleVector256(8).ConvertToRgbInPlace(values); + } + + [Benchmark] + public void SimdVector512() + { + JpegColorConverterBase.ComponentValues values = new(this.Input, 0); + + new JpegColorConverterBase.GrayScaleVector512(8).ConvertToRgbInPlace(values); } } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs index 41ab3b8316..52b5d3183f 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs @@ -108,23 +108,23 @@ public class JpegColorConverterTests { FeatureTestRunner.RunWithHwIntrinsicsFeature( RunTest, - HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX2 | HwIntrinsics.DisableSSE2 | HwIntrinsics.DisableHWIntrinsic); + HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512F | HwIntrinsics.DisableAVX2 | HwIntrinsics.DisableSSE2 | HwIntrinsics.DisableHWIntrinsic); static void RunTest(string arg) { // arrange - Type expectedType = typeof(JpegColorConverterBase.GrayscaleScalar); - if (Avx.IsSupported) + Type expectedType = typeof(JpegColorConverterBase.GrayScaleScalar); + if (JpegColorConverterBase.JpegColorConverterVector512.IsSupported) { - expectedType = typeof(JpegColorConverterBase.GrayScaleVector); + expectedType = typeof(JpegColorConverterBase.GrayScaleVector512); } - else if (Sse2.IsSupported) + else if (JpegColorConverterBase.JpegColorConverterVector256.IsSupported) { - expectedType = typeof(JpegColorConverterBase.GrayScaleVector); + expectedType = typeof(JpegColorConverterBase.GrayScaleVector256); } - else if (AdvSimd.IsSupported) + else if (JpegColorConverterBase.JpegColorConverterVector128.IsSupported) { - expectedType = typeof(JpegColorConverterBase.GrayScaleVector); + expectedType = typeof(JpegColorConverterBase.GrayScaleVector128); } // act @@ -376,34 +376,65 @@ public class JpegColorConverterTests [Theory] [MemberData(nameof(Seeds))] - public void FromGrayscaleBasic(int seed) => - this.TestConversionToRgb(new JpegColorConverterBase.GrayscaleScalar(8), 1, seed); + public void FromGrayScaleBasic(int seed) => + this.TestConversionToRgb(new JpegColorConverterBase.GrayScaleScalar(8), 1, seed); [Theory] [MemberData(nameof(Seeds))] - public void FromGrayscaleVector(int seed) - { - JpegColorConverterBase.GrayScaleVector converter = new(8); + public void FromGrayScaleVector512(int seed) => + this.TestConversionToRgb( + new JpegColorConverterBase.GrayScaleVector512(8), + 1, + seed, + new JpegColorConverterBase.GrayScaleScalar(8)); - if (!converter.IsAvailable) - { - this.Output.WriteLine( - $"Skipping test - {converter.GetType().Name} is not supported on current hardware."); - return; - } + [Theory] + [MemberData(nameof(Seeds))] + public void FromGrayScaleVector256(int seed) => + this.TestConversionToRgb( + new JpegColorConverterBase.GrayScaleVector256(8), + 1, + seed, + new JpegColorConverterBase.GrayScaleScalar(8)); - FeatureTestRunner.RunWithHwIntrinsicsFeature( - RunTest, + [Theory] + [MemberData(nameof(Seeds))] + public void FromGrayScaleVector128(int seed) => + this.TestConversionToRgb( + new JpegColorConverterBase.GrayScaleVector128(8), + 1, seed, - IntrinsicsConfig); + new JpegColorConverterBase.GrayScaleScalar(8)); - static void RunTest(string arg) => - ValidateConversionToRgb( - new JpegColorConverterBase.GrayScaleVector(8), - 1, - FeatureTestRunner.Deserialize(arg), - new JpegColorConverterBase.GrayscaleScalar(8)); - } + [Theory] + [MemberData(nameof(Seeds))] + public void FromRgbToGrayScaleVector512(int seed) => + this.TestConversionFromRgb( + new JpegColorConverterBase.GrayScaleVector512(8), + 1, + seed, + new JpegColorConverterBase.GrayScaleScalar(8), + precision: 2); + + [Theory] + [MemberData(nameof(Seeds))] + public void FromRgbToGrayScaleVector256(int seed) => + this.TestConversionFromRgb( + new JpegColorConverterBase.GrayScaleVector256(8), + 1, + seed, + new JpegColorConverterBase.GrayScaleScalar(8), + precision: 2); + + [Theory] + [MemberData(nameof(Seeds))] + public void FromRgbToGrayScaleVector128(int seed) => + this.TestConversionFromRgb( + new JpegColorConverterBase.GrayScaleVector128(8), + 1, + seed, + new JpegColorConverterBase.GrayScaleScalar(8), + precision: 2); [Theory] [MemberData(nameof(Seeds))]