Browse Source

Port Grayscale converter

pull/2917/head
James Jackson-South 1 year ago
parent
commit
87438a3a11
  1. 12
      src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykScalar.cs
  2. 19
      src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleScalar.cs
  3. 4
      src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleVector.cs
  4. 67
      src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleVector128.cs
  5. 67
      src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleVector256.cs
  6. 75
      src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleVector512.cs
  7. 22
      src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbScalar.cs
  8. 2
      src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbVector.cs
  9. 8
      src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrScalar.cs
  10. 2
      src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrVector512.cs
  11. 16
      src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs
  12. 30
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/GrayscaleColorConversion.cs
  13. 89
      tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs

12
src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykScalar.cs

@ -17,8 +17,8 @@ internal abstract partial class JpegColorConverterBase
ConvertToRgbInplace(values, this.MaximumValue); ConvertToRgbInplace(values, this.MaximumValue);
/// <inheritdoc/> /// <inheritdoc/>
public override void ConvertFromRgb(in ComponentValues values, Span<float> r, Span<float> g, Span<float> b) public override void ConvertFromRgb(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane)
=> ConvertFromRgb(values, this.MaximumValue, r, g, b); => ConvertFromRgb(values, this.MaximumValue, rLane, gLane, bLane);
public static void ConvertToRgbInplace(in ComponentValues values, float maxValue) 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<float> r, Span<float> g, Span<float> b) public static void ConvertFromRgb(in ComponentValues values, float maxValue, Span<float> rLane, Span<float> gLane, Span<float> bLane)
{ {
Span<float> c = values.Component0; Span<float> c = values.Component0;
Span<float> m = values.Component1; Span<float> m = values.Component1;
@ -51,9 +51,9 @@ internal abstract partial class JpegColorConverterBase
for (int i = 0; i < c.Length; i++) for (int i = 0; i < c.Length; i++)
{ {
float ctmp = 255f - r[i]; float ctmp = 255f - rLane[i];
float mtmp = 255f - g[i]; float mtmp = 255f - gLane[i];
float ytmp = 255f - b[i]; float ytmp = 255f - bLane[i];
float ktmp = MathF.Min(MathF.Min(ctmp, mtmp), ytmp); float ktmp = MathF.Min(MathF.Min(ctmp, mtmp), ytmp);
if (ktmp >= 255f) if (ktmp >= 255f)

19
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 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) : base(JpegColorSpace.Grayscale, precision)
{ {
} }
/// <inheritdoc/> /// <inheritdoc/>
public override void ConvertToRgbInPlace(in ComponentValues values) public override void ConvertToRgbInPlace(in ComponentValues values)
=> ConvertToRgbInplace(values.Component0, this.MaximumValue); => ConvertToRgbInPlace(values.Component0, this.MaximumValue);
/// <inheritdoc/> /// <inheritdoc/>
public override void ConvertFromRgb(in ComponentValues values, Span<float> r, Span<float> g, Span<float> b) public override void ConvertFromRgb(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane)
=> ConvertCoreInplaceFromRgb(values, r, g, b); => ConvertFromRgbScalar(values, rLane, gLane, bLane);
internal static void ConvertToRgbInplace(Span<float> values, float maxValue) internal static void ConvertToRgbInPlace(Span<float> values, float maxValue)
{ {
ref float valuesRef = ref MemoryMarshal.GetReference(values); ref float valuesRef = ref MemoryMarshal.GetReference(values);
float scale = 1 / maxValue; float scale = 1 / maxValue;
@ -34,15 +34,14 @@ internal abstract partial class JpegColorConverterBase
} }
} }
internal static void ConvertCoreInplaceFromRgb(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane) internal static void ConvertFromRgbScalar(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane)
{ {
Span<float> c0 = values.Component0; Span<float> c0 = values.Component0;
for (int i = 0; i < c0.Length; i++) for (int i = 0; i < c0.Length; i++)
{ {
// luminocity = (0.299 * r) + (0.587 * g) + (0.114 * b) // luminosity = (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] = (float)((0.299f * rLane[i]) + (0.587f * gLane[i]) + (0.114f * bLane[i]));
c0[i] = luma;
} }
} }
} }

4
src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleVector.cs

