diff --git a/.gitattributes b/.gitattributes
index f7bd4d061e..7de2c15977 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -85,18 +85,12 @@
###############################################################################
*.basis binary
*.dll binary
-*.eot binary
*.exe binary
-*.otf binary
*.pdf binary
*.ppt binary
*.pptx binary
*.pvr binary
*.snk binary
-*.ttc binary
-*.ttf binary
-*.woff binary
-*.woff2 binary
*.xls binary
*.xlsx binary
###############################################################################
@@ -126,6 +120,7 @@
*.dds filter=lfs diff=lfs merge=lfs -text
*.ktx filter=lfs diff=lfs merge=lfs -text
*.ktx2 filter=lfs diff=lfs merge=lfs -text
+*.astc filter=lfs diff=lfs merge=lfs -text
*.pam filter=lfs diff=lfs merge=lfs -text
*.pbm filter=lfs diff=lfs merge=lfs -text
*.pgm filter=lfs diff=lfs merge=lfs -text
@@ -143,3 +138,12 @@
# Handle ICC files by git lfs
###############################################################################
*.icc filter=lfs diff=lfs merge=lfs -text
+###############################################################################
+# Handle font files by git lfs
+###############################################################################
+*.eot filter=lfs diff=lfs merge=lfs -text
+*.otf filter=lfs diff=lfs merge=lfs -text
+*.ttc filter=lfs diff=lfs merge=lfs -text
+*.ttf filter=lfs diff=lfs merge=lfs -text
+*.woff filter=lfs diff=lfs merge=lfs -text
+*.woff2 filter=lfs diff=lfs merge=lfs -text
diff --git a/ImageSharp.sln b/ImageSharp.sln
index 13dd2fba7e..7a52040374 100644
--- a/ImageSharp.sln
+++ b/ImageSharp.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.0.31903.59
+# Visual Studio Version 18
+VisualStudioVersion = 18.5.11723.231 stable
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_root", "_root", "{C317F1B1-D75E-4C6D-83EB-80367343E0D7}"
ProjectSection(SolutionItems) = preProject
@@ -45,6 +45,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp", "src\ImageShar
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{56801022-D71A-4FBE-BC5B-CBA08E2284EC}"
ProjectSection(SolutionItems) = preProject
+ tests\coverlet.runsettings = tests\coverlet.runsettings
tests\Directory.Build.props = tests\Directory.Build.props
tests\Directory.Build.targets = tests\Directory.Build.targets
tests\ImageSharp.Tests.ruleset = tests\ImageSharp.Tests.ruleset
diff --git a/shared-infrastructure b/shared-infrastructure
index a1d3ac2049..7ac5703452 160000
--- a/shared-infrastructure
+++ b/shared-infrastructure
@@ -1 +1 @@
-Subproject commit a1d3ac20494631e3cc13132897573796b0e4ee6d
+Subproject commit 7ac5703452348d9295db31fc0912c2bd9e419dc9
diff --git a/src/ImageSharp/ColorProfiles/WorkingSpaces/GammaWorkingSpace.cs b/src/ImageSharp/ColorProfiles/WorkingSpaces/GammaWorkingSpace.cs
index 91fa426241..a3959f12e4 100644
--- a/src/ImageSharp/ColorProfiles/WorkingSpaces/GammaWorkingSpace.cs
+++ b/src/ImageSharp/ColorProfiles/WorkingSpaces/GammaWorkingSpace.cs
@@ -62,6 +62,7 @@ public override bool Equals(object? obj)
///
public override int GetHashCode() => HashCode.Combine(
+ typeof(GammaWorkingSpace),
this.WhitePoint,
this.ChromaticityCoordinates,
this.Gamma);
diff --git a/src/ImageSharp/ColorProfiles/WorkingSpaces/RgbWorkingSpace.cs b/src/ImageSharp/ColorProfiles/WorkingSpaces/RgbWorkingSpace.cs
index 97069b856b..b278dd3177 100644
--- a/src/ImageSharp/ColorProfiles/WorkingSpaces/RgbWorkingSpace.cs
+++ b/src/ImageSharp/ColorProfiles/WorkingSpaces/RgbWorkingSpace.cs
@@ -70,8 +70,10 @@ public override bool Equals(object? obj)
return true;
}
- if (obj is RgbWorkingSpace other)
+ if (obj.GetType() == this.GetType())
{
+ RgbWorkingSpace other = (RgbWorkingSpace)obj;
+
return this.WhitePoint.Equals(other.WhitePoint)
&& this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates);
}
@@ -81,5 +83,5 @@ public override bool Equals(object? obj)
///
public override int GetHashCode()
- => HashCode.Combine(this.WhitePoint, this.ChromaticityCoordinates);
+ => HashCode.Combine(this.GetType(), this.WhitePoint, this.ChromaticityCoordinates);
}
diff --git a/src/ImageSharp/Common/Tuples/Octet{T}.cs b/src/ImageSharp/Common/Tuples/Octet{T}.cs
deleted file mode 100644
index f73bdd3390..0000000000
--- a/src/ImageSharp/Common/Tuples/Octet{T}.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-namespace SixLabors.ImageSharp.Tuples;
-
-///
-/// Contains 8 element value tuples of various types.
-///
-[StructLayout(LayoutKind.Sequential)]
-internal struct Octet
- where T : unmanaged
-{
- public T V0;
- public T V1;
- public T V2;
- public T V3;
- public T V4;
- public T V5;
- public T V6;
- public T V7;
-
- ///
- public override readonly string ToString()
- {
- return $"Octet<{typeof(T)}>({this.V0},{this.V1},{this.V2},{this.V3},{this.V4},{this.V5},{this.V6},{this.V7})";
- }
-}
-
-///
-/// Extension methods for the type.
-///
-internal static class OctetExtensions
-{
- ///
- /// Loads the fields in a target of from one of type.
- ///
- /// The target of instance.
- /// The source of instance.
- [MethodImpl(InliningOptions.ShortMethod)]
- public static void LoadFrom(ref this Octet destination, ref Octet source)
- {
- destination.V0 = source.V0;
- destination.V1 = source.V1;
- destination.V2 = source.V2;
- destination.V3 = source.V3;
- destination.V4 = source.V4;
- destination.V5 = source.V5;
- destination.V6 = source.V6;
- destination.V7 = source.V7;
- }
-
- ///
- /// Loads the fields in a target of from one of type.
- ///
- /// The target of instance.
- /// The source of instance.
- [MethodImpl(InliningOptions.ShortMethod)]
- public static void LoadFrom(ref this Octet destination, ref Octet source)
- {
- destination.V0 = (byte)source.V0;
- destination.V1 = (byte)source.V1;
- destination.V2 = (byte)source.V2;
- destination.V3 = (byte)source.V3;
- destination.V4 = (byte)source.V4;
- destination.V5 = (byte)source.V5;
- destination.V6 = (byte)source.V6;
- destination.V7 = (byte)source.V7;
- }
-}
diff --git a/tests/Directory.Build.targets b/tests/Directory.Build.targets
index 6b25509ed8..71f2bc333c 100644
--- a/tests/Directory.Build.targets
+++ b/tests/Directory.Build.targets
@@ -19,11 +19,6 @@
-
-
diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs
index 232d8b3e27..c69510bc4d 100644
--- a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs
+++ b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs
@@ -7,7 +7,6 @@
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Tuples;
namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion;
@@ -225,8 +224,8 @@ public void Bitops_SingleTuple()
// [Benchmark]
public void Bitops_Simd()
{
- ref Octet sBase = ref Unsafe.As>(ref this.source[0]);
- ref Octet dBase = ref Unsafe.As>(ref this.dest[0]);
+ ref InlineArray8 sBase = ref Unsafe.As>(ref this.source[0]);
+ ref InlineArray8 dBase = ref Unsafe.As>(ref this.dest[0]);
for (nuint i = 0; i < (uint)this.Count / 8; i++)
{
@@ -249,9 +248,9 @@ private struct C
#pragma warning restore SA1132 // Do not combine fields
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static void BitopsSimdImpl(ref Octet s, ref Octet d)
+ private static void BitopsSimdImpl(ref InlineArray8 s, ref InlineArray8 d)
{
- Vector sVec = Unsafe.As, Vector>(ref s);
+ Vector sVec = Unsafe.As, Vector>(ref s);
Vector aMask = new(0xFF00FF00);
Vector bMask = new(0x00FF00FF);
@@ -274,7 +273,7 @@ private static void BitopsSimdImpl(ref Octet s, ref Octet d)
Vector cc = Unsafe.As>(ref c);
Vector dd = aa + cc;
- d = Unsafe.As, Octet>(ref dd);
+ d = Unsafe.As, InlineArray8>(ref dd);
}
// [Benchmark]
diff --git a/tests/ImageSharp.Benchmarks/General/Vectorization/WidenBytesToUInt32.cs b/tests/ImageSharp.Benchmarks/General/Vectorization/WidenBytesToUInt32.cs
index da7ddae41e..fd17262dec 100644
--- a/tests/ImageSharp.Benchmarks/General/Vectorization/WidenBytesToUInt32.cs
+++ b/tests/ImageSharp.Benchmarks/General/Vectorization/WidenBytesToUInt32.cs
@@ -5,8 +5,6 @@
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
-using SixLabors.ImageSharp.Tuples;
-
namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization;
[Config(typeof(Config.Short))]
@@ -30,12 +28,22 @@ public void Standard()
{
const int N = Count / 8;
- ref Octet sBase = ref Unsafe.As>(ref this.source[0]);
- ref Octet dBase = ref Unsafe.As>(ref this.dest[0]);
+ ref InlineArray8 sBase = ref Unsafe.As>(ref this.source[0]);
+ ref InlineArray8 dBase = ref Unsafe.As>(ref this.dest[0]);
for (nuint i = 0; i < N; i++)
{
- Unsafe.Add(ref dBase, i).LoadFrom(ref Unsafe.Add(ref sBase, i));
+ ref InlineArray8 source = ref Unsafe.Add(ref sBase, i);
+ ref InlineArray8 destination = ref Unsafe.Add(ref dBase, i);
+
+ destination[0] = source[0];
+ destination[1] = source[1];
+ destination[2] = source[2];
+ destination[3] = source[3];
+ destination[4] = source[4];
+ destination[5] = source[5];
+ destination[6] = source[6];
+ destination[7] = source[7];
}
}
diff --git a/tests/ImageSharp.Tests/ColorProfiles/RgbWorkingSpaceTests.cs b/tests/ImageSharp.Tests/ColorProfiles/RgbWorkingSpaceTests.cs
new file mode 100644
index 0000000000..8a38ea11fc
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/RgbWorkingSpaceTests.cs
@@ -0,0 +1,122 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Numerics;
+using SixLabors.ImageSharp.ColorProfiles;
+using SixLabors.ImageSharp.ColorProfiles.WorkingSpaces;
+
+namespace SixLabors.ImageSharp.Tests.ColorProfiles;
+
+///
+/// Tests the class.
+///
+[Trait("Color", "Conversion")]
+public class RgbWorkingSpaceTests
+{
+ private static readonly ApproximateFloatComparer TolerantComparer = new(1e-5F);
+
+ public static readonly TheoryData WorkingSpaces = new()
+ {
+ KnownRgbWorkingSpaces.SRgb,
+ KnownRgbWorkingSpaces.SRgbSimplified,
+ KnownRgbWorkingSpaces.Rec709,
+ KnownRgbWorkingSpaces.Rec2020,
+ KnownRgbWorkingSpaces.ECIRgbv2,
+ KnownRgbWorkingSpaces.AdobeRgb1998,
+ KnownRgbWorkingSpaces.ApplesRgb,
+ KnownRgbWorkingSpaces.BestRgb,
+ KnownRgbWorkingSpaces.BetaRgb,
+ KnownRgbWorkingSpaces.BruceRgb,
+ KnownRgbWorkingSpaces.CIERgb,
+ KnownRgbWorkingSpaces.ColorMatchRgb,
+ KnownRgbWorkingSpaces.DonRgb4,
+ KnownRgbWorkingSpaces.EktaSpacePS5,
+ KnownRgbWorkingSpaces.NTSCRgb,
+ KnownRgbWorkingSpaces.PALSECAMRgb,
+ KnownRgbWorkingSpaces.ProPhotoRgb,
+ KnownRgbWorkingSpaces.SMPTECRgb,
+ KnownRgbWorkingSpaces.WideGamutRgb
+ };
+
+ [Fact]
+ public void RgbWorkingSpaceEqualityRequiresSameConcreteType()
+ {
+ RgbWorkingSpace sRgb = KnownRgbWorkingSpaces.SRgb;
+ RgbWorkingSpace sRgbSimplified = KnownRgbWorkingSpaces.SRgbSimplified;
+ RgbWorkingSpace rec709 = KnownRgbWorkingSpaces.Rec709;
+
+ Assert.False(sRgb.Equals(sRgbSimplified));
+ Assert.False(sRgbSimplified.Equals(sRgb));
+ Assert.False(sRgb.Equals(rec709));
+ Assert.False(rec709.Equals(sRgb));
+
+ Assert.NotEqual(sRgb.GetHashCode(), sRgbSimplified.GetHashCode());
+ Assert.NotEqual(sRgb.GetHashCode(), rec709.GetHashCode());
+ }
+
+ [Fact]
+ public void RgbWorkingSpaceEqualityMatchesSameConcreteTypeValues()
+ {
+ RgbWorkingSpace x = new SRgbWorkingSpace(
+ KnownRgbWorkingSpaces.SRgb.WhitePoint,
+ KnownRgbWorkingSpaces.SRgb.ChromaticityCoordinates);
+
+ RgbWorkingSpace y = new SRgbWorkingSpace(
+ KnownRgbWorkingSpaces.SRgb.WhitePoint,
+ KnownRgbWorkingSpaces.SRgb.ChromaticityCoordinates);
+
+ Assert.Equal(x, y);
+ Assert.Equal(x.GetHashCode(), y.GetHashCode());
+ }
+
+ [Fact]
+ public void GammaWorkingSpaceEqualityIncludesGamma()
+ {
+ GammaWorkingSpace x = new(
+ 2.2F,
+ KnownRgbWorkingSpaces.SRgbSimplified.WhitePoint,
+ KnownRgbWorkingSpaces.SRgbSimplified.ChromaticityCoordinates);
+
+ GammaWorkingSpace y = new(
+ 1.8F,
+ KnownRgbWorkingSpaces.SRgbSimplified.WhitePoint,
+ KnownRgbWorkingSpaces.SRgbSimplified.ChromaticityCoordinates);
+
+ Assert.NotEqual(x, y);
+ Assert.NotEqual(x.GetHashCode(), y.GetHashCode());
+ }
+
+ [Theory]
+ [MemberData(nameof(WorkingSpaces))]
+ public void CompressAndExpand_RoundTripsWithTolerance(RgbWorkingSpace workingSpace)
+ {
+ Vector4[] linear =
+ [
+ new(0F, .001F, .18F, 1F), // Endpoint, below the sRGB breakpoint, common middle gray, and opaque alpha.
+ new(.0031308F, .25F, .5F, .75F), // sRGB linear/gamma breakpoint with interior values and partial alpha.
+ new(.75F, .5F, .25F, .5F), // Reversed interior values ensure channel order does not hide errors.
+ new(1F, .8F, .2F, .25F) // Upper endpoint, high/low interior values, and low alpha.
+ ];
+
+ Vector4[] expectedCompressed = new Vector4[linear.Length];
+
+ for (int i = 0; i < linear.Length; i++)
+ {
+ Vector4 compressed = workingSpace.Compress(linear[i]);
+ Vector4 expanded = workingSpace.Expand(compressed);
+
+ expectedCompressed[i] = compressed;
+
+ Assert.Equal(linear[i], expanded, TolerantComparer);
+ }
+
+ Vector4[] actualCompressed = linear.ToArray();
+ workingSpace.Compress(actualCompressed);
+
+ Assert.Equal(expectedCompressed, actualCompressed, TolerantComparer);
+
+ workingSpace.Expand(actualCompressed);
+
+ Assert.Equal(linear, actualCompressed, TolerantComparer);
+ }
+}
diff --git a/tests/ImageSharp.Tests/Common/SimdUtilsTests.Shuffle.cs b/tests/ImageSharp.Tests/Common/SimdUtilsTests.Shuffle.cs
index 81daac3e0b..12b4c34262 100644
--- a/tests/ImageSharp.Tests/Common/SimdUtilsTests.Shuffle.cs
+++ b/tests/ImageSharp.Tests/Common/SimdUtilsTests.Shuffle.cs
@@ -292,7 +292,7 @@ static void RunTest(string serialized)
FeatureTestRunner.RunWithHwIntrinsicsFeature(
RunTest,
count,
- HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX | HwIntrinsics.DisableHWIntrinsic);
+ HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512F | HwIntrinsics.DisableAVX | HwIntrinsics.DisableHWIntrinsic);
}
[Theory]
@@ -478,7 +478,7 @@ static void RunTest(string serialized)
FeatureTestRunner.RunWithHwIntrinsicsFeature(
RunTest,
count,
- HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX | HwIntrinsics.DisableHWIntrinsic);
+ HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512F | HwIntrinsics.DisableAVX | HwIntrinsics.DisableHWIntrinsic);
}
private static void TestShuffleFloat4Channel(
diff --git a/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs b/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs
index e39f9456f0..dfd0a6b307 100644
--- a/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs
+++ b/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs
@@ -133,7 +133,7 @@ static void RunTest(string serialized) => TestImpl_BulkConvertByteToNormalizedFl
FeatureTestRunner.RunWithHwIntrinsicsFeature(
RunTest,
count,
- HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512 | HwIntrinsics.DisableAVX2);
+ HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512F | HwIntrinsics.DisableAVX2);
}
[Theory]
@@ -171,7 +171,7 @@ static void RunTest(string serialized) => TestImpl_BulkConvertNormalizedFloatToB
FeatureTestRunner.RunWithHwIntrinsicsFeature(
RunTest,
count,
- HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512 | HwIntrinsics.DisableAVX2);
+ HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512F | HwIntrinsics.DisableAVX2);
}
[Theory]
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs
index 544ac85a51..610693c7f4 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs
@@ -219,7 +219,7 @@ static void RunTest(string srcSeedSerialized, string qtSeedSerialized)
RunTest,
srcSeed,
qtSeed,
- HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX | HwIntrinsics.DisableHWIntrinsic);
+ HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512F | HwIntrinsics.DisableAVX | HwIntrinsics.DisableHWIntrinsic);
}
[Fact]
@@ -391,7 +391,7 @@ static void RunTest()
// 3. DisableAvx2 - call fallback code of float implementation
FeatureTestRunner.RunWithHwIntrinsicsFeature(
RunTest,
- HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX | HwIntrinsics.DisableHWIntrinsic);
+ HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512F | HwIntrinsics.DisableAVX | HwIntrinsics.DisableHWIntrinsic);
}
[Theory]
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs
index 83c3a344da..b17a39f388 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs
@@ -152,7 +152,7 @@ static void RunTest(string serialized)
FeatureTestRunner.RunWithHwIntrinsicsFeature(
RunTest,
seed,
- HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX | HwIntrinsics.DisableHWIntrinsic);
+ HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512F | HwIntrinsics.DisableAVX | HwIntrinsics.DisableHWIntrinsic);
}
[Theory]
@@ -359,7 +359,7 @@ static void RunTest(string serialized)
FeatureTestRunner.RunWithHwIntrinsicsFeature(
RunTest,
seed,
- HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX | HwIntrinsics.DisableHWIntrinsic);
+ HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512F | HwIntrinsics.DisableAVX | HwIntrinsics.DisableHWIntrinsic);
}
}
}
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs
index 8d94fb5cf4..ba0dce4c54 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs
@@ -69,7 +69,7 @@ public void GetConverterReturnsCorrectConverterWithRgbColorSpace()
{
FeatureTestRunner.RunWithHwIntrinsicsFeature(
RunTest,
- HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512 | HwIntrinsics.DisableAVX | HwIntrinsics.DisableHWIntrinsic);
+ HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512F | HwIntrinsics.DisableAVX | HwIntrinsics.DisableHWIntrinsic);
static void RunTest(string arg)
{
@@ -102,7 +102,7 @@ public void GetConverterReturnsCorrectConverterWithGrayScaleColorSpace()
{
FeatureTestRunner.RunWithHwIntrinsicsFeature(
RunTest,
- HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512 | HwIntrinsics.DisableAVX2 | HwIntrinsics.DisableHWIntrinsic);
+ HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512F | HwIntrinsics.DisableAVX2 | HwIntrinsics.DisableHWIntrinsic);
static void RunTest(string arg)
{
@@ -168,7 +168,7 @@ public void GetConverterReturnsCorrectConverterWithYCbCrColorSpace()
{
FeatureTestRunner.RunWithHwIntrinsicsFeature(
RunTest,
- HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512 | HwIntrinsics.DisableAVX2 | HwIntrinsics.DisableHWIntrinsic);
+ HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512F | HwIntrinsics.DisableAVX2 | HwIntrinsics.DisableHWIntrinsic);
static void RunTest(string arg)
{
@@ -201,7 +201,7 @@ public void GetConverterReturnsCorrectConverterWithYcckColorSpace()
{
FeatureTestRunner.RunWithHwIntrinsicsFeature(
RunTest,
- HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512 | HwIntrinsics.DisableAVX2 | HwIntrinsics.DisableHWIntrinsic);
+ HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512F | HwIntrinsics.DisableAVX2 | HwIntrinsics.DisableHWIntrinsic);
static void RunTest(string arg)
{
diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelBlenderTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelBlenderTests.cs
index 924e94d929..ddd79bb756 100644
--- a/tests/ImageSharp.Tests/PixelFormats/PixelBlenderTests.cs
+++ b/tests/ImageSharp.Tests/PixelFormats/PixelBlenderTests.cs
@@ -1,6 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
+using System.Numerics;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.PixelFormats.PixelBlenders;
using SixLabors.ImageSharp.Tests.TestUtilities;
@@ -32,6 +33,172 @@ public class PixelBlenderTests
{ new TestPixel(), typeof(DefaultPixelBlenders.MultiplySrcOver), PixelColorBlendingMode.Multiply },
};
+ public static TheoryData BlenderModeMappings
+ {
+ get
+ {
+ TheoryData data = new();
+
+ AddBlenderModeMappings(
+ data,
+ PixelAlphaCompositionMode.Clear,
+ typeof(DefaultPixelBlenders.NormalClear),
+ typeof(DefaultPixelBlenders.MultiplyClear),
+ typeof(DefaultPixelBlenders.AddClear),
+ typeof(DefaultPixelBlenders.SubtractClear),
+ typeof(DefaultPixelBlenders.ScreenClear),
+ typeof(DefaultPixelBlenders.DarkenClear),
+ typeof(DefaultPixelBlenders.LightenClear),
+ typeof(DefaultPixelBlenders.OverlayClear),
+ typeof(DefaultPixelBlenders.HardLightClear));
+
+ AddBlenderModeMappings(
+ data,
+ PixelAlphaCompositionMode.Xor,
+ typeof(DefaultPixelBlenders.NormalXor),
+ typeof(DefaultPixelBlenders.MultiplyXor),
+ typeof(DefaultPixelBlenders.AddXor),
+ typeof(DefaultPixelBlenders.SubtractXor),
+ typeof(DefaultPixelBlenders.ScreenXor),
+ typeof(DefaultPixelBlenders.DarkenXor),
+ typeof(DefaultPixelBlenders.LightenXor),
+ typeof(DefaultPixelBlenders.OverlayXor),
+ typeof(DefaultPixelBlenders.HardLightXor));
+
+ AddBlenderModeMappings(
+ data,
+ PixelAlphaCompositionMode.Src,
+ typeof(DefaultPixelBlenders.NormalSrc),
+ typeof(DefaultPixelBlenders.MultiplySrc),
+ typeof(DefaultPixelBlenders.AddSrc),
+ typeof(DefaultPixelBlenders.SubtractSrc),
+ typeof(DefaultPixelBlenders.ScreenSrc),
+ typeof(DefaultPixelBlenders.DarkenSrc),
+ typeof(DefaultPixelBlenders.LightenSrc),
+ typeof(DefaultPixelBlenders.OverlaySrc),
+ typeof(DefaultPixelBlenders.HardLightSrc));
+
+ AddBlenderModeMappings(
+ data,
+ PixelAlphaCompositionMode.SrcAtop,
+ typeof(DefaultPixelBlenders.NormalSrcAtop),
+ typeof(DefaultPixelBlenders.MultiplySrcAtop),
+ typeof(DefaultPixelBlenders.AddSrcAtop),
+ typeof(DefaultPixelBlenders.SubtractSrcAtop),
+ typeof(DefaultPixelBlenders.ScreenSrcAtop),
+ typeof(DefaultPixelBlenders.DarkenSrcAtop),
+ typeof(DefaultPixelBlenders.LightenSrcAtop),
+ typeof(DefaultPixelBlenders.OverlaySrcAtop),
+ typeof(DefaultPixelBlenders.HardLightSrcAtop));
+
+ AddBlenderModeMappings(
+ data,
+ PixelAlphaCompositionMode.SrcIn,
+ typeof(DefaultPixelBlenders.NormalSrcIn),
+ typeof(DefaultPixelBlenders.MultiplySrcIn),
+ typeof(DefaultPixelBlenders.AddSrcIn),
+ typeof(DefaultPixelBlenders.SubtractSrcIn),
+ typeof(DefaultPixelBlenders.ScreenSrcIn),
+ typeof(DefaultPixelBlenders.DarkenSrcIn),
+ typeof(DefaultPixelBlenders.LightenSrcIn),
+ typeof(DefaultPixelBlenders.OverlaySrcIn),
+ typeof(DefaultPixelBlenders.HardLightSrcIn));
+
+ AddBlenderModeMappings(
+ data,
+ PixelAlphaCompositionMode.SrcOut,
+ typeof(DefaultPixelBlenders.NormalSrcOut),
+ typeof(DefaultPixelBlenders.MultiplySrcOut),
+ typeof(DefaultPixelBlenders.AddSrcOut),
+ typeof(DefaultPixelBlenders.SubtractSrcOut),
+ typeof(DefaultPixelBlenders.ScreenSrcOut),
+ typeof(DefaultPixelBlenders.DarkenSrcOut),
+ typeof(DefaultPixelBlenders.LightenSrcOut),
+ typeof(DefaultPixelBlenders.OverlaySrcOut),
+ typeof(DefaultPixelBlenders.HardLightSrcOut));
+
+ AddBlenderModeMappings(
+ data,
+ PixelAlphaCompositionMode.Dest,
+ typeof(DefaultPixelBlenders.NormalDest),
+ typeof(DefaultPixelBlenders.MultiplyDest),
+ typeof(DefaultPixelBlenders.AddDest),
+ typeof(DefaultPixelBlenders.SubtractDest),
+ typeof(DefaultPixelBlenders.ScreenDest),
+ typeof(DefaultPixelBlenders.DarkenDest),
+ typeof(DefaultPixelBlenders.LightenDest),
+ typeof(DefaultPixelBlenders.OverlayDest),
+ typeof(DefaultPixelBlenders.HardLightDest));
+
+ AddBlenderModeMappings(
+ data,
+ PixelAlphaCompositionMode.DestAtop,
+ typeof(DefaultPixelBlenders.NormalDestAtop),
+ typeof(DefaultPixelBlenders.MultiplyDestAtop),
+ typeof(DefaultPixelBlenders.AddDestAtop),
+ typeof(DefaultPixelBlenders.SubtractDestAtop),
+ typeof(DefaultPixelBlenders.ScreenDestAtop),
+ typeof(DefaultPixelBlenders.DarkenDestAtop),
+ typeof(DefaultPixelBlenders.LightenDestAtop),
+ typeof(DefaultPixelBlenders.OverlayDestAtop),
+ typeof(DefaultPixelBlenders.HardLightDestAtop));
+
+ AddBlenderModeMappings(
+ data,
+ PixelAlphaCompositionMode.DestIn,
+ typeof(DefaultPixelBlenders.NormalDestIn),
+ typeof(DefaultPixelBlenders.MultiplyDestIn),
+ typeof(DefaultPixelBlenders.AddDestIn),
+ typeof(DefaultPixelBlenders.SubtractDestIn),
+ typeof(DefaultPixelBlenders.ScreenDestIn),
+ typeof(DefaultPixelBlenders.DarkenDestIn),
+ typeof(DefaultPixelBlenders.LightenDestIn),
+ typeof(DefaultPixelBlenders.OverlayDestIn),
+ typeof(DefaultPixelBlenders.HardLightDestIn));
+
+ AddBlenderModeMappings(
+ data,
+ PixelAlphaCompositionMode.DestOut,
+ typeof(DefaultPixelBlenders.NormalDestOut),
+ typeof(DefaultPixelBlenders.MultiplyDestOut),
+ typeof(DefaultPixelBlenders.AddDestOut),
+ typeof(DefaultPixelBlenders.SubtractDestOut),
+ typeof(DefaultPixelBlenders.ScreenDestOut),
+ typeof(DefaultPixelBlenders.DarkenDestOut),
+ typeof(DefaultPixelBlenders.LightenDestOut),
+ typeof(DefaultPixelBlenders.OverlayDestOut),
+ typeof(DefaultPixelBlenders.HardLightDestOut));
+
+ AddBlenderModeMappings(
+ data,
+ PixelAlphaCompositionMode.DestOver,
+ typeof(DefaultPixelBlenders.NormalDestOver),
+ typeof(DefaultPixelBlenders.MultiplyDestOver),
+ typeof(DefaultPixelBlenders.AddDestOver),
+ typeof(DefaultPixelBlenders.SubtractDestOver),
+ typeof(DefaultPixelBlenders.ScreenDestOver),
+ typeof(DefaultPixelBlenders.DarkenDestOver),
+ typeof(DefaultPixelBlenders.LightenDestOver),
+ typeof(DefaultPixelBlenders.OverlayDestOver),
+ typeof(DefaultPixelBlenders.HardLightDestOver));
+
+ AddBlenderModeMappings(
+ data,
+ PixelAlphaCompositionMode.SrcOver,
+ typeof(DefaultPixelBlenders.NormalSrcOver),
+ typeof(DefaultPixelBlenders.MultiplySrcOver),
+ typeof(DefaultPixelBlenders.AddSrcOver),
+ typeof(DefaultPixelBlenders.SubtractSrcOver),
+ typeof(DefaultPixelBlenders.ScreenSrcOver),
+ typeof(DefaultPixelBlenders.DarkenSrcOver),
+ typeof(DefaultPixelBlenders.LightenSrcOver),
+ typeof(DefaultPixelBlenders.OverlaySrcOver),
+ typeof(DefaultPixelBlenders.HardLightSrcOver));
+
+ return data;
+ }
+ }
+
[Theory]
[MemberData(nameof(BlenderMappings))]
public void ReturnsCorrectBlender(TestPixel pixel, Type type, PixelColorBlendingMode mode)
@@ -41,6 +208,126 @@ public void ReturnsCorrectBlender(TestPixel pixel, Type type, Pi
Assert.IsType(type, blender);
}
+ [Theory]
+ [MemberData(nameof(BlenderModeMappings))]
+ public void ReturnsCorrectBlenderForAllModeCombinations(PixelColorBlendingMode colorMode, PixelAlphaCompositionMode alphaMode, Type type)
+ {
+ PixelBlender blender = PixelOperations.Instance.GetPixelBlender(colorMode, alphaMode);
+ Assert.IsType(type, blender);
+ }
+
+ [Fact]
+ public void BlendFunctionsAreCalledForAllModeCombinations() =>
+ FeatureTestRunner.RunWithHwIntrinsicsFeature(
+ ExerciseAllBlenderModeCombinations,
+ HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512F | HwIntrinsics.DisableAVX | HwIntrinsics.DisableHWIntrinsic);
+
+ [Fact]
+ public void Blend_WithConstantSourceAndSingleAmount()
+ {
+ PixelBlender blender = new DefaultPixelBlenders.NormalSrcOver();
+ Rgba32[] destination = new Rgba32[2];
+ Rgba32[] background =
+ [
+ Color.Red.ToPixel(),
+ Color.Green.ToPixel()
+ ];
+
+ Rgba32 source = Color.Blue.ToPixel();
+
+ blender.Blend(Configuration.Default, destination, background, source, 1F);
+
+ Assert.Equal(source, destination[0]);
+ Assert.Equal(source, destination[1]);
+ }
+
+ [Fact]
+ public void Blend_WithConstantSourceSingleAmountAndWorkingBuffer()
+ {
+ PixelBlender blender = new DefaultPixelBlenders.NormalSrcOver();
+ Rgba32[] destination = new Rgba32[2];
+ Rgba32[] background =
+ [
+ Color.Red.ToPixel(),
+ Color.Green.ToPixel()
+ ];
+
+ Rgba32 source = Color.Blue.ToPixel();
+ Vector4[] workingBuffer = new Vector4[destination.Length * 2];
+
+ blender.Blend(Configuration.Default, destination, background, source, 1F, workingBuffer);
+
+ Assert.Equal(source, destination[0]);
+ Assert.Equal(source, destination[1]);
+ }
+
+ [Fact]
+ public void Blend_WithConstantSourceAndAmountSpan()
+ {
+ PixelBlender blender = new DefaultPixelBlenders.NormalSrcOver();
+ Rgba32[] destination = new Rgba32[2];
+ Rgba32[] background =
+ [
+ Color.Red.ToPixel(),
+ Color.Green.ToPixel()
+ ];
+
+ Rgba32 source = Color.Blue.ToPixel();
+ float[] amount = [1F, 1F];
+
+ blender.Blend(Configuration.Default, destination, background, source, amount);
+
+ Assert.Equal(source, destination[0]);
+ Assert.Equal(source, destination[1]);
+ }
+
+ [Fact]
+ public void Blend_WithConstantSourceAmountSpanAndWorkingBuffer()
+ {
+ PixelBlender blender = new DefaultPixelBlenders.NormalSrcOver();
+ Rgba32[] destination = new Rgba32[2];
+ Rgba32[] background =
+ [
+ Color.Red.ToPixel(),
+ Color.Green.ToPixel()
+ ];
+
+ Rgba32 source = Color.Blue.ToPixel();
+ float[] amount = [1F, 1F];
+ Vector4[] workingBuffer = new Vector4[destination.Length * 2];
+
+ blender.Blend(Configuration.Default, destination, background, source, amount, workingBuffer);
+
+ Assert.Equal(source, destination[0]);
+ Assert.Equal(source, destination[1]);
+ }
+
+ [Fact]
+ public void Blend_WithSourceSpanAmountSpanAndWorkingBuffer()
+ {
+ PixelBlender blender = new DefaultPixelBlenders.NormalSrcOver();
+ Rgba32[] destination = new Rgba32[2];
+ Rgba32[] background =
+ [
+ Color.Red.ToPixel(),
+ Color.Green.ToPixel()
+ ];
+
+ Rgba32[] source =
+ [
+ Color.Blue.ToPixel(),
+ Color.Yellow.ToPixel()
+ ];
+
+ float[] amount = [1F, 1F];
+ Vector4[] workingBuffer = new Vector4[destination.Length * 3];
+
+ blender.Blend(Configuration.Default, destination, background, source, amount, workingBuffer);
+
+ Assert.Equal(source[0], destination[0]);
+ Assert.Equal(source[1], destination[1]);
+ }
+
public static TheoryData ColorBlendingExpectedResults = new()
{
{ Color.MistyRose.ToPixel(), Color.MidnightBlue.ToPixel(), 1, PixelColorBlendingMode.Normal, Color.MidnightBlue.ToPixel() },
@@ -92,4 +379,67 @@ public void TestAlphaCompositionModes(Rgba32 backdrop, Rgba32 source, float opac
// var str = actualResult.Rgba.ToString("X8"); // used to extract expectedResults
Assert.Equal(actualResult.ToVector4(), expectedResult.ToVector4());
}
+
+ private static void AddBlenderModeMappings(
+ TheoryData data,
+ PixelAlphaCompositionMode alphaMode,
+ Type normal,
+ Type multiply,
+ Type add,
+ Type subtract,
+ Type screen,
+ Type darken,
+ Type lighten,
+ Type overlay,
+ Type hardLight)
+ {
+ data.Add(PixelColorBlendingMode.Normal, alphaMode, normal);
+ data.Add(PixelColorBlendingMode.Multiply, alphaMode, multiply);
+ data.Add(PixelColorBlendingMode.Add, alphaMode, add);
+ data.Add(PixelColorBlendingMode.Subtract, alphaMode, subtract);
+ data.Add(PixelColorBlendingMode.Screen, alphaMode, screen);
+ data.Add(PixelColorBlendingMode.Darken, alphaMode, darken);
+ data.Add(PixelColorBlendingMode.Lighten, alphaMode, lighten);
+ data.Add(PixelColorBlendingMode.Overlay, alphaMode, overlay);
+ data.Add(PixelColorBlendingMode.HardLight, alphaMode, hardLight);
+ }
+
+ private static void ExerciseAllBlenderModeCombinations()
+ {
+ foreach (PixelAlphaCompositionMode alphaMode in Enum.GetValues())
+ {
+ foreach (PixelColorBlendingMode colorMode in Enum.GetValues())
+ {
+ PixelBlender blender = PixelOperations.Instance.GetPixelBlender(colorMode, alphaMode);
+ ExerciseBlender(blender);
+ }
+ }
+ }
+
+ private static void ExerciseBlender(PixelBlender blender)
+ {
+ Rgba32 background = Color.MistyRose.ToPixel();
+ Rgba32 source = Color.MidnightBlue.ToPixel();
+ float[] amount = [1F, 1F, 1F, 1F];
+
+ Rgba32 expected = blender.Blend(background, source, 1F);
+
+ Rgba32[] destination = new Rgba32[4];
+ Rgba32[] backgroundSpan = [background, background, background, background];
+ Rgba32[] sourceSpan = [source, source, source, source];
+ Vector4[] sourceSpanBuffer = new Vector4[destination.Length * 3];
+ Vector4[] constantSourceBuffer = new Vector4[destination.Length * 2];
+
+ blender.Blend(Configuration.Default, destination, backgroundSpan, sourceSpan, 1F, sourceSpanBuffer);
+ Assert.All(destination, x => Assert.Equal(expected, x));
+
+ blender.Blend(Configuration.Default, destination, backgroundSpan, source, 1F, constantSourceBuffer);
+ Assert.All(destination, x => Assert.Equal(expected, x));
+
+ blender.Blend(Configuration.Default, destination, backgroundSpan, sourceSpan, amount, sourceSpanBuffer);
+ Assert.All(destination, x => Assert.Equal(expected, x));
+
+ blender.Blend(Configuration.Default, destination, backgroundSpan, source, amount, constantSourceBuffer);
+ Assert.All(destination, x => Assert.Equal(expected, x));
+ }
}
diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffCompositorTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffCompositorTests.cs
index 994b7d02ee..f8c296846b 100644
--- a/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffCompositorTests.cs
+++ b/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffCompositorTests.cs
@@ -59,7 +59,7 @@ TestImageProvider provider
FeatureTestRunner.RunWithHwIntrinsicsFeature(
RunTest,
- HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512 | HwIntrinsics.DisableAVX,
+ HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512F | HwIntrinsics.DisableAVX,
provider,
mode.ToString());
}
diff --git a/tests/ImageSharp.Tests/TestUtilities/FeatureTesting/FeatureTestRunner.cs b/tests/ImageSharp.Tests/TestUtilities/FeatureTesting/FeatureTestRunner.cs
index be3e9ccd5d..4cd30fc571 100644
--- a/tests/ImageSharp.Tests/TestUtilities/FeatureTesting/FeatureTestRunner.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/FeatureTesting/FeatureTestRunner.cs
@@ -439,7 +439,7 @@ public enum HwIntrinsics : long
DisableSSE42 = 1L << 1,
DisableAVX = 1L << 2,
DisableAVX2 = 1L << 3,
- DisableAVX512 = 1L << 4,
+ DisableAVX512F = 1L << 4,
DisableAVX512v2 = 1L << 5,
DisableAVX512v3 = 1L << 6,
DisableAVX10v1 = 1L << 7,
diff --git a/tests/coverlet.runsettings b/tests/coverlet.runsettings
index cffce3540b..f327b47a2e 100644
--- a/tests/coverlet.runsettings
+++ b/tests/coverlet.runsettings
@@ -9,7 +9,7 @@
lcov
- [SixLabors.*]*
+ [SixLabors.ImageSharp*]*
true