@ -34,7 +34,7 @@ internal abstract partial class JpegColorConverterBase
/// <inheritdoc/> /// <inheritdoc/>
protected override void ConvertToRgbInPlaceScalarRemainder(in ComponentValues values) protected override void ConvertToRgbInPlaceScalarRemainder(in ComponentValues values)
=> GrayscaleScalar.ConvertToRgbInplace(values.Component0, this.MaximumValue); => GrayScaleScalar.ConvertToRgbInPlace(values.Component0, this.MaximumValue);
/// <inheritdoc/> /// <inheritdoc/>
protected override void ConvertFromRgbVectorized(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane) protected override void ConvertFromRgbVectorized(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane)
@ -67,6 +67,6 @@ internal abstract partial class JpegColorConverterBase
/// <inheritdoc/> /// <inheritdoc/>
protected override void ConvertFromRgbScalarRemainder(in ComponentValues values, Span<float> r, Span<float> g, Span<float> b) protected override void ConvertFromRgbScalarRemainder(in ComponentValues values, Span<float> r, Span<float> g, Span<float> b)
=> GrayscaleScalar.ConvertCoreInplaceFromRgb(values, r, g, b); => GrayScaleScalar.ConvertFromRgbScalar(values, r, g, b);
} }
} }

67
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)
{
}
/// <inheritdoc/>
public override void ConvertToRgbInPlace(in ComponentValues values)
{
ref Vector128<float> c0Base =
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component0));
// Used for the color conversion
Vector128<float> scale = Vector128.Create(1 / this.MaximumValue);
nuint n = values.Component0.Vector128Count<float>();
for (nuint i = 0; i < n; i++)
{
ref Vector128<float> c0 = ref Unsafe.Add(ref c0Base, i);
c0 *= scale;
}
}
/// <inheritdoc/>
public override void ConvertFromRgb(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane)
{
ref Vector128<float> destLuminance =
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component0));
ref Vector128<float> srcRed =
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(rLane));
ref Vector128<float> srcGreen =
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(gLane));
ref Vector128<float> srcBlue =
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(bLane));
// Used for the color conversion
Vector128<float> f0299 = Vector128.Create(0.299f);
Vector128<float> f0587 = Vector128.Create(0.587f);
Vector128<float> f0114 = Vector128.Create(0.114f);
nuint n = values.Component0.Vector128Count<float>();
for (nuint i = 0; i < n; i++)
{
ref Vector128<float> r = ref Unsafe.Add(ref srcRed, i);
ref Vector128<float> g = ref Unsafe.Add(ref srcGreen, i);
ref Vector128<float> 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);
}
}
}
}

67
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)
{
}
/// <inheritdoc/>
public override void ConvertToRgbInPlace(in ComponentValues values)
{
ref Vector256<float> c0Base =
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component0));
// Used for the color conversion
Vector256<float> scale = Vector256.Create(1 / this.MaximumValue);
nuint n = values.Component0.Vector256Count<float>();
for (nuint i = 0; i < n; i++)
{
ref Vector256<float> c0 = ref Unsafe.Add(ref c0Base, i);
c0 *= scale;
}
}
/// <inheritdoc/>
public override void ConvertFromRgb(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane)
{
ref Vector256<float> destLuminance =
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component0));
ref Vector256<float> srcRed =
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(rLane));
ref Vector256<float> srcGreen =
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(gLane));
ref Vector256<float> srcBlue =
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(bLane));
// Used for the color conversion
Vector256<float> f0299 = Vector256.Create(0.299f);
Vector256<float> f0587 = Vector256.Create(0.587f);
Vector256<float> f0114 = Vector256.Create(0.114f);
nuint n = values.Component0.Vector256Count<float>();
for (nuint i = 0; i < n; i++)
{
ref Vector256<float> r = ref Unsafe.Add(ref srcRed, i);
ref Vector256<float> g = ref Unsafe.Add(ref srcGreen, i);
ref Vector256<float> 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);
}
}
}
}

75
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)
{
}
/// <inheritdoc/>
protected override void ConvertToRgbInPlaceVectorized(in ComponentValues values)
{
ref Vector512<float> c0Base =
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component0));
// Used for the color conversion
Vector512<float> scale = Vector512.Create(1 / this.MaximumValue);
nuint n = values.Component0.Vector512Count<float>();
for (nuint i = 0; i < n; i++)
{
ref Vector512<float> c0 = ref Unsafe.Add(ref c0Base, i);
c0 *= scale;
}
}
/// <inheritdoc/>
protected override void ConvertFromRgbVectorized(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane)
{
ref Vector512<float> destLuminance =
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component0));
ref Vector512<float> srcRed =
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(rLane));
ref Vector512<float> srcGreen =
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(gLane));
ref Vector512<float> srcBlue =
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(bLane));
// Used for the color conversion
Vector512<float> f0299 = Vector512.Create(0.299f);
Vector512<float> f0587 = Vector512.Create(0.587f);
Vector512<float> f0114 = Vector512.Create(0.114f);
nuint n = values.Component0.Vector512Count<float>();
for (nuint i = 0; i < n; i++)
{
ref Vector512<float> r = ref Unsafe.Add(ref srcRed, i);
ref Vector512<float> g = ref Unsafe.Add(ref srcGreen, i);
ref Vector512<float> 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);
}
}
/// <inheritdoc/>
protected override void ConvertToRgbInPlaceScalarRemainder(in ComponentValues values)
=> GrayScaleScalar.ConvertToRgbInPlace(values.Component0, this.MaximumValue);
/// <inheritdoc/>
protected override void ConvertFromRgbScalarRemainder(in ComponentValues values, Span<float> r, Span<float> g, Span<float> b)
=> GrayScaleScalar.ConvertFromRgbScalar(values, r, g, b);
}
}

22
src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbScalar.cs

@ -14,24 +14,24 @@ internal abstract partial class JpegColorConverterBase
/// <inheritdoc/> /// <inheritdoc/>
public override void ConvertToRgbInPlace(in ComponentValues values) public override void ConvertToRgbInPlace(in ComponentValues values)
=> ConvertToRgbInplace(values, this.MaximumValue); => ConvertToRgbInPlace(values, this.MaximumValue);
/// <inheritdoc/> /// <inheritdoc/>
public override void ConvertFromRgb(in ComponentValues values, Span<float> r, Span<float> g, Span<float> b) public override void ConvertFromRgb(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane)
=> ConvertFromRgb(values, r, g, b); => 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.Component0, maxValue);
GrayscaleScalar.ConvertToRgbInplace(values.Component1, maxValue); GrayScaleScalar.ConvertToRgbInPlace(values.Component1, maxValue);
GrayscaleScalar.ConvertToRgbInplace(values.Component2, maxValue); GrayScaleScalar.ConvertToRgbInPlace(values.Component2, maxValue);
} }
internal static void ConvertFromRgb(ComponentValues values, Span<float> r, Span<float> g, Span<float> b) internal static void ConvertFromRgb(ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane)
{ {
r.CopyTo(values.Component0); rLane.CopyTo(values.Component0);
g.CopyTo(values.Component1); gLane.CopyTo(values.Component1);
b.CopyTo(values.Component2); bLane.CopyTo(values.Component2);
} }
} }
} }

2
src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbVector.cs

@ -42,7 +42,7 @@ internal abstract partial class JpegColorConverterBase
/// <inheritdoc/> /// <inheritdoc/>
protected override void ConvertToRgbInPlaceScalarRemainder(in ComponentValues values) protected override void ConvertToRgbInPlaceScalarRemainder(in ComponentValues values)
=> RgbScalar.ConvertToRgbInplace(values, this.MaximumValue); => RgbScalar.ConvertToRgbInPlace(values, this.MaximumValue);
/// <inheritdoc/> /// <inheritdoc/>
protected override void ConvertFromRgbVectorized(in ComponentValues values, Span<float> r, Span<float> g, Span<float> b) protected override void ConvertFromRgbVectorized(in ComponentValues values, Span<float> r, Span<float> g, Span<float> b)

8
src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrScalar.cs

@ -20,13 +20,13 @@ internal abstract partial class JpegColorConverterBase
/// <inheritdoc/> /// <inheritdoc/>
public override void ConvertToRgbInPlace(in ComponentValues values) public override void ConvertToRgbInPlace(in ComponentValues values)
=> ConvertToRgbInplace(values, this.MaximumValue, this.HalfValue); => ConvertToRgbInPlace(values, this.MaximumValue, this.HalfValue);
/// <inheritdoc/> /// <inheritdoc/>
public override void ConvertFromRgb(in ComponentValues values, Span<float> r, Span<float> g, Span<float> b) public override void ConvertFromRgb(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane)
=> ConvertFromRgb(values, this.HalfValue, r, g, b); => 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<float> c0 = values.Component0; Span<float> c0 = values.Component0;
Span<float> c1 = values.Component1; Span<float> c1 = values.Component1;

2
src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrVector512.cs

@ -114,7 +114,7 @@ internal abstract partial class JpegColorConverterBase
/// <inheritdoc/> /// <inheritdoc/>
protected override void ConvertToRgbInPlaceScalarRemainder(in ComponentValues values) protected override void ConvertToRgbInPlaceScalarRemainder(in ComponentValues values)
=> YCbCrScalar.ConvertToRgbInplace(values, this.MaximumValue, this.HalfValue); => YCbCrScalar.ConvertToRgbInPlace(values, this.MaximumValue, this.HalfValue);
/// <inheritdoc/> /// <inheritdoc/>
protected override void ConvertFromRgbScalarRemainder(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane) protected override void ConvertFromRgbScalarRemainder(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane)

16
src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs

@ -178,12 +178,22 @@ internal abstract partial class JpegColorConverterBase
/// <param name="precision">The precision in bits.</param> /// <param name="precision">The precision in bits.</param>
private static JpegColorConverterBase GetGrayScaleConverter(int precision) 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);
} }
/// <summary> /// <summary>

30
tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/GrayscaleColorConversion.cs

@ -7,9 +7,9 @@ using SixLabors.ImageSharp.Formats.Jpeg.Components;
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg; namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg;
[Config(typeof(Config.Short))] [Config(typeof(Config.Short))]
public class GrayscaleColorConversion : ColorConversionBenchmark public class GrayScaleColorConversion : ColorConversionBenchmark
{ {
public GrayscaleColorConversion() public GrayScaleColorConversion()
: base(1) : base(1)
{ {
} }
@ -17,16 +17,32 @@ public class GrayscaleColorConversion : ColorConversionBenchmark
[Benchmark(Baseline = true)] [Benchmark(Baseline = true)]
public void Scalar() 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] [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);
} }
} }

89
tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs

@ -108,23 +108,23 @@ public class JpegColorConverterTests
{ {
FeatureTestRunner.RunWithHwIntrinsicsFeature( FeatureTestRunner.RunWithHwIntrinsicsFeature(
RunTest, RunTest,
HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX2 | HwIntrinsics.DisableSSE2 | HwIntrinsics.DisableHWIntrinsic); HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512F | HwIntrinsics.DisableAVX2 | HwIntrinsics.DisableSSE2 | HwIntrinsics.DisableHWIntrinsic);
static void RunTest(string arg) static void RunTest(string arg)
{ {
// arrange // arrange
Type expectedType = typeof(JpegColorConverterBase.GrayscaleScalar); Type expectedType = typeof(JpegColorConverterBase.GrayScaleScalar);
if (Avx.IsSupported) 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 // act
@ -376,34 +376,65 @@ public class JpegColorConverterTests
[Theory] [Theory]
[MemberData(nameof(Seeds))] [MemberData(nameof(Seeds))]
public void FromGrayscaleBasic(int seed) => public void FromGrayScaleBasic(int seed) =>
this.TestConversionToRgb(new JpegColorConverterBase.GrayscaleScalar(8), 1, seed); this.TestConversionToRgb(new JpegColorConverterBase.GrayScaleScalar(8), 1, seed);
[Theory] [Theory]
[MemberData(nameof(Seeds))] [MemberData(nameof(Seeds))]
public void FromGrayscaleVector(int seed) public void FromGrayScaleVector512(int seed) =>
{ this.TestConversionToRgb(
JpegColorConverterBase.GrayScaleVector converter = new(8); new JpegColorConverterBase.GrayScaleVector512(8),
1,
seed,
new JpegColorConverterBase.GrayScaleScalar(8));
if (!converter.IsAvailable) [Theory]
{ [MemberData(nameof(Seeds))]
this.Output.WriteLine( public void FromGrayScaleVector256(int seed) =>
$"Skipping test - {converter.GetType().Name} is not supported on current hardware."); this.TestConversionToRgb(
return; new JpegColorConverterBase.GrayScaleVector256(8),
} 1,
seed,
new JpegColorConverterBase.GrayScaleScalar(8));
FeatureTestRunner.RunWithHwIntrinsicsFeature( [Theory]
RunTest, [MemberData(nameof(Seeds))]
public void FromGrayScaleVector128(int seed) =>
this.TestConversionToRgb(
new JpegColorConverterBase.GrayScaleVector128(8),
1,
seed, seed,
IntrinsicsConfig); new JpegColorConverterBase.GrayScaleScalar(8));
static void RunTest(string arg) => [Theory]
ValidateConversionToRgb( [MemberData(nameof(Seeds))]
new JpegColorConverterBase.GrayScaleVector(8), public void FromRgbToGrayScaleVector512(int seed) =>
1, this.TestConversionFromRgb(
FeatureTestRunner.Deserialize<int>(arg), new JpegColorConverterBase.GrayScaleVector512(8),
new JpegColorConverterBase.GrayscaleScalar(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] [Theory]
[MemberData(nameof(Seeds))] [MemberData(nameof(Seeds))]

Loading…
Cancel
Save