diff --git a/.editorconfig b/.editorconfig
index c28089d720..af1e5b44c1 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -104,8 +104,8 @@ dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:war
 dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning
 dotnet_style_parentheses_in_other_operators = always_for_clarity:suggestion
 # Expression-level preferences
-dotnet_style_object_initializer = true:warning
-dotnet_style_collection_initializer = true:warning
+dotnet_style_object_initializer = true:error
+dotnet_style_collection_initializer = true:error
 dotnet_style_explicit_tuple_names = true:warning
 dotnet_style_prefer_inferred_tuple_names = true:warning
 dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning
@@ -135,9 +135,9 @@ csharp_style_prefer_null_check_over_type_check = true:warning
 # https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/language-rules#c-style-rules
 [*.{cs,csx,cake}]
 # 'var' preferences
-csharp_style_var_for_built_in_types = false:warning
-csharp_style_var_when_type_is_apparent = false:warning
-csharp_style_var_elsewhere = false:warning
+csharp_style_var_for_built_in_types = false:error
+csharp_style_var_when_type_is_apparent = false:error
+csharp_style_var_elsewhere = false:error
 # Expression-bodied members
 csharp_style_expression_bodied_methods = true:warning
 csharp_style_expression_bodied_constructors = true:warning
@@ -160,7 +160,7 @@ csharp_style_pattern_local_over_anonymous_function = true:warning
 csharp_style_deconstructed_variable_declaration = true:warning
 csharp_style_prefer_index_operator = true:warning
 csharp_style_prefer_range_operator = true:warning
-csharp_style_implicit_object_creation_when_type_is_apparent = true:warning
+csharp_style_implicit_object_creation_when_type_is_apparent = true:error
 # "Null" checking preferences
 csharp_style_throw_expression = true:warning
 csharp_style_conditional_delegate_call = true:warning
diff --git a/.gitattributes b/.gitattributes
index b5f742ab47..f7bd4d061e 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -136,3 +136,10 @@
 *.ico               filter=lfs diff=lfs merge=lfs -text
 *.cur               filter=lfs diff=lfs merge=lfs -text
 *.ani               filter=lfs diff=lfs merge=lfs -text
+*.heic              filter=lfs diff=lfs merge=lfs -text
+*.hif               filter=lfs diff=lfs merge=lfs -text
+*.avif              filter=lfs diff=lfs merge=lfs -text
+###############################################################################
+# Handle ICC files by git lfs
+###############################################################################
+*.icc               filter=lfs diff=lfs merge=lfs -text
diff --git a/shared-infrastructure b/shared-infrastructure
index 1dbfb576c8..5e13cde851 160000
--- a/shared-infrastructure
+++ b/shared-infrastructure
@@ -1 +1 @@
-Subproject commit 1dbfb576c83507645265c79e03369b66cdc0379f
+Subproject commit 5e13cde851a3d6e95d0dfdde2a57071f1efda9c3
diff --git a/src/ImageSharp/ColorProfiles/CieLab.cs b/src/ImageSharp/ColorProfiles/CieLab.cs
index 377cc20a99..98cb2e613a 100644
--- a/src/ImageSharp/ColorProfiles/CieLab.cs
+++ b/src/ImageSharp/ColorProfiles/CieLab.cs
@@ -4,6 +4,7 @@
 using System.Numerics;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
 
 namespace SixLabors.ImageSharp.ColorProfiles;
 
@@ -82,6 +83,49 @@ public CieLab(Vector3 vector)
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     public static bool operator !=(CieLab left, CieLab right) => !left.Equals(right);
 
+    /// <inheritdoc/>
+    public Vector4 ToScaledVector4()
+    {
+        Vector3 v3 = default;
+        v3 += this.AsVector3Unsafe();
+        v3 += new Vector3(0, 128F, 128F);
+        v3 /= new Vector3(100F, 255F, 255F);
+        return new Vector4(v3, 1F);
+    }
+
+    /// <inheritdoc/>
+    public static CieLab FromScaledVector4(Vector4 source)
+    {
+        Vector3 v3 = source.AsVector3();
+        v3 *= new Vector3(100F, 255, 255);
+        v3 -= new Vector3(0, 128F, 128F);
+        return new CieLab(v3);
+    }
+
+    /// <inheritdoc/>
+    public static void ToScaledVector4(ReadOnlySpan<CieLab> source, Span<Vector4> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = source[i].ToScaledVector4();
+        }
+    }
+
+    /// <inheritdoc/>
+    public static void FromScaledVector4(ReadOnlySpan<Vector4> source, Span<CieLab> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = FromScaledVector4(source[i]);
+        }
+    }
+
     /// <inheritdoc/>
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     public static CieLab FromProfileConnectingSpace(ColorConversionOptions options, in CieXyz source)
@@ -136,7 +180,7 @@ public CieXyz ToProfileConnectingSpace(ColorConversionOptions options)
         float yr = l > CieConstants.Kappa * CieConstants.Epsilon ? Numerics.Pow3((l + 16F) / 116F) : l / CieConstants.Kappa;
         float zr = fz3 > CieConstants.Epsilon ? fz3 : ((116F * fz) - 16F) / CieConstants.Kappa;
 
-        CieXyz whitePoint = options.WhitePoint;
+        CieXyz whitePoint = options.SourceWhitePoint;
         Vector3 wxyz = new(whitePoint.X, whitePoint.Y, whitePoint.Z);
         Vector3 xyzr = new(xr, yr, zr);
 
diff --git a/src/ImageSharp/ColorProfiles/CieLch.cs b/src/ImageSharp/ColorProfiles/CieLch.cs
index 1319783406..2e495b9a77 100644
--- a/src/ImageSharp/ColorProfiles/CieLch.cs
+++ b/src/ImageSharp/ColorProfiles/CieLch.cs
@@ -4,6 +4,7 @@
 using System.Numerics;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
 
 namespace SixLabors.ImageSharp.ColorProfiles;
 
@@ -50,7 +51,7 @@ public CieLch(Vector3 vector)
 
     /// <summary>
     /// Gets the a chroma component.
-    /// <remarks>A value ranging from 0 to 200.</remarks>
+    /// <remarks>A value ranging from -200 to 200.</remarks>
     /// </summary>
     public float C { get; }
 
@@ -82,6 +83,49 @@ public CieLch(Vector3 vector)
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     public static bool operator !=(CieLch left, CieLch right) => !left.Equals(right);
 
+    /// <inheritdoc/>
+    public Vector4 ToScaledVector4()
+    {
+        Vector3 v3 = default;
+        v3 += this.AsVector3Unsafe();
+        v3 += new Vector3(0, 200, 0);
+        v3 /= new Vector3(100, 400, 360);
+        return new Vector4(v3, 1F);
+    }
+
+    /// <inheritdoc/>
+    public static CieLch FromScaledVector4(Vector4 source)
+    {
+        Vector3 v3 = source.AsVector3();
+        v3 *= new Vector3(100, 400, 360);
+        v3 -= new Vector3(0, 200, 0);
+        return new CieLch(v3);
+    }
+
+    /// <inheritdoc/>
+    public static void ToScaledVector4(ReadOnlySpan<CieLch> source, Span<Vector4> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = source[i].ToScaledVector4();
+        }
+    }
+
+    /// <inheritdoc/>
+    public static void FromScaledVector4(ReadOnlySpan<Vector4> source, Span<CieLch> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = FromScaledVector4(source[i]);
+        }
+    }
+
     /// <inheritdoc/>
     public static CieLch FromProfileConnectingSpace(ColorConversionOptions options, in CieLab source)
     {
diff --git a/src/ImageSharp/ColorProfiles/CieLchuv.cs b/src/ImageSharp/ColorProfiles/CieLchuv.cs
index 7fd95feb19..c131d4bc64 100644
--- a/src/ImageSharp/ColorProfiles/CieLchuv.cs
+++ b/src/ImageSharp/ColorProfiles/CieLchuv.cs
@@ -4,6 +4,7 @@
 using System.Numerics;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
 
 namespace SixLabors.ImageSharp.ColorProfiles;
 
@@ -51,7 +52,7 @@ public CieLchuv(Vector3 vector)
 
     /// <summary>
     /// Gets the a chroma component.
-    /// <remarks>A value ranging from 0 to 200.</remarks>
+    /// <remarks>A value ranging from -200 to 200.</remarks>
     /// </summary>
     public float C { get; }
 
@@ -81,6 +82,49 @@ public CieLchuv(Vector3 vector)
     /// </returns>
     public static bool operator !=(CieLchuv left, CieLchuv right) => !left.Equals(right);
 
+    /// <inheritdoc/>
+    public Vector4 ToScaledVector4()
+    {
+        Vector3 v3 = default;
+        v3 += this.AsVector3Unsafe();
+        v3 += new Vector3(0, 200, 0);
+        v3 /= new Vector3(100, 400, 360);
+        return new Vector4(v3, 1F);
+    }
+
+    /// <inheritdoc/>
+    public static CieLchuv FromScaledVector4(Vector4 source)
+    {
+        Vector3 v3 = source.AsVector3();
+        v3 *= new Vector3(100, 400, 360);
+        v3 -= new Vector3(0, 200, 0);
+        return new CieLchuv(v3);
+    }
+
+    /// <inheritdoc/>
+    public static void ToScaledVector4(ReadOnlySpan<CieLchuv> source, Span<Vector4> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = source[i].ToScaledVector4();
+        }
+    }
+
+    /// <inheritdoc/>
+    public static void FromScaledVector4(ReadOnlySpan<Vector4> source, Span<CieLchuv> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = FromScaledVector4(source[i]);
+        }
+    }
+
     /// <inheritdoc/>
     public static CieLchuv FromProfileConnectingSpace(ColorConversionOptions options, in CieXyz source)
     {
diff --git a/src/ImageSharp/ColorProfiles/CieLuv.cs b/src/ImageSharp/ColorProfiles/CieLuv.cs
index 97e2826f74..bcc958cb48 100644
--- a/src/ImageSharp/ColorProfiles/CieLuv.cs
+++ b/src/ImageSharp/ColorProfiles/CieLuv.cs
@@ -84,6 +84,18 @@ public CieLuv(Vector3 vector)
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     public static bool operator !=(CieLuv left, CieLuv right) => !left.Equals(right);
 
+    /// <inheritdoc/>
+    public Vector4 ToScaledVector4() => throw new NotImplementedException();
+
+    /// <inheritdoc/>
+    public static CieLuv FromScaledVector4(Vector4 source) => throw new NotImplementedException();
+
+    /// <inheritdoc/>
+    public static void ToScaledVector4(ReadOnlySpan<CieLuv> source, Span<Vector4> destination) => throw new NotImplementedException();
+
+    /// <inheritdoc/>
+    public static void FromScaledVector4(ReadOnlySpan<Vector4> source, Span<CieLuv> destination) => throw new NotImplementedException();
+
     /// <inheritdoc/>
     public static CieLuv FromProfileConnectingSpace(ColorConversionOptions options, in CieXyz source)
     {
@@ -143,7 +155,7 @@ public CieXyz ToProfileConnectingSpace(ColorConversionOptions options)
         // Use doubles here for accuracy.
         // Conversion algorithm described here:
         // http://www.brucelindbloom.com/index.html?Eqn_Luv_to_XYZ.html
-        CieXyz whitePoint = options.WhitePoint;
+        CieXyz whitePoint = options.SourceWhitePoint;
 
         double l = this.L, u = this.U, v = this.V;
 
diff --git a/src/ImageSharp/ColorProfiles/CieXyy.cs b/src/ImageSharp/ColorProfiles/CieXyy.cs
index 62873df147..7fa943e9ea 100644
--- a/src/ImageSharp/ColorProfiles/CieXyy.cs
+++ b/src/ImageSharp/ColorProfiles/CieXyy.cs
@@ -4,6 +4,7 @@
 using System.Numerics;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
 
 namespace SixLabors.ImageSharp.ColorProfiles;
 
@@ -83,6 +84,38 @@ public CieXyy(Vector3 vector)
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     public static bool operator !=(CieXyy left, CieXyy right) => !left.Equals(right);
 
+    /// <inheritdoc/>
+    public Vector4 ToScaledVector4()
+        => new(this.AsVector3Unsafe(), 1F);
+
+    /// <inheritdoc/>
+    public static CieXyy FromScaledVector4(Vector4 source)
+        => new(source.AsVector3());
+
+    /// <inheritdoc/>
+    public static void ToScaledVector4(ReadOnlySpan<CieXyy> source, Span<Vector4> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = source[i].ToScaledVector4();
+        }
+    }
+
+    /// <inheritdoc/>
+    public static void FromScaledVector4(ReadOnlySpan<Vector4> source, Span<CieXyy> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = FromScaledVector4(source[i]);
+        }
+    }
+
     /// <inheritdoc/>
     public static CieXyy FromProfileConnectingSpace(ColorConversionOptions options, in CieXyz source)
     {
diff --git a/src/ImageSharp/ColorProfiles/CieXyz.cs b/src/ImageSharp/ColorProfiles/CieXyz.cs
index 07f9b47f9b..d64857606e 100644
--- a/src/ImageSharp/ColorProfiles/CieXyz.cs
+++ b/src/ImageSharp/ColorProfiles/CieXyz.cs
@@ -4,6 +4,7 @@
 using System.Numerics;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
 
 namespace SixLabors.ImageSharp.ColorProfiles;
 
@@ -88,6 +89,47 @@ public CieXyz(Vector3 vector)
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     public Vector3 ToVector3() => new(this.X, this.Y, this.Z);
 
+    /// <inheritdoc/>
+    public Vector4 ToScaledVector4()
+    {
+        Vector3 v3 = default;
+        v3 += this.AsVector3Unsafe();
+        v3 *= 32768F / 65535;
+        return new Vector4(v3, 1F);
+    }
+
+    /// <inheritdoc/>
+    public static CieXyz FromScaledVector4(Vector4 source)
+    {
+        Vector3 v3 = source.AsVector3();
+        v3 *= 65535 / 32768F;
+        return new CieXyz(v3);
+    }
+
+    /// <inheritdoc/>
+    public static void ToScaledVector4(ReadOnlySpan<CieXyz> source, Span<Vector4> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = source[i].ToScaledVector4();
+        }
+    }
+
+    /// <inheritdoc/>
+    public static void FromScaledVector4(ReadOnlySpan<Vector4> source, Span<CieXyz> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = FromScaledVector4(source[i]);
+        }
+    }
+
     /// <inheritdoc/>
     public static CieXyz FromProfileConnectingSpace(ColorConversionOptions options, in CieXyz source)
         => new(source.X, source.Y, source.Z);
diff --git a/src/ImageSharp/ColorProfiles/Cmyk.cs b/src/ImageSharp/ColorProfiles/Cmyk.cs
index e924904497..4359fa4a96 100644
--- a/src/ImageSharp/ColorProfiles/Cmyk.cs
+++ b/src/ImageSharp/ColorProfiles/Cmyk.cs
@@ -89,6 +89,32 @@ public Cmyk(Vector4 vector)
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     public static bool operator !=(Cmyk left, Cmyk right) => !left.Equals(right);
 
+    /// <inheritdoc/>
+    public Vector4 ToScaledVector4()
+    {
+        Vector4 v4 = default;
+        v4 += this.AsVector4Unsafe();
+        return v4;
+    }
+
+    /// <inheritdoc/>
+    public static Cmyk FromScaledVector4(Vector4 source)
+        => new(source);
+
+    /// <inheritdoc/>
+    public static void ToScaledVector4(ReadOnlySpan<Cmyk> source, Span<Vector4> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+        MemoryMarshal.Cast<Cmyk, Vector4>(source).CopyTo(destination);
+    }
+
+    /// <inheritdoc/>
+    public static void FromScaledVector4(ReadOnlySpan<Vector4> source, Span<Cmyk> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+        MemoryMarshal.Cast<Vector4, Cmyk>(source).CopyTo(destination);
+    }
+
     /// <inheritdoc/>
     public static Cmyk FromProfileConnectingSpace(ColorConversionOptions options, in Rgb source)
     {
diff --git a/src/ImageSharp/ColorProfiles/ColorConversionOptions.cs b/src/ImageSharp/ColorProfiles/ColorConversionOptions.cs
index 1eb118834a..0f05c7e403 100644
--- a/src/ImageSharp/ColorProfiles/ColorConversionOptions.cs
+++ b/src/ImageSharp/ColorProfiles/ColorConversionOptions.cs
@@ -4,6 +4,7 @@
 using System.Numerics;
 using SixLabors.ImageSharp.ColorProfiles.WorkingSpaces;
 using SixLabors.ImageSharp.Memory;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
 
 namespace SixLabors.ImageSharp.ColorProfiles;
 
@@ -27,7 +28,7 @@ public class ColorConversionOptions
     /// <summary>
     /// Gets the source white point used for chromatic adaptation in conversions from/to XYZ color space.
     /// </summary>
-    public CieXyz WhitePoint { get; init; } = KnownIlluminants.D50;
+    public CieXyz SourceWhitePoint { get; init; } = KnownIlluminants.D50;
 
     /// <summary>
     /// Gets the destination white point used for chromatic adaptation in conversions from/to XYZ color space.
@@ -37,13 +38,23 @@ public class ColorConversionOptions
     /// <summary>
     /// Gets the source working space used for companding in conversions from/to XYZ color space.
     /// </summary>
-    public RgbWorkingSpace RgbWorkingSpace { get; init; } = KnownRgbWorkingSpaces.SRgb;
+    public RgbWorkingSpace SourceRgbWorkingSpace { get; init; } = KnownRgbWorkingSpaces.SRgb;
 
     /// <summary>
     /// Gets the destination working space used for companding in conversions from/to XYZ color space.
     /// </summary>
     public RgbWorkingSpace TargetRgbWorkingSpace { get; init; } = KnownRgbWorkingSpaces.SRgb;
 
+    /// <summary>
+    /// Gets the source ICC profile.
+    /// </summary>
+    public IccProfile? SourceIccProfile { get; init; }
+
+    /// <summary>
+    /// Gets the target ICC profile.
+    /// </summary>
+    public IccProfile? TargetIccProfile { get; init; }
+
     /// <summary>
     /// Gets the transformation matrix used in conversion to perform chromatic adaptation.
     /// <see cref="KnownChromaticAdaptationMatrices"/> for further information. Default is Bradford.
diff --git a/src/ImageSharp/ColorProfiles/ColorProfileConverter.cs b/src/ImageSharp/ColorProfiles/ColorProfileConverter.cs
index 18b90a622a..fa3f3d7e21 100644
--- a/src/ImageSharp/ColorProfiles/ColorProfileConverter.cs
+++ b/src/ImageSharp/ColorProfiles/ColorProfileConverter.cs
@@ -33,8 +33,8 @@ public ColorProfileConverter(ColorConversionOptions options)
                where TTo : struct, IColorProfile
     {
         CieXyz sourceWhitePoint = TFrom.GetChromaticAdaptionWhitePointSource() == ChromaticAdaptionWhitePointSource.WhitePoint
-            ? this.Options.WhitePoint
-            : this.Options.RgbWorkingSpace.WhitePoint;
+            ? this.Options.SourceWhitePoint
+            : this.Options.SourceRgbWorkingSpace.WhitePoint;
 
         CieXyz targetWhitePoint = TTo.GetChromaticAdaptionWhitePointSource() == ChromaticAdaptionWhitePointSource.WhitePoint
             ? this.Options.TargetWhitePoint
@@ -42,4 +42,7 @@ public ColorProfileConverter(ColorConversionOptions options)
 
         return (sourceWhitePoint, targetWhitePoint);
     }
+
+    internal bool ShouldUseIccProfiles()
+        => this.Options.SourceIccProfile != null && this.Options.TargetIccProfile != null;
 }
diff --git a/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieLabCieLab.cs b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieLabCieLab.cs
index 41ae4b08fa..a2dd5d9ced 100644
--- a/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieLabCieLab.cs
+++ b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieLabCieLab.cs
@@ -12,6 +12,11 @@ public static TTo Convert<TFrom, TTo>(this ColorProfileConverter converter, in T
         where TFrom : struct, IColorProfile<TFrom, CieLab>
         where TTo : struct, IColorProfile<TTo, CieLab>
     {
+        if (converter.ShouldUseIccProfiles())
+        {
+            return converter.ConvertUsingIccProfile<TFrom, TTo>(source);
+        }
+
         ColorConversionOptions options = converter.Options;
 
         // Convert to input PCS
@@ -33,6 +38,12 @@ public static void Convert<TFrom, TTo>(this ColorProfileConverter converter, Rea
         where TFrom : struct, IColorProfile<TFrom, CieLab>
         where TTo : struct, IColorProfile<TTo, CieLab>
     {
+        if (converter.ShouldUseIccProfiles())
+        {
+            converter.ConvertUsingIccProfile(source, destination);
+            return;
+        }
+
         ColorConversionOptions options = converter.Options;
 
         // Convert to input PCS.
diff --git a/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieLabCieXyz.cs b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieLabCieXyz.cs
index 04937e927e..096622564c 100644
--- a/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieLabCieXyz.cs
+++ b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieLabCieXyz.cs
@@ -12,6 +12,11 @@ public static TTo Convert<TFrom, TTo>(this ColorProfileConverter converter, in T
         where TFrom : struct, IColorProfile<TFrom, CieLab>
         where TTo : struct, IColorProfile<TTo, CieXyz>
     {
+        if (converter.ShouldUseIccProfiles())
+        {
+            return converter.ConvertUsingIccProfile<TFrom, TTo>(source);
+        }
+
         ColorConversionOptions options = converter.Options;
 
         // Convert to input PCS
@@ -32,6 +37,12 @@ public static void Convert<TFrom, TTo>(this ColorProfileConverter converter, Rea
         where TFrom : struct, IColorProfile<TFrom, CieLab>
         where TTo : struct, IColorProfile<TTo, CieXyz>
     {
+        if (converter.ShouldUseIccProfiles())
+        {
+            converter.ConvertUsingIccProfile(source, destination);
+            return;
+        }
+
         ColorConversionOptions options = converter.Options;
 
         // Convert to input PCS.
diff --git a/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieLabRgb.cs b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieLabRgb.cs
index 47e4d2a80a..51be13799c 100644
--- a/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieLabRgb.cs
+++ b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieLabRgb.cs
@@ -12,6 +12,11 @@ public static TTo Convert<TFrom, TTo>(this ColorProfileConverter converter, in T
         where TFrom : struct, IColorProfile<TFrom, CieLab>
         where TTo : struct, IColorProfile<TTo, Rgb>
     {
+        if (converter.ShouldUseIccProfiles())
+        {
+            return converter.ConvertUsingIccProfile<TFrom, TTo>(source);
+        }
+
         ColorConversionOptions options = converter.Options;
 
         // Convert to input PCS
@@ -33,6 +38,12 @@ public static void Convert<TFrom, TTo>(this ColorProfileConverter converter, Rea
         where TFrom : struct, IColorProfile<TFrom, CieLab>
         where TTo : struct, IColorProfile<TTo, Rgb>
     {
+        if (converter.ShouldUseIccProfiles())
+        {
+            converter.ConvertUsingIccProfile(source, destination);
+            return;
+        }
+
         ColorConversionOptions options = converter.Options;
 
         // Convert to input PCS.
diff --git a/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieXyzCieLab.cs b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieXyzCieLab.cs
index 6b1575d04c..3bab4e7b16 100644
--- a/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieXyzCieLab.cs
+++ b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieXyzCieLab.cs
@@ -12,6 +12,11 @@ public static TTo Convert<TFrom, TTo>(this ColorProfileConverter converter, in T
         where TFrom : struct, IColorProfile<TFrom, CieXyz>
         where TTo : struct, IColorProfile<TTo, CieLab>
     {
+        if (converter.ShouldUseIccProfiles())
+        {
+            return converter.ConvertUsingIccProfile<TFrom, TTo>(source);
+        }
+
         ColorConversionOptions options = converter.Options;
 
         // Convert to input PCS
@@ -32,6 +37,12 @@ public static void Convert<TFrom, TTo>(this ColorProfileConverter converter, Rea
         where TFrom : struct, IColorProfile<TFrom, CieXyz>
         where TTo : struct, IColorProfile<TTo, CieLab>
     {
+        if (converter.ShouldUseIccProfiles())
+        {
+            converter.ConvertUsingIccProfile(source, destination);
+            return;
+        }
+
         ColorConversionOptions options = converter.Options;
 
         // Convert to input PCS.
diff --git a/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieXyzCieXyz.cs b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieXyzCieXyz.cs
index 8f56a5a663..5188511476 100644
--- a/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieXyzCieXyz.cs
+++ b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieXyzCieXyz.cs
@@ -12,6 +12,11 @@ public static TTo Convert<TFrom, TTo>(this ColorProfileConverter converter, in T
         where TFrom : struct, IColorProfile<TFrom, CieXyz>
         where TTo : struct, IColorProfile<TTo, CieXyz>
     {
+        if (converter.ShouldUseIccProfiles())
+        {
+            return converter.ConvertUsingIccProfile<TFrom, TTo>(source);
+        }
+
         ColorConversionOptions options = converter.Options;
 
         // Convert to input PCS
@@ -29,6 +34,12 @@ public static void Convert<TFrom, TTo>(this ColorProfileConverter converter, Rea
         where TFrom : struct, IColorProfile<TFrom, CieXyz>
         where TTo : struct, IColorProfile<TTo, CieXyz>
     {
+        if (converter.ShouldUseIccProfiles())
+        {
+            converter.ConvertUsingIccProfile(source, destination);
+            return;
+        }
+
         ColorConversionOptions options = converter.Options;
 
         // Convert to input PCS.
diff --git a/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieXyzRgb.cs b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieXyzRgb.cs
index 9cc0bd9436..c56bf214b9 100644
--- a/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieXyzRgb.cs
+++ b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsCieXyzRgb.cs
@@ -12,6 +12,11 @@ public static TTo Convert<TFrom, TTo>(this ColorProfileConverter converter, in T
         where TFrom : struct, IColorProfile<TFrom, CieXyz>
         where TTo : struct, IColorProfile<TTo, Rgb>
     {
+        if (converter.ShouldUseIccProfiles())
+        {
+            return converter.ConvertUsingIccProfile<TFrom, TTo>(source);
+        }
+
         ColorConversionOptions options = converter.Options;
 
         // Convert to input PCS
@@ -32,6 +37,12 @@ public static void Convert<TFrom, TTo>(this ColorProfileConverter converter, Rea
         where TFrom : struct, IColorProfile<TFrom, CieXyz>
         where TTo : struct, IColorProfile<TTo, Rgb>
     {
+        if (converter.ShouldUseIccProfiles())
+        {
+            converter.ConvertUsingIccProfile(source, destination);
+            return;
+        }
+
         ColorConversionOptions options = converter.Options;
 
         // Convert to input PCS.
diff --git a/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsIcc.cs b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsIcc.cs
new file mode 100644
index 0000000000..da9a52ae28
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsIcc.cs
@@ -0,0 +1,412 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Buffers;
+using System.Diagnostics.CodeAnalysis;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using SixLabors.ImageSharp.ColorProfiles.Icc;
+using SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
+using SixLabors.ImageSharp.Memory;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.ColorProfiles;
+
+internal static class ColorProfileConverterExtensionsIcc
+{
+    internal static TTo ConvertUsingIccProfile<TFrom, TTo>(this ColorProfileConverter converter, in TFrom source)
+        where TFrom : struct, IColorProfile<TFrom>
+        where TTo : struct, IColorProfile<TTo>
+    {
+        // TODO: Validation of ICC Profiles against color profile. Is this possible?
+        if (converter.Options.SourceIccProfile is null)
+        {
+            throw new InvalidOperationException("Source ICC profile is missing.");
+        }
+
+        if (converter.Options.TargetIccProfile is null)
+        {
+            throw new InvalidOperationException("Target ICC profile is missing.");
+        }
+
+        ConversionParams sourceParams = new(converter.Options.SourceIccProfile, toPcs: true);
+        ConversionParams targetParams = new(converter.Options.TargetIccProfile, toPcs: false);
+
+        ColorProfileConverter pcsConverter = new(new ColorConversionOptions
+        {
+            MemoryAllocator = converter.Options.MemoryAllocator,
+            SourceWhitePoint = new CieXyz(converter.Options.SourceIccProfile.Header.PcsIlluminant),
+            TargetWhitePoint = new CieXyz(converter.Options.TargetIccProfile.Header.PcsIlluminant),
+        });
+
+        Vector4 sourcePcs = sourceParams.Converter.Calculate(source.ToScaledVector4());
+
+        // if both profiles need PCS adjustment, they both share the same unadjusted PCS space
+        // cancelling out the need to make the adjustment
+        // except if using TRC transforms, which always requires perceptual handling
+        // TODO: this does not include adjustment for absolute intent, which would double existing complexity, suggest throwing exception and addressing in future update
+        bool anyProfileNeedsPerceptualAdjustment = sourceParams.HasNoPerceptualHandling || targetParams.HasNoPerceptualHandling;
+        bool oneProfileHasV2PerceptualAdjustment = sourceParams.HasV2PerceptualHandling ^ targetParams.HasV2PerceptualHandling;
+
+        Vector4 targetPcs = anyProfileNeedsPerceptualAdjustment || oneProfileHasV2PerceptualAdjustment
+            ? GetTargetPcsWithPerceptualAdjustment(sourcePcs, sourceParams, targetParams, pcsConverter)
+            : GetTargetPcsWithoutAdjustment(sourcePcs, sourceParams, targetParams, pcsConverter);
+
+        return TTo.FromScaledVector4(targetParams.Converter.Calculate(targetPcs));
+    }
+
+    // TODO: update to match workflow of the function above
+    internal static void ConvertUsingIccProfile<TFrom, TTo>(this ColorProfileConverter converter, ReadOnlySpan<TFrom> source, Span<TTo> destination)
+        where TFrom : struct, IColorProfile<TFrom>
+        where TTo : struct, IColorProfile<TTo>
+    {
+        // TODO: Validation of ICC Profiles against color profile. Is this possible?
+        if (converter.Options.SourceIccProfile is null)
+        {
+            throw new InvalidOperationException("Source ICC profile is missing.");
+        }
+
+        if (converter.Options.TargetIccProfile is null)
+        {
+            throw new InvalidOperationException("Target ICC profile is missing.");
+        }
+
+        Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(destination));
+
+        ColorProfileConverter pcsConverter = new(new ColorConversionOptions()
+        {
+            MemoryAllocator = converter.Options.MemoryAllocator,
+
+            // TODO: Double check this but I think these are normalized values.
+            SourceWhitePoint = CieXyz.FromScaledVector4(new(converter.Options.SourceIccProfile.Header.PcsIlluminant, 1F)),
+            TargetWhitePoint = CieXyz.FromScaledVector4(new(converter.Options.TargetIccProfile.Header.PcsIlluminant, 1F)),
+        });
+
+        IccDataToPcsConverter sourceConverter = new(converter.Options.SourceIccProfile);
+        IccPcsToDataConverter targetConverter = new(converter.Options.TargetIccProfile);
+        IccColorSpaceType sourcePcsType = converter.Options.SourceIccProfile.Header.ProfileConnectionSpace;
+        IccColorSpaceType targetPcsType = converter.Options.TargetIccProfile.Header.ProfileConnectionSpace;
+        IccVersion sourceVersion = converter.Options.SourceIccProfile.Header.Version;
+        IccVersion targetVersion = converter.Options.TargetIccProfile.Header.Version;
+
+        using IMemoryOwner<Vector4> pcsBuffer = converter.Options.MemoryAllocator.Allocate<Vector4>(source.Length);
+        Span<Vector4> pcsNormalized = pcsBuffer.GetSpan();
+
+        // First normalize the values.
+        TFrom.ToScaledVector4(source, pcsNormalized);
+
+        // Now convert to the PCS space.
+        sourceConverter.Calculate(pcsNormalized, pcsNormalized);
+
+        // Profile connecting spaces can only be Lab, XYZ.
+        if (sourcePcsType is IccColorSpaceType.CieLab && targetPcsType is IccColorSpaceType.CieXyz)
+        {
+            // Convert from Lab to XYZ.
+            using IMemoryOwner<CieLab> pcsFromBuffer = converter.Options.MemoryAllocator.Allocate<CieLab>(source.Length);
+            Span<CieLab> pcsFrom = pcsFromBuffer.GetSpan();
+            CieLab.FromScaledVector4(pcsNormalized, pcsFrom);
+
+            using IMemoryOwner<CieXyz> pcsToBuffer = converter.Options.MemoryAllocator.Allocate<CieXyz>(source.Length);
+            Span<CieXyz> pcsTo = pcsToBuffer.GetSpan();
+            pcsConverter.Convert<CieLab, CieXyz>(pcsFrom, pcsTo);
+
+            // Convert to the target normalized PCS space.
+            CieXyz.ToScaledVector4(pcsTo, pcsNormalized);
+        }
+        else if (sourcePcsType is IccColorSpaceType.CieXyz && targetPcsType is IccColorSpaceType.CieLab)
+        {
+            // Convert from XYZ to Lab.
+            using IMemoryOwner<CieXyz> pcsFromBuffer = converter.Options.MemoryAllocator.Allocate<CieXyz>(source.Length);
+            Span<CieXyz> pcsFrom = pcsFromBuffer.GetSpan();
+            CieXyz.FromScaledVector4(pcsNormalized, pcsFrom);
+
+            using IMemoryOwner<CieLab> pcsToBuffer = converter.Options.MemoryAllocator.Allocate<CieLab>(source.Length);
+            Span<CieLab> pcsTo = pcsToBuffer.GetSpan();
+            pcsConverter.Convert<CieXyz, CieLab>(pcsFrom, pcsTo);
+
+            // Convert to the target normalized PCS space.
+            CieLab.ToScaledVector4(pcsTo, pcsNormalized);
+        }
+        else if (sourcePcsType is IccColorSpaceType.CieXyz && targetPcsType is IccColorSpaceType.CieXyz)
+        {
+            // Convert from XYZ to XYZ.
+            using IMemoryOwner<CieXyz> pcsFromToBuffer = converter.Options.MemoryAllocator.Allocate<CieXyz>(source.Length);
+            Span<CieXyz> pcsFromTo = pcsFromToBuffer.GetSpan();
+            CieXyz.FromScaledVector4(pcsNormalized, pcsFromTo);
+
+            pcsConverter.Convert<CieXyz, CieXyz>(pcsFromTo, pcsFromTo);
+
+            // Convert to the target normalized PCS space.
+            CieXyz.ToScaledVector4(pcsFromTo, pcsNormalized);
+        }
+        else if (sourcePcsType is IccColorSpaceType.CieLab && targetPcsType is IccColorSpaceType.CieLab)
+        {
+            // Convert from Lab to Lab.
+            if (sourceVersion.Major == 4 && targetVersion.Major == 2)
+            {
+                // Convert from Lab v4 to Lab v2.
+                LabToLabV2(pcsNormalized, pcsNormalized);
+            }
+            else if (sourceVersion.Major == 2 && targetVersion.Major == 4)
+            {
+                // Convert from Lab v2 to Lab v4.
+                LabV2ToLab(pcsNormalized, pcsNormalized);
+            }
+
+            using IMemoryOwner<CieLab> pcsFromToBuffer = converter.Options.MemoryAllocator.Allocate<CieLab>(source.Length);
+            Span<CieLab> pcsFromTo = pcsFromToBuffer.GetSpan();
+            CieLab.FromScaledVector4(pcsNormalized, pcsFromTo);
+
+            pcsConverter.Convert<CieLab, CieLab>(pcsFromTo, pcsFromTo);
+
+            // Convert to the target normalized PCS space.
+            CieLab.ToScaledVector4(pcsFromTo, pcsNormalized);
+        }
+
+        // Convert to the target space.
+        targetConverter.Calculate(pcsNormalized, pcsNormalized);
+        TTo.FromScaledVector4(pcsNormalized, destination);
+    }
+
+    private static Vector4 GetTargetPcsWithoutAdjustment(
+        Vector4 sourcePcs,
+        ConversionParams sourceParams,
+        ConversionParams targetParams,
+        ColorProfileConverter pcsConverter)
+    {
+        // Profile connecting spaces can only be Lab, XYZ.
+        // 16-bit Lab encodings changed from v2 to v4, but 16-bit LUTs always use the legacy encoding regardless of version
+        // so ensure that Lab is using the correct encoding when a 16-bit LUT is used
+        switch (sourceParams.PcsType)
+        {
+            // Convert from Lab to XYZ.
+            case IccColorSpaceType.CieLab when targetParams.PcsType is IccColorSpaceType.CieXyz:
+            {
+                sourcePcs = sourceParams.Is16BitLutEntry ? LabV2ToLab(sourcePcs) : sourcePcs;
+                CieLab lab = CieLab.FromScaledVector4(sourcePcs);
+                CieXyz xyz = pcsConverter.Convert<CieLab, CieXyz>(in lab);
+                return xyz.ToScaledVector4();
+            }
+
+            // Convert from XYZ to Lab.
+            case IccColorSpaceType.CieXyz when targetParams.PcsType is IccColorSpaceType.CieLab:
+            {
+                CieXyz xyz = CieXyz.FromScaledVector4(sourcePcs);
+                CieLab lab = pcsConverter.Convert<CieXyz, CieLab>(in xyz);
+                Vector4 targetPcs = lab.ToScaledVector4();
+                return targetParams.Is16BitLutEntry ? LabToLabV2(targetPcs) : targetPcs;
+            }
+
+            // Convert from XYZ to XYZ.
+            case IccColorSpaceType.CieXyz when targetParams.PcsType is IccColorSpaceType.CieXyz:
+            {
+                CieXyz xyz = CieXyz.FromScaledVector4(sourcePcs);
+                CieXyz targetXyz = pcsConverter.Convert<CieXyz, CieXyz>(in xyz);
+                return targetXyz.ToScaledVector4();
+            }
+
+            // Convert from Lab to Lab.
+            case IccColorSpaceType.CieLab when targetParams.PcsType is IccColorSpaceType.CieLab:
+            {
+                // if both source and target LUT use same v2 LAB encoding, no need to correct them
+                if (sourceParams.Is16BitLutEntry && targetParams.Is16BitLutEntry)
+                {
+                    CieLab sourceLab = CieLab.FromScaledVector4(sourcePcs);
+                    CieLab targetLab = pcsConverter.Convert<CieLab, CieLab>(in sourceLab);
+                    return targetLab.ToScaledVector4();
+                }
+                else
+                {
+                    sourcePcs = sourceParams.Is16BitLutEntry ? LabV2ToLab(sourcePcs) : sourcePcs;
+                    CieLab sourceLab = CieLab.FromScaledVector4(sourcePcs);
+                    CieLab targetLab = pcsConverter.Convert<CieLab, CieLab>(in sourceLab);
+                    Vector4 targetPcs = targetLab.ToScaledVector4();
+                    return targetParams.Is16BitLutEntry ? LabToLabV2(targetPcs) : targetPcs;
+                }
+            }
+
+            default:
+                throw new ArgumentOutOfRangeException($"Source PCS {sourceParams.PcsType} to target PCS {targetParams.PcsType} is not supported");
+        }
+    }
+
+    /// <summary>
+    /// Effectively this is <see cref="GetTargetPcsWithoutAdjustment"/> with an extra step in the middle.
+    /// It adjusts PCS by compensating for the black point used for perceptual intent in v2 profiles.
+    /// The adjustment needs to be performed in XYZ space, potentially an overhead of 2 more conversions.
+    /// Not required if both spaces need V2 correction, since they both have the same understanding of the PCS.
+    /// Not compatible with PCS adjustment for absolute intent.
+    /// </summary>
+    /// <param name="sourcePcs">The source PCS values.</param>
+    /// <param name="sourceParams">The source profile parameters.</param>
+    /// <param name="targetParams">The target profile parameters.</param>
+    /// <param name="pcsConverter">The converter to use for the PCS adjustments.</param>
+    /// <exception cref="ArgumentOutOfRangeException">Thrown when the source or target PCS is not supported.</exception>
+    private static Vector4 GetTargetPcsWithPerceptualAdjustment(
+        Vector4 sourcePcs,
+        ConversionParams sourceParams,
+        ConversionParams targetParams,
+        ColorProfileConverter pcsConverter)
+    {
+        // all conversions are funneled through XYZ in case PCS adjustments need to be made
+        CieXyz xyz;
+
+        switch (sourceParams.PcsType)
+        {
+            // 16-bit Lab encodings changed from v2 to v4, but 16-bit LUTs always use the legacy encoding regardless of version
+            // so convert Lab to modern v4 encoding when returned from a 16-bit LUT
+            case IccColorSpaceType.CieLab:
+                sourcePcs = sourceParams.Is16BitLutEntry ? LabV2ToLab(sourcePcs) : sourcePcs;
+                CieLab lab = CieLab.FromScaledVector4(sourcePcs);
+                xyz = pcsConverter.Convert<CieLab, CieXyz>(in lab);
+                break;
+            case IccColorSpaceType.CieXyz:
+                xyz = CieXyz.FromScaledVector4(sourcePcs);
+                break;
+            default:
+                throw new ArgumentOutOfRangeException($"Source PCS {sourceParams.PcsType} is not supported");
+        }
+
+        bool oneProfileHasV2PerceptualAdjustment = sourceParams.HasV2PerceptualHandling ^ targetParams.HasV2PerceptualHandling;
+
+        // when converting from device to PCS with v2 perceptual intent
+        // the black point needs to be adjusted to v4 after converting the PCS values
+        if (sourceParams.HasNoPerceptualHandling ||
+            (oneProfileHasV2PerceptualAdjustment && sourceParams.HasV2PerceptualHandling))
+        {
+            Vector3 vector = xyz.ToVector3();
+
+            // when using LAB PCS, negative values are clipped before PCS adjustment (in DemoIccMAX)
+            if (sourceParams.PcsType == IccColorSpaceType.CieLab)
+            {
+                vector = Vector3.Max(vector, Vector3.Zero);
+            }
+
+            xyz = new CieXyz(AdjustPcsFromV2BlackPoint(vector));
+        }
+
+        // when converting from PCS to device with v2 perceptual intent
+        // the black point needs to be adjusted to v2 before converting the PCS values
+        if (targetParams.HasNoPerceptualHandling ||
+            (oneProfileHasV2PerceptualAdjustment && targetParams.HasV2PerceptualHandling))
+        {
+            Vector3 vector = AdjustPcsToV2BlackPoint(xyz.ToVector3());
+
+            // when using XYZ PCS, negative values are clipped after PCS adjustment (in DemoIccMAX)
+            if (targetParams.PcsType == IccColorSpaceType.CieXyz)
+            {
+                vector = Vector3.Max(vector, Vector3.Zero);
+            }
+
+            xyz = new CieXyz(vector);
+        }
+
+        switch (targetParams.PcsType)
+        {
+            // 16-bit Lab encodings changed from v2 to v4, but 16-bit LUTs always use the legacy encoding regardless of version
+            // so convert Lab back to legacy encoding before using in a 16-bit LUT
+            case IccColorSpaceType.CieLab:
+                CieLab lab = pcsConverter.Convert<CieXyz, CieLab>(in xyz);
+                Vector4 targetPcs = lab.ToScaledVector4();
+                return targetParams.Is16BitLutEntry ? LabToLabV2(targetPcs) : targetPcs;
+            case IccColorSpaceType.CieXyz:
+                return xyz.ToScaledVector4();
+            default:
+                throw new ArgumentOutOfRangeException($"Target PCS {targetParams.PcsType} is not supported");
+        }
+    }
+
+    // as per DemoIccMAX icPerceptual values in IccCmm.h
+    // refBlack = 0.00336F, 0.0034731F, 0.00287F
+    // refWhite = 0.9642F, 1.0000F, 0.8249F
+    // scale = 1 - (refBlack / refWhite)
+    // offset = refBlack
+    private static Vector3 AdjustPcsFromV2BlackPoint(Vector3 xyz)
+        => (xyz * new Vector3(0.9965153F, 0.9965269F, 0.9965208F)) + new Vector3(0.00336F, 0.0034731F, 0.00287F);
+
+    // as per DemoIccMAX icPerceptual values in IccCmm.h
+    // refBlack = 0.00336F, 0.0034731F, 0.00287F
+    // refWhite = 0.9642F, 1.0000F, 0.8249F
+    // scale = 1 / (1 - (refBlack / refWhite))
+    // offset = -refBlack * scale
+    private static Vector3 AdjustPcsToV2BlackPoint(Vector3 xyz)
+        => (xyz * new Vector3(1.0034969F, 1.0034852F, 1.0034913F)) - new Vector3(0.0033717495F, 0.0034852044F, 0.0028800198F);
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private static Vector4 LabToLabV2(Vector4 input)
+        => input * 65280F / 65535F;
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private static Vector4 LabV2ToLab(Vector4 input)
+        => input * 65535F / 65280F;
+
+    private static void LabToLabV2(Span<Vector4> source, Span<Vector4> destination)
+        => LabToLab(source, destination, 65280F / 65535F);
+
+    private static void LabV2ToLab(Span<Vector4> source, Span<Vector4> destination)
+        => LabToLab(source, destination, 65535F / 65280F);
+
+    private static void LabToLab(Span<Vector4> source, Span<Vector4> destination, [ConstantExpected] float scale)
+    {
+        if (Vector.IsHardwareAccelerated)
+        {
+            Vector<float> vScale = new(scale);
+            int i = 0;
+
+            // SIMD loop
+            int simdBatchSize = Vector<float>.Count / 4; // Number of Vector4 elements per SIMD batch
+            for (; i <= source.Length - simdBatchSize; i += simdBatchSize)
+            {
+                // Load the vector from source span
+                Vector<float> v = Unsafe.ReadUnaligned<Vector<float>>(ref Unsafe.As<Vector4, byte>(ref source[i]));
+
+                // Scale the vector
+                v *= vScale;
+
+                // Write the scaled vector to the destination span
+                Unsafe.WriteUnaligned(ref Unsafe.As<Vector4, byte>(ref destination[i]), v);
+            }
+
+            // Scalar fallback for remaining elements
+            for (; i < source.Length; i++)
+            {
+                destination[i] = source[i] * scale;
+            }
+        }
+        else
+        {
+            // Scalar fallback if SIMD is not supported
+            for (int i = 0; i < source.Length; i++)
+            {
+                destination[i] = source[i] * scale;
+            }
+        }
+    }
+
+    private class ConversionParams
+    {
+        private readonly IccProfile profile;
+
+        internal ConversionParams(IccProfile profile, bool toPcs)
+        {
+            this.profile = profile;
+            this.Converter = toPcs ? new IccDataToPcsConverter(profile) : new IccPcsToDataConverter(profile);
+        }
+
+        internal IccConverterBase Converter { get; }
+
+        internal IccProfileHeader Header => this.profile.Header;
+
+        internal IccRenderingIntent Intent => this.Header.RenderingIntent;
+
+        internal IccColorSpaceType PcsType => this.Header.ProfileConnectionSpace;
+
+        internal IccVersion Version => this.Header.Version;
+
+        internal bool HasV2PerceptualHandling => this.Intent == IccRenderingIntent.Perceptual && this.Version.Major == 2;
+
+        internal bool HasNoPerceptualHandling => this.Intent == IccRenderingIntent.Perceptual && this.Converter.IsTrc;
+
+        internal bool Is16BitLutEntry => this.Converter.Is16BitLutEntry;
+    }
+}
diff --git a/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsRgbCieLab.cs b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsRgbCieLab.cs
index 415dd94c3f..badbcc6831 100644
--- a/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsRgbCieLab.cs
+++ b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsRgbCieLab.cs
@@ -12,6 +12,11 @@ public static TTo Convert<TFrom, TTo>(this ColorProfileConverter converter, in T
         where TFrom : struct, IColorProfile<TFrom, Rgb>
         where TTo : struct, IColorProfile<TTo, CieLab>
     {
+        if (converter.ShouldUseIccProfiles())
+        {
+            return converter.ConvertUsingIccProfile<TFrom, TTo>(source);
+        }
+
         ColorConversionOptions options = converter.Options;
 
         // Convert to input PCS
@@ -33,6 +38,12 @@ public static void Convert<TFrom, TTo>(this ColorProfileConverter converter, Rea
         where TFrom : struct, IColorProfile<TFrom, Rgb>
         where TTo : struct, IColorProfile<TTo, CieLab>
     {
+        if (converter.ShouldUseIccProfiles())
+        {
+            converter.ConvertUsingIccProfile(source, destination);
+            return;
+        }
+
         ColorConversionOptions options = converter.Options;
 
         // Convert to input PCS.
diff --git a/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsRgbCieXyz.cs b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsRgbCieXyz.cs
index a13f645778..cd7d5e4d65 100644
--- a/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsRgbCieXyz.cs
+++ b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsRgbCieXyz.cs
@@ -12,6 +12,11 @@ public static TTo Convert<TFrom, TTo>(this ColorProfileConverter converter, in T
         where TFrom : struct, IColorProfile<TFrom, Rgb>
         where TTo : struct, IColorProfile<TTo, CieXyz>
     {
+        if (converter.ShouldUseIccProfiles())
+        {
+            return converter.ConvertUsingIccProfile<TFrom, TTo>(source);
+        }
+
         ColorConversionOptions options = converter.Options;
 
         // Convert to input PCS
@@ -32,6 +37,12 @@ public static void Convert<TFrom, TTo>(this ColorProfileConverter converter, Rea
         where TFrom : struct, IColorProfile<TFrom, Rgb>
         where TTo : struct, IColorProfile<TTo, CieXyz>
     {
+        if (converter.ShouldUseIccProfiles())
+        {
+            converter.ConvertUsingIccProfile(source, destination);
+            return;
+        }
+
         ColorConversionOptions options = converter.Options;
 
         // Convert to input PCS.
diff --git a/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsRgbRgb.cs b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsRgbRgb.cs
index c1c75dea1b..2a4b64b1ca 100644
--- a/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsRgbRgb.cs
+++ b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsRgbRgb.cs
@@ -12,6 +12,11 @@ public static TTo Convert<TFrom, TTo>(this ColorProfileConverter converter, in T
         where TFrom : struct, IColorProfile<TFrom, Rgb>
         where TTo : struct, IColorProfile<TTo, Rgb>
     {
+        if (converter.ShouldUseIccProfiles())
+        {
+            return converter.ConvertUsingIccProfile<TFrom, TTo>(source);
+        }
+
         ColorConversionOptions options = converter.Options;
 
         // Convert to input PCS
@@ -33,6 +38,12 @@ public static void Convert<TFrom, TTo>(this ColorProfileConverter converter, Rea
         where TFrom : struct, IColorProfile<TFrom, Rgb>
         where TTo : struct, IColorProfile<TTo, Rgb>
     {
+        if (converter.ShouldUseIccProfiles())
+        {
+            converter.ConvertUsingIccProfile(source, destination);
+            return;
+        }
+
         ColorConversionOptions options = converter.Options;
 
         // Convert to input PCS.
diff --git a/src/ImageSharp/ColorProfiles/Hsl.cs b/src/ImageSharp/ColorProfiles/Hsl.cs
index 2c98c7df99..6b84f955b8 100644
--- a/src/ImageSharp/ColorProfiles/Hsl.cs
+++ b/src/ImageSharp/ColorProfiles/Hsl.cs
@@ -4,6 +4,7 @@
 using System.Numerics;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
 
 namespace SixLabors.ImageSharp.ColorProfiles;
 
@@ -83,6 +84,38 @@ public Hsl(Vector3 vector)
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     public static bool operator !=(Hsl left, Hsl right) => !left.Equals(right);
 
+    /// <inheritdoc/>
+    public Vector4 ToScaledVector4()
+        => new(this.AsVector3Unsafe() / 360F, 1F);
+
+    /// <inheritdoc/>
+    public static Hsl FromScaledVector4(Vector4 source)
+        => new(source.AsVector3() * 360F);
+
+    /// <inheritdoc/>
+    public static void ToScaledVector4(ReadOnlySpan<Hsl> source, Span<Vector4> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = source[i].ToScaledVector4();
+        }
+    }
+
+    /// <inheritdoc/>
+    public static void FromScaledVector4(ReadOnlySpan<Vector4> source, Span<Hsl> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = FromScaledVector4(source[i]);
+        }
+    }
+
     /// <inheritdoc/>
     public static Hsl FromProfileConnectingSpace(ColorConversionOptions options, in Rgb source)
     {
diff --git a/src/ImageSharp/ColorProfiles/Hsv.cs b/src/ImageSharp/ColorProfiles/Hsv.cs
index 7535f2463d..a7735bb195 100644
--- a/src/ImageSharp/ColorProfiles/Hsv.cs
+++ b/src/ImageSharp/ColorProfiles/Hsv.cs
@@ -4,6 +4,7 @@
 using System.Numerics;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
 
 namespace SixLabors.ImageSharp.ColorProfiles;
 
@@ -81,6 +82,38 @@ public Hsv(Vector3 vector)
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     public static bool operator !=(Hsv left, Hsv right) => !left.Equals(right);
 
+    /// <inheritdoc/>
+    public Vector4 ToScaledVector4()
+        => new(this.AsVector3Unsafe() / 360F, 1F);
+
+    /// <inheritdoc/>
+    public static Hsv FromScaledVector4(Vector4 source)
+        => new(source.AsVector3() * 360F);
+
+    /// <inheritdoc/>
+    public static void ToScaledVector4(ReadOnlySpan<Hsv> source, Span<Vector4> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = source[i].ToScaledVector4();
+        }
+    }
+
+    /// <inheritdoc/>
+    public static void FromScaledVector4(ReadOnlySpan<Vector4> source, Span<Hsv> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = FromScaledVector4(source[i]);
+        }
+    }
+
     /// <inheritdoc/>
     public static Hsv FromProfileConnectingSpace(ColorConversionOptions options, in Rgb source)
     {
diff --git a/src/ImageSharp/ColorProfiles/HunterLab.cs b/src/ImageSharp/ColorProfiles/HunterLab.cs
index 43ad2ac5c0..d53d4c8134 100644
--- a/src/ImageSharp/ColorProfiles/HunterLab.cs
+++ b/src/ImageSharp/ColorProfiles/HunterLab.cs
@@ -4,6 +4,7 @@
 using System.Numerics;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
 
 namespace SixLabors.ImageSharp.ColorProfiles;
 
@@ -80,6 +81,49 @@ public HunterLab(Vector3 vector)
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     public static bool operator !=(HunterLab left, HunterLab right) => !left.Equals(right);
 
+    /// <inheritdoc/>
+    public Vector4 ToScaledVector4()
+    {
+        Vector3 v3 = default;
+        v3 += this.AsVector3Unsafe();
+        v3 += new Vector3(0, 128F, 128F);
+        v3 /= new Vector3(100F, 255F, 255F);
+        return new Vector4(v3, 1F);
+    }
+
+    /// <inheritdoc/>
+    public static HunterLab FromScaledVector4(Vector4 source)
+    {
+        Vector3 v3 = source.AsVector3();
+        v3 *= new Vector3(100F, 255, 255);
+        v3 -= new Vector3(0, 128F, 128F);
+        return new HunterLab(v3);
+    }
+
+    /// <inheritdoc/>
+    public static void ToScaledVector4(ReadOnlySpan<HunterLab> source, Span<Vector4> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = source[i].ToScaledVector4();
+        }
+    }
+
+    /// <inheritdoc/>
+    public static void FromScaledVector4(ReadOnlySpan<Vector4> source, Span<HunterLab> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = FromScaledVector4(source[i]);
+        }
+    }
+
     /// <inheritdoc/>
     public static HunterLab FromProfileConnectingSpace(ColorConversionOptions options, in CieXyz source)
     {
@@ -127,7 +171,7 @@ public CieXyz ToProfileConnectingSpace(ColorConversionOptions options)
     {
         // Conversion algorithm described here:
         // http://en.wikipedia.org/wiki/Lab_color_space#Hunter_Lab
-        CieXyz whitePoint = options.WhitePoint;
+        CieXyz whitePoint = options.SourceWhitePoint;
         float l = this.L, a = this.A, b = this.B;
         float xn = whitePoint.X, yn = whitePoint.Y, zn = whitePoint.Z;
 
diff --git a/src/ImageSharp/ColorProfiles/IColorProfile.cs b/src/ImageSharp/ColorProfiles/IColorProfile.cs
index 6a1b2ee8d0..f678fb2c96 100644
--- a/src/ImageSharp/ColorProfiles/IColorProfile.cs
+++ b/src/ImageSharp/ColorProfiles/IColorProfile.cs
@@ -1,6 +1,8 @@
 // Copyright (c) Six Labors.
 // Licensed under the Six Labors Split License.
 
+using System.Numerics;
+
 namespace SixLabors.ImageSharp.ColorProfiles;
 
 /// <summary>
@@ -15,18 +17,60 @@ public interface IColorProfile
     public static abstract ChromaticAdaptionWhitePointSource GetChromaticAdaptionWhitePointSource();
 }
 
+/// <summary>
+/// Defines the contract for all color profiles.
+/// </summary>
+/// <typeparam name="TSelf">The type of color profile.</typeparam>
+public interface IColorProfile<TSelf> : IColorProfile, IEquatable<TSelf>
+    where TSelf : IColorProfile<TSelf>
+{
+    /// <summary>
+    /// Expands the pixel into a generic ("scaled") <see cref="Vector4"/> representation
+    /// with values scaled and clamped between <value>0</value> and <value>1</value>.
+    /// The vector components are typically expanded in least to greatest significance order.
+    /// </summary>
+    /// <returns>The <see cref="Vector4"/>.</returns>
+    Vector4 ToScaledVector4();
+
+#pragma warning disable CA1000 // Do not declare static members on generic types
+    /// <summary>
+    /// Initializes the color instance from a generic a generic ("scaled") <see cref="Vector4"/> representation
+    /// with values scaled and clamped between <value>0</value> and <value>1</value>.
+    /// </summary>
+    /// <param name="source">The vector to load the pixel from.</param>
+    /// <returns>The <typeparamref name="TSelf"/>.</returns>
+    public static abstract TSelf FromScaledVector4(Vector4 source);
+
+    /// <summary>
+    /// Converts the span of colors to a generic ("scaled") <see cref="Vector4"/> representation
+    /// with values scaled and clamped between <value>0</value> and <value>1</value>.
+    /// </summary>
+    /// <param name="source">The color span to convert from.</param>
+    /// <param name="destination">The vector span to write the results to.</param>
+    public static abstract void ToScaledVector4(ReadOnlySpan<TSelf> source, Span<Vector4> destination);
+
+    /// <summary>
+    /// Converts the span of colors from a generic ("scaled") <see cref="Vector4"/> representation
+    /// with values scaled and clamped between <value>0</value> and <value>1</value>.
+    /// </summary>
+    /// <param name="source">The vector span to convert from.</param>
+    /// <param name="destination">The color span to write the results to.</param>
+    public static abstract void FromScaledVector4(ReadOnlySpan<Vector4> source, Span<TSelf> destination);
+#pragma warning restore CA1000 // Do not declare static members on generic types
+}
+
 /// <summary>
 /// Defines the contract for all color profiles.
 /// </summary>
 /// <typeparam name="TSelf">The type of color profile.</typeparam>
 /// <typeparam name="TProfileSpace">The type of color profile connecting space.</typeparam>
-public interface IColorProfile<TSelf, TProfileSpace> : IColorProfile, IEquatable<TSelf>
+public interface IColorProfile<TSelf, TProfileSpace> : IColorProfile<TSelf>
     where TSelf : IColorProfile<TSelf, TProfileSpace>
     where TProfileSpace : struct, IProfileConnectingSpace
 {
 #pragma warning disable CA1000 // Do not declare static members on generic types
     /// <summary>
-    /// Converts the color from the profile connection space.
+    /// Initializes the color instance from the profile connection space.
     /// </summary>
     /// <param name="options">The color profile conversion options.</param>
     /// <param name="source">The color profile connecting space.</param>
diff --git a/src/ImageSharp/ColorProfiles/Icc/Calculators/ClutCalculator.cs b/src/ImageSharp/ColorProfiles/Icc/Calculators/ClutCalculator.cs
new file mode 100644
index 0000000000..e14a4dde6a
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/Calculators/ClutCalculator.cs
@@ -0,0 +1,502 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Numerics;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.ColorProfiles.Icc.Calculators;
+
+/// <summary>
+/// Implements interpolation methods for color profile lookup tables.
+/// Adapted from ICC Reference implementation:
+/// https://github.com/InternationalColorConsortium/DemoIccMAX/blob/79ecb74135ad47bac7d42692905a079839b7e105/IccProfLib/IccTagLut.cpp
+/// </summary>
+internal class ClutCalculator : IVector4Calculator
+{
+    private readonly int inputCount;
+    private readonly int outputCount;
+    private readonly float[] lut;
+    private readonly byte[] gridPointCount;
+    private readonly byte[] maxGridPoint;
+    private readonly int[] indexFactor;
+    private readonly int[] dimSize;
+    private readonly int nodeCount;
+    private readonly float[][] nodes;
+    private readonly float[] g;
+    private readonly uint[] ig;
+    private readonly float[] s;
+    private readonly float[] df;
+    private readonly uint[] nPower;
+    private int n000;
+    private int n001;
+    private int n010;
+    private int n011;
+    private int n100;
+    private int n101;
+    private int n110;
+    private int n111;
+    private int n1000;
+
+    public ClutCalculator(IccClut clut)
+    {
+        Guard.NotNull(clut, nameof(clut));
+        Guard.MustBeGreaterThan(clut.InputChannelCount, 0, nameof(clut.InputChannelCount));
+        Guard.MustBeGreaterThan(clut.OutputChannelCount, 0, nameof(clut.OutputChannelCount));
+
+        this.inputCount = clut.InputChannelCount;
+        this.outputCount = clut.OutputChannelCount;
+        this.g = new float[this.inputCount];
+        this.ig = new uint[this.inputCount];
+        this.s = new float[this.inputCount];
+        this.nPower = new uint[16];
+        this.lut = clut.Values;
+        this.nodeCount = (int)Math.Pow(2, clut.InputChannelCount);
+        this.df = new float[this.nodeCount];
+        this.nodes = new float[this.nodeCount][];
+        this.dimSize = new int[this.inputCount];
+        this.gridPointCount = clut.GridPointCount;
+        this.maxGridPoint = new byte[this.inputCount];
+        for (int i = 0; i < this.inputCount; i++)
+        {
+            this.maxGridPoint[i] = (byte)(this.gridPointCount[i] - 1);
+        }
+
+        this.dimSize[this.inputCount - 1] = this.outputCount;
+        for (int i = this.inputCount - 2; i >= 0; i--)
+        {
+            this.dimSize[i] = this.dimSize[i + 1] * this.gridPointCount[i + 1];
+        }
+
+        this.indexFactor = this.CalculateIndexFactor();
+    }
+
+    public unsafe Vector4 Calculate(Vector4 value)
+    {
+        Vector4 result = default;
+        switch (this.inputCount)
+        {
+            case 1:
+                this.Interpolate1d((float*)&value, (float*)&result);
+                break;
+            case 2:
+                this.Interpolate2d((float*)&value, (float*)&result);
+                break;
+            case 3:
+                this.Interpolate3d((float*)&value, (float*)&result);
+                break;
+            case 4:
+                this.Interpolate4d((float*)&value, (float*)&result);
+                break;
+            default:
+                this.InterpolateNd((float*)&value, (float*)&result);
+                break;
+        }
+
+        return result;
+    }
+
+    private int[] CalculateIndexFactor()
+    {
+        int[] factors = new int[16];
+        switch (this.inputCount)
+        {
+            case 1:
+                factors[0] = this.n000 = 0;
+                factors[1] = this.n001 = this.dimSize[0];
+                break;
+            case 2:
+                factors[0] = this.n000 = 0;
+                factors[1] = this.n001 = this.dimSize[0];
+                factors[2] = this.n010 = this.dimSize[1];
+                factors[3] = this.n011 = this.n001 + this.n010;
+                break;
+            case 3:
+                factors[0] = this.n000 = 0;
+                factors[1] = this.n001 = this.dimSize[0];
+                factors[2] = this.n010 = this.dimSize[1];
+                factors[3] = this.n011 = this.n001 + this.n010;
+                factors[4] = this.n100 = this.dimSize[2];
+                factors[5] = this.n101 = this.n100 + this.n001;
+                factors[6] = this.n110 = this.n100 + this.n010;
+                factors[7] = this.n111 = this.n110 + this.n001;
+                break;
+            case 4:
+                factors[0] = 0;
+                factors[1] = this.n001 = this.dimSize[0];
+                factors[2] = this.n010 = this.dimSize[1];
+                factors[3] = factors[2] + factors[1];
+                factors[4] = this.n100 = this.dimSize[2];
+                factors[5] = factors[4] + factors[1];
+                factors[6] = factors[4] + factors[2];
+                factors[7] = factors[4] + factors[3];
+                factors[8] = this.n1000 = this.dimSize[3];
+                factors[9] = factors[8] + factors[1];
+                factors[10] = factors[8] + factors[2];
+                factors[11] = factors[8] + factors[3];
+                factors[12] = factors[8] + factors[4];
+                factors[13] = factors[8] + factors[5];
+                factors[14] = factors[8] + factors[6];
+                factors[15] = factors[8] + factors[7];
+                break;
+            default:
+                // Initialize ND interpolation variables.
+                factors[0] = 0;
+                int count;
+                for (count = 0; count < this.inputCount; count++)
+                {
+                    this.nPower[count] = (uint)(1 << (this.inputCount - 1 - count));
+                }
+
+                uint[] nPower = [0, 1];
+                count = 0;
+                int nFlag = 1;
+                for (uint j = 1; j < this.nodeCount; j++)
+                {
+                    if (j == nPower[1])
+                    {
+                        factors[j] = this.dimSize[count];
+                        nPower[0] = (uint)(1 << count);
+                        count++;
+                        nPower[1] = (uint)(1 << count);
+                        nFlag = 1;
+                    }
+                    else
+                    {
+                        factors[j] = factors[nPower[0]] + factors[nFlag];
+                        nFlag++;
+                    }
+                }
+
+                break;
+        }
+
+        return factors;
+    }
+
+    /// <summary>
+    /// One dimensional interpolation function.
+    /// </summary>
+    /// <param name="srcPixel">The input pixel values, which will be interpolated.</param>
+    /// <param name="destPixel">The interpolated output pixels.</param>
+    private unsafe void Interpolate1d(float* srcPixel, float* destPixel)
+    {
+        byte mx = this.maxGridPoint[0];
+
+        float x = UnitClip(srcPixel[0]) * mx;
+
+        uint ix = (uint)x;
+
+        float u = x - ix;
+
+        if (ix == mx)
+        {
+            ix--;
+            u = 1.0f;
+        }
+
+        float nu = (float)(1.0 - u);
+
+        int i;
+        Span<float> p = this.lut.AsSpan((int)(ix * this.n001));
+
+        // Normalize grid units.
+        float dF0 = nu;
+        float dF1 = u;
+
+        int offset = 0;
+        for (i = 0; i < this.outputCount; i++)
+        {
+            destPixel[i] = (float)((p[offset + this.n000] * dF0) + (p[offset + this.n001] * dF1));
+            offset++;
+        }
+    }
+
+    /// <summary>
+    /// Two dimensional interpolation function.
+    /// </summary>
+    /// <param name="srcPixel">The input pixel values, which will be interpolated.</param>
+    /// <param name="destPixel">The interpolated output pixels.</param>
+    private unsafe void Interpolate2d(float* srcPixel, float* destPixel)
+    {
+        byte mx = this.maxGridPoint[0];
+        byte my = this.maxGridPoint[1];
+
+        float x = UnitClip(srcPixel[0]) * mx;
+        float y = UnitClip(srcPixel[1]) * my;
+
+        uint ix = (uint)x;
+        uint iy = (uint)y;
+
+        float u = x - ix;
+        float t = y - iy;
+
+        if (ix == mx)
+        {
+            ix--;
+            u = 1.0f;
+        }
+
+        if (iy == my)
+        {
+            iy--;
+            t = 1.0f;
+        }
+
+        float nt = (float)(1.0 - t);
+        float nu = (float)(1.0 - u);
+
+        int i;
+        Span<float> p = this.lut.AsSpan((int)((ix * this.n001) + (iy * this.n010)));
+
+        // Normalize grid units.
+        float dF0 = nt * nu;
+        float dF1 = nt * u;
+        float dF2 = t * nu;
+        float dF3 = t * u;
+
+        int offset = 0;
+        for (i = 0; i < this.outputCount; i++)
+        {
+            destPixel[i] = (float)((p[offset + this.n000] * dF0) + (p[offset + this.n001] * dF1) + (p[offset + this.n010] * dF2) + (p[offset + this.n011] * dF3));
+            offset++;
+        }
+    }
+
+    /// <summary>
+    /// Three dimensional interpolation function.
+    /// </summary>
+    /// <param name="srcPixel">The input pixel values, which will be interpolated.</param>
+    /// <param name="destPixel">The interpolated output pixels.</param>
+    private unsafe void Interpolate3d(float* srcPixel, float* destPixel)
+    {
+        byte mx = this.maxGridPoint[0];
+        byte my = this.maxGridPoint[1];
+        byte mz = this.maxGridPoint[2];
+
+        float x = UnitClip(srcPixel[0]) * mx;
+        float y = UnitClip(srcPixel[1]) * my;
+        float z = UnitClip(srcPixel[2]) * mz;
+
+        uint ix = (uint)x;
+        uint iy = (uint)y;
+        uint iz = (uint)z;
+
+        float u = x - ix;
+        float t = y - iy;
+        float s = z - iz;
+
+        if (ix == mx)
+        {
+            ix--;
+            u = 1.0f;
+        }
+
+        if (iy == my)
+        {
+            iy--;
+            t = 1.0f;
+        }
+
+        if (iz == mz)
+        {
+            iz--;
+            s = 1.0f;
+        }
+
+        float ns = (float)(1.0 - s);
+        float nt = (float)(1.0 - t);
+        float nu = (float)(1.0 - u);
+
+        Span<float> p = this.lut.AsSpan((int)((ix * this.n001) + (iy * this.n010) + (iz * this.n100)));
+
+        // Normalize grid units
+        float dF0 = ns * nt * nu;
+        float dF1 = ns * nt * u;
+        float dF2 = ns * t * nu;
+        float dF3 = ns * t * u;
+        float dF4 = s * nt * nu;
+        float dF5 = s * nt * u;
+        float dF6 = s * t * nu;
+        float dF7 = s * t * u;
+
+        int offset = 0;
+        for (int i = 0; i < this.outputCount; i++)
+        {
+            float pv = (p[offset + this.n000] * dF0) + (p[offset + this.n001] * dF1) + (p[offset + this.n010] * dF2) + (p[offset + this.n011] * dF3) +
+                       (p[offset + this.n100] * dF4) + (p[offset + this.n101] * dF5) + (p[offset + this.n110] * dF6) + (p[offset + this.n111] * dF7);
+
+            destPixel[i] = pv;
+            offset++;
+        }
+    }
+
+    /// <summary>
+    /// Four dimensional interpolation function.
+    /// </summary>
+    /// <param name="srcPixel">The input pixel values, which will be interpolated.</param>
+    /// <param name="destPixel">The interpolated output pixels.</param>
+    private unsafe void Interpolate4d(float* srcPixel, float* destPixel)
+    {
+        byte mw = this.maxGridPoint[0];
+        byte mx = this.maxGridPoint[1];
+        byte my = this.maxGridPoint[2];
+        byte mz = this.maxGridPoint[3];
+
+        float w = UnitClip(srcPixel[0]) * mw;
+        float x = UnitClip(srcPixel[1]) * mx;
+        float y = UnitClip(srcPixel[2]) * my;
+        float z = UnitClip(srcPixel[3]) * mz;
+
+        uint iw = (uint)w;
+        uint ix = (uint)x;
+        uint iy = (uint)y;
+        uint iz = (uint)z;
+
+        float v = w - iw;
+        float u = x - ix;
+        float t = y - iy;
+        float s = z - iz;
+
+        if (iw == mw)
+        {
+            iw--;
+            v = 1.0f;
+        }
+
+        if (ix == mx)
+        {
+            ix--;
+            u = 1.0f;
+        }
+
+        if (iy == my)
+        {
+            iy--;
+            t = 1.0f;
+        }
+
+        if (iz == mz)
+        {
+            iz--;
+            s = 1.0f;
+        }
+
+        float ns = (float)(1.0 - s);
+        float nt = (float)(1.0 - t);
+        float nu = (float)(1.0 - u);
+        float nv = (float)(1.0 - v);
+
+        Span<float> p = this.lut.AsSpan((int)((iw * this.n001) + (ix * this.n010) + (iy * this.n100) + (iz * this.n1000)));
+
+        // Normalize grid units.
+        float[] dF =
+        [
+            ns * nt * nu * nv,
+            ns * nt * nu * v,
+            ns * nt * u * nv,
+            ns * nt * u * v,
+            ns * t * nu * nv,
+            ns * t * nu * v,
+            ns * t * u * nv,
+            ns * t * u * v,
+            s * nt * nu * nv,
+            s * nt * nu * v,
+            s * nt * u * nv,
+            s * nt * u * v,
+            s * t * nu * nv,
+            s * t * nu * v,
+            s * t * u * nv,
+            s * t * u * v,
+        ];
+
+        int offset = 0;
+        for (int i = 0; i < this.outputCount; i++)
+        {
+            float pv = 0.0f;
+            for (int j = 0; j < 16; j++)
+            {
+                pv += p[offset + this.indexFactor[j]] * dF[j];
+            }
+
+            destPixel[i] = pv;
+            offset++;
+        }
+    }
+
+    /// <summary>
+    /// Generic N-dimensional interpolation function.
+    /// </summary>
+    /// <param name="srcPixel">The input pixel values, which will be interpolated.</param>
+    /// <param name="destPixel">The interpolated output pixels.</param>
+    private unsafe void InterpolateNd(float* srcPixel, float* destPixel)
+    {
+        int index = 0;
+        for (int i = 0; i < this.inputCount; i++)
+        {
+            this.g[i] = UnitClip(srcPixel[i]) * this.maxGridPoint[i];
+            this.ig[i] = (uint)this.g[i];
+            this.s[this.inputCount - 1 - i] = this.g[i] - this.ig[i];
+            if (this.ig[i] == this.maxGridPoint[i])
+            {
+                this.ig[i]--;
+                this.s[this.inputCount - 1 - i] = 1.0f;
+            }
+
+            index += (int)this.ig[i] * this.dimSize[i];
+        }
+
+        Span<float> p = this.lut.AsSpan(index);
+        float[] temp = new float[2];
+        bool nFlag = false;
+
+        for (int i = 0; i < this.nodeCount; i++)
+        {
+            this.df[i] = 1.0f;
+        }
+
+        for (int i = 0; i < this.inputCount; i++)
+        {
+            temp[0] = 1.0f - this.s[i];
+            temp[1] = this.s[i];
+            index = (int)this.nPower[i];
+            for (int j = 0; j < this.nodeCount; j++)
+            {
+                this.df[j] *= temp[nFlag ? 1 : 0];
+                if ((j + 1) % index == 0)
+                {
+                    nFlag = !nFlag;
+                }
+            }
+
+            nFlag = false;
+        }
+
+        int offset = 0;
+        for (int i = 0; i < this.outputCount; i++)
+        {
+            float pv = 0;
+            for (int j = 0; j < this.nodeCount; j++)
+            {
+                pv += p[offset + this.indexFactor[j]] * this.df[j];
+            }
+
+            destPixel[i] = pv;
+            offset++;
+        }
+    }
+
+    private static float UnitClip(float v)
+    {
+        if (v < 0)
+        {
+            return 0;
+        }
+
+        if (v > 1.0)
+        {
+            return 1.0f;
+        }
+
+        return v;
+    }
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/Calculators/ColorTrcCalculator.cs b/src/ImageSharp/ColorProfiles/Icc/Calculators/ColorTrcCalculator.cs
new file mode 100644
index 0000000000..cc0b727ba3
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/Calculators/ColorTrcCalculator.cs
@@ -0,0 +1,65 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.ColorProfiles.Icc.Calculators;
+
+internal class ColorTrcCalculator : IVector4Calculator
+{
+    private readonly TrcCalculator curveCalculator;
+    private readonly Matrix4x4 matrix;
+    private readonly bool toPcs;
+
+    public ColorTrcCalculator(
+        IccXyzTagDataEntry redMatrixColumn,
+        IccXyzTagDataEntry greenMatrixColumn,
+        IccXyzTagDataEntry blueMatrixColumn,
+        IccTagDataEntry redTrc,
+        IccTagDataEntry greenTrc,
+        IccTagDataEntry blueTrc,
+        bool toPcs)
+    {
+        this.toPcs = toPcs;
+        this.curveCalculator = new TrcCalculator([redTrc, greenTrc, blueTrc], !toPcs);
+
+        Vector3 mr = redMatrixColumn.Data[0];
+        Vector3 mg = greenMatrixColumn.Data[0];
+        Vector3 mb = blueMatrixColumn.Data[0];
+        this.matrix = new Matrix4x4(mr.X, mr.Y, mr.Z, 0, mg.X, mg.Y, mg.Z, 0, mb.X, mb.Y, mb.Z, 0, 0, 0, 0, 1);
+
+        if (!toPcs)
+        {
+            Matrix4x4.Invert(this.matrix, out this.matrix);
+        }
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public Vector4 Calculate(Vector4 value)
+    {
+        if (this.toPcs)
+        {
+            // input is always linear RGB
+            value = this.curveCalculator.Calculate(value);
+            CieXyz xyz = new(Vector4.Transform(value, this.matrix).AsVector3());
+
+            // when data to PCS, output from calculator is descaled XYZ
+            // but downstream process requires scaled XYZ
+            // (see DemoMaxICC IccCmm.cpp : CIccXformMatrixTRC::Apply)
+            return xyz.ToScaledVector4();
+        }
+        else
+        {
+            // input is always XYZ
+            Vector4 xyz = Vector4.Transform(value, this.matrix);
+
+            // when data to PCS, upstream process provides scaled XYZ
+            // but input to calculator is descaled XYZ
+            // (see DemoMaxICC IccCmm.cpp : CIccXformMatrixTRC::Apply)
+            xyz = new(CieXyz.FromScaledVector4(xyz).ToVector3(), 1);
+            return this.curveCalculator.Calculate(xyz);
+        }
+    }
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/Calculators/CurveCalculator.CalculationType.cs b/src/ImageSharp/ColorProfiles/Icc/Calculators/CurveCalculator.CalculationType.cs
new file mode 100644
index 0000000000..b3e26e2a29
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/Calculators/CurveCalculator.CalculationType.cs
@@ -0,0 +1,14 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
+
+internal partial class CurveCalculator
+{
+    private enum CalculationType
+    {
+        Identity,
+        Gamma,
+        Lut,
+    }
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/Calculators/CurveCalculator.cs b/src/ImageSharp/ColorProfiles/Icc/Calculators/CurveCalculator.cs
new file mode 100644
index 0000000000..232f4349c2
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/Calculators/CurveCalculator.cs
@@ -0,0 +1,47 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+#nullable disable
+
+using SixLabors.ImageSharp.ColorProfiles.Icc.Calculators;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
+
+internal partial class CurveCalculator : ISingleCalculator
+{
+    private readonly LutCalculator lutCalculator;
+    private readonly float gamma;
+    private readonly CalculationType type;
+
+    public CurveCalculator(IccCurveTagDataEntry entry, bool inverted)
+    {
+        if (entry.IsIdentityResponse)
+        {
+            this.type = CalculationType.Identity;
+        }
+        else if (entry.IsGamma)
+        {
+            this.gamma = entry.Gamma;
+            if (inverted)
+            {
+                this.gamma = 1f / this.gamma;
+            }
+
+            this.type = CalculationType.Gamma;
+        }
+        else
+        {
+            this.lutCalculator = new LutCalculator(entry.CurveData, inverted);
+            this.type = CalculationType.Lut;
+        }
+    }
+
+    public float Calculate(float value)
+        => this.type switch
+        {
+            CalculationType.Identity => value,
+            CalculationType.Gamma => MathF.Pow(value, this.gamma), // TODO: This could be optimized using a LUT. See SrgbCompanding
+            CalculationType.Lut => this.lutCalculator.Calculate(value),
+            _ => throw new InvalidOperationException("Invalid calculation type"),
+        };
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/Calculators/GrayTrcCalculator.cs b/src/ImageSharp/ColorProfiles/Icc/Calculators/GrayTrcCalculator.cs
new file mode 100644
index 0000000000..8d823c1e95
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/Calculators/GrayTrcCalculator.cs
@@ -0,0 +1,19 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.ColorProfiles.Icc.Calculators;
+
+internal class GrayTrcCalculator : IVector4Calculator
+{
+    private readonly TrcCalculator calculator;
+
+    public GrayTrcCalculator(IccTagDataEntry grayTrc, bool toPcs)
+        => this.calculator = new TrcCalculator(new IccTagDataEntry[] { grayTrc }, !toPcs);
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public Vector4 Calculate(Vector4 value) => this.calculator.Calculate(value);
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/Calculators/ISingleCalculator.cs b/src/ImageSharp/ColorProfiles/Icc/Calculators/ISingleCalculator.cs
new file mode 100644
index 0000000000..ce9b7d2f9b
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/Calculators/ISingleCalculator.cs
@@ -0,0 +1,17 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+namespace SixLabors.ImageSharp.ColorProfiles.Icc.Calculators;
+
+/// <summary>
+/// Represents an ICC calculator with a single floating point value and result
+/// </summary>
+internal interface ISingleCalculator
+{
+    /// <summary>
+    /// Calculates a result from the given value
+    /// </summary>
+    /// <param name="value">The input value</param>
+    /// <returns>The calculated result</returns>
+    float Calculate(float value);
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/Calculators/IVector4Calculator.cs b/src/ImageSharp/ColorProfiles/Icc/Calculators/IVector4Calculator.cs
new file mode 100644
index 0000000000..9beea79503
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/Calculators/IVector4Calculator.cs
@@ -0,0 +1,19 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Numerics;
+
+namespace SixLabors.ImageSharp.ColorProfiles.Icc.Calculators;
+
+/// <summary>
+/// Represents an ICC calculator with <see cref="Vector4"/> values and results
+/// </summary>
+internal interface IVector4Calculator
+{
+    /// <summary>
+    /// Calculates a result from the given values
+    /// </summary>
+    /// <param name="value">The input values</param>
+    /// <returns>The calculated result</returns>
+    Vector4 Calculate(Vector4 value);
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/Calculators/LutABCalculator.CalculationType.cs b/src/ImageSharp/ColorProfiles/Icc/Calculators/LutABCalculator.CalculationType.cs
new file mode 100644
index 0000000000..a09150c9b6
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/Calculators/LutABCalculator.CalculationType.cs
@@ -0,0 +1,18 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
+
+internal partial class LutABCalculator
+{
+    private enum CalculationType
+    {
+        AtoB = 1 << 3,
+        BtoA = 1 << 4,
+
+        SingleCurve = 1,
+        CurveMatrix = 2,
+        CurveClut = 3,
+        Full = 4,
+    }
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/Calculators/LutABCalculator.cs b/src/ImageSharp/ColorProfiles/Icc/Calculators/LutABCalculator.cs
new file mode 100644
index 0000000000..f891f66749
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/Calculators/LutABCalculator.cs
@@ -0,0 +1,135 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+#nullable disable
+
+using System.Numerics;
+using SixLabors.ImageSharp.ColorProfiles.Icc.Calculators;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
+
+internal partial class LutABCalculator : IVector4Calculator
+{
+    private CalculationType type;
+    private TrcCalculator curveACalculator;
+    private TrcCalculator curveBCalculator;
+    private TrcCalculator curveMCalculator;
+    private MatrixCalculator matrixCalculator;
+    private ClutCalculator clutCalculator;
+
+    public LutABCalculator(IccLutAToBTagDataEntry entry)
+    {
+        Guard.NotNull(entry, nameof(entry));
+        this.Init(entry.CurveA, entry.CurveB, entry.CurveM, entry.Matrix3x1, entry.Matrix3x3, entry.ClutValues);
+        this.type |= CalculationType.AtoB;
+    }
+
+    public LutABCalculator(IccLutBToATagDataEntry entry)
+    {
+        Guard.NotNull(entry, nameof(entry));
+        this.Init(entry.CurveA, entry.CurveB, entry.CurveM, entry.Matrix3x1, entry.Matrix3x3, entry.ClutValues);
+        this.type |= CalculationType.BtoA;
+    }
+
+    public Vector4 Calculate(Vector4 value)
+    {
+        switch (this.type)
+        {
+            case CalculationType.Full | CalculationType.AtoB:
+                value = this.curveACalculator.Calculate(value);
+                value = this.clutCalculator.Calculate(value);
+                value = this.curveMCalculator.Calculate(value);
+                value = this.matrixCalculator.Calculate(value);
+                return this.curveBCalculator.Calculate(value);
+
+            case CalculationType.Full | CalculationType.BtoA:
+                value = this.curveBCalculator.Calculate(value);
+                value = this.matrixCalculator.Calculate(value);
+                value = this.curveMCalculator.Calculate(value);
+                value = this.clutCalculator.Calculate(value);
+                return this.curveACalculator.Calculate(value);
+
+            case CalculationType.CurveClut | CalculationType.AtoB:
+                value = this.curveACalculator.Calculate(value);
+                value = this.clutCalculator.Calculate(value);
+                return this.curveBCalculator.Calculate(value);
+
+            case CalculationType.CurveClut | CalculationType.BtoA:
+                value = this.curveBCalculator.Calculate(value);
+                value = this.clutCalculator.Calculate(value);
+                return this.curveACalculator.Calculate(value);
+
+            case CalculationType.CurveMatrix | CalculationType.AtoB:
+                value = this.curveMCalculator.Calculate(value);
+                value = this.matrixCalculator.Calculate(value);
+                return this.curveBCalculator.Calculate(value);
+
+            case CalculationType.CurveMatrix | CalculationType.BtoA:
+                value = this.curveBCalculator.Calculate(value);
+                value = this.matrixCalculator.Calculate(value);
+                return this.curveMCalculator.Calculate(value);
+
+            case CalculationType.SingleCurve | CalculationType.AtoB:
+            case CalculationType.SingleCurve | CalculationType.BtoA:
+                return this.curveBCalculator.Calculate(value);
+
+            default:
+                throw new InvalidOperationException("Invalid calculation type");
+        }
+    }
+
+    private void Init(IccTagDataEntry[] curveA, IccTagDataEntry[] curveB, IccTagDataEntry[] curveM, Vector3? matrix3x1, Matrix4x4? matrix3x3, IccClut clut)
+    {
+        bool hasACurve = curveA != null;
+        bool hasBCurve = curveB != null;
+        bool hasMCurve = curveM != null;
+        bool hasMatrix = matrix3x1 != null && matrix3x3 != null;
+        bool hasClut = clut != null;
+
+        if (hasBCurve && hasMatrix && hasMCurve && hasClut && hasACurve)
+        {
+            this.type = CalculationType.Full;
+        }
+        else if (hasBCurve && hasClut && hasACurve)
+        {
+            this.type = CalculationType.CurveClut;
+        }
+        else if (hasBCurve && hasMatrix && hasMCurve)
+        {
+            this.type = CalculationType.CurveMatrix;
+        }
+        else if (hasBCurve)
+        {
+            this.type = CalculationType.SingleCurve;
+        }
+        else
+        {
+            throw new InvalidIccProfileException("AToB or BToA tag has an invalid configuration");
+        }
+
+        if (hasACurve)
+        {
+            this.curveACalculator = new TrcCalculator(curveA, false);
+        }
+
+        if (hasBCurve)
+        {
+            this.curveBCalculator = new TrcCalculator(curveB, false);
+        }
+
+        if (hasMCurve)
+        {
+            this.curveMCalculator = new TrcCalculator(curveM, false);
+        }
+
+        if (hasMatrix)
+        {
+            this.matrixCalculator = new MatrixCalculator(matrix3x3.Value, matrix3x1.Value);
+        }
+
+        if (hasClut)
+        {
+            this.clutCalculator = new ClutCalculator(clut);
+        }
+    }
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/Calculators/LutCalculator.cs b/src/ImageSharp/ColorProfiles/Icc/Calculators/LutCalculator.cs
new file mode 100644
index 0000000000..83704ae214
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/Calculators/LutCalculator.cs
@@ -0,0 +1,77 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Runtime.CompilerServices;
+
+namespace SixLabors.ImageSharp.ColorProfiles.Icc.Calculators;
+
+internal class LutCalculator : ISingleCalculator
+{
+    private readonly float[] lut;
+    private readonly bool inverse;
+
+    public LutCalculator(float[] lut, bool inverse)
+    {
+        Guard.NotNull(lut, nameof(lut));
+
+        this.lut = lut;
+        this.inverse = inverse;
+    }
+
+    public float Calculate(float value)
+    {
+        if (this.inverse)
+        {
+            return this.LookupInverse(value);
+        }
+
+        return this.Lookup(value);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private float Lookup(float value)
+    {
+        value = Math.Max(value, 0);
+
+        float factor = value * (this.lut.Length - 1);
+        int index = (int)factor;
+        float low = this.lut[index];
+
+        float high = 1F;
+        if (index < this.lut.Length - 1)
+        {
+            high = this.lut[index + 1];
+        }
+
+        return low + ((high - low) * (factor - index));
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private float LookupInverse(float value)
+    {
+        int index = Array.BinarySearch(this.lut, value);
+        if (index >= 0)
+        {
+            return index / (float)(this.lut.Length - 1);
+        }
+
+        index = ~index;
+        if (index == 0)
+        {
+            return 0;
+        }
+        else if (index == this.lut.Length)
+        {
+            return 1;
+        }
+
+        float high = this.lut[index];
+        float low = this.lut[index - 1];
+
+        float valuePercent = (value - low) / (high - low);
+        float lutRange = 1 / (float)(this.lut.Length - 1);
+        float lutLow = (index - 1) / (float)(this.lut.Length - 1);
+
+        return lutLow + (valuePercent * lutRange);
+    }
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/Calculators/LutEntryCalculator.cs b/src/ImageSharp/ColorProfiles/Icc/Calculators/LutEntryCalculator.cs
new file mode 100644
index 0000000000..c97578ee3f
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/Calculators/LutEntryCalculator.cs
@@ -0,0 +1,80 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+#nullable disable
+
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.ColorProfiles.Icc.Calculators;
+
+internal class LutEntryCalculator : IVector4Calculator
+{
+    private LutCalculator[] inputCurve;
+    private LutCalculator[] outputCurve;
+    private ClutCalculator clutCalculator;
+    private Matrix4x4 matrix;
+    private bool doTransform;
+
+    public LutEntryCalculator(IccLut8TagDataEntry lut)
+    {
+        Guard.NotNull(lut, nameof(lut));
+        this.Init(lut.InputValues, lut.OutputValues, lut.ClutValues, lut.Matrix);
+        this.Is16Bit = false;
+    }
+
+    public LutEntryCalculator(IccLut16TagDataEntry lut)
+    {
+        Guard.NotNull(lut, nameof(lut));
+        this.Init(lut.InputValues, lut.OutputValues, lut.ClutValues, lut.Matrix);
+        this.Is16Bit = true;
+    }
+
+    internal bool Is16Bit { get; }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public Vector4 Calculate(Vector4 value)
+    {
+        if (this.doTransform)
+        {
+            value = Vector4.Transform(value, this.matrix);
+        }
+
+        value = CalculateLut(this.inputCurve, value);
+        value = this.clutCalculator.Calculate(value);
+        return CalculateLut(this.outputCurve, value);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private static Vector4 CalculateLut(LutCalculator[] lut, Vector4 value)
+    {
+        ref float f = ref Unsafe.As<Vector4, float>(ref value);
+        for (int i = 0; i < lut.Length; i++)
+        {
+            Unsafe.Add(ref f, i) = lut[i].Calculate(Unsafe.Add(ref f, i));
+        }
+
+        return value;
+    }
+
+    private void Init(IccLut[] inputCurve, IccLut[] outputCurve, IccClut clut, Matrix4x4 matrix)
+    {
+        this.inputCurve = InitLut(inputCurve);
+        this.outputCurve = InitLut(outputCurve);
+        this.clutCalculator = new ClutCalculator(clut);
+        this.matrix = matrix;
+
+        this.doTransform = !matrix.IsIdentity && inputCurve.Length == 3;
+    }
+
+    private static LutCalculator[] InitLut(IccLut[] curves)
+    {
+        LutCalculator[] calculators = new LutCalculator[curves.Length];
+        for (int i = 0; i < curves.Length; i++)
+        {
+            calculators[i] = new LutCalculator(curves[i].Values, false);
+        }
+
+        return calculators;
+    }
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/Calculators/MatrixCalculator.cs b/src/ImageSharp/ColorProfiles/Icc/Calculators/MatrixCalculator.cs
new file mode 100644
index 0000000000..6be1fdbf95
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/Calculators/MatrixCalculator.cs
@@ -0,0 +1,26 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Numerics;
+using System.Runtime.CompilerServices;
+
+namespace SixLabors.ImageSharp.ColorProfiles.Icc.Calculators;
+
+internal class MatrixCalculator : IVector4Calculator
+{
+    private Matrix4x4 matrix2D;
+    private Vector4 matrix1D;
+
+    public MatrixCalculator(Matrix4x4 matrix3x3, Vector3 matrix3x1)
+    {
+        this.matrix2D = matrix3x3;
+        this.matrix1D = new Vector4(matrix3x1, 0);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public Vector4 Calculate(Vector4 value)
+    {
+        Vector4 transformed = Vector4.Transform(value, this.matrix2D);
+        return Vector4.Add(this.matrix1D, transformed);
+    }
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/Calculators/ParametricCurveCalculator.cs b/src/ImageSharp/ColorProfiles/Icc/Calculators/ParametricCurveCalculator.cs
new file mode 100644
index 0000000000..2a3945e270
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/Calculators/ParametricCurveCalculator.cs
@@ -0,0 +1,130 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Runtime.CompilerServices;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.ColorProfiles.Icc.Calculators;
+
+internal class ParametricCurveCalculator : ISingleCalculator
+{
+    private readonly IccParametricCurve curve;
+    private readonly IccParametricCurveType type;
+    private const IccParametricCurveType InvertedFlag = (IccParametricCurveType)(1 << 3);
+
+    public ParametricCurveCalculator(IccParametricCurveTagDataEntry entry, bool inverted)
+    {
+        Guard.NotNull(entry, nameof(entry));
+        this.curve = entry.Curve;
+        this.type = entry.Curve.Type;
+
+        if (inverted)
+        {
+            this.type |= InvertedFlag;
+        }
+    }
+
+    public float Calculate(float value)
+        => this.type switch
+        {
+            IccParametricCurveType.Type1 => this.CalculateGamma(value),
+            IccParametricCurveType.Cie122_1996 => this.CalculateCie122(value),
+            IccParametricCurveType.Iec61966_3 => this.CalculateIec61966(value),
+            IccParametricCurveType.SRgb => this.CalculateSRgb(value),
+            IccParametricCurveType.Type5 => this.CalculateType5(value),
+            IccParametricCurveType.Type1 | InvertedFlag => this.CalculateInvertedGamma(value),
+            IccParametricCurveType.Cie122_1996 | InvertedFlag => this.CalculateInvertedCie122(value),
+            IccParametricCurveType.Iec61966_3 | InvertedFlag => this.CalculateInvertedIec61966(value),
+            IccParametricCurveType.SRgb | InvertedFlag => this.CalculateInvertedSRgb(value),
+            IccParametricCurveType.Type5 | InvertedFlag => this.CalculateInvertedType5(value),
+            _ => throw new InvalidIccProfileException("ParametricCurve"),
+        };
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private float CalculateGamma(float value) => MathF.Pow(value, this.curve.G);
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private float CalculateCie122(float value)
+    {
+        if (value >= -this.curve.B / this.curve.A)
+        {
+            return MathF.Pow((this.curve.A * value) + this.curve.B, this.curve.G);
+        }
+
+        return 0;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private float CalculateIec61966(float value)
+    {
+        if (value >= -this.curve.B / this.curve.A)
+        {
+            return MathF.Pow((this.curve.A * value) + this.curve.B, this.curve.G) + this.curve.C;
+        }
+
+        return this.curve.C;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private float CalculateSRgb(float value)
+    {
+        if (value >= this.curve.D)
+        {
+            return MathF.Pow((this.curve.A * value) + this.curve.B, this.curve.G);
+        }
+
+        return this.curve.C * value;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private float CalculateType5(float value)
+    {
+        if (value >= this.curve.D)
+        {
+            return MathF.Pow((this.curve.A * value) + this.curve.B, this.curve.G) + this.curve.E;
+        }
+
+        return (this.curve.C * value) + this.curve.F;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private float CalculateInvertedGamma(float value)
+        => MathF.Pow(value, 1 / this.curve.G);
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private float CalculateInvertedCie122(float value)
+        => (MathF.Pow(value, 1 / this.curve.G) - this.curve.B) / this.curve.A;
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private float CalculateInvertedIec61966(float value)
+    {
+        if (value >= this.curve.C)
+        {
+            return (MathF.Pow(value - this.curve.C, 1 / this.curve.G) - this.curve.B) / this.curve.A;
+        }
+
+        return -this.curve.B / this.curve.A;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private float CalculateInvertedSRgb(float value)
+    {
+        if (value >= MathF.Pow((this.curve.A * this.curve.D) + this.curve.B, this.curve.G))
+        {
+            return (MathF.Pow(value, 1 / this.curve.G) - this.curve.B) / this.curve.A;
+        }
+
+        return value / this.curve.C;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private float CalculateInvertedType5(float value)
+    {
+        if (value >= (this.curve.C * this.curve.D) + this.curve.F)
+        {
+            return (MathF.Pow(value - this.curve.E, 1 / this.curve.G) - this.curve.B) / this.curve.A;
+        }
+
+        return (value - this.curve.F) / this.curve.C;
+    }
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/Calculators/TrcCalculator.cs b/src/ImageSharp/ColorProfiles/Icc/Calculators/TrcCalculator.cs
new file mode 100644
index 0000000000..b4b5028ed7
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/Calculators/TrcCalculator.cs
@@ -0,0 +1,41 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.ColorProfiles.Icc.Calculators;
+
+internal class TrcCalculator : IVector4Calculator
+{
+    private readonly ISingleCalculator[] calculators;
+
+    public TrcCalculator(IccTagDataEntry[] entries, bool inverted)
+    {
+        Guard.NotNull(entries, nameof(entries));
+
+        this.calculators = new ISingleCalculator[entries.Length];
+        for (int i = 0; i < entries.Length; i++)
+        {
+            this.calculators[i] = entries[i] switch
+            {
+                IccCurveTagDataEntry curve => new CurveCalculator(curve, inverted),
+                IccParametricCurveTagDataEntry parametricCurve => new ParametricCurveCalculator(parametricCurve, inverted),
+                _ => throw new InvalidIccProfileException("Invalid Entry."),
+            };
+        }
+    }
+
+    public unsafe Vector4 Calculate(Vector4 value)
+    {
+        ref float f = ref Unsafe.As<Vector4, float>(ref value);
+        for (int i = 0; i < this.calculators.Length; i++)
+        {
+            Unsafe.Add(ref f, i) = this.calculators[i].Calculate(Unsafe.Add(ref f, i));
+        }
+
+        return value;
+    }
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/IccConverterBase.Checks.cs b/src/ImageSharp/ColorProfiles/Icc/IccConverterBase.Checks.cs
new file mode 100644
index 0000000000..2b078e09fe
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/IccConverterBase.Checks.cs
@@ -0,0 +1,155 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+#nullable disable
+
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
+
+/// <summary>
+/// Color converter for ICC profiles
+/// </summary>
+internal abstract partial class IccConverterBase
+{
+    private static ConversionMethod GetConversionMethod(IccProfile profile, IccRenderingIntent renderingIntent) => profile.Header.Class switch
+    {
+        IccProfileClass.InputDevice or
+        IccProfileClass.DisplayDevice or
+        IccProfileClass.OutputDevice or
+        IccProfileClass.ColorSpace => CheckMethod1(profile, renderingIntent),
+        IccProfileClass.DeviceLink or IccProfileClass.Abstract => CheckMethod2(profile),
+        _ => ConversionMethod.Invalid,
+    };
+
+    private static ConversionMethod CheckMethod1(IccProfile profile, IccRenderingIntent renderingIntent)
+    {
+        ConversionMethod method = CheckMethodD(profile, renderingIntent);
+        if (method != ConversionMethod.Invalid)
+        {
+            return method;
+        }
+
+        method = CheckMethodA(profile, renderingIntent);
+        if (method != ConversionMethod.Invalid)
+        {
+            return method;
+        }
+
+        method = CheckMethodA0(profile);
+        if (method != ConversionMethod.Invalid)
+        {
+            return method;
+        }
+
+        method = CheckMethodTrc(profile);
+        if (method != ConversionMethod.Invalid)
+        {
+            return method;
+        }
+
+        return ConversionMethod.Invalid;
+    }
+
+    private static ConversionMethod CheckMethodD(IccProfile profile, IccRenderingIntent renderingIntent)
+    {
+        if ((HasTag(profile, IccProfileTag.DToB0) || HasTag(profile, IccProfileTag.BToD0))
+            && renderingIntent == IccRenderingIntent.Perceptual)
+        {
+            return ConversionMethod.D0;
+        }
+
+        if ((HasTag(profile, IccProfileTag.DToB1) || HasTag(profile, IccProfileTag.BToD1))
+            && renderingIntent == IccRenderingIntent.MediaRelativeColorimetric)
+        {
+            return ConversionMethod.D1;
+        }
+
+        if ((HasTag(profile, IccProfileTag.DToB2) || HasTag(profile, IccProfileTag.BToD2))
+            && renderingIntent == IccRenderingIntent.Saturation)
+        {
+            return ConversionMethod.D2;
+        }
+
+        if ((HasTag(profile, IccProfileTag.DToB3) || HasTag(profile, IccProfileTag.BToD3))
+            && renderingIntent == IccRenderingIntent.AbsoluteColorimetric)
+        {
+            return ConversionMethod.D3;
+        }
+
+        return ConversionMethod.Invalid;
+    }
+
+    private static ConversionMethod CheckMethodA(IccProfile profile, IccRenderingIntent renderingIntent)
+    {
+        if ((HasTag(profile, IccProfileTag.AToB0) || HasTag(profile, IccProfileTag.BToA0))
+            && renderingIntent == IccRenderingIntent.Perceptual)
+        {
+            return ConversionMethod.A0;
+        }
+
+        if ((HasTag(profile, IccProfileTag.AToB1) || HasTag(profile, IccProfileTag.BToA1))
+            && renderingIntent == IccRenderingIntent.MediaRelativeColorimetric)
+        {
+            return ConversionMethod.A1;
+        }
+
+        if ((HasTag(profile, IccProfileTag.AToB2) || HasTag(profile, IccProfileTag.BToA2))
+            && renderingIntent == IccRenderingIntent.Saturation)
+        {
+            return ConversionMethod.A2;
+        }
+
+        return ConversionMethod.Invalid;
+    }
+
+    private static ConversionMethod CheckMethodA0(IccProfile profile)
+    {
+        bool valid = HasTag(profile, IccProfileTag.AToB0) || HasTag(profile, IccProfileTag.BToA0);
+        return valid ? ConversionMethod.A0 : ConversionMethod.Invalid;
+    }
+
+    private static ConversionMethod CheckMethodTrc(IccProfile profile)
+    {
+        if (HasTag(profile, IccProfileTag.RedMatrixColumn)
+            && HasTag(profile, IccProfileTag.GreenMatrixColumn)
+            && HasTag(profile, IccProfileTag.BlueMatrixColumn)
+            && HasTag(profile, IccProfileTag.RedTrc)
+            && HasTag(profile, IccProfileTag.GreenTrc)
+            && HasTag(profile, IccProfileTag.BlueTrc))
+        {
+            return ConversionMethod.ColorTrc;
+        }
+
+        if (HasTag(profile, IccProfileTag.GrayTrc))
+        {
+            return ConversionMethod.GrayTrc;
+        }
+
+        return ConversionMethod.Invalid;
+    }
+
+    private static ConversionMethod CheckMethod2(IccProfile profile)
+    {
+        if (HasTag(profile, IccProfileTag.DToB0) || HasTag(profile, IccProfileTag.BToD0))
+        {
+            return ConversionMethod.D0;
+        }
+
+        if (HasTag(profile, IccProfileTag.AToB0) || HasTag(profile, IccProfileTag.AToB0))
+        {
+            return ConversionMethod.A0;
+        }
+
+        return ConversionMethod.Invalid;
+    }
+
+    private static bool HasTag(IccProfile profile, IccProfileTag tag)
+        => profile.Entries.Any(t => t.TagSignature == tag);
+
+    private static IccTagDataEntry GetTag(IccProfile profile, IccProfileTag tag)
+        => Array.Find(profile.Entries, t => t.TagSignature == tag);
+
+    private static T GetTag<T>(IccProfile profile, IccProfileTag tag)
+        where T : IccTagDataEntry
+        => profile.Entries.OfType<T>().FirstOrDefault(t => t.TagSignature == tag);
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/IccConverterBase.ConversionMethod.cs b/src/ImageSharp/ColorProfiles/Icc/IccConverterBase.ConversionMethod.cs
new file mode 100644
index 0000000000..3967560210
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/IccConverterBase.ConversionMethod.cs
@@ -0,0 +1,66 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
+
+/// <summary>
+/// Color converter for ICC profiles
+/// </summary>
+internal abstract partial class IccConverterBase
+{
+    /// <summary>
+    /// Conversion methods with ICC profiles
+    /// </summary>
+    private enum ConversionMethod
+    {
+        /// <summary>
+        /// Conversion using anything but Multi Process Elements with perceptual rendering intent
+        /// </summary>
+        A0,
+
+        /// <summary>
+        /// Conversion using anything but Multi Process Elements with relative colorimetric rendering intent
+        /// </summary>
+        A1,
+
+        /// <summary>
+        /// Conversion using anything but Multi Process Elements with saturation rendering intent
+        /// </summary>
+        A2,
+
+        /// <summary>
+        /// Conversion using Multi Process Elements with perceptual rendering intent
+        /// </summary>
+        D0,
+
+        /// <summary>
+        /// Conversion using Multi Process Elements with relative colorimetric rendering intent
+        /// </summary>
+        D1,
+
+        /// <summary>
+        /// Conversion using Multi Process Elements with saturation rendering intent
+        /// </summary>
+        D2,
+
+        /// <summary>
+        /// Conversion using Multi Process Elements with absolute colorimetric rendering intent
+        /// </summary>
+        D3,
+
+        /// <summary>
+        /// Conversion of more than one channel using tone reproduction curves
+        /// </summary>
+        ColorTrc,
+
+        /// <summary>
+        /// Conversion of exactly one channel using a tone reproduction curve
+        /// </summary>
+        GrayTrc,
+
+        /// <summary>
+        /// No valid conversion method available or found
+        /// </summary>
+        Invalid,
+    }
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/IccConverterbase.Conversions.cs b/src/ImageSharp/ColorProfiles/Icc/IccConverterbase.Conversions.cs
new file mode 100644
index 0000000000..b06d3e7b0c
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/IccConverterbase.Conversions.cs
@@ -0,0 +1,109 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using SixLabors.ImageSharp.ColorProfiles.Icc.Calculators;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
+
+/// <summary>
+/// Color converter for ICC profiles
+/// </summary>
+internal abstract partial class IccConverterBase
+{
+    private IVector4Calculator calculator;
+
+    internal bool Is16BitLutEntry => this.calculator is LutEntryCalculator { Is16Bit: true };
+
+    internal bool IsTrc => this.calculator is ColorTrcCalculator or GrayTrcCalculator;
+
+    /// <summary>
+    /// Checks the profile for available conversion methods and gathers all the information's necessary for it.
+    /// </summary>
+    /// <param name="profile">The profile to use for the conversion.</param>
+    /// <param name="toPcs">True if the conversion is to the Profile Connection Space.</param>
+    /// <param name="renderingIntent">The wanted rendering intent. Can be ignored if not available.</param>
+    /// <exception cref="InvalidIccProfileException">Invalid conversion method.</exception>
+    protected void Init(IccProfile profile, bool toPcs, IccRenderingIntent renderingIntent)
+        => this.calculator = GetConversionMethod(profile, renderingIntent) switch
+        {
+            ConversionMethod.D0 => toPcs ?
+                                InitD(profile, IccProfileTag.DToB0) :
+                                InitD(profile, IccProfileTag.BToD0),
+            ConversionMethod.D1 => toPcs ?
+                                InitD(profile, IccProfileTag.DToB1) :
+                                InitD(profile, IccProfileTag.BToD1),
+            ConversionMethod.D2 => toPcs ?
+                                InitD(profile, IccProfileTag.DToB2) :
+                                InitD(profile, IccProfileTag.BToD2),
+            ConversionMethod.D3 => toPcs ?
+                                InitD(profile, IccProfileTag.DToB3) :
+                                InitD(profile, IccProfileTag.BToD3),
+            ConversionMethod.A0 => toPcs ?
+                                InitA(profile, IccProfileTag.AToB0) :
+                                InitA(profile, IccProfileTag.BToA0),
+            ConversionMethod.A1 => toPcs ?
+                                InitA(profile, IccProfileTag.AToB1) :
+                                InitA(profile, IccProfileTag.BToA1),
+            ConversionMethod.A2 => toPcs ?
+                                InitA(profile, IccProfileTag.AToB2) :
+                                InitA(profile, IccProfileTag.BToA2),
+            ConversionMethod.ColorTrc => InitColorTrc(profile, toPcs),
+            ConversionMethod.GrayTrc => InitGrayTrc(profile, toPcs),
+            _ => throw new InvalidIccProfileException("Invalid conversion method."),
+        };
+
+    private static IVector4Calculator InitA(IccProfile profile, IccProfileTag tag)
+        => GetTag(profile, tag) switch
+        {
+            IccLut8TagDataEntry lut8 => new LutEntryCalculator(lut8),
+            IccLut16TagDataEntry lut16 => new LutEntryCalculator(lut16),
+            IccLutAToBTagDataEntry lutAtoB => new LutABCalculator(lutAtoB),
+            IccLutBToATagDataEntry lutBtoA => new LutABCalculator(lutBtoA),
+            _ => throw new InvalidIccProfileException("Invalid entry."),
+        };
+
+    private static IVector4Calculator InitD(IccProfile profile, IccProfileTag tag)
+    {
+        IccMultiProcessElementsTagDataEntry entry = GetTag<IccMultiProcessElementsTagDataEntry>(profile, tag)
+            ?? throw new InvalidIccProfileException("Entry is null.");
+
+        throw new NotImplementedException("Multi process elements are not supported");
+    }
+
+    private static ColorTrcCalculator InitColorTrc(IccProfile profile, bool toPcs)
+    {
+        IccXyzTagDataEntry redMatrixColumn = GetTag<IccXyzTagDataEntry>(profile, IccProfileTag.RedMatrixColumn);
+        IccXyzTagDataEntry greenMatrixColumn = GetTag<IccXyzTagDataEntry>(profile, IccProfileTag.GreenMatrixColumn);
+        IccXyzTagDataEntry blueMatrixColumn = GetTag<IccXyzTagDataEntry>(profile, IccProfileTag.BlueMatrixColumn);
+
+        IccTagDataEntry redTrc = GetTag(profile, IccProfileTag.RedTrc);
+        IccTagDataEntry greenTrc = GetTag(profile, IccProfileTag.GreenTrc);
+        IccTagDataEntry blueTrc = GetTag(profile, IccProfileTag.BlueTrc);
+
+        if (redMatrixColumn == null ||
+            greenMatrixColumn == null ||
+            blueMatrixColumn == null ||
+            redTrc == null ||
+            greenTrc == null ||
+            blueTrc == null)
+        {
+            throw new InvalidIccProfileException("Missing matrix column or channel.");
+        }
+
+        return new ColorTrcCalculator(
+            redMatrixColumn,
+            greenMatrixColumn,
+            blueMatrixColumn,
+            redTrc,
+            greenTrc,
+            blueTrc,
+            toPcs);
+    }
+
+    private static GrayTrcCalculator InitGrayTrc(IccProfile profile, bool toPcs)
+    {
+        IccTagDataEntry entry = GetTag(profile, IccProfileTag.GrayTrc);
+        return new GrayTrcCalculator(entry, toPcs);
+    }
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/IccConverterbase.cs b/src/ImageSharp/ColorProfiles/Icc/IccConverterbase.cs
new file mode 100644
index 0000000000..eb096534e1
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/IccConverterbase.cs
@@ -0,0 +1,49 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+#nullable disable
+
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
+
+/// <summary>
+/// Color converter for ICC profiles
+/// </summary>
+internal abstract partial class IccConverterBase
+{
+    /// <summary>
+    /// Initializes a new instance of the <see cref="IccConverterBase"/> class.
+    /// </summary>
+    /// <param name="profile">The ICC profile to use for the conversions</param>
+    /// <param name="toPcs">True if the conversion is to the profile connection space (PCS); False if the conversion is to the data space</param>
+    protected IccConverterBase(IccProfile profile, bool toPcs)
+    {
+        Guard.NotNull(profile, nameof(profile));
+        this.Init(profile, toPcs, profile.Header.RenderingIntent);
+    }
+
+    /// <summary>
+    /// Converts colors with the initially provided ICC profile
+    /// </summary>
+    /// <param name="value">The value to convert</param>
+    /// <returns>The converted value</returns>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public Vector4 Calculate(Vector4 value) => this.calculator.Calculate(value);
+
+    /// <summary>
+    /// Converts colors with the initially provided ICC profile
+    /// </summary>
+    /// <param name="source">The source colors</param>
+    /// <param name="destination">The destination colors</param>
+    public void Calculate(ReadOnlySpan<Vector4> source, Span<Vector4> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = this.Calculate(source[i]);
+        }
+    }
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/IccDataToDataConverter.cs b/src/ImageSharp/ColorProfiles/Icc/IccDataToDataConverter.cs
new file mode 100644
index 0000000000..173948a6eb
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/IccDataToDataConverter.cs
@@ -0,0 +1,22 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.ColorProfiles.Icc;
+
+/// <summary>
+/// Color converter for ICC profiles
+/// </summary>
+internal class IccDataToDataConverter : IccConverterBase
+{
+    /// <summary>
+    /// Initializes a new instance of the <see cref="IccDataToDataConverter"/> class.
+    /// </summary>
+    /// <param name="profile">The ICC profile to use for the conversions</param>
+    public IccDataToDataConverter(IccProfile profile)
+        : base(profile, true) // toPCS is true because in this case the PCS space is also a data space
+    {
+    }
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/IccDataToPcsConverter.cs b/src/ImageSharp/ColorProfiles/Icc/IccDataToPcsConverter.cs
new file mode 100644
index 0000000000..d9e42a8d97
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/IccDataToPcsConverter.cs
@@ -0,0 +1,22 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.ColorProfiles.Icc;
+
+/// <summary>
+/// Color converter for ICC profiles
+/// </summary>
+internal class IccDataToPcsConverter : IccConverterBase
+{
+    /// <summary>
+    /// Initializes a new instance of the <see cref="IccDataToPcsConverter"/> class.
+    /// </summary>
+    /// <param name="profile">The ICC profile to use for the conversions</param>
+    public IccDataToPcsConverter(IccProfile profile)
+        : base(profile, true)
+    {
+    }
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/IccPcsToDataConverter.cs b/src/ImageSharp/ColorProfiles/Icc/IccPcsToDataConverter.cs
new file mode 100644
index 0000000000..d174529b65
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/IccPcsToDataConverter.cs
@@ -0,0 +1,22 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.ColorProfiles.Icc;
+
+/// <summary>
+/// Color converter for ICC profiles
+/// </summary>
+internal class IccPcsToDataConverter : IccConverterBase
+{
+    /// <summary>
+    /// Initializes a new instance of the <see cref="IccPcsToDataConverter"/> class.
+    /// </summary>
+    /// <param name="profile">The ICC profile to use for the conversions</param>
+    public IccPcsToDataConverter(IccProfile profile)
+        : base(profile, false)
+    {
+    }
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/IccPcsToPcsConverter.cs b/src/ImageSharp/ColorProfiles/Icc/IccPcsToPcsConverter.cs
new file mode 100644
index 0000000000..98e069e401
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/IccPcsToPcsConverter.cs
@@ -0,0 +1,22 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.ColorProfiles.Icc;
+
+/// <summary>
+/// Color converter for ICC profiles
+/// </summary>
+internal class IccPcsToPcsConverter : IccConverterBase
+{
+    /// <summary>
+    /// Initializes a new instance of the <see cref="IccPcsToPcsConverter"/> class.
+    /// </summary>
+    /// <param name="profile">The ICC profile to use for the conversions</param>
+    public IccPcsToPcsConverter(IccProfile profile)
+        : base(profile, true)
+    {
+    }
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/IccProfileConverter.cs b/src/ImageSharp/ColorProfiles/Icc/IccProfileConverter.cs
new file mode 100644
index 0000000000..c8c4de4a60
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/IccProfileConverter.cs
@@ -0,0 +1,144 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Buffers;
+using System.Numerics;
+using SixLabors.ImageSharp.Advanced;
+using SixLabors.ImageSharp.Memory;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.PixelFormats;
+
+namespace SixLabors.ImageSharp.ColorProfiles.Icc;
+
+/// <summary>
+/// Allows the conversion between ICC profiles.
+/// </summary>
+internal static class IccProfileConverter
+{
+    /// <summary>
+    /// Performs a conversion of the image pixels based on the input and output ICC profiles.
+    /// </summary>
+    /// <param name="image">The image to convert.</param>
+    /// <param name="inputIccProfile">The input ICC profile.</param>
+    /// <param name="outputIccProfile">The output ICC profile. </param>
+    public static void Convert(Image image, IccProfile inputIccProfile, IccProfile outputIccProfile)
+        => image.AcceptVisitor(new IccProfileConverterVisitor(inputIccProfile, outputIccProfile));
+
+    /// <summary>
+    /// Performs a conversion of the image pixels based on the input and output ICC profiles.
+    /// </summary>
+    /// <typeparam name="TPixel">The type of pixel.</typeparam>
+    /// <param name="image">The image to convert.</param>
+    /// <param name="inputIccProfile">The input ICC profile.</param>
+    /// <param name="outputIccProfile">The output ICC profile. </param>
+    public static void Convert<TPixel>(Image<TPixel> image, IccProfile inputIccProfile, IccProfile outputIccProfile)
+        where TPixel : unmanaged, IPixel<TPixel>
+    {
+        IccDataToPcsConverter converterDataToPcs = new(inputIccProfile);
+        IccPcsToDataConverter converterPcsToData = new(outputIccProfile);
+        Configuration configuration = image.Configuration;
+
+        image.ProcessPixelRows(accessor =>
+        {
+            ColorProfileConverter converter = new(new ColorConversionOptions()
+            {
+                SourceWhitePoint = new CieXyz(inputIccProfile.Header.PcsIlluminant),
+                TargetWhitePoint = new CieXyz(outputIccProfile.Header.PcsIlluminant),
+            });
+
+            // TODO: Our Xxy/Lab conversion are dependent on the version number. We are applying the conversion using V4
+            // but we should use the correct algorithm per version. This includes Lab/Lab Xyz/Xyz.
+            using IMemoryOwner<Vector4> vectors = configuration.MemoryAllocator.Allocate<Vector4>(accessor.Width);
+            Span<Vector4> vectorsSpan = vectors.GetSpan();
+
+            // TODO: For debugging - remove.
+            // It appears we have a scaling problem. The pcs values differ by on average 0.000001.
+            Span<Vector4> temp = new Vector4[vectorsSpan.Length];
+
+            for (int y = 0; y < accessor.Height; y++)
+            {
+                Span<TPixel> row = accessor.GetRowSpan(y);
+                PixelOperations<TPixel>.Instance.ToVector4(configuration, row, vectorsSpan, PixelConversionModifiers.Scale);
+
+                if (inputIccProfile.Header.ProfileConnectionSpace == IccColorSpaceType.CieLab &&
+                    outputIccProfile.Header.ProfileConnectionSpace == IccColorSpaceType.CieXyz)
+                {
+                    for (int x = 0; x < vectorsSpan.Length; x++)
+                    {
+                        Vector4 pcs = converterDataToPcs.Calculate(vectorsSpan[x]);
+                        temp[x] = pcs;
+                        pcs = PcsToLab(pcs);
+                        CieLab lab = new(pcs.X, pcs.Y, pcs.Z);
+                        CieXyz xyz = converter.Convert<CieLab, CieXyz>(in lab);
+                        pcs = XyzToPcs(pcs, xyz);
+
+                        vectorsSpan[x] = converterPcsToData.Calculate(pcs);
+                    }
+                }
+                else if (inputIccProfile.Header.ProfileConnectionSpace == IccColorSpaceType.CieXyz &&
+                         outputIccProfile.Header.ProfileConnectionSpace == IccColorSpaceType.CieLab)
+                {
+                    for (int x = 0; x < vectorsSpan.Length; x++)
+                    {
+                        Vector4 pcs = converterDataToPcs.Calculate(vectorsSpan[x]);
+                        CieXyz xyz = new(pcs.X, pcs.Y, pcs.Z);
+                        CieLab lab = converter.Convert<CieXyz, CieLab>(in xyz);
+                        pcs = LabToPcs(pcs, lab);
+                        vectorsSpan[x] = converterPcsToData.Calculate(pcs);
+                    }
+                }
+                else
+                {
+                    for (int x = 0; x < vectorsSpan.Length; x++)
+                    {
+                        Vector4 pcs = converterDataToPcs.Calculate(vectorsSpan[x]);
+                        vectorsSpan[x] = converterPcsToData.Calculate(pcs);
+                    }
+                }
+
+                PixelOperations<TPixel>.Instance.FromVector4Destructive(configuration, vectorsSpan, row, PixelConversionModifiers.Scale);
+            }
+        });
+
+        image.Metadata.IccProfile = outputIccProfile;
+    }
+
+    private static unsafe Vector4 PcsToLab(Vector4 input)
+    {
+        Vector3* v = (Vector3*)&input;
+        v[0] *= new Vector3(100f, 255, 255);
+        v[0] -= new Vector3(0, 128F, 128F);
+        return input;
+    }
+
+    private static unsafe Vector4 LabToPcs(Vector4 input, CieLab lab)
+    {
+        Vector3* v = (Vector3*)&input;
+        v[0] = new Vector3(lab.L, lab.A + 128F, lab.B + 128F);
+        v[0] /= 100F;
+        return input;
+    }
+
+    private static unsafe Vector4 XyzToPcs(Vector4 input, CieXyz xyz)
+    {
+        Vector3* v = (Vector3*)&input;
+        v[0] = xyz.ToVector3();
+        v[0] *= 32768 / 65535f;
+        return input;
+    }
+
+    private readonly struct IccProfileConverterVisitor : IImageVisitor
+    {
+        private readonly IccProfile inputIccProfile;
+        private readonly IccProfile outputIccProfile;
+
+        public IccProfileConverterVisitor(IccProfile inputIccProfile, IccProfile outputIccProfile)
+        {
+            this.inputIccProfile = inputIccProfile;
+            this.outputIccProfile = outputIccProfile;
+        }
+
+        public void Visit<TPixel>(Image<TPixel> image)
+            where TPixel : unmanaged, IPixel<TPixel> => Convert(image, this.inputIccProfile, this.outputIccProfile);
+    }
+}
diff --git a/src/ImageSharp/ColorProfiles/Icc/SrgbV4Profile.Generated.cs b/src/ImageSharp/ColorProfiles/Icc/SrgbV4Profile.Generated.cs
new file mode 100644
index 0000000000..45c231aa67
--- /dev/null
+++ b/src/ImageSharp/ColorProfiles/Icc/SrgbV4Profile.Generated.cs
@@ -0,0 +1,45 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+// <auto-generated />
+
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
+
+internal static class SrgbV4Profile
+{
+    // Generated using the sRGB-v4.icc profile found at https://github.com/saucecontrol/Compact-ICC-Profiles
+    private static ReadOnlySpan<byte> Data => new byte[]
+    {
+        0, 0, 1, 224, 108, 99, 109, 115, 4, 32, 0, 0, 109, 110, 116, 114, 82, 71, 66, 32, 88, 89, 90, 32, 7, 226, 0, 3, 0,
+        20, 0, 9, 0, 14, 0, 29, 97, 99, 115, 112, 77, 83, 70, 84, 0, 0, 0, 0, 115, 97, 119, 115, 99, 116, 114, 108, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 214, 0, 1, 0, 0, 0, 0, 211, 45, 104, 97, 110, 100, 163, 178, 171,
+        223, 92, 167, 3, 18, 168, 85, 164, 236, 53, 122, 209, 243, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 100, 101, 115, 99, 0, 0, 0, 252, 0, 0, 0, 36, 99,
+        112, 114, 116, 0, 0, 1, 32, 0, 0, 0, 34, 119, 116, 112, 116, 0, 0, 1, 68, 0, 0, 0, 20, 99, 104, 97, 100, 0, 0,
+        1, 88, 0, 0, 0, 44, 114, 88, 89, 90, 0, 0, 1, 132, 0, 0, 0, 20, 103, 88, 89, 90, 0, 0, 1, 152, 0, 0, 0,
+        20, 98, 88, 89, 90, 0, 0, 1, 172, 0, 0, 0, 20, 114, 84, 82, 67, 0, 0, 1, 192, 0, 0, 0, 32, 103, 84, 82, 67,
+        0, 0, 1, 192, 0, 0, 0, 32, 98, 84, 82, 67, 0, 0, 1, 192, 0, 0, 0, 32, 109, 108, 117, 99, 0, 0, 0, 0, 0,
+        0, 0, 1, 0, 0, 0, 12, 101, 110, 85, 83, 0, 0, 0, 8, 0, 0, 0, 28, 0, 115, 0, 82, 0, 71, 0, 66, 109, 108,
+        117, 99, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 12, 101, 110, 85, 83, 0, 0, 0, 6, 0, 0, 0, 28, 0, 67, 0,
+        67, 0, 48, 0, 33, 88, 89, 90, 32, 0, 0, 0, 0, 0, 0, 246, 214, 0, 1, 0, 0, 0, 0, 211, 45, 115, 102, 51, 50,
+        0, 0, 0, 0, 0, 1, 12, 63, 0, 0, 5, 221, 255, 255, 243, 38, 0, 0, 7, 144, 0, 0, 253, 146, 255, 255, 251, 161, 255,
+        255, 253, 162, 0, 0, 3, 220, 0, 0, 192, 113, 88, 89, 90, 32, 0, 0, 0, 0, 0, 0, 111, 160, 0, 0, 56, 242, 0, 0,
+        3, 143, 88, 89, 90, 32, 0, 0, 0, 0, 0, 0, 98, 150, 0, 0, 183, 137, 0, 0, 24, 218, 88, 89, 90, 32, 0, 0, 0,
+        0, 0, 0, 36, 160, 0, 0, 15, 133, 0, 0, 182, 196, 112, 97, 114, 97, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 102, 105,
+        0, 0, 242, 167, 0, 0, 13, 89, 0, 0, 19, 208, 0, 0, 10, 91,
+    };
+
+    private static readonly Lazy<IccProfile> LazyIccProfile = new(() => GetIccProfile());
+
+    public static IccProfile GetProfile() => LazyIccProfile.Value;
+
+    private static IccProfile GetIccProfile()
+    {
+        byte[] buffer = new byte[Data.Length];
+        Data.CopyTo(buffer);
+        return new IccProfile(buffer);
+    }
+}
+
diff --git a/src/ImageSharp/ColorProfiles/Lms.cs b/src/ImageSharp/ColorProfiles/Lms.cs
index 5a6791b2d7..b3d29c9c9b 100644
--- a/src/ImageSharp/ColorProfiles/Lms.cs
+++ b/src/ImageSharp/ColorProfiles/Lms.cs
@@ -4,6 +4,7 @@
 using System.Numerics;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
 
 namespace SixLabors.ImageSharp.ColorProfiles;
 
@@ -89,6 +90,49 @@ public Lms(Vector3 vector)
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     public Vector3 ToVector3() => new(this.L, this.M, this.S);
 
+    /// <inheritdoc/>
+    public Vector4 ToScaledVector4()
+    {
+        Vector3 v3 = default;
+        v3 += this.AsVector3Unsafe();
+        v3 += new Vector3(1F);
+        v3 /= 2F;
+        return new Vector4(v3, 1F);
+    }
+
+    /// <inheritdoc/>
+    public static Lms FromScaledVector4(Vector4 source)
+    {
+        Vector3 v3 = source.AsVector3();
+        v3 *= 2F;
+        v3 -= new Vector3(1F);
+        return new Lms(v3);
+    }
+
+    /// <inheritdoc/>
+    public static void ToScaledVector4(ReadOnlySpan<Lms> source, Span<Vector4> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = source[i].ToScaledVector4();
+        }
+    }
+
+    /// <inheritdoc/>
+    public static void FromScaledVector4(ReadOnlySpan<Vector4> source, Span<Lms> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = FromScaledVector4(source[i]);
+        }
+    }
+
     /// <inheritdoc/>
     public static Lms FromProfileConnectingSpace(ColorConversionOptions options, in CieXyz source)
     {
diff --git a/src/ImageSharp/ColorProfiles/Rgb.cs b/src/ImageSharp/ColorProfiles/Rgb.cs
index 6698e12cb8..eb98318b55 100644
--- a/src/ImageSharp/ColorProfiles/Rgb.cs
+++ b/src/ImageSharp/ColorProfiles/Rgb.cs
@@ -4,6 +4,7 @@
 using System.Numerics;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
 using SixLabors.ImageSharp.ColorProfiles.WorkingSpaces;
 
 namespace SixLabors.ImageSharp.ColorProfiles;
@@ -81,6 +82,49 @@ public Rgb(Vector3 source)
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     public static bool operator !=(Rgb left, Rgb right) => !left.Equals(right);
 
+    /// <summary>
+    /// Initializes the color instance from a generic scaled <see cref="Vector4"/>.
+    /// </summary>
+    /// <param name="source">The vector to load the color from.</param>
+    /// <returns>The <see cref="Rgb"/>.</returns>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public static Rgb FromScaledVector4(Vector4 source)
+        => new(source.AsVector3());
+
+    /// <summary>
+    /// Expands the color into a generic ("scaled") <see cref="Vector4"/> representation
+    /// with values scaled and usually clamped between <value>0</value> and <value>1</value>.
+    /// The vector components are typically expanded in least to greatest significance order.
+    /// </summary>
+    /// <returns>The <see cref="Vector4"/>.</returns>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public Vector4 ToScaledVector4()
+        => new(this.ToScaledVector3(), 1F);
+
+    /// <inheritdoc/>
+    public static void ToScaledVector4(ReadOnlySpan<Rgb> source, Span<Vector4> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = source[i].ToScaledVector4();
+        }
+    }
+
+    /// <inheritdoc/>
+    public static void FromScaledVector4(ReadOnlySpan<Vector4> source, Span<Rgb> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = FromScaledVector4(source[i]);
+        }
+    }
+
     /// <inheritdoc/>
     public static Rgb FromProfileConnectingSpace(ColorConversionOptions options, in CieXyz source)
     {
@@ -108,10 +152,10 @@ public static void FromProfileConnectionSpace(ColorConversionOptions options, Re
     public CieXyz ToProfileConnectingSpace(ColorConversionOptions options)
     {
         // First expand to linear rgb
-        Rgb linear = FromScaledVector4(options.RgbWorkingSpace.Expand(this.ToScaledVector4()));
+        Rgb linear = FromScaledVector4(options.SourceRgbWorkingSpace.Expand(this.ToScaledVector4()));
 
         // Then convert to xyz
-        return new CieXyz(Vector3.Transform(linear.ToScaledVector3(), GetRgbToCieXyzMatrix(options.RgbWorkingSpace)));
+        return new CieXyz(Vector3.Transform(linear.ToScaledVector3(), GetRgbToCieXyzMatrix(options.SourceRgbWorkingSpace)));
     }
 
     /// <inheritdoc/>
@@ -119,13 +163,13 @@ public static void ToProfileConnectionSpace(ColorConversionOptions options, Read
     {
         Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
 
-        Matrix4x4 matrix = GetRgbToCieXyzMatrix(options.RgbWorkingSpace);
+        Matrix4x4 matrix = GetRgbToCieXyzMatrix(options.SourceRgbWorkingSpace);
         for (int i = 0; i < source.Length; i++)
         {
             Rgb rgb = source[i];
 
             // First expand to linear rgb
-            Rgb linear = FromScaledVector4(options.RgbWorkingSpace.Expand(rgb.ToScaledVector4()));
+            Rgb linear = FromScaledVector4(options.SourceRgbWorkingSpace.Expand(rgb.ToScaledVector4()));
 
             // Then convert to xyz
             destination[i] = new CieXyz(Vector3.Transform(linear.ToScaledVector3(), matrix));
@@ -133,7 +177,8 @@ public static void ToProfileConnectionSpace(ColorConversionOptions options, Read
     }
 
     /// <inheritdoc/>
-    public static ChromaticAdaptionWhitePointSource GetChromaticAdaptionWhitePointSource() => ChromaticAdaptionWhitePointSource.RgbWorkingSpace;
+    public static ChromaticAdaptionWhitePointSource GetChromaticAdaptionWhitePointSource()
+        => ChromaticAdaptionWhitePointSource.RgbWorkingSpace;
 
     /// <summary>
     /// Initializes the color instance from a generic scaled <see cref="Vector3"/>.
@@ -141,19 +186,8 @@ public static void ToProfileConnectionSpace(ColorConversionOptions options, Read
     /// <param name="source">The vector to load the color from.</param>
     /// <returns>The <see cref="Rgb"/>.</returns>
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public static Rgb FromScaledVector3(Vector3 source) => new(Vector3.Clamp(source, Vector3.Zero, Vector3.One));
-
-    /// <summary>
-    /// Initializes the color instance from a generic scaled <see cref="Vector4"/>.
-    /// </summary>
-    /// <param name="source">The vector to load the color from.</param>
-    /// <returns>The <see cref="Rgb"/>.</returns>
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public static Rgb FromScaledVector4(Vector4 source)
-    {
-        source = Vector4.Clamp(source, Vector4.Zero, Vector4.One);
-        return new(source.X, source.Y, source.Z);
-    }
+    public static Rgb FromScaledVector3(Vector3 source)
+        => new(source);
 
     /// <summary>
     /// Initializes the color instance for a source clamped between <value>0</value> and <value>1</value>
@@ -161,7 +195,8 @@ public static Rgb FromScaledVector4(Vector4 source)
     /// <param name="source">The source to load the color from.</param>
     /// <returns>The <see cref="Rgb"/>.</returns>
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public static Rgb Clamp(Rgb source) => new(Vector3.Clamp(new(source.R, source.G, source.B), Vector3.Zero, Vector3.One));
+    public static Rgb Clamp(Rgb source)
+        => new(Vector3.Clamp(source.AsVector3Unsafe(), Vector3.Zero, Vector3.One));
 
     /// <summary>
     /// Expands the color into a generic ("scaled") <see cref="Vector3"/> representation
@@ -170,24 +205,12 @@ public static Rgb FromScaledVector4(Vector4 source)
     /// </summary>
     /// <returns>The <see cref="Vector3"/>.</returns>
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public Vector3 ToScaledVector3() => Clamp(this).ToVector3();
-
-    /// <summary>
-    /// Expands the color into a generic <see cref="Vector3"/> representation.
-    /// The vector components are typically expanded in least to greatest significance order.
-    /// </summary>
-    /// <returns>The <see cref="Vector3"/>.</returns>
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public Vector3 ToVector3() => new(this.R, this.G, this.B);
-
-    /// <summary>
-    /// Expands the color into a generic ("scaled") <see cref="Vector4"/> representation
-    /// with values scaled and usually clamped between <value>0</value> and <value>1</value>.
-    /// The vector components are typically expanded in least to greatest significance order.
-    /// </summary>
-    /// <returns>The <see cref="Vector4"/>.</returns>
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public Vector4 ToScaledVector4() => new(this.ToScaledVector3(), 1f);
+    public Vector3 ToScaledVector3()
+    {
+        Vector3 v3 = default;
+        v3 += this.AsVector3Unsafe();
+        return v3;
+    }
 
     /// <inheritdoc/>
     public override int GetHashCode() => HashCode.Combine(this.R, this.G, this.B);
diff --git a/src/ImageSharp/ColorProfiles/YCbCr.cs b/src/ImageSharp/ColorProfiles/YCbCr.cs
index 03bd1d3120..dfd9351dcc 100644
--- a/src/ImageSharp/ColorProfiles/YCbCr.cs
+++ b/src/ImageSharp/ColorProfiles/YCbCr.cs
@@ -4,6 +4,7 @@
 using System.Numerics;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
 
 namespace SixLabors.ImageSharp.ColorProfiles;
 
@@ -82,6 +83,47 @@ public YCbCr(Vector3 vector)
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     public static bool operator !=(YCbCr left, YCbCr right) => !left.Equals(right);
 
+    /// <inheritdoc/>
+    public Vector4 ToScaledVector4()
+    {
+        Vector3 v3 = default;
+        v3 += this.AsVector3Unsafe();
+        v3 /= Max;
+        return new Vector4(v3, 1F);
+    }
+
+    /// <inheritdoc/>
+    public static YCbCr FromScaledVector4(Vector4 source)
+    {
+        Vector3 v3 = source.AsVector3();
+        v3 *= Max;
+        return new YCbCr(v3);
+    }
+
+    /// <inheritdoc/>
+    public static void ToScaledVector4(ReadOnlySpan<YCbCr> source, Span<Vector4> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = source[i].ToScaledVector4();
+        }
+    }
+
+    /// <inheritdoc/>
+    public static void FromScaledVector4(ReadOnlySpan<Vector4> source, Span<YCbCr> destination)
+    {
+        Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
+
+        // TODO: Optimize via SIMD
+        for (int i = 0; i < source.Length; i++)
+        {
+            destination[i] = FromScaledVector4(source[i]);
+        }
+    }
+
     /// <inheritdoc/>
     public static YCbCr FromProfileConnectingSpace(ColorConversionOptions options, in Rgb source)
     {
diff --git a/src/ImageSharp/Common/Extensions/Vector4Extensions.cs b/src/ImageSharp/Common/Extensions/Vector4Extensions.cs
new file mode 100644
index 0000000000..4e8ea61742
--- /dev/null
+++ b/src/ImageSharp/Common/Extensions/Vector4Extensions.cs
@@ -0,0 +1,21 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+#if !NET9_0_OR_GREATER
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+namespace SixLabors.ImageSharp;
+
+internal static class Vector4Extensions
+{
+    /// <summary>
+    /// Reinterprets a <see cref="Vector4" /> as a new <see cref="Vector3" />.
+    /// </summary>
+    /// <param name="value">The vector to reinterpret.</param>
+    /// <returns><paramref name="value" /> reinterpreted as a new <see cref="Vector3" />.</returns>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public static Vector3 AsVector3(this Vector4 value) => value.AsVector128().AsVector3();
+}
+#endif
diff --git a/src/ImageSharp/Formats/ColorProfileHandling.cs b/src/ImageSharp/Formats/ColorProfileHandling.cs
new file mode 100644
index 0000000000..e6f4b0a6a0
--- /dev/null
+++ b/src/ImageSharp/Formats/ColorProfileHandling.cs
@@ -0,0 +1,21 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+namespace SixLabors.ImageSharp.Formats;
+
+/// <summary>
+/// Provides enumeration of methods that control how ICC profiles are handled during decode.
+/// </summary>
+public enum ColorProfileHandling
+{
+    /// <summary>
+    /// Leaves any embedded ICC color profiles intact.
+    /// </summary>
+    Preserve,
+
+    /// <summary>
+    /// Transforms the pixels of the image based on the conversion of any embedded ICC color profiles to sRGB V4 profile.
+    /// The original profile is then replaced.
+    /// </summary>
+    Convert
+}
diff --git a/src/ImageSharp/Formats/DecoderOptions.cs b/src/ImageSharp/Formats/DecoderOptions.cs
index 3b16159b7e..f606d2fff2 100644
--- a/src/ImageSharp/Formats/DecoderOptions.cs
+++ b/src/ImageSharp/Formats/DecoderOptions.cs
@@ -60,5 +60,10 @@ public sealed class DecoderOptions
     /// </summary>
     public SegmentIntegrityHandling SegmentIntegrityHandling { get; init; } = SegmentIntegrityHandling.IgnoreNonCritical;
 
+    /// <summary>
+    /// Gets a value that controls how ICC profiles are handled during decode.
+    /// </summary>
+    public ColorProfileHandling ColorProfileHandling { get; init; }
+
     internal void SetConfiguration(Configuration configuration) => this.configuration = configuration;
 }
diff --git a/src/ImageSharp/Formats/ImageDecoder.cs b/src/ImageSharp/Formats/ImageDecoder.cs
index e58cd6a6de..0a8144712a 100644
--- a/src/ImageSharp/Formats/ImageDecoder.cs
+++ b/src/ImageSharp/Formats/ImageDecoder.cs
@@ -1,8 +1,11 @@
 // Copyright (c) Six Labors.
 // Licensed under the Six Labors Split License.
 
+using SixLabors.ImageSharp.ColorProfiles.Icc;
+using SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
 using SixLabors.ImageSharp.IO;
 using SixLabors.ImageSharp.Metadata;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
 using SixLabors.ImageSharp.PixelFormats;
 using SixLabors.ImageSharp.Processing;
 
@@ -23,6 +26,7 @@ public Image<TPixel> Decode<TPixel>(DecoderOptions options, Stream stream)
             stream,
             s => this.Decode<TPixel>(options, s, default));
 
+        TransformColorProfile(options, image);
         this.SetDecoderFormat(options.Configuration, image);
 
         return image;
@@ -36,6 +40,7 @@ public Image Decode(DecoderOptions options, Stream stream)
             stream,
             s => this.Decode(options, s, default));
 
+        TransformColorProfile(options, image);
         this.SetDecoderFormat(options.Configuration, image);
 
         return image;
@@ -46,11 +51,12 @@ public async Task<Image<TPixel>> DecodeAsync<TPixel>(DecoderOptions options, Str
         where TPixel : unmanaged, IPixel<TPixel>
     {
         Image<TPixel> image = await WithSeekableMemoryStreamAsync(
-                options,
-                stream,
-                (s, ct) => this.Decode<TPixel>(options, s, ct),
-                cancellationToken).ConfigureAwait(false);
+            options,
+            stream,
+            (s, ct) => this.Decode<TPixel>(options, s, ct),
+            cancellationToken).ConfigureAwait(false);
 
+        TransformColorProfile(options, image);
         this.SetDecoderFormat(options.Configuration, image);
 
         return image;
@@ -65,6 +71,7 @@ public async Task<Image> DecodeAsync(DecoderOptions options, Stream stream, Canc
             (s, ct) => this.Decode(options, s, ct),
             cancellationToken).ConfigureAwait(false);
 
+        TransformColorProfile(options, image);
         this.SetDecoderFormat(options.Configuration, image);
 
         return image;
@@ -159,6 +166,25 @@ protected static void ScaleToTargetSize(DecoderOptions options, Image image)
         }
     }
 
+    /// <summary>
+    /// Converts the decoded image color profile if present to a V4 sRGB profile.
+    /// </summary>
+    /// <param name="options">The decoder options.</param>
+    /// <param name="image">The image.</param>
+    protected static void TransformColorProfile(DecoderOptions options, Image image)
+    {
+        if (options.ColorProfileHandling == ColorProfileHandling.Preserve)
+        {
+            return;
+        }
+
+        IccProfile? profile = image.Metadata?.IccProfile;
+        if (profile is not null)
+        {
+            IccProfileConverter.Convert(image, profile, SrgbV4Profile.GetProfile());
+        }
+    }
+
     /// <summary>
     /// Determines whether the decoded image should be resized.
     /// </summary>
diff --git a/src/ImageSharp/Formats/SpecializedImageDecoder{T}.cs b/src/ImageSharp/Formats/SpecializedImageDecoder{T}.cs
index 59fa59bb97..2fb15aed29 100644
--- a/src/ImageSharp/Formats/SpecializedImageDecoder{T}.cs
+++ b/src/ImageSharp/Formats/SpecializedImageDecoder{T}.cs
@@ -23,7 +23,9 @@ public Image<TPixel> Decode<TPixel>(T options, Stream stream)
             stream,
             s => this.Decode<TPixel>(options, s, default));
 
+        TransformColorProfile(options.GeneralOptions, image);
         this.SetDecoderFormat(options.GeneralOptions.Configuration, image);
+
         return image;
     }
 
@@ -35,7 +37,9 @@ public Image Decode(T options, Stream stream)
             stream,
             s => this.Decode(options, s, default));
 
+        TransformColorProfile(options.GeneralOptions, image);
         this.SetDecoderFormat(options.GeneralOptions.Configuration, image);
+
         return image;
     }
 
@@ -49,7 +53,9 @@ public async Task<Image<TPixel>> DecodeAsync<TPixel>(T options, Stream stream, C
             (s, ct) => this.Decode<TPixel>(options, s, ct),
             cancellationToken).ConfigureAwait(false);
 
+        TransformColorProfile(options.GeneralOptions, image);
         this.SetDecoderFormat(options.GeneralOptions.Configuration, image);
+
         return image;
     }
 
@@ -62,7 +68,9 @@ public async Task<Image> DecodeAsync(T options, Stream stream, CancellationToken
             (s, ct) => this.Decode(options, s, ct),
             cancellationToken).ConfigureAwait(false);
 
+        TransformColorProfile(options.GeneralOptions, image);
         this.SetDecoderFormat(options.GeneralOptions.Configuration, image);
+
         return image;
     }
 
diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.Lut.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.Lut.cs
index e88dd8d9e1..f3ce6cd79c 100644
--- a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.Lut.cs
+++ b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.Lut.cs
@@ -4,24 +4,21 @@
 namespace SixLabors.ImageSharp.Metadata.Profiles.Icc;
 
 /// <summary>
-/// Provides methods to read ICC data types
+/// Provides methods to read ICC data types.
 /// </summary>
 internal sealed partial class IccDataReader
 {
     /// <summary>
-    /// Reads an 8bit lookup table
+    /// Reads an 8bit lookup table.
     /// </summary>
-    /// <returns>The read LUT</returns>
-    public IccLut ReadLut8()
-    {
-        return new IccLut(this.ReadBytes(256));
-    }
+    /// <returns>The read LUT.</returns>
+    public IccLut ReadLut8() => new(this.ReadBytes(256));
 
     /// <summary>
-    /// Reads a 16bit lookup table
+    /// Reads a 16bit lookup table.
     /// </summary>
-    /// <param name="count">The number of entries</param>
-    /// <returns>The read LUT</returns>
+    /// <param name="count">The number of entries.</param>
+    /// <returns>The read LUT.</returns>
     public IccLut ReadLut16(int count)
     {
         var values = new ushort[count];
@@ -34,16 +31,16 @@ public IccLut ReadLut16(int count)
     }
 
     /// <summary>
-    /// Reads a CLUT depending on type
+    /// Reads a CLUT depending on type.
     /// </summary>
-    /// <param name="inChannelCount">Input channel count</param>
-    /// <param name="outChannelCount">Output channel count</param>
+    /// <param name="inChannelCount">Input channel count.</param>
+    /// <param name="outChannelCount">Output channel count.</param>
     /// <param name="isFloat">If true, it's read as CLUTf32,
-    /// else read as either CLUT8 or CLUT16 depending on embedded information</param>
-    /// <returns>The read CLUT</returns>
+    /// else read as either CLUT8 or CLUT16 depending on embedded information.</param>
+    /// <returns>The read CLUT.</returns>
     public IccClut ReadClut(int inChannelCount, int outChannelCount, bool isFloat)
     {
-        // Grid-points are always 16 bytes long but only 0-inChCount are used
+        // Grid-points are always 16 bytes long but only 0-inChCount are used.
         var gridPointCount = new byte[inChannelCount];
         Buffer.BlockCopy(this.data, this.AddIndex(16), gridPointCount, 0, inChannelCount);
 
@@ -67,15 +64,14 @@ public IccClut ReadClut(int inChannelCount, int outChannelCount, bool isFloat)
     }
 
     /// <summary>
-    /// Reads an 8 bit CLUT
+    /// Reads an 8 bit CLUT.
     /// </summary>
-    /// <param name="inChannelCount">Input channel count</param>
-    /// <param name="outChannelCount">Output channel count</param>
-    /// <param name="gridPointCount">Grid point count for each CLUT channel</param>
-    /// <returns>The read CLUT8</returns>
+    /// <param name="inChannelCount">Input channel count.</param>
+    /// <param name="outChannelCount">Output channel count.</param>
+    /// <param name="gridPointCount">Grid point count for each CLUT channel.</param>
+    /// <returns>The read CLUT8.</returns>
     public IccClut ReadClut8(int inChannelCount, int outChannelCount, byte[] gridPointCount)
     {
-        int start = this.currentIndex;
         int length = 0;
         for (int i = 0; i < inChannelCount; i++)
         {
@@ -86,27 +82,26 @@ public IccClut ReadClut8(int inChannelCount, int outChannelCount, byte[] gridPoi
 
         const float Max = byte.MaxValue;
 
-        var values = new float[length][];
+        float[] values = new float[length * outChannelCount];
+        int offset = 0;
         for (int i = 0; i < length; i++)
         {
-            values[i] = new float[outChannelCount];
             for (int j = 0; j < outChannelCount; j++)
             {
-                values[i][j] = this.data[this.currentIndex++] / Max;
+                values[offset++] = this.data[this.currentIndex++] / Max;
             }
         }
 
-        this.currentIndex = start + (length * outChannelCount);
-        return new IccClut(values, gridPointCount, IccClutDataType.UInt8);
+        return new IccClut(values, gridPointCount, IccClutDataType.UInt8, outChannelCount);
     }
 
     /// <summary>
-    /// Reads a 16 bit CLUT
+    /// Reads a 16 bit CLUT.
     /// </summary>
-    /// <param name="inChannelCount">Input channel count</param>
-    /// <param name="outChannelCount">Output channel count</param>
-    /// <param name="gridPointCount">Grid point count for each CLUT channel</param>
-    /// <returns>The read CLUT16</returns>
+    /// <param name="inChannelCount">Input channel count.</param>
+    /// <param name="outChannelCount">Output channel count.</param>
+    /// <param name="gridPointCount">Grid point count for each CLUT channel.</param>
+    /// <returns>The read CLUT16.</returns>
     public IccClut ReadClut16(int inChannelCount, int outChannelCount, byte[] gridPointCount)
     {
         int start = this.currentIndex;
@@ -120,27 +115,27 @@ public IccClut ReadClut16(int inChannelCount, int outChannelCount, byte[] gridPo
 
         const float Max = ushort.MaxValue;
 
-        var values = new float[length][];
+        float[] values = new float[length * outChannelCount];
+        int offset = 0;
         for (int i = 0; i < length; i++)
         {
-            values[i] = new float[outChannelCount];
             for (int j = 0; j < outChannelCount; j++)
             {
-                values[i][j] = this.ReadUInt16() / Max;
+                values[offset++] = this.ReadUInt16() / Max;
             }
         }
 
         this.currentIndex = start + (length * outChannelCount * 2);
-        return new IccClut(values, gridPointCount, IccClutDataType.UInt16);
+        return new IccClut(values, gridPointCount, IccClutDataType.UInt16, outChannelCount);
     }
 
     /// <summary>
-    /// Reads a 32bit floating point CLUT
+    /// Reads a 32bit floating point CLUT.
     /// </summary>
-    /// <param name="inChCount">Input channel count</param>
-    /// <param name="outChCount">Output channel count</param>
-    /// <param name="gridPointCount">Grid point count for each CLUT channel</param>
-    /// <returns>The read CLUTf32</returns>
+    /// <param name="inChCount">Input channel count.</param>
+    /// <param name="outChCount">Output channel count.</param>
+    /// <param name="gridPointCount">Grid point count for each CLUT channel.</param>
+    /// <returns>The read CLUTf32.</returns>
     public IccClut ReadClutF32(int inChCount, int outChCount, byte[] gridPointCount)
     {
         int start = this.currentIndex;
@@ -152,17 +147,17 @@ public IccClut ReadClutF32(int inChCount, int outChCount, byte[] gridPointCount)
 
         length /= inChCount;
 
-        var values = new float[length][];
+        float[] values = new float[length * outChCount];
+        int offset = 0;
         for (int i = 0; i < length; i++)
         {
-            values[i] = new float[outChCount];
             for (int j = 0; j < outChCount; j++)
             {
-                values[i][j] = this.ReadSingle();
+                values[offset++] = this.ReadSingle();
             }
         }
 
         this.currentIndex = start + (length * outChCount * 4);
-        return new IccClut(values, gridPointCount, IccClutDataType.Float);
+        return new IccClut(values, gridPointCount, IccClutDataType.Float, outChCount);
     }
 }
diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.Matrix.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.Matrix.cs
index 61ecda4aab..ecc9bfbffb 100644
--- a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.Matrix.cs
+++ b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.Matrix.cs
@@ -17,16 +17,23 @@ internal sealed partial class IccDataReader
     /// <returns>The read matrix</returns>
     public float[,] ReadMatrix(int xCount, int yCount, bool isSingle)
     {
-        var matrix = new float[xCount, yCount];
-        for (int y = 0; y < yCount; y++)
+        float[,] matrix = new float[xCount, yCount];
+
+        if (isSingle)
         {
-            for (int x = 0; x < xCount; x++)
+            for (int y = 0; y < yCount; y++)
             {
-                if (isSingle)
+                for (int x = 0; x < xCount; x++)
                 {
                     matrix[x, y] = this.ReadSingle();
                 }
-                else
+            }
+        }
+        else
+        {
+            for (int y = 0; y < yCount; y++)
+            {
+                for (int x = 0; x < xCount; x++)
                 {
                     matrix[x, y] = this.ReadFix16();
                 }
@@ -44,14 +51,17 @@ internal sealed partial class IccDataReader
     /// <returns>The read matrix</returns>
     public float[] ReadMatrix(int yCount, bool isSingle)
     {
-        var matrix = new float[yCount];
-        for (int i = 0; i < yCount; i++)
+        float[] matrix = new float[yCount];
+        if (isSingle)
         {
-            if (isSingle)
+            for (int i = 0; i < yCount; i++)
             {
                 matrix[i] = this.ReadSingle();
             }
-            else
+        }
+        else
+        {
+            for (int i = 0; i < yCount; i++)
             {
                 matrix[i] = this.ReadFix16();
             }
diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.Primitives.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.Primitives.cs
index 47d946d443..7a526ef1af 100644
--- a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.Primitives.cs
+++ b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.Primitives.cs
@@ -16,55 +16,37 @@ internal sealed partial class IccDataReader
     /// Reads an ushort
     /// </summary>
     /// <returns>the value</returns>
-    public ushort ReadUInt16()
-    {
-        return BinaryPrimitives.ReadUInt16BigEndian(this.data.AsSpan(this.AddIndex(2), 2));
-    }
+    public ushort ReadUInt16() => BinaryPrimitives.ReadUInt16BigEndian(this.data.AsSpan(this.AddIndex(2), 2));
 
     /// <summary>
     /// Reads a short
     /// </summary>
     /// <returns>the value</returns>
-    public short ReadInt16()
-    {
-        return BinaryPrimitives.ReadInt16BigEndian(this.data.AsSpan(this.AddIndex(2), 2));
-    }
+    public short ReadInt16() => BinaryPrimitives.ReadInt16BigEndian(this.data.AsSpan(this.AddIndex(2), 2));
 
     /// <summary>
     /// Reads an uint
     /// </summary>
     /// <returns>the value</returns>
-    public uint ReadUInt32()
-    {
-        return BinaryPrimitives.ReadUInt32BigEndian(this.data.AsSpan(this.AddIndex(4), 4));
-    }
+    public uint ReadUInt32() => BinaryPrimitives.ReadUInt32BigEndian(this.data.AsSpan(this.AddIndex(4), 4));
 
     /// <summary>
     /// Reads an int
     /// </summary>
     /// <returns>the value</returns>
-    public int ReadInt32()
-    {
-        return BinaryPrimitives.ReadInt32BigEndian(this.data.AsSpan(this.AddIndex(4), 4));
-    }
+    public int ReadInt32() => BinaryPrimitives.ReadInt32BigEndian(this.data.AsSpan(this.AddIndex(4), 4));
 
     /// <summary>
     /// Reads an ulong
     /// </summary>
     /// <returns>the value</returns>
-    public ulong ReadUInt64()
-    {
-        return BinaryPrimitives.ReadUInt64BigEndian(this.data.AsSpan(this.AddIndex(8), 8));
-    }
+    public ulong ReadUInt64() => BinaryPrimitives.ReadUInt64BigEndian(this.data.AsSpan(this.AddIndex(8), 8));
 
     /// <summary>
     /// Reads a long
     /// </summary>
     /// <returns>the value</returns>
-    public long ReadInt64()
-    {
-        return BinaryPrimitives.ReadInt64BigEndian(this.data.AsSpan(this.AddIndex(8), 8));
-    }
+    public long ReadInt64() => BinaryPrimitives.ReadInt64BigEndian(this.data.AsSpan(this.AddIndex(8), 8));
 
     /// <summary>
     /// Reads a float.
@@ -152,10 +134,7 @@ public string ReadUnicodeString(int length)
     /// Reads an unsigned 16bit number with 8 value bits and 8 fractional bits.
     /// </summary>
     /// <returns>The number as double</returns>
-    public float ReadUFix8()
-    {
-        return this.ReadUInt16() / 256f;
-    }
+    public float ReadUFix8() => this.ReadUInt16() / 256f;
 
     /// <summary>
     /// Reads a number of bytes and advances the index.
diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs
index ddfc625152..c1b22e82bf 100644
--- a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs
+++ b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs
@@ -8,21 +8,19 @@
 namespace SixLabors.ImageSharp.Metadata.Profiles.Icc;
 
 /// <summary>
-/// Provides methods to read ICC data types
+/// Provides methods to read ICC data types.
 /// </summary>
 internal sealed partial class IccDataReader
 {
     /// <summary>
-    /// Reads a tag data entry
+    /// Reads a tag data entry.
     /// </summary>
-    /// <param name="info">The table entry with reading information</param>
-    /// <returns>the tag data entry</returns>
+    /// <param name="info">The table entry with reading information.</param>
+    /// <returns>The tag data entry.</returns>
     public IccTagDataEntry ReadTagDataEntry(IccTagTableEntry info)
     {
         this.currentIndex = (int)info.Offset;
-        IccTypeSignature type = this.ReadTagDataEntryHeader();
-
-        switch (type)
+        switch (this.ReadTagDataEntryHeader())
         {
             case IccTypeSignature.Chromaticity:
                 return this.ReadChromaticityTagDataEntry();
@@ -103,10 +101,10 @@ public IccTagDataEntry ReadTagDataEntry(IccTagTableEntry info)
     /// <summary>
     /// Reads the header of a <see cref="IccTagDataEntry"/>
     /// </summary>
-    /// <returns>The read signature</returns>
+    /// <returns>The read signature.</returns>
     public IccTypeSignature ReadTagDataEntryHeader()
     {
-        var type = (IccTypeSignature)this.ReadUInt32();
+        IccTypeSignature type = (IccTypeSignature)this.ReadUInt32();
         this.AddIndex(4); // 4 bytes are not used
         return type;
     }
@@ -114,7 +112,7 @@ public IccTypeSignature ReadTagDataEntryHeader()
     /// <summary>
     /// Reads the header of a <see cref="IccTagDataEntry"/> and checks if it's the expected value
     /// </summary>
-    /// <param name="expected">expected value to check against</param>
+    /// <param name="expected">The expected value to check against.</param>
     public void ReadCheckTagDataEntryHeader(IccTypeSignature expected)
     {
         IccTypeSignature type = this.ReadTagDataEntryHeader();
@@ -127,8 +125,8 @@ public void ReadCheckTagDataEntryHeader(IccTypeSignature expected)
     /// <summary>
     /// Reads a <see cref="IccTagDataEntry"/> with an unknown <see cref="IccTypeSignature"/>
     /// </summary>
-    /// <param name="size">The size of the entry in bytes</param>
-    /// <returns>The read entry</returns>
+    /// <param name="size">The size of the entry in bytes.</param>
+    /// <returns>The read entry.</returns>
     public IccUnknownTagDataEntry ReadUnknownTagDataEntry(uint size)
     {
         int count = (int)size - 8;  // 8 is the tag header size
@@ -138,7 +136,7 @@ public IccUnknownTagDataEntry ReadUnknownTagDataEntry(uint size)
     /// <summary>
     /// Reads a <see cref="IccChromaticityTagDataEntry"/>
     /// </summary>
-    /// <returns>The read entry</returns>
+    /// <returns>The read entry.</returns>
     public IccChromaticityTagDataEntry ReadChromaticityTagDataEntry()
     {
         ushort channelCount = this.ReadUInt16();
@@ -152,7 +150,7 @@ public IccChromaticityTagDataEntry ReadChromaticityTagDataEntry()
         }
         else
         {
-            // The type is not know, so the values need be read
+            // The type is not know, so the values need be read.
             double[][] values = new double[channelCount][];
             for (int i = 0; i < channelCount; i++)
             {
@@ -166,7 +164,7 @@ public IccChromaticityTagDataEntry ReadChromaticityTagDataEntry()
     /// <summary>
     /// Reads a <see cref="IccColorantOrderTagDataEntry"/>
     /// </summary>
-    /// <returns>The read entry</returns>
+    /// <returns>The read entry.</returns>
     public IccColorantOrderTagDataEntry ReadColorantOrderTagDataEntry()
     {
         uint colorantCount = this.ReadUInt32();
@@ -177,7 +175,7 @@ public IccColorantOrderTagDataEntry ReadColorantOrderTagDataEntry()
     /// <summary>
     /// Reads a <see cref="IccColorantTableTagDataEntry"/>
     /// </summary>
-    /// <returns>The read entry</returns>
+    /// <returns>The read entry.</returns>
     public IccColorantTableTagDataEntry ReadColorantTableTagDataEntry()
     {
         uint colorantCount = this.ReadUInt32();
@@ -193,7 +191,7 @@ public IccColorantTableTagDataEntry ReadColorantTableTagDataEntry()
     /// <summary>
     /// Reads a <see cref="IccCurveTagDataEntry"/>
     /// </summary>
-    /// <returns>The read entry</returns>
+    /// <returns>The read entry.</returns>
     public IccCurveTagDataEntry ReadCurveTagDataEntry()
     {
         uint pointCount = this.ReadUInt32();
@@ -222,7 +220,7 @@ public IccCurveTagDataEntry ReadCurveTagDataEntry()
     /// <summary>
     /// Reads a <see cref="IccDataTagDataEntry"/>
     /// </summary>
-    /// <param name="size">The size of the entry in bytes</param>
+    /// <param name="size">The size of the entry in bytes.</param>
     /// <returns>The read entry</returns>
     public IccDataTagDataEntry ReadDataTagDataEntry(uint size)
     {
@@ -240,16 +238,13 @@ public IccDataTagDataEntry ReadDataTagDataEntry(uint size)
     /// <summary>
     /// Reads a <see cref="IccDateTimeTagDataEntry"/>
     /// </summary>
-    /// <returns>The read entry</returns>
-    public IccDateTimeTagDataEntry ReadDateTimeTagDataEntry()
-    {
-        return new IccDateTimeTagDataEntry(this.ReadDateTime());
-    }
+    /// <returns>The read entry.</returns>
+    public IccDateTimeTagDataEntry ReadDateTimeTagDataEntry() => new IccDateTimeTagDataEntry(this.ReadDateTime());
 
     /// <summary>
     /// Reads a <see cref="IccLut16TagDataEntry"/>
     /// </summary>
-    /// <returns>The read entry</returns>
+    /// <returns>The read entry.</returns>
     public IccLut16TagDataEntry ReadLut16TagDataEntry()
     {
         byte inChCount = this.data[this.AddIndex(1)];
@@ -287,7 +282,7 @@ public IccLut16TagDataEntry ReadLut16TagDataEntry()
     /// <summary>
     /// Reads a <see cref="IccLut8TagDataEntry"/>
     /// </summary>
-    /// <returns>The read entry</returns>
+    /// <returns>The read entry.</returns>
     public IccLut8TagDataEntry ReadLut8TagDataEntry()
     {
         byte inChCount = this.data[this.AddIndex(1)];
@@ -322,7 +317,7 @@ public IccLut8TagDataEntry ReadLut8TagDataEntry()
     /// <summary>
     /// Reads a <see cref="IccLutAToBTagDataEntry"/>
     /// </summary>
-    /// <returns>The read entry</returns>
+    /// <returns>The read entry.</returns>
     public IccLutAToBTagDataEntry ReadLutAtoBTagDataEntry()
     {
         int start = this.currentIndex - 8; // 8 is the tag header size
@@ -381,7 +376,7 @@ public IccLutAToBTagDataEntry ReadLutAtoBTagDataEntry()
     /// <summary>
     /// Reads a <see cref="IccLutBToATagDataEntry"/>
     /// </summary>
-    /// <returns>The read entry</returns>
+    /// <returns>The read entry.</returns>
     public IccLutBToATagDataEntry ReadLutBtoATagDataEntry()
     {
         int start = this.currentIndex - 8; // 8 is the tag header size
@@ -440,21 +435,18 @@ public IccLutBToATagDataEntry ReadLutBtoATagDataEntry()
     /// <summary>
     /// Reads a <see cref="IccMeasurementTagDataEntry"/>
     /// </summary>
-    /// <returns>The read entry</returns>
-    public IccMeasurementTagDataEntry ReadMeasurementTagDataEntry()
-    {
-        return new IccMeasurementTagDataEntry(
+    /// <returns>The read entry.</returns>
+    public IccMeasurementTagDataEntry ReadMeasurementTagDataEntry() => new(
             observer: (IccStandardObserver)this.ReadUInt32(),
             xyzBacking: this.ReadXyzNumber(),
             geometry: (IccMeasurementGeometry)this.ReadUInt32(),
             flare: this.ReadUFix16(),
             illuminant: (IccStandardIlluminant)this.ReadUInt32());
-    }
 
     /// <summary>
     /// Reads a <see cref="IccMultiLocalizedUnicodeTagDataEntry"/>
     /// </summary>
-    /// <returns>The read entry</returns>
+    /// <returns>The read entry.</returns>
     public IccMultiLocalizedUnicodeTagDataEntry ReadMultiLocalizedUnicodeTagDataEntry()
     {
         int start = this.currentIndex - 8; // 8 is the tag header size
@@ -519,7 +511,7 @@ CultureInfo ReadCulture(string language, string country)
     /// <summary>
     /// Reads a <see cref="IccMultiProcessElementsTagDataEntry"/>
     /// </summary>
-    /// <returns>The read entry</returns>
+    /// <returns>The read entry.</returns>
     public IccMultiProcessElementsTagDataEntry ReadMultiProcessElementsTagDataEntry()
     {
         int start = this.currentIndex - 8;
@@ -547,7 +539,7 @@ public IccMultiProcessElementsTagDataEntry ReadMultiProcessElementsTagDataEntry(
     /// <summary>
     /// Reads a <see cref="IccNamedColor2TagDataEntry"/>
     /// </summary>
-    /// <returns>The read entry</returns>
+    /// <returns>The read entry.</returns>
     public IccNamedColor2TagDataEntry ReadNamedColor2TagDataEntry()
     {
         int vendorFlag = this.ReadInt32();
@@ -569,15 +561,12 @@ public IccNamedColor2TagDataEntry ReadNamedColor2TagDataEntry()
     /// Reads a <see cref="IccParametricCurveTagDataEntry"/>
     /// </summary>
     /// <returns>The read entry</returns>
-    public IccParametricCurveTagDataEntry ReadParametricCurveTagDataEntry()
-    {
-        return new IccParametricCurveTagDataEntry(this.ReadParametricCurve());
-    }
+    public IccParametricCurveTagDataEntry ReadParametricCurveTagDataEntry() => new(this.ReadParametricCurve());
 
     /// <summary>
     /// Reads a <see cref="IccProfileSequenceDescTagDataEntry"/>
     /// </summary>
-    /// <returns>The read entry</returns>
+    /// <returns>The read entry.</returns>
     public IccProfileSequenceDescTagDataEntry ReadProfileSequenceDescTagDataEntry()
     {
         uint count = this.ReadUInt32();
@@ -593,7 +582,7 @@ public IccProfileSequenceDescTagDataEntry ReadProfileSequenceDescTagDataEntry()
     /// <summary>
     /// Reads a <see cref="IccProfileSequenceIdentifierTagDataEntry"/>
     /// </summary>
-    /// <returns>The read entry</returns>
+    /// <returns>The read entry.</returns>
     public IccProfileSequenceIdentifierTagDataEntry ReadProfileSequenceIdentifierTagDataEntry()
     {
         int start = this.currentIndex - 8; // 8 is the tag header size
@@ -620,7 +609,7 @@ public IccProfileSequenceIdentifierTagDataEntry ReadProfileSequenceIdentifierTag
     /// <summary>
     /// Reads a <see cref="IccResponseCurveSet16TagDataEntry"/>
     /// </summary>
-    /// <returns>The read entry</returns>
+    /// <returns>The read entry.</returns>
     public IccResponseCurveSet16TagDataEntry ReadResponseCurveSet16TagDataEntry()
     {
         int start = this.currentIndex - 8; // 8 is the tag header size
@@ -646,8 +635,8 @@ public IccResponseCurveSet16TagDataEntry ReadResponseCurveSet16TagDataEntry()
     /// <summary>
     /// Reads a <see cref="IccFix16ArrayTagDataEntry"/>
     /// </summary>
-    /// <param name="size">The size of the entry in bytes</param>
-    /// <returns>The read entry</returns>
+    /// <param name="size">The size of the entry in bytes.</param>
+    /// <returns>The read entry.</returns>
     public IccFix16ArrayTagDataEntry ReadFix16ArrayTagDataEntry(uint size)
     {
         uint count = (size - 8) / 4;
@@ -663,27 +652,21 @@ public IccFix16ArrayTagDataEntry ReadFix16ArrayTagDataEntry(uint size)
     /// <summary>
     /// Reads a <see cref="IccSignatureTagDataEntry"/>
     /// </summary>
-    /// <returns>The read entry</returns>
-    public IccSignatureTagDataEntry ReadSignatureTagDataEntry()
-    {
-        return new IccSignatureTagDataEntry(this.ReadAsciiString(4));
-    }
+    /// <returns>The read entry.</returns>
+    public IccSignatureTagDataEntry ReadSignatureTagDataEntry() => new(this.ReadAsciiString(4));
 
     /// <summary>
     /// Reads a <see cref="IccTextTagDataEntry"/>
     /// </summary>
-    /// <param name="size">The size of the entry in bytes</param>
-    /// <returns>The read entry</returns>
-    public IccTextTagDataEntry ReadTextTagDataEntry(uint size)
-    {
-        return new IccTextTagDataEntry(this.ReadAsciiString((int)size - 8)); // 8 is the tag header size
-    }
+    /// <param name="size">The size of the entry in bytes.</param>
+    /// <returns>The read entry.</returns>
+    public IccTextTagDataEntry ReadTextTagDataEntry(uint size) => new(this.ReadAsciiString((int)size - 8)); // 8 is the tag header size
 
     /// <summary>
     /// Reads a <see cref="IccUFix16ArrayTagDataEntry"/>
     /// </summary>
-    /// <param name="size">The size of the entry in bytes</param>
-    /// <returns>The read entry</returns>
+    /// <param name="size">The size of the entry in bytes.</param>
+    /// <returns>The read entry.</returns>
     public IccUFix16ArrayTagDataEntry ReadUFix16ArrayTagDataEntry(uint size)
     {
         uint count = (size - 8) / 4;
@@ -699,8 +682,8 @@ public IccUFix16ArrayTagDataEntry ReadUFix16ArrayTagDataEntry(uint size)
     /// <summary>
     /// Reads a <see cref="IccUInt16ArrayTagDataEntry"/>
     /// </summary>
-    /// <param name="size">The size of the entry in bytes</param>
-    /// <returns>The read entry</returns>
+    /// <param name="size">The size of the entry in bytes.</param>
+    /// <returns>The read entry.</returns>
     public IccUInt16ArrayTagDataEntry ReadUInt16ArrayTagDataEntry(uint size)
     {
         uint count = (size - 8) / 2;
@@ -716,8 +699,8 @@ public IccUInt16ArrayTagDataEntry ReadUInt16ArrayTagDataEntry(uint size)
     /// <summary>
     /// Reads a <see cref="IccUInt32ArrayTagDataEntry"/>
     /// </summary>
-    /// <param name="size">The size of the entry in bytes</param>
-    /// <returns>The read entry</returns>
+    /// <param name="size">The size of the entry in bytes.</param>
+    /// <returns>The read entry.</returns>
     public IccUInt32ArrayTagDataEntry ReadUInt32ArrayTagDataEntry(uint size)
     {
         uint count = (size - 8) / 4;
@@ -733,8 +716,8 @@ public IccUInt32ArrayTagDataEntry ReadUInt32ArrayTagDataEntry(uint size)
     /// <summary>
     /// Reads a <see cref="IccUInt64ArrayTagDataEntry"/>
     /// </summary>
-    /// <param name="size">The size of the entry in bytes</param>
-    /// <returns>The read entry</returns>
+    /// <param name="size">The size of the entry in bytes.</param>
+    /// <returns>The read entry.</returns>
     public IccUInt64ArrayTagDataEntry ReadUInt64ArrayTagDataEntry(uint size)
     {
         uint count = (size - 8) / 8;
@@ -750,8 +733,8 @@ public IccUInt64ArrayTagDataEntry ReadUInt64ArrayTagDataEntry(uint size)
     /// <summary>
     /// Reads a <see cref="IccUInt8ArrayTagDataEntry"/>
     /// </summary>
-    /// <param name="size">The size of the entry in bytes</param>
-    /// <returns>The read entry</returns>
+    /// <param name="size">The size of the entry in bytes.</param>
+    /// <returns>The read entry.</returns>
     public IccUInt8ArrayTagDataEntry ReadUInt8ArrayTagDataEntry(uint size)
     {
         int count = (int)size - 8; // 8 is the tag header size
@@ -763,20 +746,17 @@ public IccUInt8ArrayTagDataEntry ReadUInt8ArrayTagDataEntry(uint size)
     /// <summary>
     /// Reads a <see cref="IccViewingConditionsTagDataEntry"/>
     /// </summary>
-    /// <returns>The read entry</returns>
-    public IccViewingConditionsTagDataEntry ReadViewingConditionsTagDataEntry()
-    {
-        return new IccViewingConditionsTagDataEntry(
+    /// <returns>The read entry.</returns>
+    public IccViewingConditionsTagDataEntry ReadViewingConditionsTagDataEntry() => new(
             illuminantXyz: this.ReadXyzNumber(),
             surroundXyz: this.ReadXyzNumber(),
             illuminant: (IccStandardIlluminant)this.ReadUInt32());
-    }
 
     /// <summary>
     /// Reads a <see cref="IccXyzTagDataEntry"/>
     /// </summary>
-    /// <param name="size">The size of the entry in bytes</param>
-    /// <returns>The read entry</returns>
+    /// <param name="size">The size of the entry in bytes.</param>
+    /// <returns>The read entry.</returns>
     public IccXyzTagDataEntry ReadXyzTagDataEntry(uint size)
     {
         uint count = (size - 8) / 12;
@@ -792,7 +772,7 @@ public IccXyzTagDataEntry ReadXyzTagDataEntry(uint size)
     /// <summary>
     /// Reads a <see cref="IccTextDescriptionTagDataEntry"/>
     /// </summary>
-    /// <returns>The read entry</returns>
+    /// <returns>The read entry.</returns>
     public IccTextDescriptionTagDataEntry ReadTextDescriptionTagDataEntry()
     {
         string unicodeValue, scriptcodeValue;
@@ -832,7 +812,7 @@ public IccTextDescriptionTagDataEntry ReadTextDescriptionTagDataEntry()
     /// <summary>
     /// Reads a <see cref="IccTextDescriptionTagDataEntry"/>
     /// </summary>
-    /// <returns>The read entry</returns>
+    /// <returns>The read entry.</returns>
     public IccCrdInfoTagDataEntry ReadCrdInfoTagDataEntry()
     {
         uint productNameCount = this.ReadUInt32();
@@ -856,7 +836,7 @@ public IccCrdInfoTagDataEntry ReadCrdInfoTagDataEntry()
     /// <summary>
     /// Reads a <see cref="IccScreeningTagDataEntry"/>
     /// </summary>
-    /// <returns>The read entry</returns>
+    /// <returns>The read entry.</returns>
     public IccScreeningTagDataEntry ReadScreeningTagDataEntry()
     {
         var flags = (IccScreeningFlag)this.ReadInt32();
@@ -873,7 +853,7 @@ public IccScreeningTagDataEntry ReadScreeningTagDataEntry()
     /// <summary>
     /// Reads a <see cref="IccUcrBgTagDataEntry"/>
     /// </summary>
-    /// <param name="size">The size of the entry in bytes</param>
+    /// <param name="size">The size of the entry in bytes.</param>
     /// <returns>The read entry</returns>
     public IccUcrBgTagDataEntry ReadUcrBgTagDataEntry(uint size)
     {
diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Lut.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Lut.cs
index 703a3896bb..29394c0820 100644
--- a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Lut.cs
+++ b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Lut.cs
@@ -4,15 +4,15 @@
 namespace SixLabors.ImageSharp.Metadata.Profiles.Icc;
 
 /// <content>
-/// Provides methods to write ICC data types
+/// Provides methods to write ICC data types.
 /// </content>
 internal sealed partial class IccDataWriter
 {
     /// <summary>
-    /// Writes an 8bit lookup table
+    /// Writes an 8bit lookup table.
     /// </summary>
-    /// <param name="value">The LUT to write</param>
-    /// <returns>The number of bytes written</returns>
+    /// <param name="value">The LUT to write.</param>
+    /// <returns>The number of bytes written.</returns>
     public int WriteLut8(IccLut value)
     {
         foreach (float item in value.Values)
@@ -24,10 +24,10 @@ public int WriteLut8(IccLut value)
     }
 
     /// <summary>
-    /// Writes an 16bit lookup table
+    /// Writes an 16bit lookup table.
     /// </summary>
-    /// <param name="value">The LUT to write</param>
-    /// <returns>The number of bytes written</returns>
+    /// <param name="value">The LUT to write.</param>
+    /// <returns>The number of bytes written.</returns>
     public int WriteLut16(IccLut value)
     {
         foreach (float item in value.Values)
@@ -39,10 +39,10 @@ public int WriteLut16(IccLut value)
     }
 
     /// <summary>
-    /// Writes an color lookup table
+    /// Writes an color lookup table.
     /// </summary>
-    /// <param name="value">The CLUT to write</param>
-    /// <returns>The number of bytes written</returns>
+    /// <param name="value">The CLUT to write.</param>
+    /// <returns>The number of bytes written.</returns>
     public int WriteClut(IccClut value)
     {
         int count = this.WriteArray(value.GridPointCount);
@@ -67,57 +67,48 @@ public int WriteClut(IccClut value)
     }
 
     /// <summary>
-    /// Writes a 8bit color lookup table
+    /// Writes a 8bit color lookup table.
     /// </summary>
-    /// <param name="value">The CLUT to write</param>
-    /// <returns>The number of bytes written</returns>
+    /// <param name="value">The CLUT to write.</param>
+    /// <returns>The number of bytes written.</returns>
     public int WriteClut8(IccClut value)
     {
         int count = 0;
-        foreach (float[] inArray in value.Values)
+        foreach (float item in value.Values)
         {
-            foreach (float item in inArray)
-            {
-                count += this.WriteByte((byte)Numerics.Clamp((item * byte.MaxValue) + 0.5F, 0, byte.MaxValue));
-            }
+            count += this.WriteByte((byte)Numerics.Clamp((item * byte.MaxValue) + 0.5F, 0, byte.MaxValue));
         }
 
         return count;
     }
 
     /// <summary>
-    /// Writes a 16bit color lookup table
+    /// Writes a 16bit color lookup table.
     /// </summary>
-    /// <param name="value">The CLUT to write</param>
-    /// <returns>The number of bytes written</returns>
+    /// <param name="value">The CLUT to write.</param>
+    /// <returns>The number of bytes written.</returns>
     public int WriteClut16(IccClut value)
     {
         int count = 0;
-        foreach (float[] inArray in value.Values)
+        foreach (float item in value.Values)
         {
-            foreach (float item in inArray)
-            {
-                count += this.WriteUInt16((ushort)Numerics.Clamp((item * ushort.MaxValue) + 0.5F, 0, ushort.MaxValue));
-            }
+            count += this.WriteUInt16((ushort)Numerics.Clamp((item * ushort.MaxValue) + 0.5F, 0, ushort.MaxValue));
         }
 
         return count;
     }
 
     /// <summary>
-    /// Writes a 32bit float color lookup table
+    /// Writes a 32bit float color lookup table.
     /// </summary>
-    /// <param name="value">The CLUT to write</param>
-    /// <returns>The number of bytes written</returns>
+    /// <param name="value">The CLUT to write.</param>
+    /// <returns>The number of bytes written.</returns>
     public int WriteClutF32(IccClut value)
     {
         int count = 0;
-        foreach (float[] inArray in value.Values)
+        foreach (float item in value.Values)
         {
-            foreach (float item in inArray)
-            {
-                count += this.WriteSingle(item);
-            }
+            count += this.WriteSingle(item);
         }
 
         return count;
diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Matrix.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Matrix.cs
index 1e5f359e09..636cc90a57 100644
--- a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Matrix.cs
+++ b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Matrix.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
 // Licensed under the Six Labors Split License.
 
 using System.Numerics;
@@ -61,15 +61,21 @@ public int WriteMatrix(Matrix4x4 value, bool isSingle)
     public int WriteMatrix(in DenseMatrix<float> value, bool isSingle)
     {
         int count = 0;
-        for (int y = 0; y < value.Rows; y++)
+        if (isSingle)
         {
-            for (int x = 0; x < value.Columns; x++)
+            for (int y = 0; y < value.Rows; y++)
             {
-                if (isSingle)
+                for (int x = 0; x < value.Columns; x++)
                 {
                     count += this.WriteSingle(value[x, y]);
                 }
-                else
+            }
+        }
+        else
+        {
+            for (int y = 0; y < value.Rows; y++)
+            {
+                for (int x = 0; x < value.Columns; x++)
                 {
                     count += this.WriteFix16(value[x, y]);
                 }
@@ -88,15 +94,22 @@ public int WriteMatrix(in DenseMatrix<float> value, bool isSingle)
     public int WriteMatrix(float[,] value, bool isSingle)
     {
         int count = 0;
-        for (int y = 0; y < value.GetLength(1); y++)
+
+        if (isSingle)
         {
-            for (int x = 0; x < value.GetLength(0); x++)
+            for (int y = 0; y < value.GetLength(1); y++)
             {
-                if (isSingle)
+                for (int x = 0; x < value.GetLength(0); x++)
                 {
                     count += this.WriteSingle(value[x, y]);
                 }
-                else
+            }
+        }
+        else
+        {
+            for (int y = 0; y < value.GetLength(1); y++)
+            {
+                for (int x = 0; x < value.GetLength(0); x++)
                 {
                     count += this.WriteFix16(value[x, y]);
                 }
diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs
index 1f9c101fb5..6019a0bff7 100644
--- a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs
+++ b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs
@@ -231,7 +231,7 @@ public int WriteLut8TagDataEntry(IccLut8TagDataEntry value)
     {
         int count = this.WriteByte((byte)value.InputChannelCount);
         count += this.WriteByte((byte)value.OutputChannelCount);
-        count += this.WriteByte((byte)value.ClutValues.Values[0].Length);
+        count += this.WriteByte((byte)value.ClutValues.OutputChannelCount);
         count += this.WriteEmpty(1);
 
         count += this.WriteMatrix(value.Matrix, false);
diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Enums/IccFormulaCurveType.cs b/src/ImageSharp/Metadata/Profiles/ICC/Enums/IccFormulaCurveType.cs
index e0c6f4c962..27af2a91f7 100644
--- a/src/ImageSharp/Metadata/Profiles/ICC/Enums/IccFormulaCurveType.cs
+++ b/src/ImageSharp/Metadata/Profiles/ICC/Enums/IccFormulaCurveType.cs
@@ -14,7 +14,7 @@ internal enum IccFormulaCurveType : ushort
     Type1 = 0,
 
     /// <summary>
-    /// Type 1: Y = a * log10 (b * X^γ + c) + d
+    /// Type 2: Y = a * log10 (b * X^γ + c) + d
     /// </summary>
     Type2 = 1,
 
diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Exceptions/InvalidIccProfileException.cs b/src/ImageSharp/Metadata/Profiles/ICC/Exceptions/InvalidIccProfileException.cs
index c1cb3f10f0..c6b4b65773 100644
--- a/src/ImageSharp/Metadata/Profiles/ICC/Exceptions/InvalidIccProfileException.cs
+++ b/src/ImageSharp/Metadata/Profiles/ICC/Exceptions/InvalidIccProfileException.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
 // Licensed under the Six Labors Split License.
 
 namespace SixLabors.ImageSharp.Metadata.Profiles.Icc;
diff --git a/src/ImageSharp/Metadata/Profiles/ICC/IccProfile.cs b/src/ImageSharp/Metadata/Profiles/ICC/IccProfile.cs
index ac78318f2b..da015b2b07 100644
--- a/src/ImageSharp/Metadata/Profiles/ICC/IccProfile.cs
+++ b/src/ImageSharp/Metadata/Profiles/ICC/IccProfile.cs
@@ -190,7 +190,6 @@ private void InitializeHeader()
             return;
         }
 
-        IccReader reader = new();
         this.header = IccReader.ReadHeader(this.data);
     }
 
@@ -207,7 +206,6 @@ private void InitializeEntries()
             return;
         }
 
-        IccReader reader = new();
         this.entries = IccReader.ReadTagData(this.data);
     }
 }
diff --git a/src/ImageSharp/Metadata/Profiles/ICC/IccReader.cs b/src/ImageSharp/Metadata/Profiles/ICC/IccReader.cs
index 45074c9a6e..074712d302 100644
--- a/src/ImageSharp/Metadata/Profiles/ICC/IccReader.cs
+++ b/src/ImageSharp/Metadata/Profiles/ICC/IccReader.cs
@@ -83,28 +83,19 @@ private static IccTagDataEntry[] ReadTagData(IccDataReader reader)
     {
         IccTagTableEntry[] tagTable = ReadTagTable(reader);
         List<IccTagDataEntry> entries = new(tagTable.Length);
-        Dictionary<uint, IccTagDataEntry> store = new();
 
         foreach (IccTagTableEntry tag in tagTable)
         {
             IccTagDataEntry entry;
-            if (store.TryGetValue(tag.Offset, out IccTagDataEntry? value))
+
+            try
             {
-                entry = value;
+                entry = reader.ReadTagDataEntry(tag);
             }
-            else
+            catch
             {
-                try
-                {
-                    entry = reader.ReadTagDataEntry(tag);
-                }
-                catch
-                {
-                    // Ignore tags that could not be read
-                    continue;
-                }
-
-                store.Add(tag.Offset, entry);
+                // Ignore tags that could not be read
+                continue;
             }
 
             entry.TagSignature = tag.Signature;
diff --git a/src/ImageSharp/Metadata/Profiles/ICC/IccTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/IccTagDataEntry.cs
index 12228f3f58..f7a99645bb 100644
--- a/src/ImageSharp/Metadata/Profiles/ICC/IccTagDataEntry.cs
+++ b/src/ImageSharp/Metadata/Profiles/ICC/IccTagDataEntry.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
 // Licensed under the Six Labors Split License.
 
 namespace SixLabors.ImageSharp.Metadata.Profiles.Icc;
@@ -41,9 +41,7 @@ protected IccTagDataEntry(IccTypeSignature signature, IccProfileTag tagSignature
 
     /// <inheritdoc/>
     public override bool Equals(object? obj)
-    {
-        return obj is IccTagDataEntry entry && this.Equals(entry);
-    }
+        => obj is IccTagDataEntry entry && this.Equals(entry);
 
     /// <inheritdoc/>
     public virtual bool Equals(IccTagDataEntry? other)
diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccClut.cs b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccClut.cs
index 26a882810e..bbec7ce43e 100644
--- a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccClut.cs
+++ b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccClut.cs
@@ -1,20 +1,21 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
 // Licensed under the Six Labors Split License.
 
 namespace SixLabors.ImageSharp.Metadata.Profiles.Icc;
 
 /// <summary>
-/// Color Lookup Table
+/// Color Lookup Table.
 /// </summary>
 internal sealed class IccClut : IEquatable<IccClut>
 {
     /// <summary>
     /// Initializes a new instance of the <see cref="IccClut"/> class.
     /// </summary>
-    /// <param name="values">The CLUT values</param>
-    /// <param name="gridPointCount">The gridpoint count</param>
-    /// <param name="type">The data type of this CLUT</param>
-    public IccClut(float[][] values, byte[] gridPointCount, IccClutDataType type)
+    /// <param name="values">The CLUT values.</param>
+    /// <param name="gridPointCount">The gridpoint count.</param>
+    /// <param name="type">The data type of this CLUT.</param>
+    /// <param name="outputChannelCount">The output channels count.</param>
+    public IccClut(float[] values, byte[] gridPointCount, IccClutDataType type, int outputChannelCount)
     {
         Guard.NotNull(values, nameof(values));
         Guard.NotNull(gridPointCount, nameof(gridPointCount));
@@ -22,91 +23,33 @@ public IccClut(float[][] values, byte[] gridPointCount, IccClutDataType type)
         this.Values = values;
         this.DataType = type;
         this.InputChannelCount = gridPointCount.Length;
-        this.OutputChannelCount = values[0].Length;
+        this.OutputChannelCount = outputChannelCount;
         this.GridPointCount = gridPointCount;
         this.CheckValues();
     }
 
     /// <summary>
-    /// Initializes a new instance of the <see cref="IccClut"/> class.
-    /// </summary>
-    /// <param name="values">The CLUT values</param>
-    /// <param name="gridPointCount">The gridpoint count</param>
-    public IccClut(ushort[][] values, byte[] gridPointCount)
-    {
-        Guard.NotNull(values, nameof(values));
-        Guard.NotNull(gridPointCount, nameof(gridPointCount));
-
-        const float Max = ushort.MaxValue;
-
-        this.Values = new float[values.Length][];
-        for (int i = 0; i < values.Length; i++)
-        {
-            this.Values[i] = new float[values[i].Length];
-            for (int j = 0; j < values[i].Length; j++)
-            {
-                this.Values[i][j] = values[i][j] / Max;
-            }
-        }
-
-        this.DataType = IccClutDataType.UInt16;
-        this.InputChannelCount = gridPointCount.Length;
-        this.OutputChannelCount = values[0].Length;
-        this.GridPointCount = gridPointCount;
-        this.CheckValues();
-    }
-
-    /// <summary>
-    /// Initializes a new instance of the <see cref="IccClut"/> class.
-    /// </summary>
-    /// <param name="values">The CLUT values</param>
-    /// <param name="gridPointCount">The gridpoint count</param>
-    public IccClut(byte[][] values, byte[] gridPointCount)
-    {
-        Guard.NotNull(values, nameof(values));
-        Guard.NotNull(gridPointCount, nameof(gridPointCount));
-
-        const float Max = byte.MaxValue;
-
-        this.Values = new float[values.Length][];
-        for (int i = 0; i < values.Length; i++)
-        {
-            this.Values[i] = new float[values[i].Length];
-            for (int j = 0; j < values[i].Length; j++)
-            {
-                this.Values[i][j] = values[i][j] / Max;
-            }
-        }
-
-        this.DataType = IccClutDataType.UInt8;
-        this.InputChannelCount = gridPointCount.Length;
-        this.OutputChannelCount = values[0].Length;
-        this.GridPointCount = gridPointCount;
-        this.CheckValues();
-    }
-
-    /// <summary>
-    /// Gets the values that make up this table
+    /// Gets the values that make up this table.
     /// </summary>
-    public float[][] Values { get; }
+    public float[] Values { get; }
 
     /// <summary>
-    /// Gets the CLUT data type (important when writing a profile)
+    /// Gets the CLUT data type (important when writing a profile).
     /// </summary>
     public IccClutDataType DataType { get; }
 
     /// <summary>
-    /// Gets the number of input channels
+    /// Gets the number of input channels.
     /// </summary>
     public int InputChannelCount { get; }
 
     /// <summary>
-    /// Gets the number of output channels
+    /// Gets the number of output channels.
     /// </summary>
     public int OutputChannelCount { get; }
 
     /// <summary>
-    /// Gets the number of grid points per input channel
+    /// Gets the number of grid points per input channel.
     /// </summary>
     public byte[] GridPointCount { get; }
 
@@ -134,15 +77,12 @@ public bool Equals(IccClut? other)
     public override bool Equals(object? obj) => obj is IccClut other && this.Equals(other);
 
     /// <inheritdoc/>
-    public override int GetHashCode()
-    {
-        return HashCode.Combine(
+    public override int GetHashCode() => HashCode.Combine(
             this.Values,
             this.DataType,
             this.InputChannelCount,
             this.OutputChannelCount,
             this.GridPointCount);
-    }
 
     private bool EqualsValuesArray(IccClut other)
     {
@@ -153,7 +93,7 @@ private bool EqualsValuesArray(IccClut other)
 
         for (int i = 0; i < this.Values.Length; i++)
         {
-            if (!this.Values[i].AsSpan().SequenceEqual(other.Values[i]))
+            if (!this.Values.SequenceEqual(other.Values))
             {
                 return false;
             }
@@ -167,17 +107,13 @@ private void CheckValues()
         Guard.MustBeBetweenOrEqualTo(this.InputChannelCount, 1, 15, nameof(this.InputChannelCount));
         Guard.MustBeBetweenOrEqualTo(this.OutputChannelCount, 1, 15, nameof(this.OutputChannelCount));
 
-        bool isLengthDifferent = this.Values.Any(t => t.Length != this.OutputChannelCount);
-        Guard.IsFalse(isLengthDifferent, nameof(this.Values), "The number of output values varies");
-
         int length = 0;
         for (int i = 0; i < this.InputChannelCount; i++)
         {
             length += (int)Math.Pow(this.GridPointCount[i], this.InputChannelCount);
         }
 
-        length /= this.InputChannelCount;
-
-        Guard.IsTrue(this.Values.Length == length, nameof(this.Values), "Length of values array does not match the grid points");
+        // TODO: Disabled this check, not sure if this check is correct.
+        // Guard.IsTrue(this.Values.Length == length, nameof(this.Values), "Length of values array does not match the grid points");
     }
 }
diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccTagTableEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccTagTableEntry.cs
index e7d7461d5d..a71cbfaf5a 100644
--- a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccTagTableEntry.cs
+++ b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccTagTableEntry.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
 // Licensed under the Six Labors Split License.
 
 namespace SixLabors.ImageSharp.Metadata.Profiles.Icc;
@@ -49,9 +49,7 @@ public IccTagTableEntry(IccProfileTag signature, uint offset, uint dataSize)
     /// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
     /// </returns>
     public static bool operator ==(IccTagTableEntry left, IccTagTableEntry right)
-    {
-        return left.Equals(right);
-    }
+        => left.Equals(right);
 
     /// <summary>
     /// Compares two <see cref="IccTagTableEntry"/> objects for equality.
@@ -62,9 +60,7 @@ public IccTagTableEntry(IccProfileTag signature, uint offset, uint dataSize)
     /// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
     /// </returns>
     public static bool operator !=(IccTagTableEntry left, IccTagTableEntry right)
-    {
-        return !left.Equals(right);
-    }
+        => !left.Equals(right);
 
     /// <inheritdoc/>
     public override bool Equals(object? obj) => obj is IccTagTableEntry other && this.Equals(other);
diff --git a/src/ImageSharp/PixelFormats/IPixel.cs b/src/ImageSharp/PixelFormats/IPixel.cs
index adf386614d..528b3e76d4 100644
--- a/src/ImageSharp/PixelFormats/IPixel.cs
+++ b/src/ImageSharp/PixelFormats/IPixel.cs
@@ -23,7 +23,8 @@ public interface IPixel<TSelf> : IPixel, IEquatable<TSelf>
     static abstract PixelOperations<TSelf> CreatePixelOperations();
 
     /// <summary>
-    /// Initializes the pixel instance from a generic scaled <see cref="Vector4"/>.
+    /// Initializes the pixel instance from a generic a generic ("scaled") <see cref="Vector4"/> representation
+    /// with values scaled and clamped between <value>0</value> and <value>1</value>
     /// </summary>
     /// <param name="source">The vector to load the pixel from.</param>
     /// <returns>The <typeparamref name="TSelf"/>.</returns>
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs
index 0aa7bad237..b03a54c585 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs
@@ -61,7 +61,8 @@ public Rgb24(byte r, byte g, byte b)
     /// <param name="color">The instance of <see cref="Rgb"/> to convert.</param>
     /// <returns>An instance of <see cref="Rgb24"/>.</returns>
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public static implicit operator Rgb24(Rgb color) => FromScaledVector4(new Vector4(color.ToVector3(), 1f));
+    public static implicit operator Rgb24(Rgb color)
+        => FromScaledVector4(new Vector4(color.ToScaledVector3(), 1F));
 
     /// <summary>
     /// Compares two <see cref="Rgb24"/> objects for equality.
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs
index 0491553430..507d6d70b6 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs
@@ -187,7 +187,7 @@ public uint PackedValue
     /// <param name="color">The instance of <see cref="Rgb"/> to convert.</param>
     /// <returns>An instance of <see cref="Rgba32"/>.</returns>
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public static implicit operator Rgba32(Rgb color) => FromScaledVector4(new Vector4(color.ToVector3(), 1F));
+    public static implicit operator Rgba32(Rgb color) => FromScaledVector4(new Vector4(color.ToScaledVector3(), 1F));
 
     /// <summary>
     /// Compares two <see cref="Rgba32"/> objects for equality.
diff --git a/tests/ImageSharp.Benchmarks/Color/RgbWorkingSpaceAdapt.cs b/tests/ImageSharp.Benchmarks/Color/RgbWorkingSpaceAdapt.cs
index 6cd8df3fc7..b847e3ac54 100644
--- a/tests/ImageSharp.Benchmarks/Color/RgbWorkingSpaceAdapt.cs
+++ b/tests/ImageSharp.Benchmarks/Color/RgbWorkingSpaceAdapt.cs
@@ -13,7 +13,7 @@ public class RgbWorkingSpaceAdapt
 
     private static readonly RGBColor RGBColor = new(0.206162, 0.260277, 0.746717);
 
-    private static readonly ColorProfileConverter ColorProfileConverter = new(new ColorConversionOptions { RgbWorkingSpace = KnownRgbWorkingSpaces.WideGamutRgb, TargetRgbWorkingSpace = KnownRgbWorkingSpaces.SRgb });
+    private static readonly ColorProfileConverter ColorProfileConverter = new(new ColorConversionOptions { SourceRgbWorkingSpace = KnownRgbWorkingSpaces.WideGamutRgb, TargetRgbWorkingSpace = KnownRgbWorkingSpaces.SRgb });
 
     private static readonly IColorConverter<RGBColor, RGBColor> ColourfulConverter = new ConverterBuilder().FromRGB(RGBWorkingSpaces.WideGamutRGB).ToRGB(RGBWorkingSpaces.sRGB).Build();
 
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieLabAndCieLchConversionTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieLabAndCieLchConversionTests.cs
index 9a894c7760..d6e3738952 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieLabAndCieLchConversionTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieLabAndCieLchConversionTests.cs
@@ -12,6 +12,7 @@ namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 /// Test data generated using:
 /// <see href="http://www.brucelindbloom.com/index.html?ColorCalculator.html"/>
 /// </remarks>
+[Trait("Color", "Conversion")]
 public class CieLabAndCieLchConversionTests
 {
     private static readonly ApproximateColorProfileComparer Comparer = new(.0001f);
@@ -30,7 +31,7 @@ public void Convert_Lch_to_Lab(float l, float c, float h, float l2, float a, flo
         // Arrange
         CieLch input = new(l, c, h);
         CieLab expected = new(l2, a, b);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D50, TargetWhitePoint = KnownIlluminants.D50 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D50, TargetWhitePoint = KnownIlluminants.D50 };
         ColorProfileConverter converter = new(options);
 
         Span<CieLch> inputSpan = new CieLch[5];
@@ -65,7 +66,7 @@ public void Convert_Lab_to_Lch(float l, float a, float b, float l2, float c, flo
         // Arrange
         CieLab input = new(l, a, b);
         CieLch expected = new(l2, c, h);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D50, TargetWhitePoint = KnownIlluminants.D50 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D50, TargetWhitePoint = KnownIlluminants.D50 };
         ColorProfileConverter converter = new(options);
 
         Span<CieLab> inputSpan = new CieLab[5];
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieLabAndCieLchuvConversionTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieLabAndCieLchuvConversionTests.cs
index 4b1b5e1a56..73fa7128fa 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieLabAndCieLchuvConversionTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieLabAndCieLchuvConversionTests.cs
@@ -24,7 +24,7 @@ public void Convert_Lchuv_To_Lab(float l, float c, float h, float l2, float a, f
         // Arrange
         CieLchuv input = new(l, c, h);
         CieLab expected = new(l2, a, b);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D50 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D50 };
         ColorProfileConverter converter = new(options);
 
         Span<CieLchuv> inputSpan = new CieLchuv[5];
@@ -53,7 +53,7 @@ public void Convert_Lab_To_Lchuv(float l, float a, float b, float l2, float c, f
         // Arrange
         CieLab input = new(l, a, b);
         CieLchuv expected = new(l2, c, h);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D50, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D50, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<CieLab> inputSpan = new CieLab[5];
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieLabAndCieLuvConversionTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieLabAndCieLuvConversionTests.cs
index 44756c779a..0846bdda3f 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieLabAndCieLuvConversionTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieLabAndCieLuvConversionTests.cs
@@ -24,7 +24,7 @@ public void Convert_CieLuv_To_CieLab(float l, float u, float v, float l2, float
         // Arrange
         CieLuv input = new(l, u, v);
         CieLab expected = new(l2, a, b);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D50 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D50 };
         ColorProfileConverter converter = new(options);
 
         Span<CieLuv> inputSpan = new CieLuv[5];
@@ -53,7 +53,7 @@ public void Convert_CieLab_To_CieLuv(float l, float a, float b, float l2, float
         // Arrange
         CieLab input = new(l, a, b);
         CieLuv expected = new(l2, u, v);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D50, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D50, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<CieLab> inputSpan = new CieLab[5];
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieLabTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieLabTests.cs
index 3c015259b1..69fabc7508 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieLabTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieLabTests.cs
@@ -9,6 +9,7 @@ namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 /// <summary>
 /// Tests the <see cref="CieLab"/> struct.
 /// </summary>
+[Trait("Color", "Conversion")]
 public class CieLabTests
 {
     [Fact]
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieLchAndCieLuvConversionTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieLchAndCieLuvConversionTests.cs
index 598d4af335..12313281fa 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieLchAndCieLuvConversionTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieLchAndCieLuvConversionTests.cs
@@ -20,7 +20,7 @@ public void Convert_CieLch_to_CieLuv(float l, float c, float h, float l2, float
         // Arrange
         CieLch input = new(l, c, h);
         CieLuv expected = new(l2, u, v);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D50, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D50, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<CieLch> inputSpan = new CieLch[5];
@@ -48,7 +48,7 @@ public void Convert_CieLuv_to_CieLch(float l2, float u, float v, float l, float
         // Arrange
         CieLuv input = new(l2, u, v);
         CieLch expected = new(l, c, h);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D50 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D50 };
         ColorProfileConverter converter = new(options);
 
         Span<CieLuv> inputSpan = new CieLuv[5];
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieLchuvAndCieLchConversionTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieLchuvAndCieLchConversionTests.cs
index a3e0b45e0d..857bdb3da1 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieLchuvAndCieLchConversionTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieLchuvAndCieLchConversionTests.cs
@@ -20,7 +20,7 @@ public void Convert_CieLch_To_CieLchuv(float l2, float c2, float h2, float l, fl
         // Arrange
         CieLch input = new(l2, c2, h2);
         CieLchuv expected = new(l, c, h);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D50, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D50, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<CieLch> inputSpan = new CieLch[5];
@@ -48,7 +48,7 @@ public void Convert_CieLchuv_To_CieLch(float l, float c, float h, float l2, floa
         // Arrange
         CieLchuv input = new(l, c, h);
         CieLch expected = new(l2, c2, h2);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D50 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D50 };
         ColorProfileConverter converter = new(options);
 
         Span<CieLchuv> inputSpan = new CieLchuv[5];
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieLchuvAndCieLuvConversionTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieLchuvAndCieLuvConversionTests.cs
index 465237490d..424cb8cc77 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieLchuvAndCieLuvConversionTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieLchuvAndCieLuvConversionTests.cs
@@ -12,6 +12,7 @@ namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 /// Test data generated using:
 /// <see href="http://www.brucelindbloom.com/index.html?ColorCalculator.html"/>
 /// </remarks>
+[Trait("Color", "Conversion")]
 public class CieLchuvAndCieLuvConversionTests
 {
     private static readonly ApproximateColorProfileComparer Comparer = new(.0001F);
@@ -30,7 +31,7 @@ public void Convert_CieLchuv_to_CieLuv(float l, float c, float h, float l2, floa
         // Arrange
         CieLchuv input = new(l, c, h);
         CieLuv expected = new(l2, u, v);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<CieLchuv> inputSpan = new CieLchuv[5];
@@ -66,7 +67,7 @@ public void Convert_CieLuv_to_CieLchuv(float l, float u, float v, float l2, floa
         // Arrange
         CieLuv input = new(l, u, v);
         CieLchuv expected = new(l2, c, h);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<CieLuv> inputSpan = new CieLuv[5];
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieLchuvAndCmykConversionTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieLchuvAndCmykConversionTests.cs
index 60ac3da16e..3c8a93ee12 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieLchuvAndCmykConversionTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieLchuvAndCmykConversionTests.cs
@@ -20,7 +20,7 @@ public void Convert_Cmyk_to_CieLchuv(float c2, float m, float y, float k, float
         // Arrange
         Cmyk input = new(c2, m, y, k);
         CieLchuv expected = new(l, c, h);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<Cmyk> inputSpan = new Cmyk[5];
@@ -49,7 +49,7 @@ public void Convert_CieLchuv_to_Cmyk(float l, float c, float h, float c2, float
         // Arrange
         CieLchuv input = new(l, c, h);
         Cmyk expected = new(c2, m, y, k);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<CieLchuv> inputSpan = new CieLchuv[5];
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieLchuvTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieLchuvTests.cs
index 0b737cdfca..3fe550a5ba 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieLchuvTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieLchuvTests.cs
@@ -9,6 +9,7 @@ namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 /// <summary>
 /// Tests the <see cref="CieLchuv"/> struct.
 /// </summary>
+[Trait("Color", "Conversion")]
 public class CieLchuvTests
 {
     [Fact]
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndCieXyyConversionTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndCieXyyConversionTests.cs
index e73edcda7c..08e73a1a71 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndCieXyyConversionTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndCieXyyConversionTests.cs
@@ -20,7 +20,7 @@ public void Convert_CieLuv_to_CieXyy(float l, float u, float v, float x, float y
         // Arrange
         CieLuv input = new(l, u, v);
         CieXyy expected = new(x, y, yl);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<CieLuv> inputSpan = new CieLuv[5];
@@ -49,7 +49,7 @@ public void Convert_CieXyy_to_CieLuv(float x, float y, float yl, float l, float
         // Arrange
         CieXyy input = new(x, y, yl);
         CieLuv expected = new(l, u, v);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<CieXyy> inputSpan = new CieXyy[5];
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndHslConversionTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndHslConversionTests.cs
index b178b22b20..bfcd236c75 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndHslConversionTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndHslConversionTests.cs
@@ -20,7 +20,7 @@ public void Convert_CieLuv_to_Hsl(float l, float u, float v, float h, float s, f
         // Arrange
         CieLuv input = new(l, u, v);
         Hsl expected = new(h, s, l2);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<CieLuv> inputSpan = new CieLuv[5];
@@ -49,7 +49,7 @@ public void Convert_Hsl_to_CieLuv(float h, float s, float l2, float l, float u,
         // Arrange
         Hsl input = new(h, s, l2);
         CieLuv expected = new(l, u, v);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<Hsl> inputSpan = new Hsl[5];
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndHsvConversionTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndHsvConversionTests.cs
index 2866093377..8a25f95b7b 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndHsvConversionTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndHsvConversionTests.cs
@@ -20,7 +20,7 @@ public void Convert_CieLuv_to_Hsv(float l, float u, float v, float h, float s, f
         // Arrange
         CieLuv input = new(l, u, v);
         Hsv expected = new(h, s, v2);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<CieLuv> inputSpan = new CieLuv[5];
@@ -49,7 +49,7 @@ public void Convert_Hsv_to_CieLuv(float h, float s, float v2, float l, float u,
         // Arrange
         Hsv input = new(h, s, v2);
         CieLuv expected = new(l, u, v);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<Hsv> inputSpan = new Hsv[5];
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndHunterLabConversionTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndHunterLabConversionTests.cs
index 73b605fb62..1c667f6794 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndHunterLabConversionTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndHunterLabConversionTests.cs
@@ -20,7 +20,7 @@ public void Convert_CieLuv_To_HunterLab(float l, float u, float v, float l2, flo
         // Arrange
         CieLuv input = new(l, u, v);
         HunterLab expected = new(l2, a, b);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D50 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D50 };
         ColorProfileConverter converter = new(options);
 
         Span<CieLuv> inputSpan = new CieLuv[5];
@@ -49,7 +49,7 @@ public void Convert_HunterLab_To_CieLuv(float l2, float a, float b, float l, flo
         // Arrange
         HunterLab input = new(l2, a, b);
         CieLuv expected = new(l, u, v);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D50, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D50, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<HunterLab> inputSpan = new HunterLab[5];
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndLmsConversionTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndLmsConversionTests.cs
index 812ca44ddc..812b2b61e5 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndLmsConversionTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndLmsConversionTests.cs
@@ -20,7 +20,7 @@ public void Convert_CieLuv_to_Lms(float l, float u, float v, float l2, float m,
         // Arrange
         CieLuv input = new(l, u, v);
         Lms expected = new(l2, m, s);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<CieLuv> inputSpan = new CieLuv[5];
@@ -49,7 +49,7 @@ public void Convert_Lms_to_CieLuv(float l2, float m, float s, float l, float u,
         // Arrange
         Lms input = new(l2, m, s);
         CieLuv expected = new(l, u, v);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<Lms> inputSpan = new Lms[5];
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndRgbConversionTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndRgbConversionTests.cs
index f1da6e33fd..1af802326e 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndRgbConversionTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndRgbConversionTests.cs
@@ -20,7 +20,7 @@ public void Convert_CieLuv_to_Rgb(float l, float u, float v, float r, float g, f
         // Arrange
         CieLuv input = new(l, u, v);
         Rgb expected = new(r, g, b);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<CieLuv> inputSpan = new CieLuv[5];
@@ -49,7 +49,7 @@ public void Convert_Rgb_to_CieLuv(float r, float g, float b, float l, float u, f
         // Arrange
         Rgb input = new(r, g, b);
         CieLuv expected = new(l, u, v);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<Rgb> inputSpan = new Rgb[5];
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndYCbCrConversionTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndYCbCrConversionTests.cs
index fa7e2ece3f..0d5dd60e61 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndYCbCrConversionTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndYCbCrConversionTests.cs
@@ -20,7 +20,7 @@ public void Convert_CieLuv_to_YCbCr(float l, float u, float v, float y, float cb
         // Arrange
         CieLuv input = new(l, u, v);
         YCbCr expected = new(y, cb, cr);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<CieLuv> inputSpan = new CieLuv[5];
@@ -49,7 +49,7 @@ public void Convert_YCbCr_to_CieLuv(float y, float cb, float cr, float l, float
         // Arrange
         YCbCr input = new(y, cb, cr);
         CieLuv expected = new(l, u, v);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<YCbCr> inputSpan = new YCbCr[5];
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieLuvTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieLuvTests.cs
index db903a0bf5..173491081d 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieLuvTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieLuvTests.cs
@@ -9,6 +9,7 @@ namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 /// <summary>
 /// Tests the <see cref="CieLuv"/> struct.
 /// </summary>
+[Trait("Color", "Conversion")]
 public class CieLuvTests
 {
     [Fact]
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieXyChromaticityCoordinatesTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieXyChromaticityCoordinatesTests.cs
index a85a08a21e..8bc71f1e18 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieXyChromaticityCoordinatesTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieXyChromaticityCoordinatesTests.cs
@@ -8,6 +8,7 @@ namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 /// <summary>
 /// Tests the <see cref="CieXyChromaticityCoordinates"/> struct.
 /// </summary>
+[Trait("Color", "Conversion")]
 public class CieXyChromaticityCoordinatesTests
 {
     [Fact]
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieXyyTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieXyyTests.cs
index 245512f8a8..80904c5df1 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieXyyTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieXyyTests.cs
@@ -9,6 +9,7 @@ namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 /// <summary>
 /// Tests the <see cref="CieXyy"/> struct.
 /// </summary>
+[Trait("Color", "Conversion")]
 public class CieXyyTests
 {
     [Fact]
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieXyzAndCieLabConversionTest.cs b/tests/ImageSharp.Tests/ColorProfiles/CieXyzAndCieLabConversionTest.cs
index cb4d028895..76fceec413 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieXyzAndCieLabConversionTest.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieXyzAndCieLabConversionTest.cs
@@ -12,6 +12,7 @@ namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 /// Test data generated using:
 /// <see href="http://www.brucelindbloom.com/index.html?ColorCalculator.html"/>
 /// </remarks>
+[Trait("Color", "Conversion")]
 public class CieXyzAndCieLabConversionTest
 {
     private static readonly ApproximateColorProfileComparer Comparer = new(.0001f);
@@ -29,7 +30,7 @@ public void Convert_Lab_to_Xyz(float l, float a, float b, float x, float y, floa
     {
         // Arrange
         CieLab input = new(l, a, b);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
         CieXyz expected = new(x, y, z);
 
@@ -62,7 +63,7 @@ public void Convert_Xyz_to_Lab(float x, float y, float z, float l, float a, floa
     {
         // Arrange
         CieXyz input = new(x, y, z);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
         CieLab expected = new(l, a, b);
 
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieXyzAndCieLuvConversionTest.cs b/tests/ImageSharp.Tests/ColorProfiles/CieXyzAndCieLuvConversionTest.cs
index 944b990054..b269818ae8 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieXyzAndCieLuvConversionTest.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieXyzAndCieLuvConversionTest.cs
@@ -29,7 +29,7 @@ public void Convert_Xyz_To_Luv(float x, float y, float z, float l, float u, floa
         CieXyz input = new(x, y, z);
         CieLuv expected = new(l, u, v);
 
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<CieXyz> inputSpan = new CieXyz[5];
@@ -64,7 +64,7 @@ public void Convert_Luv_To_Xyz(float l, float u, float v, float x, float y, floa
         CieLuv input = new(l, u, v);
         CieXyz expected = new(x, y, z);
 
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetWhitePoint = KnownIlluminants.D65 };
         ColorProfileConverter converter = new(options);
 
         Span<CieLuv> inputSpan = new CieLuv[5];
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieXyzAndCieXyyConversionTest.cs b/tests/ImageSharp.Tests/ColorProfiles/CieXyzAndCieXyyConversionTest.cs
index 7b1d0ac781..48bb6c1e16 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieXyzAndCieXyyConversionTest.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieXyzAndCieXyyConversionTest.cs
@@ -12,6 +12,7 @@ namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 /// Test data generated using:
 /// <see href="http://www.brucelindbloom.com/index.html?ColorCalculator.html"/>
 /// </remarks>
+[Trait("Color", "Conversion")]
 public class CieXyzAndCieXyyConversionTest
 {
     private static readonly ApproximateColorProfileComparer Comparer = new(.0001F);
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieXyzAndLmsConversionTest.cs b/tests/ImageSharp.Tests/ColorProfiles/CieXyzAndLmsConversionTest.cs
index 185fcd256c..c7898904da 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieXyzAndLmsConversionTest.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieXyzAndLmsConversionTest.cs
@@ -11,6 +11,7 @@ namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 /// <remarks>
 /// Test data generated using original colorful library.
 /// </remarks>
+[Trait("Color", "Conversion")]
 public class CieXyzAndLmsConversionTest
 {
     private static readonly ApproximateColorProfileComparer Comparer = new(.0001f);
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieXyzTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieXyzTests.cs
index 88138304a8..683b3b6611 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieXyzTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieXyzTests.cs
@@ -9,6 +9,7 @@ namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 /// <summary>
 /// Tests the <see cref="CieXyz"/> struct.
 /// </summary>
+[Trait("Color", "Conversion")]
 public class CieXyzTests
 {
     [Fact]
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CmykTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CmykTests.cs
index e2044a75d0..22b7a7f70c 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CmykTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CmykTests.cs
@@ -9,6 +9,7 @@ namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 /// <summary>
 /// Tests the <see cref="Cmyk"/> struct.
 /// </summary>
+[Trait("Color", "Conversion")]
 public class CmykTests
 {
     [Fact]
diff --git a/tests/ImageSharp.Tests/ColorProfiles/ColorProfileConverterChomaticAdaptationTests.cs b/tests/ImageSharp.Tests/ColorProfiles/ColorProfileConverterChomaticAdaptationTests.cs
index a90e5b9e86..525220d8e0 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/ColorProfileConverterChomaticAdaptationTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/ColorProfileConverterChomaticAdaptationTests.cs
@@ -26,7 +26,7 @@ public void Adapt_RGB_WideGamutRGB_To_sRGB(float r1, float g1, float b1, float r
         Rgb expected = new(r2, g2, b2);
         ColorConversionOptions options = new()
         {
-            RgbWorkingSpace = KnownRgbWorkingSpaces.WideGamutRgb,
+            SourceRgbWorkingSpace = KnownRgbWorkingSpaces.WideGamutRgb,
             TargetRgbWorkingSpace = KnownRgbWorkingSpaces.SRgb
         };
         ColorProfileConverter converter = new(options);
@@ -49,7 +49,7 @@ public void Adapt_RGB_SRGB_To_WideGamutRGB(float r1, float g1, float b1, float r
         Rgb expected = new(r2, g2, b2);
         ColorConversionOptions options = new()
         {
-            RgbWorkingSpace = KnownRgbWorkingSpaces.SRgb,
+            SourceRgbWorkingSpace = KnownRgbWorkingSpaces.SRgb,
             TargetRgbWorkingSpace = KnownRgbWorkingSpaces.WideGamutRgb
         };
         ColorProfileConverter converter = new(options);
@@ -71,7 +71,7 @@ public void Adapt_Lab_D65_To_D50(float l1, float a1, float b1, float l2, float a
         CieLab expected = new(l2, a2, b2);
         ColorConversionOptions options = new()
         {
-            WhitePoint = KnownIlluminants.D65,
+            SourceWhitePoint = KnownIlluminants.D65,
             TargetWhitePoint = KnownIlluminants.D50
         };
         ColorProfileConverter converter = new(options);
@@ -93,7 +93,7 @@ public void Adapt_Xyz_D65_To_D50_Bradford(float x1, float y1, float z1, float x2
         CieXyz expected = new(x2, y2, z2);
         ColorConversionOptions options = new()
         {
-            WhitePoint = KnownIlluminants.D65,
+            SourceWhitePoint = KnownIlluminants.D65,
             TargetWhitePoint = KnownIlluminants.D50,
             AdaptationMatrix = KnownChromaticAdaptationMatrices.Bradford
         };
@@ -117,7 +117,7 @@ public void Adapt_Xyz_D65_To_D50_XyzScaling(float x1, float y1, float z1, float
         CieXyz expected = new(x2, y2, z2);
         ColorConversionOptions options = new()
         {
-            WhitePoint = KnownIlluminants.D65,
+            SourceWhitePoint = KnownIlluminants.D65,
             TargetWhitePoint = KnownIlluminants.D50,
             AdaptationMatrix = KnownChromaticAdaptationMatrices.XyzScaling
         };
@@ -141,7 +141,7 @@ public void Adapt_HunterLab_D65_To_D50(float l1, float a1, float b1, float l2, f
         HunterLab expected = new(l2, a2, b2);
         ColorConversionOptions options = new()
         {
-            WhitePoint = KnownIlluminants.D65,
+            SourceWhitePoint = KnownIlluminants.D65,
             TargetWhitePoint = KnownIlluminants.D50,
         };
 
@@ -164,7 +164,7 @@ public void Adapt_CieLchuv_D65_To_D50_XyzScaling(float l1, float c1, float h1, f
         CieLchuv expected = new(l2, c2, h2);
         ColorConversionOptions options = new()
         {
-            WhitePoint = KnownIlluminants.D65,
+            SourceWhitePoint = KnownIlluminants.D65,
             TargetWhitePoint = KnownIlluminants.D50,
             AdaptationMatrix = KnownChromaticAdaptationMatrices.XyzScaling
         };
@@ -187,7 +187,7 @@ public void Adapt_CieLch_D65_To_D50_XyzScaling(float l1, float c1, float h1, flo
         CieLch expected = new(l2, c2, h2);
         ColorConversionOptions options = new()
         {
-            WhitePoint = KnownIlluminants.D65,
+            SourceWhitePoint = KnownIlluminants.D65,
             TargetWhitePoint = KnownIlluminants.D50,
             AdaptationMatrix = KnownChromaticAdaptationMatrices.XyzScaling
         };
diff --git a/tests/ImageSharp.Tests/ColorProfiles/HslTests.cs b/tests/ImageSharp.Tests/ColorProfiles/HslTests.cs
index d18e65117e..6697cbfde2 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/HslTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/HslTests.cs
@@ -9,6 +9,7 @@ namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 /// <summary>
 /// Tests the <see cref="Hsl"/> struct.
 /// </summary>
+[Trait("Color", "Conversion")]
 public class HslTests
 {
     [Fact]
diff --git a/tests/ImageSharp.Tests/ColorProfiles/HsvTests.cs b/tests/ImageSharp.Tests/ColorProfiles/HsvTests.cs
index 46f58b18e2..dd71fcd3ff 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/HsvTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/HsvTests.cs
@@ -9,6 +9,7 @@ namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 /// <summary>
 /// Tests the <see cref="Hsv"/> struct.
 /// </summary>
+[Trait("Color", "Conversion")]
 public class HsvTests
 {
     [Fact]
diff --git a/tests/ImageSharp.Tests/ColorProfiles/HunterLabTests.cs b/tests/ImageSharp.Tests/ColorProfiles/HunterLabTests.cs
index 5fbdd0788f..af06b3c91f 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/HunterLabTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/HunterLabTests.cs
@@ -9,6 +9,7 @@ namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 /// <summary>
 /// Tests the <see cref="HunterLab"/> struct.
 /// </summary>
+[Trait("Color", "Conversion")]
 public class HunterLabTests
 {
     [Fact]
diff --git a/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/ClutCalculatorTests.cs b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/ClutCalculatorTests.cs
new file mode 100644
index 0000000000..249e7f4ed1
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/ClutCalculatorTests.cs
@@ -0,0 +1,27 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Numerics;
+using SixLabors.ImageSharp.ColorProfiles.Icc.Calculators;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc.Conversion;
+
+namespace SixLabors.ImageSharp.Tests.ColorProfiles.Icc.Calculators;
+
+/// <summary>
+/// Tests ICC <see cref="ClutCalculator"/>
+/// </summary>
+[Trait("Color", "Conversion")]
+public class ClutCalculatorTests
+{
+    [Theory]
+    [MemberData(nameof(IccConversionDataClut.ClutConversionTestData), MemberType = typeof(IccConversionDataClut))]
+    internal void ClutCalculator_WithClut_ReturnsResult(IccClut lut, Vector4 input, Vector4 expected)
+    {
+        ClutCalculator calculator = new(lut);
+
+        Vector4 result = calculator.Calculate(input);
+
+        VectorAssert.Equal(expected, result, 4);
+    }
+}
diff --git a/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/CurveCalculatorTests.cs b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/CurveCalculatorTests.cs
new file mode 100644
index 0000000000..0608637619
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/CurveCalculatorTests.cs
@@ -0,0 +1,26 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc.Conversion;
+
+namespace SixLabors.ImageSharp.Tests.ColorProfiles.Icc.Calculators;
+
+/// <summary>
+/// Tests ICC <see cref="CurveCalculator"/>
+/// </summary>
+[Trait("Color", "Conversion")]
+public class CurveCalculatorTests
+{
+    [Theory]
+    [MemberData(nameof(IccConversionDataTrc.CurveConversionTestData), MemberType = typeof(IccConversionDataTrc))]
+    internal void CurveCalculator_WithCurveEntry_ReturnsResult(IccCurveTagDataEntry curve, bool inverted, float input, float expected)
+    {
+        CurveCalculator calculator = new(curve, inverted);
+
+        float result = calculator.Calculate(input);
+
+        Assert.Equal(expected, result, 4f);
+    }
+}
diff --git a/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/LutABCalculatorTests.cs b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/LutABCalculatorTests.cs
new file mode 100644
index 0000000000..5be984b4b9
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/LutABCalculatorTests.cs
@@ -0,0 +1,39 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Numerics;
+using SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc.Conversion;
+
+namespace SixLabors.ImageSharp.Tests.ColorProfiles.Icc.Calculators
+{
+    /// <summary>
+    /// Tests ICC <see cref="LutABCalculator"/>
+    /// </summary>
+    [Trait("Color", "Conversion")]
+    public class LutABCalculatorTests
+    {
+        [Theory]
+        [MemberData(nameof(IccConversionDataLutAB.LutAToBConversionTestData), MemberType = typeof(IccConversionDataLutAB))]
+        internal void LutABCalculator_WithLutAToB_ReturnsResult(IccLutAToBTagDataEntry lut, Vector4 input, Vector4 expected)
+        {
+            LutABCalculator calculator = new(lut);
+
+            Vector4 result = calculator.Calculate(input);
+
+            VectorAssert.Equal(expected, result, 4);
+        }
+
+        [Theory]
+        [MemberData(nameof(IccConversionDataLutAB.LutBToAConversionTestData), MemberType = typeof(IccConversionDataLutAB))]
+        internal void LutABCalculator_WithLutBToA_ReturnsResult(IccLutBToATagDataEntry lut, Vector4 input, Vector4 expected)
+        {
+            LutABCalculator calculator = new(lut);
+
+            Vector4 result = calculator.Calculate(input);
+
+            VectorAssert.Equal(expected, result, 4);
+        }
+    }
+}
diff --git a/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/LutCalculatorTests.cs b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/LutCalculatorTests.cs
new file mode 100644
index 0000000000..d5d2736f71
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/LutCalculatorTests.cs
@@ -0,0 +1,26 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using SixLabors.ImageSharp.ColorProfiles.Icc.Calculators;
+using SixLabors.ImageSharp.Tests.TestDataIcc.Conversion;
+
+namespace SixLabors.ImageSharp.Tests.ColorProfiles.Icc.Calculators
+{
+    /// <summary>
+    /// Tests ICC <see cref="LutCalculator"/>
+    /// </summary>
+    [Trait("Color", "Conversion")]
+    public class LutCalculatorTests
+    {
+        [Theory]
+        [MemberData(nameof(IccConversionDataLut.LutConversionTestData), MemberType = typeof(IccConversionDataLut))]
+        internal void LutCalculator_WithLut_ReturnsResult(float[] lut, bool inverted, float input, float expected)
+        {
+            LutCalculator calculator = new(lut, inverted);
+
+            float result = calculator.Calculate(input);
+
+            Assert.Equal(expected, result, 4f);
+        }
+    }
+}
diff --git a/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/LutEntryCalculatorTests.cs b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/LutEntryCalculatorTests.cs
new file mode 100644
index 0000000000..0493521140
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/LutEntryCalculatorTests.cs
@@ -0,0 +1,39 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Numerics;
+using SixLabors.ImageSharp.ColorProfiles.Icc.Calculators;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc.Conversion;
+
+namespace SixLabors.ImageSharp.Tests.ColorProfiles.Icc.Calculators
+{
+    /// <summary>
+    /// Tests ICC <see cref="LutEntryCalculator"/>
+    /// </summary>
+    [Trait("Color", "Conversion")]
+    public class LutEntryCalculatorTests
+    {
+        [Theory]
+        [MemberData(nameof(IccConversionDataLutEntry.Lut8ConversionTestData), MemberType = typeof(IccConversionDataLutEntry))]
+        internal void LutEntryCalculator_WithLut8_ReturnsResult(IccLut8TagDataEntry lut, Vector4 input, Vector4 expected)
+        {
+            LutEntryCalculator calculator = new(lut);
+
+            Vector4 result = calculator.Calculate(input);
+
+            VectorAssert.Equal(expected, result, 4);
+        }
+
+        [Theory]
+        [MemberData(nameof(IccConversionDataLutEntry.Lut16ConversionTestData), MemberType = typeof(IccConversionDataLutEntry))]
+        internal void LutEntryCalculator_WithLut16_ReturnsResult(IccLut16TagDataEntry lut, Vector4 input, Vector4 expected)
+        {
+            LutEntryCalculator calculator = new(lut);
+
+            Vector4 result = calculator.Calculate(input);
+
+            VectorAssert.Equal(expected, result, 4);
+        }
+    }
+}
diff --git a/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/MatrixCalculatorTests.cs b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/MatrixCalculatorTests.cs
new file mode 100644
index 0000000000..22b25b84d1
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/MatrixCalculatorTests.cs
@@ -0,0 +1,27 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Numerics;
+using SixLabors.ImageSharp.ColorProfiles.Icc.Calculators;
+using SixLabors.ImageSharp.Tests.TestDataIcc.Conversion;
+
+namespace SixLabors.ImageSharp.Tests.ColorProfiles.Icc.Calculators
+{
+    /// <summary>
+    /// Tests ICC <see cref="MatrixCalculator"/>
+    /// </summary>
+    [Trait("Color", "Conversion")]
+    public class MatrixCalculatorTests
+    {
+        [Theory]
+        [MemberData(nameof(IccConversionDataMatrix.MatrixConversionTestData), MemberType = typeof(IccConversionDataMatrix))]
+        internal void MatrixCalculator_WithMatrix_ReturnsResult(Matrix4x4 matrix2D, Vector3 matrix1D, Vector4 input, Vector4 expected)
+        {
+            MatrixCalculator calculator = new(matrix2D, matrix1D);
+
+            Vector4 result = calculator.Calculate(input);
+
+            VectorAssert.Equal(expected, result, 4);
+        }
+    }
+}
diff --git a/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/ParametricCurveCalculatorTests.cs b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/ParametricCurveCalculatorTests.cs
new file mode 100644
index 0000000000..ca3608b8cf
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/ParametricCurveCalculatorTests.cs
@@ -0,0 +1,27 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using SixLabors.ImageSharp.ColorProfiles.Icc.Calculators;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc.Conversion;
+
+namespace SixLabors.ImageSharp.Tests.ColorProfiles.Icc.Calculators
+{
+    /// <summary>
+    /// Tests ICC <see cref="ParametricCurveCalculator"/>
+    /// </summary>
+    [Trait("Color", "Conversion")]
+    public class ParametricCurveCalculatorTests
+    {
+        [Theory]
+        [MemberData(nameof(IccConversionDataTrc.ParametricCurveConversionTestData), MemberType = typeof(IccConversionDataTrc))]
+        internal void ParametricCurveCalculator_WithCurveEntry_ReturnsResult(IccParametricCurveTagDataEntry curve, bool inverted, float input, float expected)
+        {
+            ParametricCurveCalculator calculator = new(curve, inverted);
+
+            float result = calculator.Calculate(input);
+
+            Assert.Equal(expected, result, 4f);
+        }
+    }
+}
diff --git a/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/TrcCalculatorTests.cs b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/TrcCalculatorTests.cs
new file mode 100644
index 0000000000..d86e32453d
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/TrcCalculatorTests.cs
@@ -0,0 +1,28 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Numerics;
+using SixLabors.ImageSharp.ColorProfiles.Icc.Calculators;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc.Conversion;
+
+namespace SixLabors.ImageSharp.Tests.ColorProfiles.Icc.Calculators
+{
+    /// <summary>
+    /// Tests ICC <see cref="TrcCalculator"/>
+    /// </summary>
+    [Trait("Color", "Conversion")]
+    public class TrcCalculatorTests
+    {
+        [Theory]
+        [MemberData(nameof(IccConversionDataTrc.TrcArrayConversionTestData), MemberType = typeof(IccConversionDataTrc))]
+        internal void TrcCalculator_WithCurvesArray_ReturnsResult(IccTagDataEntry[] entries, bool inverted, Vector4 input, Vector4 expected)
+        {
+            TrcCalculator calculator = new(entries, inverted);
+
+            Vector4 result = calculator.Calculate(input);
+
+            VectorAssert.Equal(expected, result, 4);
+        }
+    }
+}
diff --git a/tests/ImageSharp.Tests/ColorProfiles/Icc/ColorProfileConverterTests.Icc.cs b/tests/ImageSharp.Tests/ColorProfiles/Icc/ColorProfileConverterTests.Icc.cs
new file mode 100644
index 0000000000..b8564a3489
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/Icc/ColorProfileConverterTests.Icc.cs
@@ -0,0 +1,156 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Numerics;
+using SixLabors.ImageSharp.ColorProfiles;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using Wacton.Unicolour;
+using Wacton.Unicolour.Icc;
+using Xunit.Abstractions;
+using Rgb = SixLabors.ImageSharp.ColorProfiles.Rgb;
+
+namespace SixLabors.ImageSharp.Tests.ColorProfiles.Icc;
+
+public class ColorProfileConverterTests(ITestOutputHelper testOutputHelper)
+{
+    [Theory]
+    [InlineData(TestIccProfiles.Fogra39, TestIccProfiles.Fogra39)] // CMYK -> LAB -> CMYK (commonly used v2 profiles)
+    [InlineData(TestIccProfiles.Fogra39, TestIccProfiles.Swop2006)] // CMYK -> LAB -> CMYK (commonly used v2 profiles)
+    [InlineData(TestIccProfiles.Swop2006, TestIccProfiles.Fogra39)] // CMYK -> LAB -> CMYK (commonly used v2 profiles)
+    [InlineData(TestIccProfiles.Swop2006, TestIccProfiles.Swop2006)] // CMYK -> LAB -> CMYK (commonly used v2 profiles)
+    [InlineData(TestIccProfiles.Fogra39, TestIccProfiles.JapanColor2003)] // CMYK -> LAB -> CMYK (different bit depth v2 LUTs, 8-bit vs 16-bit)
+    [InlineData(TestIccProfiles.JapanColor2011, TestIccProfiles.Fogra39)] // CMYK -> LAB -> CMYK (different LUT versions, v2 vs v4)
+    [InlineData(TestIccProfiles.Fogra39, TestIccProfiles.Cgats21)] // CMYK -> LAB -> RGB (different LUT versions, v2 vs v4)
+    [InlineData(TestIccProfiles.Fogra39, TestIccProfiles.StandardRgbV4)] // RGB -> LAB -> CMYK (different LUT versions, v4 vs v2)
+    [InlineData(TestIccProfiles.StandardRgbV4, TestIccProfiles.Fogra39)] // RGB -> LAB -> XYZ -> RGB (different LUT elements, B-Matrix-M-CLUT-A vs B-Matrix-M)
+    [InlineData(TestIccProfiles.StandardRgbV4, TestIccProfiles.RommRgb)] // RGB -> XYZ -> LAB -> RGB (different LUT elements, B-Matrix-M vs B-Matrix-M-CLUT-A)
+    [InlineData(TestIccProfiles.RommRgb, TestIccProfiles.StandardRgbV4)] // CMYK -> LAB -> CMYK (different bit depth v2 LUTs, 16-bit vs 8-bit)
+    [InlineData(TestIccProfiles.Fogra39, TestIccProfiles.StandardRgbV2, 0.0005)] // CMYK -> LAB -> XYZ -> RGB (different LUT tags, A2B vs TRC) --- tolerance slightly higher due to difference in inverse curve implementation
+    [InlineData(TestIccProfiles.StandardRgbV2, TestIccProfiles.Fogra39)] // RGB -> XYZ -> LAB -> CMYK (different LUT tags, TRC vs A2B)
+    public void CanConvertIccProfiles(string sourceProfile, string targetProfile, double tolerance = 0.00005)
+    {
+        // for 3-channel spaces, 4th item is ignored
+        List<float[]> inputs =
+        [
+            [0, 0, 0, 0],
+            [1, 0, 0, 0],
+            [0, 1, 0, 0],
+            [0, 0, 1, 0],
+            [0, 0, 0, 1],
+            [1, 1, 1, 1],
+            [0.5f, 0.5f, 0.5f, 0.5f],
+            [0.199678659f, 0.67982769f, 0.805381715f, 0.982666492f], // requires clipping before source is PCS adjusted for Fogra39 -> sRGBv2
+            [0.776568174f, 0.961630166f, 0.31032759f, 0.895294666f], // requires clipping after target is PCS adjusted for Fogra39 -> sRGBv2
+            [GetNormalizedRandomValue(), GetNormalizedRandomValue(), GetNormalizedRandomValue(), GetNormalizedRandomValue()]
+        ];
+
+        foreach (float[] input in inputs)
+        {
+            double[] expectedTargetValues = GetExpectedTargetValues(sourceProfile, targetProfile, input);
+            Vector4 actualTargetValues = GetActualTargetValues(input, sourceProfile, targetProfile);
+
+            testOutputHelper.WriteLine($"Input {string.Join(", ", input)} · Expected output {string.Join(", ", expectedTargetValues)}");
+            for (int i = 0; i < expectedTargetValues.Length; i++)
+            {
+                Assert.Equal(expectedTargetValues[i], actualTargetValues[i], tolerance);
+            }
+        }
+    }
+
+    private static double[] GetExpectedTargetValues(string sourceProfile, string targetProfile, float[] input)
+    {
+        Wacton.Unicolour.Configuration sourceConfig = TestIccProfiles.GetUnicolourConfiguration(sourceProfile);
+        Wacton.Unicolour.Configuration targetConfig = TestIccProfiles.GetUnicolourConfiguration(targetProfile);
+
+        if (sourceConfig.Icc.Error != null || targetConfig.Icc.Error != null)
+        {
+            Assert.Fail("Unicolour does not support the ICC profile - test values will need to be calculated manually");
+        }
+
+        /* This is a hack to trick Unicolour to work in the same way as ImageSharp.
+         * ImageSharp bypasses PCS adjustment for v2 perceptual intent if source and target both need it
+         * as they both share the same understanding of what the PCS is (see ColorProfileConverterExtensionsIcc.GetTargetPcsWithPerceptualAdjustment)
+         * Unicolour does not support a direct profile-to-profile conversion so will always perform PCS adjustment for v2 perceptual intent.
+         * However, PCS adjustment clips negative XYZ values, causing those particular values in Unicolour and ImageSharp to diverge.
+         * It's unclear to me if there's a fundamental correct answer here.
+         *
+         * There are two obvious ways to keep Unicolour and ImageSharp values aligned:
+         * 1. Make ImageSharp always perform PCS adjustment, clipping negative XYZ values during the process - but creates a lot more calculations
+         * 2. Make Unicolour stop performing PCS adjustment, allowing negative XYZ values during conversion
+         *
+         * Option 2 is implemented by modifying the profiles so they claim to be v4 profiles
+         * since v4 perceptual profiles do not apply PCS adjustment.
+         */
+        bool isSourcePerceptualV2 = sourceConfig.Icc.Intent == Intent.Perceptual && sourceConfig.Icc.Profile!.Header.ProfileVersion.Major == 2;
+        bool isTargetPerceptualV2 = targetConfig.Icc.Intent == Intent.Perceptual && targetConfig.Icc.Profile!.Header.ProfileVersion.Major == 2;
+        if (isSourcePerceptualV2 && isTargetPerceptualV2)
+        {
+            sourceConfig = GetUnicolourConfigAsV4Header(sourceConfig);
+            targetConfig = GetUnicolourConfigAsV4Header(targetConfig);
+        }
+
+        Channels channels = new(input.Select(value => (double)value).ToArray());
+        Unicolour source = new(sourceConfig, channels);
+        Unicolour target = source.ConvertToConfiguration(targetConfig);
+        return target.Icc.Values;
+    }
+
+    private static Wacton.Unicolour.Configuration GetUnicolourConfigAsV4Header(Wacton.Unicolour.Configuration config)
+    {
+        string profilePath = config.Icc.Profile!.FileInfo.FullName;
+        string modifiedFilename = $"{Path.GetFileNameWithoutExtension(profilePath)}_modified.icc";
+        string modifiedProfile = Path.Combine(Path.GetDirectoryName(profilePath)!, modifiedFilename);
+
+        Wacton.Unicolour.Configuration modifiedConfig;
+        if (!TestIccProfiles.HasUnicolourConfiguration(modifiedProfile))
+        {
+            byte[] bytes = File.ReadAllBytes(profilePath);
+            bytes[8] = 4; // byte 8 of profile is major version
+            File.WriteAllBytes(modifiedProfile, bytes);
+            modifiedConfig = TestIccProfiles.GetUnicolourConfiguration(modifiedProfile);
+            File.Delete(modifiedProfile);
+        }
+        else
+        {
+            modifiedConfig = TestIccProfiles.GetUnicolourConfiguration(modifiedProfile);
+        }
+
+        return modifiedConfig;
+    }
+
+    private static Vector4 GetActualTargetValues(float[] input, string sourceProfile, string targetProfile)
+    {
+        ColorProfileConverter converter = new(new ColorConversionOptions
+        {
+            SourceIccProfile = TestIccProfiles.GetProfile(sourceProfile),
+            TargetIccProfile = TestIccProfiles.GetProfile(targetProfile)
+        });
+
+        IccColorSpaceType sourceDataSpace = converter.Options.SourceIccProfile!.Header.DataColorSpace;
+        IccColorSpaceType targetDataSpace = converter.Options.TargetIccProfile!.Header.DataColorSpace;
+        return sourceDataSpace switch
+        {
+            IccColorSpaceType.Cmyk when targetDataSpace == IccColorSpaceType.Cmyk
+                => converter.Convert<Cmyk, Cmyk>(new Cmyk(new Vector4(input))).ToScaledVector4(),
+            IccColorSpaceType.Cmyk when targetDataSpace == IccColorSpaceType.Rgb
+                => converter.Convert<Cmyk, Rgb>(new Cmyk(new Vector4(input))).ToScaledVector4(),
+            IccColorSpaceType.Rgb when targetDataSpace == IccColorSpaceType.Cmyk
+                => converter.Convert<Rgb, Cmyk>(new Rgb(new Vector3(input))).ToScaledVector4(),
+            IccColorSpaceType.Rgb when targetDataSpace == IccColorSpaceType.Rgb
+                => converter.Convert<Rgb, Rgb>(new Rgb(new Vector3(input))).ToScaledVector4(),
+            _ => throw new NotSupportedException($"Unsupported ICC profile data color space conversion: {sourceDataSpace} -> {targetDataSpace}")
+        };
+    }
+
+    private static float GetNormalizedRandomValue()
+    {
+        // Generate a random value between 0 (inclusive) and 1 (exclusive).
+        double value = Random.Shared.NextDouble();
+
+        // If the random value is exactly 0, return 0F to ensure inclusivity at the lower bound.
+        // For non-zero values, add a small increment (0.0000001F) to ensure the range
+        // is inclusive at the upper bound while retaining precision.
+        // Clamp the result between 0 and 1 to ensure it does not exceed the bounds.
+        return value == 0 ? 0F : Math.Clamp((float)value + 0.0000001F, 0, 1);
+    }
+}
diff --git a/tests/ImageSharp.Tests/ColorProfiles/Icc/IccProfileConverterTests.cs b/tests/ImageSharp.Tests/ColorProfiles/Icc/IccProfileConverterTests.cs
new file mode 100644
index 0000000000..ad8193774d
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/Icc/IccProfileConverterTests.cs
@@ -0,0 +1,68 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using SixLabors.ImageSharp.ColorProfiles.Icc;
+using SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
+using SixLabors.ImageSharp.Formats.Png;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
+
+namespace SixLabors.ImageSharp.Tests.ColorProfiles.Icc;
+
+public class IccProfileConverterTests
+{
+    private static readonly PngEncoder Encoder = new();
+
+    [Theory(Skip = "Skip for now while we refactor the library")]
+    [WithFile(TestImages.Jpeg.ICC.AdobeRgb, PixelTypes.Rgb24)]
+    [WithFile(TestImages.Jpeg.ICC.AppleRGB, PixelTypes.Rgb24)]
+    [WithFile(TestImages.Jpeg.ICC.ColorMatch, PixelTypes.Rgb24)]
+    [WithFile(TestImages.Jpeg.ICC.WideRGB, PixelTypes.Rgb24)]
+    [WithFile(TestImages.Jpeg.ICC.SRgb, PixelTypes.Rgb24)]
+    [WithFile(TestImages.Jpeg.ICC.ProPhoto, PixelTypes.Rgb24)]
+    [WithFile(TestImages.Jpeg.ICC.CMYK, PixelTypes.Rgb24)]
+    public void CanRoundTripProfile<TPixel>(TestImageProvider<TPixel> provider)
+        where TPixel : unmanaged, IPixel<TPixel>
+    {
+        using Image<TPixel> image = provider.GetImage();
+
+        IccProfile profile = image.Metadata.IccProfile;
+
+        TPixel expected = image[0, 0];
+
+        IccProfileConverter.Convert(image, profile, profile);
+
+        image.DebugSave(provider, extension: "png", appendPixelTypeToFileName: false, appendSourceFileOrDescription: true, encoder: Encoder);
+
+        TPixel actual = image[0, 0];
+
+        Assert.Equal(expected, actual);
+    }
+
+    [Theory(Skip = "Skip for now while we refactor the library")]
+    [WithFile(TestImages.Jpeg.ICC.AdobeRgb, PixelTypes.Rgb24)]
+    [WithFile(TestImages.Jpeg.ICC.AppleRGB, PixelTypes.Rgb24)]
+    [WithFile(TestImages.Jpeg.ICC.ColorMatch, PixelTypes.Rgb24)]
+    [WithFile(TestImages.Jpeg.ICC.WideRGB, PixelTypes.Rgb24)]
+    [WithFile(TestImages.Jpeg.ICC.SRgb, PixelTypes.Rgb24)]
+    [WithFile(TestImages.Jpeg.ICC.ProPhoto, PixelTypes.Rgb24)]
+    [WithFile(TestImages.Jpeg.ICC.CMYK, PixelTypes.Rgb24)]
+    public void CanConvertToSRGB<TPixel>(TestImageProvider<TPixel> provider)
+        where TPixel : unmanaged, IPixel<TPixel>
+    {
+        using Image<TPixel> image = provider.GetImage();
+        IccProfile profile = image.Metadata.IccProfile;
+
+        IccProfile sRGBProfile = SrgbV4Profile.GetProfile();
+
+        IccProfileConverter.Convert(image, profile, sRGBProfile);
+
+        Assert.Equal(image.Metadata.IccProfile, sRGBProfile);
+
+        image.DebugSave(provider, extension: "png", appendPixelTypeToFileName: false, appendSourceFileOrDescription: true, encoder: Encoder);
+
+        // Mac reports a difference of 0.0000%
+        image.CompareToReferenceOutput(ImageComparer.Tolerant(0.0001F), provider, appendPixelTypeToFileName: false);
+    }
+}
diff --git a/tests/ImageSharp.Tests/ColorProfiles/Icc/TestIccProfiles.cs b/tests/ImageSharp.Tests/ColorProfiles/Icc/TestIccProfiles.cs
new file mode 100644
index 0000000000..3fc36a91b0
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/Icc/TestIccProfiles.cs
@@ -0,0 +1,67 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Collections.Concurrent;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using Wacton.Unicolour.Icc;
+
+namespace SixLabors.ImageSharp.Tests.ColorProfiles.Icc;
+
+internal static class TestIccProfiles
+{
+    private static readonly ConcurrentDictionary<string, IccProfile> ProfileCache = new();
+    private static readonly ConcurrentDictionary<string, Wacton.Unicolour.Configuration> UnicolourConfigurationCache = new();
+
+    /// <summary>
+    /// v2 CMYK -> LAB, output, lut16
+    /// </summary>
+    public const string Fogra39 = "Coated_Fogra39L_VIGC_300.icc";
+    /// <summary>
+    /// v2 CMYK -> LAB, output, lut16
+    /// </summary>
+    public const string Swop2006 = "SWOP2006_Coated5v2.icc";
+
+    /// <summary>
+    /// v2 CMYK -> LAB, output, lut8 (A2B tags)
+    /// </summary>
+    public const string JapanColor2011 = "JapanColor2011Coated.icc";
+
+    /// <summary>
+    /// v2 CMYK -> LAB, output, lut8 (B2A tags)
+    /// </summary>
+    public const string JapanColor2003 = "JapanColor2003WebCoated.icc";
+
+    /// <summary>
+    /// v4 CMYK -> LAB, output, lutAToB: B-CLUT-A
+    /// </summary>
+    public const string Cgats21 = "CGATS21_CRPC7.icc";
+
+    /// <summary>
+    /// v4 RGB -> XYZ, colorspace, lutAToB: B-Matrix-M [only intent 0]
+    /// </summary>
+    public const string RommRgb = "ISO22028-2_ROMM-RGB.icc";
+
+    /// <summary>
+    /// v4 RGB -> LAB, colorspace, lutAToB: B-Matrix-M-CLUT-A [only intent 0 & 1]
+    /// </summary>
+    public const string StandardRgbV4 = "sRGB_v4_ICC_preference.icc";
+
+    /// <summary>
+    /// v2 RGB -> XYZ, display, TRCs
+    /// </summary>
+    public const string StandardRgbV2 = "sRGB2014.icc";
+
+    public static IccProfile GetProfile(string file)
+        => ProfileCache.GetOrAdd(file, f => new IccProfile(File.ReadAllBytes(GetFullPath(f))));
+
+    public static Wacton.Unicolour.Configuration GetUnicolourConfiguration(string file)
+        => UnicolourConfigurationCache.GetOrAdd(
+            file,
+            f => new Wacton.Unicolour.Configuration(iccConfig: new(GetFullPath(f), Intent.Unspecified, f)));
+
+    public static bool HasUnicolourConfiguration(string file)
+        => UnicolourConfigurationCache.ContainsKey(file);
+
+    private static string GetFullPath(string file)
+        => Path.GetFullPath(Path.Combine(".", "TestDataIcc", "Profiles", file));
+}
diff --git a/tests/ImageSharp.Tests/ColorProfiles/LmsTests.cs b/tests/ImageSharp.Tests/ColorProfiles/LmsTests.cs
index 138fd544da..395b547fdb 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/LmsTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/LmsTests.cs
@@ -9,6 +9,7 @@ namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 /// <summary>
 /// Tests the <see cref="Lms"/> struct.
 /// </summary>
+[Trait("Color", "Conversion")]
 public class LmsTests
 {
     [Fact]
diff --git a/tests/ImageSharp.Tests/ColorProfiles/RgbAndCieXyzConversionTest.cs b/tests/ImageSharp.Tests/ColorProfiles/RgbAndCieXyzConversionTest.cs
index c10aa2c3c5..7b48089c7c 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/RgbAndCieXyzConversionTest.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/RgbAndCieXyzConversionTest.cs
@@ -27,7 +27,7 @@ public void Convert_XYZ_D50_To_SRGB(float x, float y, float z, float r, float g,
     {
         // Arrange
         CieXyz input = new(x, y, z);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D50, TargetRgbWorkingSpace = KnownRgbWorkingSpaces.SRgb };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D50, TargetRgbWorkingSpace = KnownRgbWorkingSpaces.SRgb };
         ColorProfileConverter converter = new(options);
         Rgb expected = new(r, g, b);
 
@@ -60,7 +60,7 @@ public void Convert_XYZ_D65_To_SRGB(float x, float y, float z, float r, float g,
     {
         // Arrange
         CieXyz input = new(x, y, z);
-        ColorConversionOptions options = new() { WhitePoint = KnownIlluminants.D65, TargetRgbWorkingSpace = KnownRgbWorkingSpaces.SRgb };
+        ColorConversionOptions options = new() { SourceWhitePoint = KnownIlluminants.D65, TargetRgbWorkingSpace = KnownRgbWorkingSpaces.SRgb };
         ColorProfileConverter converter = new(options);
         Rgb expected = new(r, g, b);
 
@@ -93,7 +93,7 @@ public void Convert_SRGB_To_XYZ_D50(float r, float g, float b, float x, float y,
     {
         // Arrange
         Rgb input = new(r, g, b);
-        ColorConversionOptions options = new() { TargetWhitePoint = KnownIlluminants.D50, RgbWorkingSpace = KnownRgbWorkingSpaces.SRgb };
+        ColorConversionOptions options = new() { TargetWhitePoint = KnownIlluminants.D50, SourceRgbWorkingSpace = KnownRgbWorkingSpaces.SRgb };
         ColorProfileConverter converter = new(options);
         CieXyz expected = new(x, y, z);
 
@@ -126,7 +126,7 @@ public void Convert_SRGB_To_XYZ_D65(float r, float g, float b, float x, float y,
     {
         // Arrange
         Rgb input = new(r, g, b);
-        ColorConversionOptions options = new() { TargetWhitePoint = KnownIlluminants.D65, RgbWorkingSpace = KnownRgbWorkingSpaces.SRgb };
+        ColorConversionOptions options = new() { TargetWhitePoint = KnownIlluminants.D65, SourceRgbWorkingSpace = KnownRgbWorkingSpaces.SRgb };
         ColorProfileConverter converter = new(options);
         CieXyz expected = new(x, y, z);
 
diff --git a/tests/ImageSharp.Tests/ColorProfiles/RgbAndCmykConversionTest.cs b/tests/ImageSharp.Tests/ColorProfiles/RgbAndCmykConversionTest.cs
index 4f4ecb70be..bd35fb7751 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/RgbAndCmykConversionTest.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/RgbAndCmykConversionTest.cs
@@ -13,6 +13,7 @@ namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 /// <see href="http://www.colorhexa.com"/>
 /// <see href="http://www.rapidtables.com/convert/color/cmyk-to-rgb.htm"/>
 /// </remarks>
+[Trait("Color", "Conversion")]
 public class RgbAndCmykConversionTest
 {
     private static readonly ApproximateColorProfileComparer Comparer = new(.0001F);
diff --git a/tests/ImageSharp.Tests/ColorProfiles/RgbAndHslConversionTest.cs b/tests/ImageSharp.Tests/ColorProfiles/RgbAndHslConversionTest.cs
index 0dc95628b9..e5874c3d13 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/RgbAndHslConversionTest.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/RgbAndHslConversionTest.cs
@@ -13,6 +13,7 @@ namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 /// <see href="http://www.colorhexa.com"/>
 /// <see href="http://www.rapidtables.com/convert/color/hsl-to-rgb"/>
 /// </remarks>
+[Trait("Color", "Conversion")]
 public class RgbAndHslConversionTest
 {
     private static readonly ApproximateColorProfileComparer Comparer = new(.0001f);
diff --git a/tests/ImageSharp.Tests/ColorProfiles/RgbAndHsvConversionTest.cs b/tests/ImageSharp.Tests/ColorProfiles/RgbAndHsvConversionTest.cs
index b89b576b6c..4a685abe5f 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/RgbAndHsvConversionTest.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/RgbAndHsvConversionTest.cs
@@ -12,6 +12,7 @@ namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 /// Test data generated using:
 /// <see href="http://www.colorhexa.com"/>
 /// </remarks>
+[Trait("Color", "Conversion")]
 public class RgbAndHsvConversionTest
 {
     private static readonly ApproximateColorProfileComparer Comparer = new(.0001f);
diff --git a/tests/ImageSharp.Tests/ColorProfiles/RgbTests.cs b/tests/ImageSharp.Tests/ColorProfiles/RgbTests.cs
index 7e4d4ee0e7..707b3e2a7d 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/RgbTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/RgbTests.cs
@@ -10,6 +10,7 @@ namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 /// <summary>
 /// Tests the <see cref="Rgb"/> struct.
 /// </summary>
+[Trait("Color", "Conversion")]
 public class RgbTests
 {
     [Fact]
diff --git a/tests/ImageSharp.Tests/ColorProfiles/StringRepresentationTests.cs b/tests/ImageSharp.Tests/ColorProfiles/StringRepresentationTests.cs
index 770c987dba..0867fcfbc2 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/StringRepresentationTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/StringRepresentationTests.cs
@@ -6,6 +6,7 @@
 
 namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 
+[Trait("Color", "Conversion")]
 public class StringRepresentationTests
 {
     private static readonly Vector3 One = new(1);
diff --git a/tests/ImageSharp.Tests/ColorProfiles/VonKriesChromaticAdaptationTests.cs b/tests/ImageSharp.Tests/ColorProfiles/VonKriesChromaticAdaptationTests.cs
index 7f5687dee2..1622af1bfb 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/VonKriesChromaticAdaptationTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/VonKriesChromaticAdaptationTests.cs
@@ -20,7 +20,7 @@ public void SingleAndBulkTransformYieldIdenticalResults(CieXyz from, CieXyz to)
     {
         ColorConversionOptions options = new()
         {
-            WhitePoint = from,
+            SourceWhitePoint = from,
             TargetWhitePoint = to
         };
 
diff --git a/tests/ImageSharp.Tests/ColorProfiles/YCbCrTests.cs b/tests/ImageSharp.Tests/ColorProfiles/YCbCrTests.cs
index f8404ad948..a88d0157a3 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/YCbCrTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/YCbCrTests.cs
@@ -9,6 +9,7 @@ namespace SixLabors.ImageSharp.Tests.ColorProfiles;
 /// <summary>
 /// Tests the <see cref="YCbCr"/> struct.
 /// </summary>
+[Trait("Color", "Conversion")]
 public class YCbCrTests
 {
     [Fact]
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.Metadata.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.Metadata.cs
index 039215bbc5..99322687cc 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.Metadata.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.Metadata.cs
@@ -7,6 +7,7 @@
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
 using SixLabors.ImageSharp.Metadata.Profiles.Iptc;
 using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Tests.TestDataIcc;
 
 namespace SixLabors.ImageSharp.Tests.Formats.Jpg;
 
@@ -77,7 +78,7 @@ public void Encode_PreservesIccProfile()
     {
         // arrange
         using Image<Rgba32> input = new(1, 1);
-        input.Metadata.IccProfile = new IccProfile(IccTestDataProfiles.Profile_Random_Array);
+        input.Metadata.IccProfile = new IccProfile(IccTestDataProfiles.ProfileRandomArray);
 
         // act
         using MemoryStream memStream = new();
diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj
index 9af4f41a81..880bf84aa8 100644
--- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj
+++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj
@@ -32,6 +32,9 @@
       <AutoGen>True</AutoGen>
       <DependentUpon>PixelOperationsTests.Specialized.Generated.tt</DependentUpon>
     </None>
+    <None Update="TestDataIcc\Profiles\*">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
   </ItemGroup>
 
   <ItemGroup>
@@ -47,6 +50,7 @@
     <PackageReference Include="runtime.osx.10.10-x64.CoreCompat.System.Drawing" Condition="'$(IsOSX)'=='true'" />
     <PackageReference Include="SharpZipLib" />
     <PackageReference Include="System.Drawing.Common" />
+    <PackageReference Include="Wacton.Unicolour" Version="5.0.0" />
   </ItemGroup>
 
   <ItemGroup>
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderCurvesTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderCurvesTests.cs
index 73ae46c2c9..86c6a5e9f2 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderCurvesTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderCurvesTests.cs
@@ -2,6 +2,7 @@
 // Licensed under the Six Labors Split License.
 
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc;
 
 namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.ICC.DataReader;
 
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderLutTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderLutTests.cs
index 63585a3bd4..a686d44872 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderLutTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderLutTests.cs
@@ -2,6 +2,7 @@
 // Licensed under the Six Labors Split License.
 
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc;
 
 namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.ICC.DataReader;
 
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderMatrixTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderMatrixTests.cs
index b81395bb2e..5ef102cd93 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderMatrixTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderMatrixTests.cs
@@ -2,6 +2,7 @@
 // Licensed under the Six Labors Split License.
 
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc;
 
 namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.ICC.DataReader;
 
@@ -9,7 +10,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.ICC.DataReader;
 public class IccDataReaderMatrixTests
 {
     [Theory]
-    [MemberData(nameof(IccTestDataMatrix.Matrix2D_FloatArrayTestData), MemberType = typeof(IccTestDataMatrix))]
+    [MemberData(nameof(IccTestDataMatrix.Matrix2DFloatArrayTestData), MemberType = typeof(IccTestDataMatrix))]
     public void ReadMatrix2D(byte[] data, int xCount, int yCount, bool isSingle, float[,] expected)
     {
         IccDataReader reader = CreateReader(data);
@@ -20,7 +21,7 @@ public void ReadMatrix2D(byte[] data, int xCount, int yCount, bool isSingle, flo
     }
 
     [Theory]
-    [MemberData(nameof(IccTestDataMatrix.Matrix1D_ArrayTestData), MemberType = typeof(IccTestDataMatrix))]
+    [MemberData(nameof(IccTestDataMatrix.Matrix1DArrayTestData), MemberType = typeof(IccTestDataMatrix))]
     public void ReadMatrix1D(byte[] data, int yCount, bool isSingle, float[] expected)
     {
         IccDataReader reader = CreateReader(data);
@@ -30,8 +31,5 @@ public void ReadMatrix1D(byte[] data, int yCount, bool isSingle, float[] expecte
         Assert.Equal(expected, output);
     }
 
-    private static IccDataReader CreateReader(byte[] data)
-    {
-        return new IccDataReader(data);
-    }
+    private static IccDataReader CreateReader(byte[] data) => new(data);
 }
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderMultiProcessElementTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderMultiProcessElementTests.cs
index 9023b1b723..930665a07c 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderMultiProcessElementTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderMultiProcessElementTests.cs
@@ -2,6 +2,7 @@
 // Licensed under the Six Labors Split License.
 
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc;
 
 namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.ICC.DataReader;
 
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderNonPrimitivesTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderNonPrimitivesTests.cs
index 91294a3dab..ee0464bb23 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderNonPrimitivesTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderNonPrimitivesTests.cs
@@ -3,6 +3,7 @@
 
 using System.Numerics;
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc;
 
 namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.ICC.DataReader;
 
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderPrimitivesTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderPrimitivesTests.cs
index b6135cd197..9c5be4c675 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderPrimitivesTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderPrimitivesTests.cs
@@ -2,6 +2,7 @@
 // Licensed under the Six Labors Split License.
 
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc;
 
 namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.ICC.DataReader;
 
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderTagDataEntryTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderTagDataEntryTests.cs
index d41707b7ce..e0cfa65431 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderTagDataEntryTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderTagDataEntryTests.cs
@@ -2,6 +2,7 @@
 // Licensed under the Six Labors Split License.
 
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc;
 
 namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.ICC.DataReader;
 
@@ -166,7 +167,7 @@ internal void ReadMeasurementTagDataEntry(byte[] data, IccMeasurementTagDataEntr
 
     [Theory]
     [MemberData(
-        nameof(IccTestDataTagDataEntry.MultiLocalizedUnicodeTagDataEntryTestData_Read),
+        nameof(IccTestDataTagDataEntry.MultiLocalizedUnicodeTagDataEntryTestDataRead),
         MemberType = typeof(IccTestDataTagDataEntry))]
     internal void ReadMultiLocalizedUnicodeTagDataEntry(byte[] data, IccMultiLocalizedUnicodeTagDataEntry expected)
     {
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderTests.cs
index f2150cc03a..6f2e868c56 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataReader/IccDataReaderTests.cs
@@ -9,8 +9,5 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.ICC.DataReader;
 public class IccDataReaderTests
 {
     [Fact]
-    public void ConstructorThrowsNullException()
-    {
-        Assert.Throws<ArgumentNullException>(() => new IccDataReader(null));
-    }
+    public void ConstructorThrowsNullException() => Assert.Throws<ArgumentNullException>(() => new IccDataReader(null));
 }
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterCurvesTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterCurvesTests.cs
index 1a23c8d002..f6ac8517d8 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterCurvesTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterCurvesTests.cs
@@ -2,6 +2,7 @@
 // Licensed under the Six Labors Split License.
 
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc;
 
 namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.ICC.DataWriter;
 
@@ -80,8 +81,5 @@ internal void WriteSampledCurveElement(byte[] expected, IccSampledCurveElement d
         Assert.Equal(expected, output);
     }
 
-    private static IccDataWriter CreateWriter()
-    {
-        return new IccDataWriter();
-    }
+    private static IccDataWriter CreateWriter() => new IccDataWriter();
 }
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterLutTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterLutTests.cs
index 4a3dc48bcb..8f696e99df 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterLutTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterLutTests.cs
@@ -2,6 +2,7 @@
 // Licensed under the Six Labors Split License.
 
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc;
 
 namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.ICC.DataWriter;
 
@@ -80,8 +81,5 @@ internal void WriteLut16(byte[] expected, IccLut data, int count)
         Assert.Equal(expected, output);
     }
 
-    private static IccDataWriter CreateWriter()
-    {
-        return new IccDataWriter();
-    }
+    private static IccDataWriter CreateWriter() => new IccDataWriter();
 }
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterLutTests1.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterLutTests1.cs
index 1973d94b89..9317b45034 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterLutTests1.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterLutTests1.cs
@@ -2,6 +2,7 @@
 // Licensed under the Six Labors Split License.
 
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc;
 
 namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.ICC.DataWriter;
 
@@ -80,8 +81,5 @@ internal void WriteLut16(byte[] expected, IccLut data, int count)
         Assert.Equal(expected, output);
     }
 
-    private static IccDataWriter CreateWriter()
-    {
-        return new IccDataWriter();
-    }
+    private static IccDataWriter CreateWriter() => new();
 }
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterLutTests2.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterLutTests2.cs
index 4ffc9e0c36..147a332c39 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterLutTests2.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterLutTests2.cs
@@ -2,6 +2,7 @@
 // Licensed under the Six Labors Split License.
 
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc;
 
 namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.ICC.DataWriter;
 
@@ -80,8 +81,5 @@ internal void WriteLut16(byte[] expected, IccLut data, int count)
         Assert.Equal(expected, output);
     }
 
-    private static IccDataWriter CreateWriter()
-    {
-        return new IccDataWriter();
-    }
+    private static IccDataWriter CreateWriter() => new();
 }
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterMatrixTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterMatrixTests.cs
index 7d046aa49b..c72d4386ad 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterMatrixTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterMatrixTests.cs
@@ -3,6 +3,7 @@
 
 using System.Numerics;
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc;
 
 namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.ICC.DataWriter;
 
@@ -10,7 +11,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.ICC.DataWriter;
 public class IccDataWriterMatrixTests
 {
     [Theory]
-    [MemberData(nameof(IccTestDataMatrix.Matrix2D_FloatArrayTestData), MemberType = typeof(IccTestDataMatrix))]
+    [MemberData(nameof(IccTestDataMatrix.Matrix2DFloatArrayTestData), MemberType = typeof(IccTestDataMatrix))]
     public void WriteMatrix2D_Array(byte[] expected, int xCount, int yCount, bool isSingle, float[,] data)
     {
         using IccDataWriter writer = CreateWriter();
@@ -22,7 +23,7 @@ public void WriteMatrix2D_Array(byte[] expected, int xCount, int yCount, bool is
     }
 
     [Theory]
-    [MemberData(nameof(IccTestDataMatrix.Matrix2D_Matrix4x4TestData), MemberType = typeof(IccTestDataMatrix))]
+    [MemberData(nameof(IccTestDataMatrix.Matrix2DMatrix4X4TestData), MemberType = typeof(IccTestDataMatrix))]
     public void WriteMatrix2D_Matrix4x4(byte[] expected, int xCount, int yCount, bool isSingle, Matrix4x4 data)
     {
         using IccDataWriter writer = CreateWriter();
@@ -34,7 +35,7 @@ public void WriteMatrix2D_Matrix4x4(byte[] expected, int xCount, int yCount, boo
     }
 
     [Theory]
-    [MemberData(nameof(IccTestDataMatrix.Matrix2D_DenseMatrixTestData), MemberType = typeof(IccTestDataMatrix))]
+    [MemberData(nameof(IccTestDataMatrix.Matrix2DDenseMatrixTestData), MemberType = typeof(IccTestDataMatrix))]
     internal void WriteMatrix2D_DenseMatrix(byte[] expected, int xCount, int yCount, bool isSingle, in DenseMatrix<float> data)
     {
         using IccDataWriter writer = CreateWriter();
@@ -46,7 +47,7 @@ internal void WriteMatrix2D_DenseMatrix(byte[] expected, int xCount, int yCount,
     }
 
     [Theory]
-    [MemberData(nameof(IccTestDataMatrix.Matrix1D_ArrayTestData), MemberType = typeof(IccTestDataMatrix))]
+    [MemberData(nameof(IccTestDataMatrix.Matrix1DArrayTestData), MemberType = typeof(IccTestDataMatrix))]
     public void WriteMatrix1D_Array(byte[] expected, int yCount, bool isSingle, float[] data)
     {
         using IccDataWriter writer = CreateWriter();
@@ -58,7 +59,7 @@ public void WriteMatrix1D_Array(byte[] expected, int yCount, bool isSingle, floa
     }
 
     [Theory]
-    [MemberData(nameof(IccTestDataMatrix.Matrix1D_Vector3TestData), MemberType = typeof(IccTestDataMatrix))]
+    [MemberData(nameof(IccTestDataMatrix.Matrix1DVector3TestData), MemberType = typeof(IccTestDataMatrix))]
     public void WriteMatrix1D_Vector3(byte[] expected, int yCount, bool isSingle, Vector3 data)
     {
         using IccDataWriter writer = CreateWriter();
@@ -69,8 +70,5 @@ public void WriteMatrix1D_Vector3(byte[] expected, int yCount, bool isSingle, Ve
         Assert.Equal(expected, output);
     }
 
-    private static IccDataWriter CreateWriter()
-    {
-        return new IccDataWriter();
-    }
+    private static IccDataWriter CreateWriter() => new();
 }
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterMultiProcessElementTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterMultiProcessElementTests.cs
index ba2add5eb9..b7259d536a 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterMultiProcessElementTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterMultiProcessElementTests.cs
@@ -2,6 +2,7 @@
 // Licensed under the Six Labors Split License.
 
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc;
 
 namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.ICC.DataWriter;
 
@@ -56,8 +57,5 @@ internal void WriteClutProcessElement(byte[] expected, IccClutProcessElement dat
         Assert.Equal(expected, output);
     }
 
-    private static IccDataWriter CreateWriter()
-    {
-        return new IccDataWriter();
-    }
+    private static IccDataWriter CreateWriter() => new();
 }
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterNonPrimitivesTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterNonPrimitivesTests.cs
index b17ed44419..b1b30d49fa 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterNonPrimitivesTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterNonPrimitivesTests.cs
@@ -3,6 +3,7 @@
 
 using System.Numerics;
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc;
 
 namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.ICC.DataWriter;
 
@@ -117,8 +118,5 @@ internal void WriteScreeningChannel(byte[] expected, IccScreeningChannel data)
         Assert.Equal(expected, output);
     }
 
-    private static IccDataWriter CreateWriter()
-    {
-        return new IccDataWriter();
-    }
+    private static IccDataWriter CreateWriter() => new();
 }
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterPrimitivesTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterPrimitivesTests.cs
index fbe8fe1ced..c8f46d3aa4 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterPrimitivesTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterPrimitivesTests.cs
@@ -2,6 +2,7 @@
 // Licensed under the Six Labors Split License.
 
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc;
 
 namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.ICC.DataWriter;
 
@@ -112,8 +113,5 @@ public void WriteUFix8(byte[] expected, float data)
         Assert.Equal(expected, output);
     }
 
-    private static IccDataWriter CreateWriter()
-    {
-        return new IccDataWriter();
-    }
+    private static IccDataWriter CreateWriter() => new();
 }
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterTagDataEntryTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterTagDataEntryTests.cs
index 7eda24c8cf..791bcee5e6 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterTagDataEntryTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterTagDataEntryTests.cs
@@ -2,6 +2,7 @@
 // Licensed under the Six Labors Split License.
 
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc;
 
 namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.ICC.DataWriter;
 
@@ -153,7 +154,7 @@ internal void WriteMeasurementTagDataEntry(byte[] expected, IccMeasurementTagDat
     }
 
     [Theory]
-    [MemberData(nameof(IccTestDataTagDataEntry.MultiLocalizedUnicodeTagDataEntryTestData_Write), MemberType = typeof(IccTestDataTagDataEntry))]
+    [MemberData(nameof(IccTestDataTagDataEntry.MultiLocalizedUnicodeTagDataEntryTestDataWrite), MemberType = typeof(IccTestDataTagDataEntry))]
     internal void WriteMultiLocalizedUnicodeTagDataEntry(byte[] expected, IccMultiLocalizedUnicodeTagDataEntry data)
     {
         using IccDataWriter writer = CreateWriter();
@@ -404,8 +405,5 @@ internal void WriteUcrBgTagDataEntry(byte[] expected, IccUcrBgTagDataEntry data,
         Assert.Equal(expected, output);
     }
 
-    private static IccDataWriter CreateWriter()
-    {
-        return new IccDataWriter();
-    }
+    private static IccDataWriter CreateWriter() => new();
 }
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterTests.cs
index 205941fcec..606a69d390 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/DataWriter/IccDataWriterTests.cs
@@ -2,6 +2,7 @@
 // Licensed under the Six Labors Split License.
 
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc;
 
 namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.ICC.DataWriter;
 
@@ -105,8 +106,5 @@ public void WriteArrayUInt64(byte[] expected, ulong[] data)
         Assert.Equal(expected, output);
     }
 
-    private static IccDataWriter CreateWriter()
-    {
-        return new IccDataWriter();
-    }
+    private static IccDataWriter CreateWriter() => new();
 }
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/IccProfileTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/IccProfileTests.cs
index fbbea97fb3..9c4abfe3e6 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/IccProfileTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/IccProfileTests.cs
@@ -2,6 +2,7 @@
 // Licensed under the Six Labors Split License.
 
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc;
 
 namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Icc;
 
@@ -20,7 +21,7 @@ public void CalculateHash_WithByteArray_CalculatesProfileHash(byte[] data, IccPr
     [Fact]
     public void CalculateHash_WithByteArray_DoesNotModifyData()
     {
-        byte[] data = IccTestDataProfiles.Profile_Random_Array;
+        byte[] data = IccTestDataProfiles.ProfileRandomArray;
         var copy = new byte[data.Length];
         Buffer.BlockCopy(data, 0, copy, 0, data.Length);
 
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/IccReaderTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/IccReaderTests.cs
index 9b2ca2a275..2a80ae9e9c 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/IccReaderTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/IccReaderTests.cs
@@ -2,24 +2,45 @@
 // Licensed under the Six Labors Split License.
 
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Tests.TestDataIcc;
 
 namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Icc;
 
 [Trait("Profile", "Icc")]
 public class IccReaderTests
 {
+    [Theory]
+    [WithFile(TestImages.Jpeg.ICC.AdobeRgb, PixelTypes.Rgb24, 10, IccColorSpaceType.Rgb, IccColorSpaceType.CieXyz, 560)]
+    [WithFile(TestImages.Jpeg.ICC.AppleRGB, PixelTypes.Rgb24, 10, IccColorSpaceType.Rgb, IccColorSpaceType.CieXyz, 552)]
+    [WithFile(TestImages.Jpeg.ICC.ColorMatch, PixelTypes.Rgb24, 10, IccColorSpaceType.Rgb, IccColorSpaceType.CieXyz, 560)]
+    [WithFile(TestImages.Jpeg.ICC.WideRGB, PixelTypes.Rgb24, 10, IccColorSpaceType.Rgb, IccColorSpaceType.CieXyz, 560)]
+    [WithFile(TestImages.Jpeg.ICC.SRgb, PixelTypes.Rgb24, 17, IccColorSpaceType.Rgb, IccColorSpaceType.CieXyz, 3144)]
+    [WithFile(TestImages.Jpeg.ICC.ProPhoto, PixelTypes.Rgb24, 12, IccColorSpaceType.Rgb, IccColorSpaceType.CieXyz, 940)]
+    [WithFile(TestImages.Jpeg.ICC.CMYK, PixelTypes.Rgb24, 10, IccColorSpaceType.Cmyk, IccColorSpaceType.CieLab, 557168)]
+    public void ReadProfile_Works<TPixel>(TestImageProvider<TPixel> provider, int expectedEntries, IccColorSpaceType expectedDataColorSpace, IccColorSpaceType expectedConnectionSpace, uint expectedDataSize)
+        where TPixel : unmanaged, IPixel<TPixel>
+    {
+        using Image<TPixel> image = provider.GetImage();
+        IccProfile profile = image.Metadata.IccProfile;
+
+        Assert.NotNull(profile);
+        Assert.Equal(expectedEntries, profile.Entries.Length);
+        Assert.Equal(expectedDataColorSpace, profile.Header.DataColorSpace);
+        Assert.Equal(expectedConnectionSpace, profile.Header.ProfileConnectionSpace);
+        Assert.Equal(expectedDataSize, profile.Header.Size);
+    }
+
     [Fact]
     public void ReadProfile_NoEntries()
     {
-        IccReader reader = this.CreateReader();
-
-        IccProfile output = IccReader.Read(IccTestDataProfiles.Header_Random_Array);
+        IccProfile output = IccReader.Read(IccTestDataProfiles.HeaderRandomArray);
 
         Assert.Equal(0, output.Entries.Length);
         Assert.NotNull(output.Header);
 
         IccProfileHeader header = output.Header;
-        IccProfileHeader expected = IccTestDataProfiles.Header_Random_Read;
+        IccProfileHeader expected = IccTestDataProfiles.HeaderRandomRead;
         Assert.Equal(header.Class, expected.Class);
         Assert.Equal(header.CmmType, expected.CmmType);
         Assert.Equal(header.CreationDate, expected.CreationDate);
@@ -38,20 +59,4 @@ public void ReadProfile_NoEntries()
         Assert.Equal(header.Size, expected.Size);
         Assert.Equal(header.Version, expected.Version);
     }
-
-    [Fact]
-    public void ReadProfile_DuplicateEntry()
-    {
-        IccReader reader = this.CreateReader();
-
-        IccProfile output = IccReader.Read(IccTestDataProfiles.Profile_Random_Array);
-
-        Assert.Equal(2, output.Entries.Length);
-        Assert.True(ReferenceEquals(output.Entries[0], output.Entries[1]));
-    }
-
-    private IccReader CreateReader()
-    {
-        return new IccReader();
-    }
 }
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/IccWriterTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/IccWriterTests.cs
index 89b63b7dcc..24671aa3c5 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/ICC/IccWriterTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/ICC/IccWriterTests.cs
@@ -2,6 +2,7 @@
 // Licensed under the Six Labors Split License.
 
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc;
 
 namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Icc;
 
@@ -11,29 +12,20 @@ public class IccWriterTests
     [Fact]
     public void WriteProfile_NoEntries()
     {
-        IccWriter writer = this.CreateWriter();
-
         var profile = new IccProfile
         {
-            Header = IccTestDataProfiles.Header_Random_Write
+            Header = IccTestDataProfiles.HeaderRandomWrite
         };
         byte[] output = IccWriter.Write(profile);
 
-        Assert.Equal(IccTestDataProfiles.Header_Random_Array, output);
+        Assert.Equal(IccTestDataProfiles.HeaderRandomArray, output);
     }
 
     [Fact]
     public void WriteProfile_DuplicateEntry()
     {
-        IccWriter writer = this.CreateWriter();
-
-        byte[] output = IccWriter.Write(IccTestDataProfiles.Profile_Random_Val);
+        byte[] output = IccWriter.Write(IccTestDataProfiles.ProfileRandomVal);
 
-        Assert.Equal(IccTestDataProfiles.Profile_Random_Array, output);
-    }
-
-    private IccWriter CreateWriter()
-    {
-        return new IccWriter();
+        Assert.Equal(IccTestDataProfiles.ProfileRandomArray, output);
     }
 }
diff --git a/tests/ImageSharp.Tests/TestDataIcc/Conversion/IccConversionDataClut.cs b/tests/ImageSharp.Tests/TestDataIcc/Conversion/IccConversionDataClut.cs
new file mode 100644
index 0000000000..397986a189
--- /dev/null
+++ b/tests/ImageSharp.Tests/TestDataIcc/Conversion/IccConversionDataClut.cs
@@ -0,0 +1,162 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Numerics;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.Tests.TestDataIcc.Conversion;
+
+public class IccConversionDataClut
+{
+    internal static IccClut Clut3x2 = new(
+        [
+            0.1f, 0.1f,
+            0.2f, 0.2f,
+            0.3f, 0.3f,
+
+            0.11f, 0.11f,
+            0.21f, 0.21f,
+            0.31f, 0.31f,
+
+            0.12f, 0.12f,
+            0.22f, 0.22f,
+            0.32f, 0.32f,
+
+            0.13f, 0.13f,
+            0.23f, 0.23f,
+            0.33f, 0.33f,
+
+            0.14f, 0.14f,
+            0.24f, 0.24f,
+            0.34f, 0.34f,
+
+            0.15f, 0.15f,
+            0.25f, 0.25f,
+            0.35f, 0.35f,
+
+            0.16f, 0.16f,
+            0.26f, 0.26f,
+            0.36f, 0.36f,
+
+            0.17f, 0.17f,
+            0.27f, 0.27f,
+            0.37f, 0.37f,
+
+            0.18f, 0.18f,
+            0.28f, 0.28f,
+            0.38f, 0.38f,
+        ],
+        [3, 3, 3],
+        IccClutDataType.Float,
+        outputChannelCount: 2);
+
+    internal static IccClut Clut3x1 = new(
+        [
+             0.10f,
+             0.20f,
+             0.30f,
+
+             0.11f,
+             0.21f,
+             0.31f,
+
+             0.12f,
+             0.22f,
+             0.32f,
+
+             0.13f,
+             0.23f,
+             0.33f,
+
+             0.14f,
+             0.24f,
+             0.34f,
+
+             0.15f,
+             0.25f,
+             0.35f,
+
+             0.16f,
+             0.26f,
+             0.36f,
+
+             0.17f,
+             0.27f,
+             0.37f,
+
+             0.18f,
+             0.28f,
+             0.38f,
+        ],
+        [3, 3, 3],
+        IccClutDataType.Float,
+        outputChannelCount: 1);
+
+    internal static IccClut Clut2x2 = new(
+        [
+            0.1f, 0.9f,
+            0.2f, 0.8f,
+            0.3f, 0.7f,
+
+            0.4f, 0.6f,
+            0.5f, 0.5f,
+            0.6f, 0.4f,
+
+            0.7f, 0.3f,
+            0.8f, 0.2f,
+            0.9f, 0.1f,
+        ],
+        [3, 3],
+        IccClutDataType.Float,
+        outputChannelCount: 2);
+
+    internal static IccClut Clut2x1 = new(
+        [
+            0.1f,
+            0.2f,
+            0.3f,
+
+            0.4f,
+            0.5f,
+            0.6f,
+
+            0.7f,
+            0.8f,
+            0.9f,
+        ],
+        [3, 3],
+        IccClutDataType.Float,
+        outputChannelCount: 1);
+
+    internal static IccClut Clut1x2 = new(
+        [
+            0f, 0.5f,
+            0.25f, 0.75f,
+            0.5f, 1f,
+        ],
+        [3],
+        IccClutDataType.Float,
+        outputChannelCount: 2);
+
+    internal static IccClut Clut1x1 = new(
+        [
+            0f,
+            0.5f,
+            1f,
+        ],
+        [3],
+        IccClutDataType.Float,
+        outputChannelCount: 1);
+
+    public static object[][] ClutConversionTestData =
+    [
+        [Clut3x2, new Vector4(0.75f, 0.75f, 0.75f, 0), new Vector4(0.31f, 0.31f, 0, 0)],
+        [Clut3x1, new Vector4(0.2f, 0.6f, 0.8f, 0), new Vector4(0.284f, 0, 0, 0)],
+        [Clut3x1, new Vector4(0.75f, 0.75f, 0.75f, 0), new Vector4(0.31f, 0, 0, 0)],
+        [Clut2x2, new Vector4(0.2f, 0.6f, 0, 0), new Vector4(0.34f, 0.66f, 0, 0)],
+        [Clut2x2, new Vector4(0.25f, 0.75f, 0, 0), new Vector4(0.4f, 0.6f, 0, 0)],
+        [Clut2x1, new Vector4(0.25f, 0.75f, 0, 0), new Vector4(0.4f, 0, 0, 0)],
+        [Clut1x2, new Vector4(0.25f, 0, 0, 0), new Vector4(0.125f, 0.625f, 0, 0)],
+        [Clut1x1, new Vector4(0.25f, 0, 0, 0), new Vector4(0.25f, 0, 0, 0)],
+    ];
+}
diff --git a/tests/ImageSharp.Tests/TestDataIcc/Conversion/IccConversionDataLut.cs b/tests/ImageSharp.Tests/TestDataIcc/Conversion/IccConversionDataLut.cs
new file mode 100644
index 0000000000..e910038efb
--- /dev/null
+++ b/tests/ImageSharp.Tests/TestDataIcc/Conversion/IccConversionDataLut.cs
@@ -0,0 +1,30 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+namespace SixLabors.ImageSharp.Tests.TestDataIcc.Conversion;
+
+public class IccConversionDataLut
+{
+    private static readonly float[] LutEven = { 0, 0.5f, 1 };
+
+    private static readonly float[] LutUneven = { 0, 0.7f, 1 };
+
+    public static object[][] LutConversionTestData =
+    {
+        new object[] { LutEven, false,  0.5f, 0.5f },
+        new object[] { LutEven, false,  0.25f, 0.25f },
+        new object[] { LutEven, false,  0.75f, 0.75f },
+
+        new object[] { LutEven, true,  0.5f, 0.5f },
+        new object[] { LutEven, true,  0.25f, 0.25f },
+        new object[] { LutEven, true,  0.75f, 0.75f },
+
+        new object[] { LutUneven, false, 0.1, 0.14 },
+        new object[] { LutUneven, false, 0.5, 0.7 },
+        new object[] { LutUneven, false, 0.75, 0.85 },
+
+        new object[] { LutUneven, true, 0.14, 0.1 },
+        new object[] { LutUneven, true, 0.7, 0.5 },
+        new object[] { LutUneven, true, 0.85, 0.75 },
+    };
+}
diff --git a/tests/ImageSharp.Tests/TestDataIcc/Conversion/IccConversionDataLutAB.cs b/tests/ImageSharp.Tests/TestDataIcc/Conversion/IccConversionDataLutAB.cs
new file mode 100644
index 0000000000..02fc23735b
--- /dev/null
+++ b/tests/ImageSharp.Tests/TestDataIcc/Conversion/IccConversionDataLutAB.cs
@@ -0,0 +1,50 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Numerics;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.Tests.TestDataIcc.Conversion;
+
+public class IccConversionDataLutAB
+{
+    private static readonly IccLutAToBTagDataEntry LutAtoBSingleCurve = new(
+       new IccTagDataEntry[]
+       {
+           IccConversionDataTrc.IdentityCurve,
+           IccConversionDataTrc.IdentityCurve,
+           IccConversionDataTrc.IdentityCurve
+       },
+       null,
+       null,
+       null,
+       null,
+       null);
+
+    // also need:
+    // # CurveM + matrix
+    // # CurveA + CLUT + CurveB
+    // # CurveA + CLUT + CurveM + Matrix + CurveB
+    private static readonly IccLutBToATagDataEntry LutBtoASingleCurve = new(
+       new IccTagDataEntry[]
+       {
+           IccConversionDataTrc.IdentityCurve,
+           IccConversionDataTrc.IdentityCurve,
+           IccConversionDataTrc.IdentityCurve
+       },
+       null,
+       null,
+       null,
+       null,
+       null);
+
+    public static object[][] LutAToBConversionTestData =
+    {
+        new object[] { LutAtoBSingleCurve, new Vector4(0.2f, 0.3f, 0.4f, 0), new Vector4(0.2f, 0.3f, 0.4f, 0) },
+    };
+
+    public static object[][] LutBToAConversionTestData =
+    {
+        new object[] { LutBtoASingleCurve, new Vector4(0.2f, 0.3f, 0.4f, 0), new Vector4(0.2f, 0.3f, 0.4f, 0) },
+    };
+}
diff --git a/tests/ImageSharp.Tests/TestDataIcc/Conversion/IccConversionDataLutEntry.cs b/tests/ImageSharp.Tests/TestDataIcc/Conversion/IccConversionDataLutEntry.cs
new file mode 100644
index 0000000000..40f54ea74c
--- /dev/null
+++ b/tests/ImageSharp.Tests/TestDataIcc/Conversion/IccConversionDataLutEntry.cs
@@ -0,0 +1,71 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Numerics;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.Tests.TestDataIcc.Conversion;
+
+public class IccConversionDataLutEntry
+{
+    private static readonly IccLut Lut256 = CreateLut(256);
+    private static readonly IccLut Lut32 = CreateLut(32);
+    private static readonly IccLut LutIdentity = CreateIdentityLut(0, 1);
+
+    // test cases were originally calculated unaware that
+    // IccConversionDataMatrix.Matrix3x3Random is actually the row-major transposed matrix
+    // of the typical column-major matrix
+    public static float[,] TestMatrix =
+    {
+        { 0.1f, 0.4f, 0.7f },
+        { 0.2f, 0.5f, 0.8f },
+        { 0.3f, 0.6f, 0.9f }
+    };
+
+    private static readonly IccLut8TagDataEntry Lut8 = new(
+        [Lut256, Lut256],
+        IccConversionDataClut.Clut2x1,
+        [Lut256]);
+
+    private static readonly IccLut16TagDataEntry Lut16 = new(
+        [Lut32, Lut32],
+        IccConversionDataClut.Clut2x1,
+        [LutIdentity]);
+
+    private static readonly IccLut8TagDataEntry Lut8Matrix = new(
+        TestMatrix,
+        [Lut256, Lut256, Lut256],
+        IccConversionDataClut.Clut3x1,
+        [Lut256]);
+
+    private static readonly IccLut16TagDataEntry Lut16Matrix = new(
+        TestMatrix,
+        [Lut32, Lut32, Lut32],
+        IccConversionDataClut.Clut3x1,
+        [LutIdentity]);
+
+    private static IccLut CreateLut(int length)
+    {
+        float[] values = new float[length];
+        for (int i = 0; i < values.Length; i++)
+        {
+            values[i] = 0.1f + (i / (float)length);
+        }
+
+        return new IccLut(values);
+    }
+
+    private static IccLut CreateIdentityLut(float min, float max) => new([min, max]);
+
+    public static object[][] Lut8ConversionTestData =
+    [
+        [Lut8, new Vector4(0.2f, 0.3f, 0, 0), new Vector4(0.4578933760499877f, 0, 0, 0)],
+        [Lut8Matrix, new Vector4(0.21f, 0.31f, 0.41f, 0), new Vector4(0.40099657491875312f, 0, 0, 0)]
+    ];
+
+    public static object[][] Lut16ConversionTestData =
+    [
+        [Lut16, new Vector4(0.2f, 0.3f, 0, 0), new Vector4(0.3543750030529918f, 0, 0, 0)],
+        [Lut16Matrix, new Vector4(0.21f, 0.31f, 0.41f, 0), new Vector4(0.29739562389689594f, 0, 0, 0)]
+    ];
+}
diff --git a/tests/ImageSharp.Tests/TestDataIcc/Conversion/IccConversionDataMatrix.cs b/tests/ImageSharp.Tests/TestDataIcc/Conversion/IccConversionDataMatrix.cs
new file mode 100644
index 0000000000..f91c32df8a
--- /dev/null
+++ b/tests/ImageSharp.Tests/TestDataIcc/Conversion/IccConversionDataMatrix.cs
@@ -0,0 +1,53 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Numerics;
+
+namespace SixLabors.ImageSharp.Tests.TestDataIcc.Conversion;
+
+public class IccConversionDataMatrix
+{
+    private static readonly Vector3 Vector3Zero = new(0.0f, 0.0f, 0.0f);
+
+    public static float[,] Matrix3x3Random =
+    {
+        { 0.1f, 0.2f, 0.3f },
+        { 0.4f, 0.5f, 0.6f },
+        { 0.7f, 0.8f, 0.9f }
+    };
+
+    public static float[,] Matrix3x3Identity =
+    {
+        { 1, 0, 0 },
+        { 0, 1, 0 },
+        { 0, 0, 1 }
+    };
+
+    public static object[][] MatrixConversionTestData =
+    {
+        new object[] { CreateMatrix(Matrix3x3Identity), Vector3Zero, new Vector4(0.5f, 0.5f, 0.5f, 0), new Vector4(0.5f, 0.5f, 0.5f, 0) },
+        new object[] { CreateMatrix(Matrix3x3Identity), new Vector3(0.2f, 0.2f, 0.2f), new Vector4(0.5f, 0.5f, 0.5f, 0), new Vector4(0.7f, 0.7f, 0.7f, 0) },
+        new object[] { CreateMatrix(Matrix3x3Random), Vector3Zero, new Vector4(0.5f, 0.5f, 0.5f, 0), new Vector4(0.6f, 0.75f, 0.9f, 0) },
+        new object[] { CreateMatrix(Matrix3x3Random), new Vector3(0.1f, 0.2f, 0.3f), new Vector4(0.5f, 0.5f, 0.5f, 0), new Vector4(0.7f, 0.95f, 1.2f, 0) },
+        new object[] { CreateMatrix(Matrix3x3Random), Vector3Zero, new Vector4(0.2f, 0.4f, 0.7f, 0), new Vector4(0.67f, 0.8f, 0.93f, 0) },
+        new object[] { CreateMatrix(Matrix3x3Random), new Vector3(0.1f, 0.2f, 0.3f), new Vector4(0.2f, 0.4f, 0.7f, 0), new Vector4(0.77f, 1, 1.23f, 0) },
+    };
+
+    private static Matrix4x4 CreateMatrix(float[,] matrix) => new(
+            matrix[0, 0],
+            matrix[0, 1],
+            matrix[0, 2],
+            0,
+            matrix[1, 0],
+            matrix[1, 1],
+            matrix[1, 2],
+            0,
+            matrix[2, 0],
+            matrix[2, 1],
+            matrix[2, 2],
+            0,
+            0,
+            0,
+            0,
+            1);
+}
diff --git a/tests/ImageSharp.Tests/TestDataIcc/Conversion/IccConversionDataMultiProcessElement.cs b/tests/ImageSharp.Tests/TestDataIcc/Conversion/IccConversionDataMultiProcessElement.cs
new file mode 100644
index 0000000000..e4adba078d
--- /dev/null
+++ b/tests/ImageSharp.Tests/TestDataIcc/Conversion/IccConversionDataMultiProcessElement.cs
@@ -0,0 +1,80 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.Tests.TestDataIcc.Conversion;
+
+public class IccConversionDataMultiProcessElement
+{
+    private static readonly IccMatrixProcessElement Matrix = new(
+        new float[,]
+    {
+        { 2, 4, 6 },
+        { 3, 5, 7 },
+    },
+        new float[] { 3, 4, 5 });
+
+    private static readonly IccClut Clut = new(
+        new[]
+        {
+            0.2f, 0.3f,
+            0.4f, 0.2f,
+
+            0.21f, 0.31f,
+            0.41f, 0.51f,
+
+            0.22f, 0.32f,
+            0.42f, 0.52f,
+
+            0.23f, 0.33f,
+            0.43f, 0.53f,
+        },
+        new byte[] { 2, 2, 2 },
+        IccClutDataType.Float,
+        outputChannelCount: 2);
+
+    private static readonly IccFormulaCurveElement FormulaCurveElement1 = new(IccFormulaCurveType.Type1, 2.2f, 0.7f, 0.2f, 0.3f, 0, 0);
+    private static readonly IccFormulaCurveElement FormulaCurveElement2 = new(IccFormulaCurveType.Type2, 2.2f, 0.9f, 0.9f, 0.02f, 0.1f, 0);
+    private static readonly IccFormulaCurveElement FormulaCurveElement3 = new(IccFormulaCurveType.Type3, 0, 0.9f, 0.9f, 1.02f, 0.1f, 0.02f);
+
+    private static readonly IccCurveSetProcessElement CurveSet1DFormula1 = Create1DSingleCurveSet(FormulaCurveElement1);
+    private static readonly IccCurveSetProcessElement CurveSet1DFormula2 = Create1DSingleCurveSet(FormulaCurveElement2);
+    private static readonly IccCurveSetProcessElement CurveSet1DFormula3 = Create1DSingleCurveSet(FormulaCurveElement3);
+
+    private static readonly IccCurveSetProcessElement CurveSet1DFormula1And2 = Create1DMultiCurveSet(new[] { 0.5f }, FormulaCurveElement1, FormulaCurveElement2);
+
+    private static readonly IccClutProcessElement ClutElement = new(Clut);
+
+    private static IccCurveSetProcessElement Create1DSingleCurveSet(IccCurveSegment segment)
+    {
+        var curve = new IccOneDimensionalCurve(new float[0], new[] { segment });
+        return new IccCurveSetProcessElement(new[] { curve });
+    }
+
+    private static IccCurveSetProcessElement Create1DMultiCurveSet(float[] breakPoints, params IccCurveSegment[] segments)
+    {
+        var curve = new IccOneDimensionalCurve(breakPoints, segments);
+        return new IccCurveSetProcessElement(new[] { curve });
+    }
+
+    public static object[][] MpeCurveConversionTestData =
+    {
+        new object[] { CurveSet1DFormula1, new[] { 0.51f }, new[] { 0.575982451f } },
+        new object[] { CurveSet1DFormula2, new[] { 0.52f }, new[] { -0.4684991f } },
+        new object[] { CurveSet1DFormula3, new[] { 0.53f }, new[] { 0.86126f } },
+
+        new object[] { CurveSet1DFormula1And2, new[] { 0.31f }, new[] { 0.445982f } },
+        new object[] { CurveSet1DFormula1And2, new[] { 0.61f }, new[] { -0.341274023f } },
+    };
+
+    public static object[][] MpeMatrixConversionTestData =
+    {
+        new object[] { Matrix, new float[] { 2, 4 }, new float[] { 19, 32, 45 } }
+    };
+
+    public static object[][] MpeClutConversionTestData =
+    {
+        new object[] { ClutElement, new[] { 0.5f, 0.5f, 0.5f }, new[] { 0.5f, 0.5f } }
+    };
+}
diff --git a/tests/ImageSharp.Tests/TestDataIcc/Conversion/IccConversionDataTrc.cs b/tests/ImageSharp.Tests/TestDataIcc/Conversion/IccConversionDataTrc.cs
new file mode 100644
index 0000000000..6cd99367a9
--- /dev/null
+++ b/tests/ImageSharp.Tests/TestDataIcc/Conversion/IccConversionDataTrc.cs
@@ -0,0 +1,76 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Numerics;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+
+namespace SixLabors.ImageSharp.Tests.TestDataIcc.Conversion;
+
+public static class IccConversionDataTrc
+{
+    internal static IccCurveTagDataEntry IdentityCurve = new();
+    internal static IccCurveTagDataEntry Gamma2Curve = new(2);
+    internal static IccCurveTagDataEntry LutCurve = new(new float[] { 0, 0.7f, 1 });
+
+    internal static IccParametricCurveTagDataEntry ParamCurve1 = new(new IccParametricCurve(2.2f));
+    internal static IccParametricCurveTagDataEntry ParamCurve2 = new(new IccParametricCurve(2.2f, 1.5f, -0.5f));
+    internal static IccParametricCurveTagDataEntry ParamCurve3 = new(new IccParametricCurve(2.2f, 1.5f, -0.5f, 0.3f));
+    internal static IccParametricCurveTagDataEntry ParamCurve4 = new(new IccParametricCurve(2.4f, 1 / 1.055f, 0.055f / 1.055f, 1 / 12.92f, 0.04045f));
+    internal static IccParametricCurveTagDataEntry ParamCurve5 = new(new IccParametricCurve(2.2f, 0.7f, 0.2f, 0.3f, 0.1f, 0.5f, 0.2f));
+
+    public static object[][] TrcArrayConversionTestData { get; } =
+    {
+        new object[]
+        {
+            new IccTagDataEntry[] { IdentityCurve, Gamma2Curve, ParamCurve1 },
+            false,
+            new Vector4(2, 2, 0.5f, 0),
+            new Vector4(2, 4, 0.217637628f, 0),
+        },
+        new object[]
+        {
+            new IccTagDataEntry[] { IdentityCurve, Gamma2Curve, ParamCurve1 },
+            true,
+            new Vector4(1, 4, 0.217637628f, 0),
+            new Vector4(1, 2, 0.5f, 0),
+        },
+    };
+
+    public static object[][] CurveConversionTestData { get; } =
+    {
+        new object[] { IdentityCurve, false, 2, 2 },
+        new object[] { Gamma2Curve, false, 2, 4 },
+        new object[] { LutCurve, false, 0.1, 0.14 },
+        new object[] { LutCurve, false, 0.5, 0.7 },
+        new object[] { LutCurve, false, 0.75, 0.85 },
+
+        new object[] { IdentityCurve, true, 2, 2 },
+        new object[] { Gamma2Curve, true, 4, 2 },
+        new object[] { LutCurve, true, 0.14, 0.1 },
+        new object[] { LutCurve, true, 0.7, 0.5 },
+        new object[] { LutCurve, true, 0.85, 0.75 },
+    };
+
+    public static object[][] ParametricCurveConversionTestData { get; } =
+    {
+        new object[] { ParamCurve1, false, 0.5f, 0.217637628f },
+        new object[] { ParamCurve2, false, 0.6f, 0.133208528f },
+        new object[] { ParamCurve2, false, 0.21f, 0 },
+        new object[] { ParamCurve3, false, 0.61f, 0.444446117f },
+        new object[] { ParamCurve3, false, 0.22f, 0.3f },
+        new object[] { ParamCurve4, false, 0.3f, 0.0732389539f },
+        new object[] { ParamCurve4, false, 0.03f, 0.00232198136f },
+        new object[] { ParamCurve5, false, 0.2f, 0.593165159f },
+        new object[] { ParamCurve5, false, 0.05f, 0.215f },
+
+        new object[] { ParamCurve1, true, 0.217637628f, 0.5f },
+        new object[] { ParamCurve2, true, 0.133208528f, 0.6f },
+        new object[] { ParamCurve2, true, 0, 1 / 3f },
+        new object[] { ParamCurve3, true, 0.444446117f, 0.61f },
+        new object[] { ParamCurve3, true, 0.3f, 1 / 3f },
+        new object[] { ParamCurve4, true, 0.0732389539f, 0.3f },
+        new object[] { ParamCurve4, true, 0.00232198136f, 0.03f },
+        new object[] { ParamCurve5, true, 0.593165159f, 0.2f },
+        new object[] { ParamCurve5, true, 0.215f, 0.05f },
+    };
+}
diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataArray.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataArray.cs
index 8288a294dd..cedd20f2d7 100644
--- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataArray.cs
+++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataArray.cs
@@ -1,7 +1,7 @@
 // Copyright (c) Six Labors.
 // Licensed under the Six Labors Split License.
 
-namespace SixLabors.ImageSharp.Tests;
+namespace SixLabors.ImageSharp.Tests.TestDataIcc;
 
 internal static class IccTestDataArray
 {
@@ -12,98 +12,98 @@ internal static class IccTestDataArray
         new object[] { UInt8, UInt8 }
     };
 
-    public static readonly ushort[] UInt16_Val = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+    public static readonly ushort[] UInt16Val = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
 
-    public static readonly byte[] UInt16_Arr = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt16_0,
-        IccTestDataPrimitives.UInt16_1,
-        IccTestDataPrimitives.UInt16_2,
-        IccTestDataPrimitives.UInt16_3,
-        IccTestDataPrimitives.UInt16_4,
-        IccTestDataPrimitives.UInt16_5,
-        IccTestDataPrimitives.UInt16_6,
-        IccTestDataPrimitives.UInt16_7,
-        IccTestDataPrimitives.UInt16_8,
-        IccTestDataPrimitives.UInt16_9);
+    public static readonly byte[] UInt16Arr = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt160,
+        IccTestDataPrimitives.UInt161,
+        IccTestDataPrimitives.UInt162,
+        IccTestDataPrimitives.UInt163,
+        IccTestDataPrimitives.UInt164,
+        IccTestDataPrimitives.UInt165,
+        IccTestDataPrimitives.UInt166,
+        IccTestDataPrimitives.UInt167,
+        IccTestDataPrimitives.UInt168,
+        IccTestDataPrimitives.UInt169);
 
     public static readonly object[][] UInt16TestData =
     {
-        new object[] { UInt16_Arr, UInt16_Val }
+        new object[] { UInt16Arr, UInt16Val }
     };
 
-    public static readonly short[] Int16_Val = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+    public static readonly short[] Int16Val = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
 
-    public static readonly byte[] Int16_Arr = ArrayHelper.Concat(
-        IccTestDataPrimitives.Int16_0,
-        IccTestDataPrimitives.Int16_1,
-        IccTestDataPrimitives.Int16_2,
-        IccTestDataPrimitives.Int16_3,
-        IccTestDataPrimitives.Int16_4,
-        IccTestDataPrimitives.Int16_5,
-        IccTestDataPrimitives.Int16_6,
-        IccTestDataPrimitives.Int16_7,
-        IccTestDataPrimitives.Int16_8,
-        IccTestDataPrimitives.Int16_9);
+    public static readonly byte[] Int16Arr = ArrayHelper.Concat(
+        IccTestDataPrimitives.Int160,
+        IccTestDataPrimitives.Int161,
+        IccTestDataPrimitives.Int162,
+        IccTestDataPrimitives.Int163,
+        IccTestDataPrimitives.Int164,
+        IccTestDataPrimitives.Int165,
+        IccTestDataPrimitives.Int166,
+        IccTestDataPrimitives.Int167,
+        IccTestDataPrimitives.Int168,
+        IccTestDataPrimitives.Int169);
 
     public static readonly object[][] Int16TestData =
     {
-        new object[] { Int16_Arr, Int16_Val }
+        new object[] { Int16Arr, Int16Val }
     };
 
-    public static readonly uint[] UInt32_Val = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+    public static readonly uint[] UInt32Val = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
 
-    public static readonly byte[] UInt32_Arr = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt32_0,
-        IccTestDataPrimitives.UInt32_1,
-        IccTestDataPrimitives.UInt32_2,
-        IccTestDataPrimitives.UInt32_3,
-        IccTestDataPrimitives.UInt32_4,
-        IccTestDataPrimitives.UInt32_5,
-        IccTestDataPrimitives.UInt32_6,
-        IccTestDataPrimitives.UInt32_7,
-        IccTestDataPrimitives.UInt32_8,
-        IccTestDataPrimitives.UInt32_9);
+    public static readonly byte[] UInt32Arr = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt320,
+        IccTestDataPrimitives.UInt321,
+        IccTestDataPrimitives.UInt322,
+        IccTestDataPrimitives.UInt323,
+        IccTestDataPrimitives.UInt324,
+        IccTestDataPrimitives.UInt325,
+        IccTestDataPrimitives.UInt326,
+        IccTestDataPrimitives.UInt327,
+        IccTestDataPrimitives.UInt328,
+        IccTestDataPrimitives.UInt329);
 
     public static readonly object[][] UInt32TestData =
     {
-        new object[] { UInt32_Arr, UInt32_Val }
+        new object[] { UInt32Arr, UInt32Val }
     };
 
-    public static readonly int[] Int32_Val = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+    public static readonly int[] Int32Val = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
 
-    public static readonly byte[] Int32_Arr = ArrayHelper.Concat(
-        IccTestDataPrimitives.Int32_0,
-        IccTestDataPrimitives.Int32_1,
-        IccTestDataPrimitives.Int32_2,
-        IccTestDataPrimitives.Int32_3,
-        IccTestDataPrimitives.Int32_4,
-        IccTestDataPrimitives.Int32_5,
-        IccTestDataPrimitives.Int32_6,
-        IccTestDataPrimitives.Int32_7,
-        IccTestDataPrimitives.Int32_8,
-        IccTestDataPrimitives.Int32_9);
+    public static readonly byte[] Int32Arr = ArrayHelper.Concat(
+        IccTestDataPrimitives.Int320,
+        IccTestDataPrimitives.Int321,
+        IccTestDataPrimitives.Int322,
+        IccTestDataPrimitives.Int323,
+        IccTestDataPrimitives.Int324,
+        IccTestDataPrimitives.Int325,
+        IccTestDataPrimitives.Int326,
+        IccTestDataPrimitives.Int327,
+        IccTestDataPrimitives.Int328,
+        IccTestDataPrimitives.Int329);
 
     public static readonly object[][] Int32TestData =
     {
-        new object[] { Int32_Arr, Int32_Val }
+        new object[] { Int32Arr, Int32Val }
     };
 
-    public static readonly ulong[] UInt64_Val = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+    public static readonly ulong[] UInt64Val = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
 
-    public static readonly byte[] UInt64_Arr = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt64_0,
-        IccTestDataPrimitives.UInt64_1,
-        IccTestDataPrimitives.UInt64_2,
-        IccTestDataPrimitives.UInt64_3,
-        IccTestDataPrimitives.UInt64_4,
-        IccTestDataPrimitives.UInt64_5,
-        IccTestDataPrimitives.UInt64_6,
-        IccTestDataPrimitives.UInt64_7,
-        IccTestDataPrimitives.UInt64_8,
-        IccTestDataPrimitives.UInt64_9);
+    public static readonly byte[] UInt64Arr = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt640,
+        IccTestDataPrimitives.UInt641,
+        IccTestDataPrimitives.UInt642,
+        IccTestDataPrimitives.UInt643,
+        IccTestDataPrimitives.UInt644,
+        IccTestDataPrimitives.UInt645,
+        IccTestDataPrimitives.UInt646,
+        IccTestDataPrimitives.UInt647,
+        IccTestDataPrimitives.UInt648,
+        IccTestDataPrimitives.UInt649);
 
     public static readonly object[][] UInt64TestData =
     {
-        new object[] { UInt64_Arr, UInt64_Val }
+        new object[] { UInt64Arr, UInt64Val }
     };
 }
diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataCurves.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataCurves.cs
index f76d2ba036..6f8244f1c7 100644
--- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataCurves.cs
+++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataCurves.cs
@@ -3,309 +3,309 @@
 
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
 
-namespace SixLabors.ImageSharp.Tests;
+namespace SixLabors.ImageSharp.Tests.TestDataIcc;
 
 internal static class IccTestDataCurves
 {
     /// <summary>
     /// Channels: 3
     /// </summary>
-    public static readonly IccResponseCurve Response_ValGrad = new IccResponseCurve(
+    public static readonly IccResponseCurve ResponseValGrad = new(
         IccCurveMeasurementEncodings.StatusA,
         new[]
         {
-            IccTestDataNonPrimitives.XyzNumber_ValVar1,
-            IccTestDataNonPrimitives.XyzNumber_ValVar2,
-            IccTestDataNonPrimitives.XyzNumber_ValVar3
+            IccTestDataNonPrimitives.XyzNumberValVar1,
+            IccTestDataNonPrimitives.XyzNumberValVar2,
+            IccTestDataNonPrimitives.XyzNumberValVar3
         },
-        new IccResponseNumber[][]
+        new[]
         {
-            new IccResponseNumber[] { IccTestDataNonPrimitives.ResponseNumber_Val1, IccTestDataNonPrimitives.ResponseNumber_Val2 },
-            new IccResponseNumber[] { IccTestDataNonPrimitives.ResponseNumber_Val3, IccTestDataNonPrimitives.ResponseNumber_Val4 },
-            new IccResponseNumber[] { IccTestDataNonPrimitives.ResponseNumber_Val5, IccTestDataNonPrimitives.ResponseNumber_Val6 },
+            new[] { IccTestDataNonPrimitives.ResponseNumberVal1, IccTestDataNonPrimitives.ResponseNumberVal2 },
+            new[] { IccTestDataNonPrimitives.ResponseNumberVal3, IccTestDataNonPrimitives.ResponseNumberVal4 },
+            new[] { IccTestDataNonPrimitives.ResponseNumberVal5, IccTestDataNonPrimitives.ResponseNumberVal6 },
         });
 
     /// <summary>
     /// Channels: 3
     /// </summary>
-    public static readonly byte[] Response_Grad = ArrayHelper.Concat(
+    public static readonly byte[] ResponseGrad = ArrayHelper.Concat(
         new byte[] { 0x53, 0x74, 0x61, 0x41 },
-        IccTestDataPrimitives.UInt32_2,
-        IccTestDataPrimitives.UInt32_2,
-        IccTestDataPrimitives.UInt32_2,
-        IccTestDataNonPrimitives.XyzNumber_Var1,
-        IccTestDataNonPrimitives.XyzNumber_Var2,
-        IccTestDataNonPrimitives.XyzNumber_Var3,
-        IccTestDataNonPrimitives.ResponseNumber_1,
-        IccTestDataNonPrimitives.ResponseNumber_2,
-        IccTestDataNonPrimitives.ResponseNumber_3,
-        IccTestDataNonPrimitives.ResponseNumber_4,
-        IccTestDataNonPrimitives.ResponseNumber_5,
-        IccTestDataNonPrimitives.ResponseNumber_6);
+        IccTestDataPrimitives.UInt322,
+        IccTestDataPrimitives.UInt322,
+        IccTestDataPrimitives.UInt322,
+        IccTestDataNonPrimitives.XyzNumberVar1,
+        IccTestDataNonPrimitives.XyzNumberVar2,
+        IccTestDataNonPrimitives.XyzNumberVar3,
+        IccTestDataNonPrimitives.ResponseNumber1,
+        IccTestDataNonPrimitives.ResponseNumber2,
+        IccTestDataNonPrimitives.ResponseNumber3,
+        IccTestDataNonPrimitives.ResponseNumber4,
+        IccTestDataNonPrimitives.ResponseNumber5,
+        IccTestDataNonPrimitives.ResponseNumber6);
 
     public static readonly object[][] ResponseCurveTestData =
     {
-        new object[] { Response_Grad, Response_ValGrad, 3 },
+        new object[] { ResponseGrad, ResponseValGrad, 3 },
     };
 
-    public static readonly IccParametricCurve Parametric_ValVar1 = new IccParametricCurve(1);
-    public static readonly IccParametricCurve Parametric_ValVar2 = new IccParametricCurve(1, 2, 3);
-    public static readonly IccParametricCurve Parametric_ValVar3 = new IccParametricCurve(1, 2, 3, 4);
-    public static readonly IccParametricCurve Parametric_ValVar4 = new IccParametricCurve(1, 2, 3, 4, 5);
-    public static readonly IccParametricCurve Parametric_ValVar5 = new IccParametricCurve(1, 2, 3, 4, 5, 6, 7);
+    public static readonly IccParametricCurve ParametricValVar1 = new(1);
+    public static readonly IccParametricCurve ParametricValVar2 = new(1, 2, 3);
+    public static readonly IccParametricCurve ParametricValVar3 = new(1, 2, 3, 4);
+    public static readonly IccParametricCurve ParametricValVar4 = new(1, 2, 3, 4, 5);
+    public static readonly IccParametricCurve ParametricValVar5 = new(1, 2, 3, 4, 5, 6, 7);
 
-    public static readonly byte[] Parametric_Var1 = ArrayHelper.Concat(
+    public static readonly byte[] ParametricVar1 = ArrayHelper.Concat(
         new byte[]
         {
             0x00, 0x00,
             0x00, 0x00,
         },
-        IccTestDataPrimitives.Fix16_1);
+        IccTestDataPrimitives.Fix161);
 
-    public static readonly byte[] Parametric_Var2 = ArrayHelper.Concat(
+    public static readonly byte[] ParametricVar2 = ArrayHelper.Concat(
         new byte[]
         {
             0x00, 0x01,
             0x00, 0x00,
         },
-        IccTestDataPrimitives.Fix16_1,
-        IccTestDataPrimitives.Fix16_2,
-        IccTestDataPrimitives.Fix16_3);
+        IccTestDataPrimitives.Fix161,
+        IccTestDataPrimitives.Fix162,
+        IccTestDataPrimitives.Fix163);
 
-    public static readonly byte[] Parametric_Var3 = ArrayHelper.Concat(
+    public static readonly byte[] ParametricVar3 = ArrayHelper.Concat(
         new byte[]
         {
             0x00, 0x02,
             0x00, 0x00,
         },
-        IccTestDataPrimitives.Fix16_1,
-        IccTestDataPrimitives.Fix16_2,
-        IccTestDataPrimitives.Fix16_3,
-        IccTestDataPrimitives.Fix16_4);
+        IccTestDataPrimitives.Fix161,
+        IccTestDataPrimitives.Fix162,
+        IccTestDataPrimitives.Fix163,
+        IccTestDataPrimitives.Fix164);
 
-    public static readonly byte[] Parametric_Var4 = ArrayHelper.Concat(
+    public static readonly byte[] ParametricVar4 = ArrayHelper.Concat(
         new byte[]
         {
             0x00, 0x03,
             0x00, 0x00,
         },
-        IccTestDataPrimitives.Fix16_1,
-        IccTestDataPrimitives.Fix16_2,
-        IccTestDataPrimitives.Fix16_3,
-        IccTestDataPrimitives.Fix16_4,
-        IccTestDataPrimitives.Fix16_5);
+        IccTestDataPrimitives.Fix161,
+        IccTestDataPrimitives.Fix162,
+        IccTestDataPrimitives.Fix163,
+        IccTestDataPrimitives.Fix164,
+        IccTestDataPrimitives.Fix165);
 
-    public static readonly byte[] Parametric_Var5 = ArrayHelper.Concat(
+    public static readonly byte[] ParametricVar5 = ArrayHelper.Concat(
         new byte[]
         {
             0x00, 0x04,
             0x00, 0x00,
         },
-        IccTestDataPrimitives.Fix16_1,
-        IccTestDataPrimitives.Fix16_2,
-        IccTestDataPrimitives.Fix16_3,
-        IccTestDataPrimitives.Fix16_4,
-        IccTestDataPrimitives.Fix16_5,
-        IccTestDataPrimitives.Fix16_6,
-        IccTestDataPrimitives.Fix16_7);
+        IccTestDataPrimitives.Fix161,
+        IccTestDataPrimitives.Fix162,
+        IccTestDataPrimitives.Fix163,
+        IccTestDataPrimitives.Fix164,
+        IccTestDataPrimitives.Fix165,
+        IccTestDataPrimitives.Fix166,
+        IccTestDataPrimitives.Fix167);
 
     public static readonly object[][] ParametricCurveTestData =
     {
-        new object[] { Parametric_Var1, Parametric_ValVar1 },
-        new object[] { Parametric_Var2, Parametric_ValVar2 },
-        new object[] { Parametric_Var3, Parametric_ValVar3 },
-        new object[] { Parametric_Var4, Parametric_ValVar4 },
-        new object[] { Parametric_Var5, Parametric_ValVar5 },
+        new object[] { ParametricVar1, ParametricValVar1 },
+        new object[] { ParametricVar2, ParametricValVar2 },
+        new object[] { ParametricVar3, ParametricValVar3 },
+        new object[] { ParametricVar4, ParametricValVar4 },
+        new object[] { ParametricVar5, ParametricValVar5 },
     };
 
     // Formula Segment
-    public static readonly IccFormulaCurveElement Formula_ValVar1 = new IccFormulaCurveElement(IccFormulaCurveType.Type1, 1, 2, 3, 4, 0, 0);
-    public static readonly IccFormulaCurveElement Formula_ValVar2 = new IccFormulaCurveElement(IccFormulaCurveType.Type2, 1, 2, 3, 4, 5, 0);
-    public static readonly IccFormulaCurveElement Formula_ValVar3 = new IccFormulaCurveElement(IccFormulaCurveType.Type3, 0, 2, 3, 4, 5, 6);
+    public static readonly IccFormulaCurveElement FormulaValVar1 = new(IccFormulaCurveType.Type1, 1, 2, 3, 4, 0, 0);
+    public static readonly IccFormulaCurveElement FormulaValVar2 = new(IccFormulaCurveType.Type2, 1, 2, 3, 4, 5, 0);
+    public static readonly IccFormulaCurveElement FormulaValVar3 = new(IccFormulaCurveType.Type3, 0, 2, 3, 4, 5, 6);
 
-    public static readonly byte[] Formula_Var1 = ArrayHelper.Concat(
+    public static readonly byte[] FormulaVar1 = ArrayHelper.Concat(
         new byte[]
         {
             0x00, 0x00,
             0x00, 0x00,
         },
-        IccTestDataPrimitives.Single_1,
-        IccTestDataPrimitives.Single_2,
-        IccTestDataPrimitives.Single_3,
-        IccTestDataPrimitives.Single_4);
+        IccTestDataPrimitives.Single1,
+        IccTestDataPrimitives.Single2,
+        IccTestDataPrimitives.Single3,
+        IccTestDataPrimitives.Single4);
 
-    public static readonly byte[] Formula_Var2 = ArrayHelper.Concat(
+    public static readonly byte[] FormulaVar2 = ArrayHelper.Concat(
         new byte[]
         {
             0x00, 0x01,
             0x00, 0x00,
         },
-        IccTestDataPrimitives.Single_1,
-        IccTestDataPrimitives.Single_2,
-        IccTestDataPrimitives.Single_3,
-        IccTestDataPrimitives.Single_4,
-        IccTestDataPrimitives.Single_5);
+        IccTestDataPrimitives.Single1,
+        IccTestDataPrimitives.Single2,
+        IccTestDataPrimitives.Single3,
+        IccTestDataPrimitives.Single4,
+        IccTestDataPrimitives.Single5);
 
-    public static readonly byte[] Formula_Var3 = ArrayHelper.Concat(
+    public static readonly byte[] FormulaVar3 = ArrayHelper.Concat(
         new byte[]
         {
             0x00, 0x02,
             0x00, 0x00,
         },
-        IccTestDataPrimitives.Single_2,
-        IccTestDataPrimitives.Single_3,
-        IccTestDataPrimitives.Single_4,
-        IccTestDataPrimitives.Single_5,
-        IccTestDataPrimitives.Single_6);
+        IccTestDataPrimitives.Single2,
+        IccTestDataPrimitives.Single3,
+        IccTestDataPrimitives.Single4,
+        IccTestDataPrimitives.Single5,
+        IccTestDataPrimitives.Single6);
 
     public static readonly object[][] FormulaCurveSegmentTestData =
     {
-        new object[] { Formula_Var1, Formula_ValVar1 },
-        new object[] { Formula_Var2, Formula_ValVar2 },
-        new object[] { Formula_Var3, Formula_ValVar3 },
+        new object[] { FormulaVar1, FormulaValVar1 },
+        new object[] { FormulaVar2, FormulaValVar2 },
+        new object[] { FormulaVar3, FormulaValVar3 },
     };
 
     // Sampled Segment
-    public static readonly IccSampledCurveElement Sampled_ValGrad1 = new IccSampledCurveElement(new float[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
-    public static readonly IccSampledCurveElement Sampled_ValGrad2 = new IccSampledCurveElement(new float[] { 9, 8, 7, 6, 5, 4, 3, 2, 1 });
-
-    public static readonly byte[] Sampled_Grad1 = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt32_9,
-        IccTestDataPrimitives.Single_1,
-        IccTestDataPrimitives.Single_2,
-        IccTestDataPrimitives.Single_3,
-        IccTestDataPrimitives.Single_4,
-        IccTestDataPrimitives.Single_5,
-        IccTestDataPrimitives.Single_6,
-        IccTestDataPrimitives.Single_7,
-        IccTestDataPrimitives.Single_8,
-        IccTestDataPrimitives.Single_9);
-
-    public static readonly byte[] Sampled_Grad2 = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt32_9,
-        IccTestDataPrimitives.Single_9,
-        IccTestDataPrimitives.Single_8,
-        IccTestDataPrimitives.Single_7,
-        IccTestDataPrimitives.Single_6,
-        IccTestDataPrimitives.Single_5,
-        IccTestDataPrimitives.Single_4,
-        IccTestDataPrimitives.Single_3,
-        IccTestDataPrimitives.Single_2,
-        IccTestDataPrimitives.Single_1);
+    public static readonly IccSampledCurveElement SampledValGrad1 = new(new float[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
+    public static readonly IccSampledCurveElement SampledValGrad2 = new(new float[] { 9, 8, 7, 6, 5, 4, 3, 2, 1 });
+
+    public static readonly byte[] SampledGrad1 = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt329,
+        IccTestDataPrimitives.Single1,
+        IccTestDataPrimitives.Single2,
+        IccTestDataPrimitives.Single3,
+        IccTestDataPrimitives.Single4,
+        IccTestDataPrimitives.Single5,
+        IccTestDataPrimitives.Single6,
+        IccTestDataPrimitives.Single7,
+        IccTestDataPrimitives.Single8,
+        IccTestDataPrimitives.Single9);
+
+    public static readonly byte[] SampledGrad2 = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt329,
+        IccTestDataPrimitives.Single9,
+        IccTestDataPrimitives.Single8,
+        IccTestDataPrimitives.Single7,
+        IccTestDataPrimitives.Single6,
+        IccTestDataPrimitives.Single5,
+        IccTestDataPrimitives.Single4,
+        IccTestDataPrimitives.Single3,
+        IccTestDataPrimitives.Single2,
+        IccTestDataPrimitives.Single1);
 
     public static readonly object[][] SampledCurveSegmentTestData =
     {
-        new object[] { Sampled_Grad1, Sampled_ValGrad1 },
-        new object[] { Sampled_Grad2, Sampled_ValGrad2 },
+        new object[] { SampledGrad1, SampledValGrad1 },
+        new object[] { SampledGrad2, SampledValGrad2 },
     };
 
-    public static readonly IccCurveSegment Segment_ValFormula1 = Formula_ValVar1;
-    public static readonly IccCurveSegment Segment_ValFormula2 = Formula_ValVar2;
-    public static readonly IccCurveSegment Segment_ValFormula3 = Formula_ValVar3;
-    public static readonly IccCurveSegment Segment_ValSampled1 = Sampled_ValGrad1;
-    public static readonly IccCurveSegment Segment_ValSampled2 = Sampled_ValGrad2;
+    public static readonly IccCurveSegment SegmentValFormula1 = FormulaValVar1;
+    public static readonly IccCurveSegment SegmentValFormula2 = FormulaValVar2;
+    public static readonly IccCurveSegment SegmentValFormula3 = FormulaValVar3;
+    public static readonly IccCurveSegment SegmentValSampled1 = SampledValGrad1;
+    public static readonly IccCurveSegment SegmentValSampled2 = SampledValGrad2;
 
-    public static readonly byte[] Segment_Formula1 = ArrayHelper.Concat(
+    public static readonly byte[] SegmentFormula1 = ArrayHelper.Concat(
         new byte[]
         {
             0x70, 0x61, 0x72, 0x66,
             0x00, 0x00, 0x00, 0x00,
         },
-        Formula_Var1);
+        FormulaVar1);
 
-    public static readonly byte[] Segment_Formula2 = ArrayHelper.Concat(
+    public static readonly byte[] SegmentFormula2 = ArrayHelper.Concat(
         new byte[]
         {
             0x70, 0x61, 0x72, 0x66,
             0x00, 0x00, 0x00, 0x00,
         },
-        Formula_Var2);
+        FormulaVar2);
 
-    public static readonly byte[] Segment_Formula3 = ArrayHelper.Concat(
+    public static readonly byte[] SegmentFormula3 = ArrayHelper.Concat(
         new byte[]
         {
             0x70, 0x61, 0x72, 0x66,
             0x00, 0x00, 0x00, 0x00,
         },
-        Formula_Var3);
+        FormulaVar3);
 
-    public static readonly byte[] Segment_Sampled1 = ArrayHelper.Concat(
+    public static readonly byte[] SegmentSampled1 = ArrayHelper.Concat(
         new byte[]
         {
             0x73, 0x61, 0x6D, 0x66,
             0x00, 0x00, 0x00, 0x00,
         },
-        Sampled_Grad1);
+        SampledGrad1);
 
-    public static readonly byte[] Segment_Sampled2 = ArrayHelper.Concat(
+    public static readonly byte[] SegmentSampled2 = ArrayHelper.Concat(
         new byte[]
         {
             0x73, 0x61, 0x6D, 0x66,
             0x00, 0x00, 0x00, 0x00,
         },
-        Sampled_Grad2);
+        SampledGrad2);
 
     public static readonly object[][] CurveSegmentTestData =
     {
-        new object[] { Segment_Formula1, Segment_ValFormula1 },
-        new object[] { Segment_Formula2, Segment_ValFormula2 },
-        new object[] { Segment_Formula3, Segment_ValFormula3 },
-        new object[] { Segment_Sampled1, Segment_ValSampled1 },
-        new object[] { Segment_Sampled2, Segment_ValSampled2 },
+        new object[] { SegmentFormula1, SegmentValFormula1 },
+        new object[] { SegmentFormula2, SegmentValFormula2 },
+        new object[] { SegmentFormula3, SegmentValFormula3 },
+        new object[] { SegmentSampled1, SegmentValSampled1 },
+        new object[] { SegmentSampled2, SegmentValSampled2 },
     };
 
-    public static readonly IccOneDimensionalCurve OneDimensional_ValFormula1 = new IccOneDimensionalCurve(
+    public static readonly IccOneDimensionalCurve OneDimensionalValFormula1 = new(
         new float[] { 0, 1 },
-        new IccCurveSegment[] { Segment_ValFormula1, Segment_ValFormula2, Segment_ValFormula3 });
+        new[] { SegmentValFormula1, SegmentValFormula2, SegmentValFormula3 });
 
-    public static readonly IccOneDimensionalCurve OneDimensional_ValFormula2 = new IccOneDimensionalCurve(
+    public static readonly IccOneDimensionalCurve OneDimensionalValFormula2 = new(
         new float[] { 0, 1 },
-        new IccCurveSegment[] { Segment_ValFormula3, Segment_ValFormula2, Segment_ValFormula1 });
+        new[] { SegmentValFormula3, SegmentValFormula2, SegmentValFormula1 });
 
-    public static readonly IccOneDimensionalCurve OneDimensional_ValSampled = new IccOneDimensionalCurve(
+    public static readonly IccOneDimensionalCurve OneDimensionalValSampled = new(
         new float[] { 0, 1 },
-        new IccCurveSegment[] { Segment_ValSampled1, Segment_ValSampled2, Segment_ValSampled1 });
+        new[] { SegmentValSampled1, SegmentValSampled2, SegmentValSampled1 });
 
-    public static readonly byte[] OneDimensional_Formula1 = ArrayHelper.Concat(
+    public static readonly byte[] OneDimensionalFormula1 = ArrayHelper.Concat(
         new byte[]
         {
             0x00, 0x03,
             0x00, 0x00,
         },
-        IccTestDataPrimitives.Single_0,
-        IccTestDataPrimitives.Single_1,
-        Segment_Formula1,
-        Segment_Formula2,
-        Segment_Formula3);
+        IccTestDataPrimitives.Single0,
+        IccTestDataPrimitives.Single1,
+        SegmentFormula1,
+        SegmentFormula2,
+        SegmentFormula3);
 
-    public static readonly byte[] OneDimensional_Formula2 = ArrayHelper.Concat(
+    public static readonly byte[] OneDimensionalFormula2 = ArrayHelper.Concat(
         new byte[]
         {
             0x00, 0x03,
             0x00, 0x00,
         },
-        IccTestDataPrimitives.Single_0,
-        IccTestDataPrimitives.Single_1,
-        Segment_Formula3,
-        Segment_Formula2,
-        Segment_Formula1);
+        IccTestDataPrimitives.Single0,
+        IccTestDataPrimitives.Single1,
+        SegmentFormula3,
+        SegmentFormula2,
+        SegmentFormula1);
 
-    public static readonly byte[] OneDimensional_Sampled = ArrayHelper.Concat(
+    public static readonly byte[] OneDimensionalSampled = ArrayHelper.Concat(
         new byte[]
         {
             0x00, 0x03,
             0x00, 0x00,
         },
-        IccTestDataPrimitives.Single_0,
-        IccTestDataPrimitives.Single_1,
-        Segment_Sampled1,
-        Segment_Sampled2,
-        Segment_Sampled1);
+        IccTestDataPrimitives.Single0,
+        IccTestDataPrimitives.Single1,
+        SegmentSampled1,
+        SegmentSampled2,
+        SegmentSampled1);
 
     public static readonly object[][] OneDimensionalCurveTestData =
     {
-        new object[] { OneDimensional_Formula1, OneDimensional_ValFormula1 },
-        new object[] { OneDimensional_Formula2, OneDimensional_ValFormula2 },
-        new object[] { OneDimensional_Sampled, OneDimensional_ValSampled },
+        new object[] { OneDimensionalFormula1, OneDimensionalValFormula1 },
+        new object[] { OneDimensionalFormula2, OneDimensionalValFormula2 },
+        new object[] { OneDimensionalSampled, OneDimensionalValSampled },
     };
 }
diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataLut.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataLut.cs
index 7a778f269b..2bd47e4497 100644
--- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataLut.cs
+++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataLut.cs
@@ -3,14 +3,14 @@
 
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
 
-namespace SixLabors.ImageSharp.Tests;
+namespace SixLabors.ImageSharp.Tests.TestDataIcc;
 
 internal static class IccTestDataLut
 {
-    public static readonly IccLut LUT8_ValGrad = CreateLUT8Val();
-    public static readonly byte[] LUT8_Grad = CreateLUT8();
+    public static readonly IccLut Lut8ValGrad = CreateLut8Val();
+    public static readonly byte[] Lut8Grad = CreateLut8();
 
-    private static IccLut CreateLUT8Val()
+    private static IccLut CreateLut8Val()
     {
         float[] result = new float[256];
         for (int i = 0; i < 256; i++)
@@ -21,7 +21,7 @@ private static IccLut CreateLUT8Val()
         return new IccLut(result);
     }
 
-    private static byte[] CreateLUT8()
+    private static byte[] CreateLut8()
     {
         byte[] result = new byte[256];
         for (int i = 0; i < 256; i++)
@@ -34,10 +34,10 @@ private static byte[] CreateLUT8()
 
     public static readonly object[][] Lut8TestData =
     {
-        new object[] { LUT8_Grad, LUT8_ValGrad },
+        new object[] { Lut8Grad, Lut8ValGrad },
     };
 
-    public static readonly IccLut LUT16_ValGrad = new IccLut(new float[]
+    public static readonly IccLut Lut16ValGrad = new(new[]
     {
         1f / ushort.MaxValue,
         2f / ushort.MaxValue,
@@ -52,48 +52,49 @@ private static byte[] CreateLUT8()
         1f
     });
 
-    public static readonly byte[] LUT16_Grad = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt16_1,
-        IccTestDataPrimitives.UInt16_2,
-        IccTestDataPrimitives.UInt16_3,
-        IccTestDataPrimitives.UInt16_4,
-        IccTestDataPrimitives.UInt16_5,
-        IccTestDataPrimitives.UInt16_6,
-        IccTestDataPrimitives.UInt16_7,
-        IccTestDataPrimitives.UInt16_8,
-        IccTestDataPrimitives.UInt16_9,
-        IccTestDataPrimitives.UInt16_32768,
-        IccTestDataPrimitives.UInt16_Max);
+    public static readonly byte[] Lut16Grad = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt161,
+        IccTestDataPrimitives.UInt162,
+        IccTestDataPrimitives.UInt163,
+        IccTestDataPrimitives.UInt164,
+        IccTestDataPrimitives.UInt165,
+        IccTestDataPrimitives.UInt166,
+        IccTestDataPrimitives.UInt167,
+        IccTestDataPrimitives.UInt168,
+        IccTestDataPrimitives.UInt169,
+        IccTestDataPrimitives.UInt1632768,
+        IccTestDataPrimitives.UInt16Max);
 
     public static readonly object[][] Lut16TestData =
     {
-        new object[] { LUT16_Grad, LUT16_ValGrad, 11 },
+        new object[] { Lut16Grad, Lut16ValGrad, 11 },
     };
 
-    public static readonly IccClut CLUT8_ValGrad = new IccClut(
-        new float[][]
+    public static readonly IccClut Clut8ValGrad = new(
+        new[]
         {
-            new float[] { 1f / byte.MaxValue, 2f / byte.MaxValue, 3f / byte.MaxValue },
-            new float[] { 4f / byte.MaxValue, 5f / byte.MaxValue, 6f / byte.MaxValue },
-            new float[] { 7f / byte.MaxValue, 8f / byte.MaxValue, 9f / byte.MaxValue },
+            1f / byte.MaxValue, 2f / byte.MaxValue, 3f / byte.MaxValue,
+            4f / byte.MaxValue, 5f / byte.MaxValue, 6f / byte.MaxValue,
+            7f / byte.MaxValue, 8f / byte.MaxValue, 9f / byte.MaxValue,
 
-            new float[] { 10f / byte.MaxValue, 11f / byte.MaxValue, 12f / byte.MaxValue },
-            new float[] { 13f / byte.MaxValue, 14f / byte.MaxValue, 15f / byte.MaxValue },
-            new float[] { 16f / byte.MaxValue, 17f / byte.MaxValue, 18f / byte.MaxValue },
+            10f / byte.MaxValue, 11f / byte.MaxValue, 12f / byte.MaxValue,
+            13f / byte.MaxValue, 14f / byte.MaxValue, 15f / byte.MaxValue,
+            16f / byte.MaxValue, 17f / byte.MaxValue, 18f / byte.MaxValue,
 
-            new float[] { 19f / byte.MaxValue, 20f / byte.MaxValue, 21f / byte.MaxValue },
-            new float[] { 22f / byte.MaxValue, 23f / byte.MaxValue, 24f / byte.MaxValue },
-            new float[] { 25f / byte.MaxValue, 26f / byte.MaxValue, 27f / byte.MaxValue },
+            19f / byte.MaxValue, 20f / byte.MaxValue, 21f / byte.MaxValue,
+            22f / byte.MaxValue, 23f / byte.MaxValue, 24f / byte.MaxValue,
+            25f / byte.MaxValue, 26f / byte.MaxValue, 27f / byte.MaxValue,
         },
         new byte[] { 3, 3 },
-        IccClutDataType.UInt8);
+        IccClutDataType.UInt8,
+        outputChannelCount: 3);
 
     /// <summary>
     /// <para>Input Channel Count: 2</para>
     /// <para>Output Channel Count: 3</para>
     /// <para>Grid-point Count: { 3, 3 }</para>
     /// </summary>
-    public static readonly byte[] CLUT8_Grad =
+    public static readonly byte[] Clut8Grad =
     {
         0x01, 0x02, 0x03,
         0x04, 0x05, 0x06,
@@ -110,33 +111,34 @@ private static byte[] CreateLUT8()
 
     public static readonly object[][] Clut8TestData =
     {
-        new object[] { CLUT8_Grad, CLUT8_ValGrad, 2, 3, new byte[] { 3, 3 } },
+        new object[] { Clut8Grad, Clut8ValGrad, 2, 3, new byte[] { 3, 3 } },
     };
 
-    public static readonly IccClut CLUT16_ValGrad = new IccClut(
-        new float[][]
+    public static readonly IccClut Clut16ValGrad = new(
+        new[]
         {
-            new float[] { 1f / ushort.MaxValue, 2f / ushort.MaxValue, 3f / ushort.MaxValue },
-            new float[] { 4f / ushort.MaxValue, 5f / ushort.MaxValue, 6f / ushort.MaxValue },
-            new float[] { 7f / ushort.MaxValue, 8f / ushort.MaxValue, 9f / ushort.MaxValue },
+            1f / ushort.MaxValue, 2f / ushort.MaxValue, 3f / ushort.MaxValue,
+            4f / ushort.MaxValue, 5f / ushort.MaxValue, 6f / ushort.MaxValue,
+            7f / ushort.MaxValue, 8f / ushort.MaxValue, 9f / ushort.MaxValue,
 
-            new float[] { 10f / ushort.MaxValue, 11f / ushort.MaxValue, 12f / ushort.MaxValue },
-            new float[] { 13f / ushort.MaxValue, 14f / ushort.MaxValue, 15f / ushort.MaxValue },
-            new float[] { 16f / ushort.MaxValue, 17f / ushort.MaxValue, 18f / ushort.MaxValue },
+            10f / ushort.MaxValue, 11f / ushort.MaxValue, 12f / ushort.MaxValue,
+            13f / ushort.MaxValue, 14f / ushort.MaxValue, 15f / ushort.MaxValue,
+            16f / ushort.MaxValue, 17f / ushort.MaxValue, 18f / ushort.MaxValue,
 
-            new float[] { 19f / ushort.MaxValue, 20f / ushort.MaxValue, 21f / ushort.MaxValue },
-            new float[] { 22f / ushort.MaxValue, 23f / ushort.MaxValue, 24f / ushort.MaxValue },
-            new float[] { 25f / ushort.MaxValue, 26f / ushort.MaxValue, 27f / ushort.MaxValue },
+            19f / ushort.MaxValue, 20f / ushort.MaxValue, 21f / ushort.MaxValue,
+            22f / ushort.MaxValue, 23f / ushort.MaxValue, 24f / ushort.MaxValue,
+            25f / ushort.MaxValue, 26f / ushort.MaxValue, 27f / ushort.MaxValue,
         },
         new byte[] { 3, 3 },
-        IccClutDataType.UInt16);
+        IccClutDataType.UInt16,
+        outputChannelCount: 3);
 
     /// <summary>
     /// <para>Input Channel Count: 2</para>
     /// <para>Output Channel Count: 3</para>
     /// <para>Grid-point Count: { 3, 3 }</para>
     /// </summary>
-    public static readonly byte[] CLUT16_Grad =
+    public static readonly byte[] Clut16Grad =
     {
         0x00, 0x01, 0x00, 0x02, 0x00, 0x03,
         0x00, 0x04, 0x00, 0x05, 0x00, 0x06,
@@ -153,88 +155,89 @@ private static byte[] CreateLUT8()
 
     public static readonly object[][] Clut16TestData =
     {
-        new object[] { CLUT16_Grad, CLUT16_ValGrad, 2, 3, new byte[] { 3, 3 } },
+        new object[] { Clut16Grad, Clut16ValGrad, 2, 3, new byte[] { 3, 3 } },
     };
 
-    public static readonly IccClut CLUTf32_ValGrad = new IccClut(
-        new float[][]
+    public static readonly IccClut CluTf32ValGrad = new(
+        new[]
         {
-            new float[] { 1f, 2f, 3f },
-            new float[] { 4f, 5f, 6f },
-            new float[] { 7f, 8f, 9f },
+            1f, 2f, 3f,
+            4f, 5f, 6f,
+            7f, 8f, 9f,
 
-            new float[] { 1f, 2f, 3f },
-            new float[] { 4f, 5f, 6f },
-            new float[] { 7f, 8f, 9f },
+            1f, 2f, 3f,
+            4f, 5f, 6f,
+            7f, 8f, 9f,
 
-            new float[] { 1f, 2f, 3f },
-            new float[] { 4f, 5f, 6f },
-            new float[] { 7f, 8f, 9f },
+            1f, 2f, 3f,
+            4f, 5f, 6f,
+            7f, 8f, 9f,
         },
         new byte[] { 3, 3 },
-        IccClutDataType.Float);
+        IccClutDataType.Float,
+        outputChannelCount: 3);
 
     /// <summary>
     /// <para>Input Channel Count: 2</para>
     /// <para>Output Channel Count: 3</para>
     /// <para>Grid-point Count: { 3, 3 }</para>
     /// </summary>
-    public static readonly byte[] CLUTf32_Grad = ArrayHelper.Concat(
-        IccTestDataPrimitives.Single_1,
-        IccTestDataPrimitives.Single_2,
-        IccTestDataPrimitives.Single_3,
-        IccTestDataPrimitives.Single_4,
-        IccTestDataPrimitives.Single_5,
-        IccTestDataPrimitives.Single_6,
-        IccTestDataPrimitives.Single_7,
-        IccTestDataPrimitives.Single_8,
-        IccTestDataPrimitives.Single_9,
-        IccTestDataPrimitives.Single_1,
-        IccTestDataPrimitives.Single_2,
-        IccTestDataPrimitives.Single_3,
-        IccTestDataPrimitives.Single_4,
-        IccTestDataPrimitives.Single_5,
-        IccTestDataPrimitives.Single_6,
-        IccTestDataPrimitives.Single_7,
-        IccTestDataPrimitives.Single_8,
-        IccTestDataPrimitives.Single_9,
-        IccTestDataPrimitives.Single_1,
-        IccTestDataPrimitives.Single_2,
-        IccTestDataPrimitives.Single_3,
-        IccTestDataPrimitives.Single_4,
-        IccTestDataPrimitives.Single_5,
-        IccTestDataPrimitives.Single_6,
-        IccTestDataPrimitives.Single_7,
-        IccTestDataPrimitives.Single_8,
-        IccTestDataPrimitives.Single_9);
+    public static readonly byte[] CluTf32Grad = ArrayHelper.Concat(
+        IccTestDataPrimitives.Single1,
+        IccTestDataPrimitives.Single2,
+        IccTestDataPrimitives.Single3,
+        IccTestDataPrimitives.Single4,
+        IccTestDataPrimitives.Single5,
+        IccTestDataPrimitives.Single6,
+        IccTestDataPrimitives.Single7,
+        IccTestDataPrimitives.Single8,
+        IccTestDataPrimitives.Single9,
+        IccTestDataPrimitives.Single1,
+        IccTestDataPrimitives.Single2,
+        IccTestDataPrimitives.Single3,
+        IccTestDataPrimitives.Single4,
+        IccTestDataPrimitives.Single5,
+        IccTestDataPrimitives.Single6,
+        IccTestDataPrimitives.Single7,
+        IccTestDataPrimitives.Single8,
+        IccTestDataPrimitives.Single9,
+        IccTestDataPrimitives.Single1,
+        IccTestDataPrimitives.Single2,
+        IccTestDataPrimitives.Single3,
+        IccTestDataPrimitives.Single4,
+        IccTestDataPrimitives.Single5,
+        IccTestDataPrimitives.Single6,
+        IccTestDataPrimitives.Single7,
+        IccTestDataPrimitives.Single8,
+        IccTestDataPrimitives.Single9);
 
     public static readonly object[][] ClutF32TestData =
     {
-        new object[] { CLUTf32_Grad, CLUTf32_ValGrad, 2, 3, new byte[] { 3, 3 } },
+        new object[] { CluTf32Grad, CluTf32ValGrad, 2, 3, new byte[] { 3, 3 } },
     };
 
-    public static readonly IccClut CLUT_Val8 = CLUT8_ValGrad;
-    public static readonly IccClut CLUT_Val16 = CLUT16_ValGrad;
-    public static readonly IccClut CLUT_Valf32 = CLUTf32_ValGrad;
+    public static readonly IccClut ClutVal8 = Clut8ValGrad;
+    public static readonly IccClut ClutVal16 = Clut16ValGrad;
+    public static readonly IccClut ClutValf32 = CluTf32ValGrad;
 
-    public static readonly byte[] CLUT_8 = ArrayHelper.Concat(
+    public static readonly byte[] Clut8 = ArrayHelper.Concat(
         new byte[16] { 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
         new byte[4] { 0x01, 0x00, 0x00, 0x00 },
-        CLUT8_Grad);
+        Clut8Grad);
 
-    public static readonly byte[] CLUT_16 = ArrayHelper.Concat(
+    public static readonly byte[] Clut16 = ArrayHelper.Concat(
         new byte[16] { 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
         new byte[4] { 0x02, 0x00, 0x00, 0x00 },
-        CLUT16_Grad);
+        Clut16Grad);
 
-    public static readonly byte[] CLUT_f32 = ArrayHelper.Concat(
+    public static readonly byte[] ClutF32 = ArrayHelper.Concat(
         new byte[16] { 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-        CLUTf32_Grad);
+        CluTf32Grad);
 
     public static readonly object[][] ClutTestData =
     {
-        new object[] { CLUT_8, CLUT_Val8, 2, 3, false },
-        new object[] { CLUT_16, CLUT_Val16, 2, 3, false },
-        new object[] { CLUT_f32, CLUT_Valf32, 2, 3, true },
+        new object[] { Clut8, ClutVal8, 2, 3, false },
+        new object[] { Clut16, ClutVal16, 2, 3, false },
+        new object[] { ClutF32, ClutValf32, 2, 3, true },
     };
 }
diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataMatrix.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataMatrix.cs
index 94df8d69a6..1a72d39b19 100644
--- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataMatrix.cs
+++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataMatrix.cs
@@ -3,16 +3,14 @@
 
 using System.Numerics;
 
-namespace SixLabors.ImageSharp.Tests;
-
-using SixLabors.ImageSharp;
+namespace SixLabors.ImageSharp.Tests.TestDataIcc;
 
 internal static class IccTestDataMatrix
 {
     /// <summary>
     /// 3x3 Matrix
     /// </summary>
-    public static readonly float[,] Single_2DArray_ValGrad =
+    public static readonly float[,] Single2DArrayValGrad =
     {
         { 1, 2, 3 },
         { 4, 5, 6 },
@@ -22,7 +20,7 @@ internal static class IccTestDataMatrix
     /// <summary>
     /// 3x3 Matrix
     /// </summary>
-    public static readonly float[,] Single_2DArray_ValIdentity =
+    public static readonly float[,] Single2DArrayValIdentity =
     {
         { 1, 0, 0 },
         { 0, 1, 0 },
@@ -32,121 +30,121 @@ internal static class IccTestDataMatrix
     /// <summary>
     /// 3x3 Matrix
     /// </summary>
-    public static readonly Matrix4x4 Single_Matrix4x4_ValGrad = new Matrix4x4(1, 2, 3, 0, 4, 5, 6, 0, 7, 8, 9, 0, 0, 0, 0, 1);
+    public static readonly Matrix4x4 SingleMatrix4X4ValGrad = new(1, 2, 3, 0, 4, 5, 6, 0, 7, 8, 9, 0, 0, 0, 0, 1);
 
     /// <summary>
     /// 3x3 Matrix
     /// </summary>
-    public static readonly Matrix4x4 Single_Matrix4x4_ValIdentity = Matrix4x4.Identity;
+    public static readonly Matrix4x4 SingleMatrix4X4ValIdentity = Matrix4x4.Identity;
 
     /// <summary>
     /// 3x3 Matrix
     /// </summary>
-    public static readonly DenseMatrix<float> Single_DenseMatrix_ValGrad = new DenseMatrix<float>(Single_2DArray_ValGrad);
+    public static readonly DenseMatrix<float> SingleDenseMatrixValGrad = new(Single2DArrayValGrad);
 
     /// <summary>
     /// 3x3 Matrix
     /// </summary>
-    public static readonly DenseMatrix<float> Single_DenseMatrix_ValIdentity = new DenseMatrix<float>(Single_2DArray_ValIdentity);
+    public static readonly DenseMatrix<float> SingleDenseMatrixValIdentity = new(Single2DArrayValIdentity);
 
     /// <summary>
     /// 3x3 Matrix
     /// </summary>
-    public static readonly byte[] Fix16_2D_Grad = ArrayHelper.Concat(
-        IccTestDataPrimitives.Fix16_1,
-        IccTestDataPrimitives.Fix16_4,
-        IccTestDataPrimitives.Fix16_7,
-        IccTestDataPrimitives.Fix16_2,
-        IccTestDataPrimitives.Fix16_5,
-        IccTestDataPrimitives.Fix16_8,
-        IccTestDataPrimitives.Fix16_3,
-        IccTestDataPrimitives.Fix16_6,
-        IccTestDataPrimitives.Fix16_9);
+    public static readonly byte[] Fix162DGrad = ArrayHelper.Concat(
+        IccTestDataPrimitives.Fix161,
+        IccTestDataPrimitives.Fix164,
+        IccTestDataPrimitives.Fix167,
+        IccTestDataPrimitives.Fix162,
+        IccTestDataPrimitives.Fix165,
+        IccTestDataPrimitives.Fix168,
+        IccTestDataPrimitives.Fix163,
+        IccTestDataPrimitives.Fix166,
+        IccTestDataPrimitives.Fix169);
 
     /// <summary>
     /// 3x3 Matrix
     /// </summary>
-    public static readonly byte[] Fix16_2D_Identity = ArrayHelper.Concat(
-        IccTestDataPrimitives.Fix16_1,
-        IccTestDataPrimitives.Fix16_0,
-        IccTestDataPrimitives.Fix16_0,
-        IccTestDataPrimitives.Fix16_0,
-        IccTestDataPrimitives.Fix16_1,
-        IccTestDataPrimitives.Fix16_0,
-        IccTestDataPrimitives.Fix16_0,
-        IccTestDataPrimitives.Fix16_0,
-        IccTestDataPrimitives.Fix16_1);
+    public static readonly byte[] Fix162DIdentity = ArrayHelper.Concat(
+        IccTestDataPrimitives.Fix161,
+        IccTestDataPrimitives.Fix160,
+        IccTestDataPrimitives.Fix160,
+        IccTestDataPrimitives.Fix160,
+        IccTestDataPrimitives.Fix161,
+        IccTestDataPrimitives.Fix160,
+        IccTestDataPrimitives.Fix160,
+        IccTestDataPrimitives.Fix160,
+        IccTestDataPrimitives.Fix161);
 
     /// <summary>
     /// 3x3 Matrix
     /// </summary>
-    public static readonly byte[] Single_2D_Grad = ArrayHelper.Concat(
-        IccTestDataPrimitives.Single_1,
-        IccTestDataPrimitives.Single_4,
-        IccTestDataPrimitives.Single_7,
-        IccTestDataPrimitives.Single_2,
-        IccTestDataPrimitives.Single_5,
-        IccTestDataPrimitives.Single_8,
-        IccTestDataPrimitives.Single_3,
-        IccTestDataPrimitives.Single_6,
-        IccTestDataPrimitives.Single_9);
-
-    public static readonly object[][] Matrix2D_FloatArrayTestData =
+    public static readonly byte[] Single2DGrad = ArrayHelper.Concat(
+        IccTestDataPrimitives.Single1,
+        IccTestDataPrimitives.Single4,
+        IccTestDataPrimitives.Single7,
+        IccTestDataPrimitives.Single2,
+        IccTestDataPrimitives.Single5,
+        IccTestDataPrimitives.Single8,
+        IccTestDataPrimitives.Single3,
+        IccTestDataPrimitives.Single6,
+        IccTestDataPrimitives.Single9);
+
+    public static readonly object[][] Matrix2DFloatArrayTestData =
     {
-        new object[] { Fix16_2D_Grad, 3, 3, false, Single_2DArray_ValGrad },
-        new object[] { Fix16_2D_Identity, 3, 3, false, Single_2DArray_ValIdentity },
-        new object[] { Single_2D_Grad, 3, 3, true, Single_2DArray_ValGrad },
+        new object[] { Fix162DGrad, 3, 3, false, Single2DArrayValGrad },
+        new object[] { Fix162DIdentity, 3, 3, false, Single2DArrayValIdentity },
+        new object[] { Single2DGrad, 3, 3, true, Single2DArrayValGrad },
     };
 
-    public static readonly object[][] Matrix2D_DenseMatrixTestData =
+    public static readonly object[][] Matrix2DDenseMatrixTestData =
     {
-        new object[] { Fix16_2D_Grad, 3, 3, false, Single_DenseMatrix_ValGrad },
-        new object[] { Fix16_2D_Identity, 3, 3, false, Single_DenseMatrix_ValIdentity },
-        new object[] { Single_2D_Grad, 3, 3, true, Single_DenseMatrix_ValGrad },
+        new object[] { Fix162DGrad, 3, 3, false, SingleDenseMatrixValGrad },
+        new object[] { Fix162DIdentity, 3, 3, false, SingleDenseMatrixValIdentity },
+        new object[] { Single2DGrad, 3, 3, true, SingleDenseMatrixValGrad },
     };
 
-    public static readonly object[][] Matrix2D_Matrix4x4TestData =
+    public static readonly object[][] Matrix2DMatrix4X4TestData =
     {
-        new object[] { Fix16_2D_Grad, 3, 3, false, Single_Matrix4x4_ValGrad },
-        new object[] { Fix16_2D_Identity, 3, 3, false, Single_Matrix4x4_ValIdentity },
-        new object[] { Single_2D_Grad, 3, 3, true, Single_Matrix4x4_ValGrad },
+        new object[] { Fix162DGrad, 3, 3, false, SingleMatrix4X4ValGrad },
+        new object[] { Fix162DIdentity, 3, 3, false, SingleMatrix4X4ValIdentity },
+        new object[] { Single2DGrad, 3, 3, true, SingleMatrix4X4ValGrad },
     };
 
     /// <summary>
     /// 3x1 Matrix
     /// </summary>
-    public static readonly float[] Single_1DArray_ValGrad = { 1, 4, 7 };
+    public static readonly float[] Single1DArrayValGrad = { 1, 4, 7 };
 
     /// <summary>
     /// 3x1 Matrix
     /// </summary>
-    public static readonly Vector3 Single_Vector3_ValGrad = new Vector3(1, 4, 7);
+    public static readonly Vector3 SingleVector3ValGrad = new(1, 4, 7);
 
     /// <summary>
     /// 3x1 Matrix
     /// </summary>
-    public static readonly byte[] Fix16_1D_Grad = ArrayHelper.Concat(
-        IccTestDataPrimitives.Fix16_1,
-        IccTestDataPrimitives.Fix16_4,
-        IccTestDataPrimitives.Fix16_7);
+    public static readonly byte[] Fix161DGrad = ArrayHelper.Concat(
+        IccTestDataPrimitives.Fix161,
+        IccTestDataPrimitives.Fix164,
+        IccTestDataPrimitives.Fix167);
 
     /// <summary>
     /// 3x1 Matrix
     /// </summary>
-    public static readonly byte[] Single_1D_Grad = ArrayHelper.Concat(
-        IccTestDataPrimitives.Single_1,
-        IccTestDataPrimitives.Single_4,
-        IccTestDataPrimitives.Single_7);
+    public static readonly byte[] Single1DGrad = ArrayHelper.Concat(
+        IccTestDataPrimitives.Single1,
+        IccTestDataPrimitives.Single4,
+        IccTestDataPrimitives.Single7);
 
-    public static readonly object[][] Matrix1D_ArrayTestData =
+    public static readonly object[][] Matrix1DArrayTestData =
     {
-        new object[] { Fix16_1D_Grad, 3, false, Single_1DArray_ValGrad },
-        new object[] { Single_1D_Grad, 3, true, Single_1DArray_ValGrad },
+        new object[] { Fix161DGrad, 3, false, Single1DArrayValGrad },
+        new object[] { Single1DGrad, 3, true, Single1DArrayValGrad },
     };
 
-    public static readonly object[][] Matrix1D_Vector3TestData =
+    public static readonly object[][] Matrix1DVector3TestData =
     {
-        new object[] { Fix16_1D_Grad, 3, false, Single_Vector3_ValGrad },
-        new object[] { Single_1D_Grad, 3, true, Single_Vector3_ValGrad },
+        new object[] { Fix161DGrad, 3, false, SingleVector3ValGrad },
+        new object[] { Single1DGrad, 3, true, SingleVector3ValGrad },
     };
 }
diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataMultiProcessElements.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataMultiProcessElements.cs
index 2c5c432710..2e3679e3af 100644
--- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataMultiProcessElements.cs
+++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataMultiProcessElements.cs
@@ -3,7 +3,7 @@
 
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
 
-namespace SixLabors.ImageSharp.Tests;
+namespace SixLabors.ImageSharp.Tests.TestDataIcc;
 
 internal static class IccTestDataMultiProcessElements
 {
@@ -11,99 +11,99 @@ internal static class IccTestDataMultiProcessElements
     /// <para>Input Channel Count: 3</para>
     /// <para>Output Channel Count: 3</para>
     /// </summary>
-    public static readonly IccCurveSetProcessElement CurvePE_ValGrad = new IccCurveSetProcessElement(new IccOneDimensionalCurve[]
+    public static readonly IccCurveSetProcessElement CurvePeValGrad = new(new[]
     {
-        IccTestDataCurves.OneDimensional_ValFormula1,
-        IccTestDataCurves.OneDimensional_ValFormula2,
-        IccTestDataCurves.OneDimensional_ValFormula1
+        IccTestDataCurves.OneDimensionalValFormula1,
+        IccTestDataCurves.OneDimensionalValFormula2,
+        IccTestDataCurves.OneDimensionalValFormula1
     });
 
     /// <summary>
     /// <para>Input Channel Count: 3</para>
     /// <para>Output Channel Count: 3</para>
     /// </summary>
-    public static readonly byte[] CurvePE_Grad = ArrayHelper.Concat(
-        IccTestDataCurves.OneDimensional_Formula1,
-        IccTestDataCurves.OneDimensional_Formula2,
-        IccTestDataCurves.OneDimensional_Formula1);
+    public static readonly byte[] CurvePeGrad = ArrayHelper.Concat(
+        IccTestDataCurves.OneDimensionalFormula1,
+        IccTestDataCurves.OneDimensionalFormula2,
+        IccTestDataCurves.OneDimensionalFormula1);
 
     public static readonly object[][] CurveSetTestData =
     {
-        new object[] { CurvePE_Grad, CurvePE_ValGrad, 3, 3 },
+        new object[] { CurvePeGrad, CurvePeValGrad, 3, 3 },
     };
 
     /// <summary>
     /// <para>Input Channel Count: 3</para>
     /// <para>Output Channel Count: 3</para>
     /// </summary>
-    public static readonly IccMatrixProcessElement MatrixPE_ValGrad = new IccMatrixProcessElement(
-        IccTestDataMatrix.Single_2DArray_ValGrad,
-        IccTestDataMatrix.Single_1DArray_ValGrad);
+    public static readonly IccMatrixProcessElement MatrixPeValGrad = new(
+        IccTestDataMatrix.Single2DArrayValGrad,
+        IccTestDataMatrix.Single1DArrayValGrad);
 
     /// <summary>
     /// <para>Input Channel Count: 3</para>
     /// <para>Output Channel Count: 3</para>
     /// </summary>
-    public static readonly byte[] MatrixPE_Grad = ArrayHelper.Concat(
-        IccTestDataMatrix.Single_2D_Grad,
-        IccTestDataMatrix.Single_1D_Grad);
+    public static readonly byte[] MatrixPeGrad = ArrayHelper.Concat(
+        IccTestDataMatrix.Single2DGrad,
+        IccTestDataMatrix.Single1DGrad);
 
     public static readonly object[][] MatrixTestData =
     {
-        new object[] { MatrixPE_Grad, MatrixPE_ValGrad, 3, 3 },
+        new object[] { MatrixPeGrad, MatrixPeValGrad, 3, 3 },
     };
 
     /// <summary>
     /// <para>Input Channel Count: 2</para>
     /// <para>Output Channel Count: 3</para>
     /// </summary>
-    public static readonly IccClutProcessElement CLUTPE_ValGrad = new IccClutProcessElement(IccTestDataLut.CLUT_Valf32);
+    public static readonly IccClutProcessElement ClutpeValGrad = new(IccTestDataLut.ClutValf32);
 
     /// <summary>
     /// <para>Input Channel Count: 2</para>
     /// <para>Output Channel Count: 3</para>
     /// </summary>
-    public static readonly byte[] CLUTPE_Grad = IccTestDataLut.CLUT_f32;
+    public static readonly byte[] ClutpeGrad = IccTestDataLut.ClutF32;
 
     public static readonly object[][] ClutTestData =
     {
-        new object[] { CLUTPE_Grad, CLUTPE_ValGrad, 2, 3 },
+        new object[] { ClutpeGrad, ClutpeValGrad, 2, 3 },
     };
 
-    public static readonly IccMultiProcessElement MPE_ValMatrix = MatrixPE_ValGrad;
-    public static readonly IccMultiProcessElement MPE_ValCLUT = CLUTPE_ValGrad;
-    public static readonly IccMultiProcessElement MPE_ValCurve = CurvePE_ValGrad;
-    public static readonly IccMultiProcessElement MPE_ValbACS = new IccBAcsProcessElement(3, 3);
-    public static readonly IccMultiProcessElement MPE_ValeACS = new IccEAcsProcessElement(3, 3);
+    public static readonly IccMultiProcessElement MpeValMatrix = MatrixPeValGrad;
+    public static readonly IccMultiProcessElement MpeValClut = ClutpeValGrad;
+    public static readonly IccMultiProcessElement MpeValCurve = CurvePeValGrad;
+    public static readonly IccMultiProcessElement MpeValbAcs = new IccBAcsProcessElement(3, 3);
+    public static readonly IccMultiProcessElement MpeValeAcs = new IccEAcsProcessElement(3, 3);
 
-    public static readonly byte[] MPE_Matrix = ArrayHelper.Concat(
+    public static readonly byte[] MpeMatrix = ArrayHelper.Concat(
         new byte[]
         {
             0x6D, 0x61, 0x74, 0x66,
             0x00, 0x03,
             0x00, 0x03,
         },
-        MatrixPE_Grad);
+        MatrixPeGrad);
 
-    public static readonly byte[] MPE_CLUT = ArrayHelper.Concat(
+    public static readonly byte[] MpeClut = ArrayHelper.Concat(
         new byte[]
         {
             0x63, 0x6C, 0x75, 0x74,
             0x00, 0x02,
             0x00, 0x03,
         },
-        CLUTPE_Grad);
+        ClutpeGrad);
 
-    public static readonly byte[] MPE_Curve = ArrayHelper.Concat(
+    public static readonly byte[] MpeCurve = ArrayHelper.Concat(
         new byte[]
         {
             0x6D, 0x66, 0x6C, 0x74,
             0x00, 0x03,
             0x00, 0x03,
         },
-        CurvePE_Grad);
+        CurvePeGrad);
 
-    public static readonly byte[] MPE_bACS =
+    public static readonly byte[] MpeBAcs =
     {
         0x62, 0x41, 0x43, 0x53,
         0x00, 0x03,
@@ -111,7 +111,7 @@ internal static class IccTestDataMultiProcessElements
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     };
 
-    public static readonly byte[] MPE_eACS =
+    public static readonly byte[] MpeEAcs =
     {
         0x65, 0x41, 0x43, 0x53,
         0x00, 0x03,
@@ -121,10 +121,10 @@ internal static class IccTestDataMultiProcessElements
 
     public static readonly object[][] MultiProcessElementTestData =
     {
-        new object[] { MPE_Matrix, MPE_ValMatrix },
-        new object[] { MPE_CLUT, MPE_ValCLUT },
-        new object[] { MPE_Curve, MPE_ValCurve },
-        new object[] { MPE_bACS, MPE_ValbACS },
-        new object[] { MPE_eACS, MPE_ValeACS },
+        new object[] { MpeMatrix, MpeValMatrix },
+        new object[] { MpeClut, MpeValClut },
+        new object[] { MpeCurve, MpeValCurve },
+        new object[] { MpeBAcs, MpeValbAcs },
+        new object[] { MpeEAcs, MpeValeAcs },
     };
 }
diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataNonPrimitives.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataNonPrimitives.cs
index c476f2e6c7..0674274246 100644
--- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataNonPrimitives.cs
+++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataNonPrimitives.cs
@@ -5,15 +5,15 @@
 using System.Numerics;
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
 
-namespace SixLabors.ImageSharp.Tests;
+namespace SixLabors.ImageSharp.Tests.TestDataIcc;
 
 internal static class IccTestDataNonPrimitives
 {
-    public static readonly DateTime DateTime_ValMin = new DateTime(1, 1, 1, 0, 0, 0, DateTimeKind.Utc);
-    public static readonly DateTime DateTime_ValMax = new DateTime(9999, 12, 31, 23, 59, 59, DateTimeKind.Utc);
-    public static readonly DateTime DateTime_ValRand1 = new DateTime(1990, 11, 26, 3, 19, 47, DateTimeKind.Utc);
+    public static readonly DateTime DateTimeValMin = new(1, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+    public static readonly DateTime DateTimeValMax = new(9999, 12, 31, 23, 59, 59, DateTimeKind.Utc);
+    public static readonly DateTime DateTimeValRand1 = new(1990, 11, 26, 3, 19, 47, DateTimeKind.Utc);
 
-    public static readonly byte[] DateTime_Min =
+    public static readonly byte[] DateTimeMin =
     {
         0x00, 0x01, // Year      1
         0x00, 0x01, // Month     1
@@ -23,7 +23,7 @@ internal static class IccTestDataNonPrimitives
         0x00, 0x00, // Second    0
     };
 
-    public static readonly byte[] DateTime_Max =
+    public static readonly byte[] DateTimeMax =
     {
             0x27, 0x0F, // Year      9999
             0x00, 0x0C, // Month     12
@@ -33,7 +33,7 @@ internal static class IccTestDataNonPrimitives
             0x00, 0x3B, // Second    59
     };
 
-    public static readonly byte[] DateTime_Invalid =
+    public static readonly byte[] DateTimeInvalid =
     {
             0xFF, 0xFF, // Year      65535
             0x00, 0x0E, // Month     14
@@ -43,7 +43,7 @@ internal static class IccTestDataNonPrimitives
             0x00, 0x3D, // Second    61
     };
 
-    public static readonly byte[] DateTime_Rand1 =
+    public static readonly byte[] DateTimeRand1 =
     {
             0x07, 0xC6, // Year      1990
             0x00, 0x0B, // Month     11
@@ -55,135 +55,135 @@ internal static class IccTestDataNonPrimitives
 
     public static readonly object[][] DateTimeTestData =
     {
-        new object[] { DateTime_Min, DateTime_ValMin },
-        new object[] { DateTime_Max, DateTime_ValMax },
-        new object[] { DateTime_Rand1, DateTime_ValRand1 },
+        new object[] { DateTimeMin, DateTimeValMin },
+        new object[] { DateTimeMax, DateTimeValMax },
+        new object[] { DateTimeRand1, DateTimeValRand1 },
     };
 
-    public static readonly IccVersion VersionNumber_ValMin = new IccVersion(0, 0, 0);
-    public static readonly IccVersion VersionNumber_Val211 = new IccVersion(2, 1, 1);
-    public static readonly IccVersion VersionNumber_Val430 = new IccVersion(4, 3, 0);
-    public static readonly IccVersion VersionNumber_ValMax = new IccVersion(255, 15, 15);
+    public static readonly IccVersion VersionNumberValMin = new(0, 0, 0);
+    public static readonly IccVersion VersionNumberVal211 = new(2, 1, 1);
+    public static readonly IccVersion VersionNumberVal430 = new(4, 3, 0);
+    public static readonly IccVersion VersionNumberValMax = new(255, 15, 15);
 
-    public static readonly byte[] VersionNumber_Min = { 0x00, 0x00, 0x00, 0x00 };
-    public static readonly byte[] VersionNumber_211 = { 0x02, 0x11, 0x00, 0x00 };
-    public static readonly byte[] VersionNumber_430 = { 0x04, 0x30, 0x00, 0x00 };
-    public static readonly byte[] VersionNumber_Max = { 0xFF, 0xFF, 0x00, 0x00 };
+    public static readonly byte[] VersionNumberMin = { 0x00, 0x00, 0x00, 0x00 };
+    public static readonly byte[] VersionNumber211 = { 0x02, 0x11, 0x00, 0x00 };
+    public static readonly byte[] VersionNumber430 = { 0x04, 0x30, 0x00, 0x00 };
+    public static readonly byte[] VersionNumberMax = { 0xFF, 0xFF, 0x00, 0x00 };
 
     public static readonly object[][] VersionNumberTestData =
     {
-        new object[] { VersionNumber_Min, VersionNumber_ValMin },
-        new object[] { VersionNumber_211, VersionNumber_Val211 },
-        new object[] { VersionNumber_430, VersionNumber_Val430 },
-        new object[] { VersionNumber_Max, VersionNumber_ValMax },
+        new object[] { VersionNumberMin, VersionNumberValMin },
+        new object[] { VersionNumber211, VersionNumberVal211 },
+        new object[] { VersionNumber430, VersionNumberVal430 },
+        new object[] { VersionNumberMax, VersionNumberValMax },
     };
 
-    public static readonly Vector3 XyzNumber_ValMin = new Vector3(IccTestDataPrimitives.Fix16_ValMin, IccTestDataPrimitives.Fix16_ValMin, IccTestDataPrimitives.Fix16_ValMin);
-    public static readonly Vector3 XyzNumber_Val0 = new Vector3(0, 0, 0);
-    public static readonly Vector3 XyzNumber_Val1 = new Vector3(1, 1, 1);
-    public static readonly Vector3 XyzNumber_ValVar1 = new Vector3(1, 2, 3);
-    public static readonly Vector3 XyzNumber_ValVar2 = new Vector3(4, 5, 6);
-    public static readonly Vector3 XyzNumber_ValVar3 = new Vector3(7, 8, 9);
-    public static readonly Vector3 XyzNumber_ValMax = new Vector3(IccTestDataPrimitives.Fix16_ValMax, IccTestDataPrimitives.Fix16_ValMax, IccTestDataPrimitives.Fix16_ValMax);
-
-    public static readonly byte[] XyzNumber_Min = ArrayHelper.Concat(IccTestDataPrimitives.Fix16_Min, IccTestDataPrimitives.Fix16_Min, IccTestDataPrimitives.Fix16_Min);
-    public static readonly byte[] XyzNumber_0 = ArrayHelper.Concat(IccTestDataPrimitives.Fix16_0, IccTestDataPrimitives.Fix16_0, IccTestDataPrimitives.Fix16_0);
-    public static readonly byte[] XyzNumber_1 = ArrayHelper.Concat(IccTestDataPrimitives.Fix16_1, IccTestDataPrimitives.Fix16_1, IccTestDataPrimitives.Fix16_1);
-    public static readonly byte[] XyzNumber_Var1 = ArrayHelper.Concat(IccTestDataPrimitives.Fix16_1, IccTestDataPrimitives.Fix16_2, IccTestDataPrimitives.Fix16_3);
-    public static readonly byte[] XyzNumber_Var2 = ArrayHelper.Concat(IccTestDataPrimitives.Fix16_4, IccTestDataPrimitives.Fix16_5, IccTestDataPrimitives.Fix16_6);
-    public static readonly byte[] XyzNumber_Var3 = ArrayHelper.Concat(IccTestDataPrimitives.Fix16_7, IccTestDataPrimitives.Fix16_8, IccTestDataPrimitives.Fix16_9);
-    public static readonly byte[] XyzNumber_Max = ArrayHelper.Concat(IccTestDataPrimitives.Fix16_Max, IccTestDataPrimitives.Fix16_Max, IccTestDataPrimitives.Fix16_Max);
+    public static readonly Vector3 XyzNumberValMin = new(IccTestDataPrimitives.Fix16ValMin, IccTestDataPrimitives.Fix16ValMin, IccTestDataPrimitives.Fix16ValMin);
+    public static readonly Vector3 XyzNumberVal0 = new(0, 0, 0);
+    public static readonly Vector3 XyzNumberVal1 = new(1, 1, 1);
+    public static readonly Vector3 XyzNumberValVar1 = new(1, 2, 3);
+    public static readonly Vector3 XyzNumberValVar2 = new(4, 5, 6);
+    public static readonly Vector3 XyzNumberValVar3 = new(7, 8, 9);
+    public static readonly Vector3 XyzNumberValMax = new(IccTestDataPrimitives.Fix16ValMax, IccTestDataPrimitives.Fix16ValMax, IccTestDataPrimitives.Fix16ValMax);
+
+    public static readonly byte[] XyzNumberMin = ArrayHelper.Concat(IccTestDataPrimitives.Fix16Min, IccTestDataPrimitives.Fix16Min, IccTestDataPrimitives.Fix16Min);
+    public static readonly byte[] XyzNumber0 = ArrayHelper.Concat(IccTestDataPrimitives.Fix160, IccTestDataPrimitives.Fix160, IccTestDataPrimitives.Fix160);
+    public static readonly byte[] XyzNumber1 = ArrayHelper.Concat(IccTestDataPrimitives.Fix161, IccTestDataPrimitives.Fix161, IccTestDataPrimitives.Fix161);
+    public static readonly byte[] XyzNumberVar1 = ArrayHelper.Concat(IccTestDataPrimitives.Fix161, IccTestDataPrimitives.Fix162, IccTestDataPrimitives.Fix163);
+    public static readonly byte[] XyzNumberVar2 = ArrayHelper.Concat(IccTestDataPrimitives.Fix164, IccTestDataPrimitives.Fix165, IccTestDataPrimitives.Fix166);
+    public static readonly byte[] XyzNumberVar3 = ArrayHelper.Concat(IccTestDataPrimitives.Fix167, IccTestDataPrimitives.Fix168, IccTestDataPrimitives.Fix169);
+    public static readonly byte[] XyzNumberMax = ArrayHelper.Concat(IccTestDataPrimitives.Fix16Max, IccTestDataPrimitives.Fix16Max, IccTestDataPrimitives.Fix16Max);
 
     public static readonly object[][] XyzNumberTestData =
     {
-        new object[] { XyzNumber_Min, XyzNumber_ValMin },
-        new object[] { XyzNumber_0, XyzNumber_Val0 },
-        new object[] { XyzNumber_Var1, XyzNumber_ValVar1 },
-        new object[] { XyzNumber_Max, XyzNumber_ValMax },
+        new object[] { XyzNumberMin, XyzNumberValMin },
+        new object[] { XyzNumber0, XyzNumberVal0 },
+        new object[] { XyzNumberVar1, XyzNumberValVar1 },
+        new object[] { XyzNumberMax, XyzNumberValMax },
     };
 
-    public static readonly IccProfileId ProfileId_ValMin = new IccProfileId(0, 0, 0, 0);
-    public static readonly IccProfileId ProfileId_ValRand = new IccProfileId(IccTestDataPrimitives.UInt32_ValRand1, IccTestDataPrimitives.UInt32_ValRand2, IccTestDataPrimitives.UInt32_ValRand3, IccTestDataPrimitives.UInt32_ValRand4);
-    public static readonly IccProfileId ProfileId_ValMax = new IccProfileId(uint.MaxValue, uint.MaxValue, uint.MaxValue, uint.MaxValue);
+    public static readonly IccProfileId ProfileIdValMin = new(0, 0, 0, 0);
+    public static readonly IccProfileId ProfileIdValRand = new(IccTestDataPrimitives.UInt32ValRand1, IccTestDataPrimitives.UInt32ValRand2, IccTestDataPrimitives.UInt32ValRand3, IccTestDataPrimitives.UInt32ValRand4);
+    public static readonly IccProfileId ProfileIdValMax = new(uint.MaxValue, uint.MaxValue, uint.MaxValue, uint.MaxValue);
 
-    public static readonly byte[] ProfileId_Min = ArrayHelper.Concat(IccTestDataPrimitives.UInt32_0, IccTestDataPrimitives.UInt32_0, IccTestDataPrimitives.UInt32_0, IccTestDataPrimitives.UInt32_0);
-    public static readonly byte[] ProfileId_Rand = ArrayHelper.Concat(IccTestDataPrimitives.UInt32_Rand1, IccTestDataPrimitives.UInt32_Rand2, IccTestDataPrimitives.UInt32_Rand3, IccTestDataPrimitives.UInt32_Rand4);
-    public static readonly byte[] ProfileId_Max = ArrayHelper.Concat(IccTestDataPrimitives.UInt32_Max, IccTestDataPrimitives.UInt32_Max, IccTestDataPrimitives.UInt32_Max, IccTestDataPrimitives.UInt32_Max);
+    public static readonly byte[] ProfileIdMin = ArrayHelper.Concat(IccTestDataPrimitives.UInt320, IccTestDataPrimitives.UInt320, IccTestDataPrimitives.UInt320, IccTestDataPrimitives.UInt320);
+    public static readonly byte[] ProfileIdRand = ArrayHelper.Concat(IccTestDataPrimitives.UInt32Rand1, IccTestDataPrimitives.UInt32Rand2, IccTestDataPrimitives.UInt32Rand3, IccTestDataPrimitives.UInt32Rand4);
+    public static readonly byte[] ProfileIdMax = ArrayHelper.Concat(IccTestDataPrimitives.UInt32Max, IccTestDataPrimitives.UInt32Max, IccTestDataPrimitives.UInt32Max, IccTestDataPrimitives.UInt32Max);
 
     public static readonly object[][] ProfileIdTestData =
     {
-        new object[] { ProfileId_Min, ProfileId_ValMin },
-        new object[] { ProfileId_Rand, ProfileId_ValRand },
-        new object[] { ProfileId_Max, ProfileId_ValMax },
+        new object[] { ProfileIdMin, ProfileIdValMin },
+        new object[] { ProfileIdRand, ProfileIdValRand },
+        new object[] { ProfileIdMax, ProfileIdValMax },
     };
 
-    public static readonly IccPositionNumber PositionNumber_ValMin = new IccPositionNumber(0, 0);
-    public static readonly IccPositionNumber PositionNumber_ValRand = new IccPositionNumber(IccTestDataPrimitives.UInt32_ValRand1, IccTestDataPrimitives.UInt32_ValRand2);
-    public static readonly IccPositionNumber PositionNumber_ValMax = new IccPositionNumber(uint.MaxValue, uint.MaxValue);
+    public static readonly IccPositionNumber PositionNumberValMin = new(0, 0);
+    public static readonly IccPositionNumber PositionNumberValRand = new(IccTestDataPrimitives.UInt32ValRand1, IccTestDataPrimitives.UInt32ValRand2);
+    public static readonly IccPositionNumber PositionNumberValMax = new(uint.MaxValue, uint.MaxValue);
 
-    public static readonly byte[] PositionNumber_Min = ArrayHelper.Concat(IccTestDataPrimitives.UInt32_0, IccTestDataPrimitives.UInt32_0);
-    public static readonly byte[] PositionNumber_Rand = ArrayHelper.Concat(IccTestDataPrimitives.UInt32_Rand1, IccTestDataPrimitives.UInt32_Rand2);
-    public static readonly byte[] PositionNumber_Max = ArrayHelper.Concat(IccTestDataPrimitives.UInt32_Max, IccTestDataPrimitives.UInt32_Max);
+    public static readonly byte[] PositionNumberMin = ArrayHelper.Concat(IccTestDataPrimitives.UInt320, IccTestDataPrimitives.UInt320);
+    public static readonly byte[] PositionNumberRand = ArrayHelper.Concat(IccTestDataPrimitives.UInt32Rand1, IccTestDataPrimitives.UInt32Rand2);
+    public static readonly byte[] PositionNumberMax = ArrayHelper.Concat(IccTestDataPrimitives.UInt32Max, IccTestDataPrimitives.UInt32Max);
 
     public static readonly object[][] PositionNumberTestData =
     {
-        new object[] { PositionNumber_Min, PositionNumber_ValMin },
-        new object[] { PositionNumber_Rand, PositionNumber_ValRand },
-        new object[] { PositionNumber_Max, PositionNumber_ValMax },
+        new object[] { PositionNumberMin, PositionNumberValMin },
+        new object[] { PositionNumberRand, PositionNumberValRand },
+        new object[] { PositionNumberMax, PositionNumberValMax },
     };
 
-    public static readonly IccResponseNumber ResponseNumber_ValMin = new IccResponseNumber(0, IccTestDataPrimitives.Fix16_ValMin);
-    public static readonly IccResponseNumber ResponseNumber_Val1 = new IccResponseNumber(1, 1);
-    public static readonly IccResponseNumber ResponseNumber_Val2 = new IccResponseNumber(2, 2);
-    public static readonly IccResponseNumber ResponseNumber_Val3 = new IccResponseNumber(3, 3);
-    public static readonly IccResponseNumber ResponseNumber_Val4 = new IccResponseNumber(4, 4);
-    public static readonly IccResponseNumber ResponseNumber_Val5 = new IccResponseNumber(5, 5);
-    public static readonly IccResponseNumber ResponseNumber_Val6 = new IccResponseNumber(6, 6);
-    public static readonly IccResponseNumber ResponseNumber_Val7 = new IccResponseNumber(7, 7);
-    public static readonly IccResponseNumber ResponseNumber_Val8 = new IccResponseNumber(8, 8);
-    public static readonly IccResponseNumber ResponseNumber_Val9 = new IccResponseNumber(9, 9);
-    public static readonly IccResponseNumber ResponseNumber_ValMax = new IccResponseNumber(ushort.MaxValue, IccTestDataPrimitives.Fix16_ValMax);
-
-    public static readonly byte[] ResponseNumber_Min = ArrayHelper.Concat(IccTestDataPrimitives.UInt16_0, IccTestDataPrimitives.Fix16_Min);
-    public static readonly byte[] ResponseNumber_1 = ArrayHelper.Concat(IccTestDataPrimitives.UInt16_1, IccTestDataPrimitives.Fix16_1);
-    public static readonly byte[] ResponseNumber_2 = ArrayHelper.Concat(IccTestDataPrimitives.UInt16_2, IccTestDataPrimitives.Fix16_2);
-    public static readonly byte[] ResponseNumber_3 = ArrayHelper.Concat(IccTestDataPrimitives.UInt16_3, IccTestDataPrimitives.Fix16_3);
-    public static readonly byte[] ResponseNumber_4 = ArrayHelper.Concat(IccTestDataPrimitives.UInt16_4, IccTestDataPrimitives.Fix16_4);
-    public static readonly byte[] ResponseNumber_5 = ArrayHelper.Concat(IccTestDataPrimitives.UInt16_5, IccTestDataPrimitives.Fix16_5);
-    public static readonly byte[] ResponseNumber_6 = ArrayHelper.Concat(IccTestDataPrimitives.UInt16_6, IccTestDataPrimitives.Fix16_6);
-    public static readonly byte[] ResponseNumber_7 = ArrayHelper.Concat(IccTestDataPrimitives.UInt16_7, IccTestDataPrimitives.Fix16_7);
-    public static readonly byte[] ResponseNumber_8 = ArrayHelper.Concat(IccTestDataPrimitives.UInt16_8, IccTestDataPrimitives.Fix16_8);
-    public static readonly byte[] ResponseNumber_9 = ArrayHelper.Concat(IccTestDataPrimitives.UInt16_9, IccTestDataPrimitives.Fix16_9);
-    public static readonly byte[] ResponseNumber_Max = ArrayHelper.Concat(IccTestDataPrimitives.UInt16_Max, IccTestDataPrimitives.Fix16_Max);
+    public static readonly IccResponseNumber ResponseNumberValMin = new(0, IccTestDataPrimitives.Fix16ValMin);
+    public static readonly IccResponseNumber ResponseNumberVal1 = new(1, 1);
+    public static readonly IccResponseNumber ResponseNumberVal2 = new(2, 2);
+    public static readonly IccResponseNumber ResponseNumberVal3 = new(3, 3);
+    public static readonly IccResponseNumber ResponseNumberVal4 = new(4, 4);
+    public static readonly IccResponseNumber ResponseNumberVal5 = new(5, 5);
+    public static readonly IccResponseNumber ResponseNumberVal6 = new(6, 6);
+    public static readonly IccResponseNumber ResponseNumberVal7 = new(7, 7);
+    public static readonly IccResponseNumber ResponseNumberVal8 = new(8, 8);
+    public static readonly IccResponseNumber ResponseNumberVal9 = new(9, 9);
+    public static readonly IccResponseNumber ResponseNumberValMax = new(ushort.MaxValue, IccTestDataPrimitives.Fix16ValMax);
+
+    public static readonly byte[] ResponseNumberMin = ArrayHelper.Concat(IccTestDataPrimitives.UInt160, IccTestDataPrimitives.Fix16Min);
+    public static readonly byte[] ResponseNumber1 = ArrayHelper.Concat(IccTestDataPrimitives.UInt161, IccTestDataPrimitives.Fix161);
+    public static readonly byte[] ResponseNumber2 = ArrayHelper.Concat(IccTestDataPrimitives.UInt162, IccTestDataPrimitives.Fix162);
+    public static readonly byte[] ResponseNumber3 = ArrayHelper.Concat(IccTestDataPrimitives.UInt163, IccTestDataPrimitives.Fix163);
+    public static readonly byte[] ResponseNumber4 = ArrayHelper.Concat(IccTestDataPrimitives.UInt164, IccTestDataPrimitives.Fix164);
+    public static readonly byte[] ResponseNumber5 = ArrayHelper.Concat(IccTestDataPrimitives.UInt165, IccTestDataPrimitives.Fix165);
+    public static readonly byte[] ResponseNumber6 = ArrayHelper.Concat(IccTestDataPrimitives.UInt166, IccTestDataPrimitives.Fix166);
+    public static readonly byte[] ResponseNumber7 = ArrayHelper.Concat(IccTestDataPrimitives.UInt167, IccTestDataPrimitives.Fix167);
+    public static readonly byte[] ResponseNumber8 = ArrayHelper.Concat(IccTestDataPrimitives.UInt168, IccTestDataPrimitives.Fix168);
+    public static readonly byte[] ResponseNumber9 = ArrayHelper.Concat(IccTestDataPrimitives.UInt169, IccTestDataPrimitives.Fix169);
+    public static readonly byte[] ResponseNumberMax = ArrayHelper.Concat(IccTestDataPrimitives.UInt16Max, IccTestDataPrimitives.Fix16Max);
 
     public static readonly object[][] ResponseNumberTestData =
     {
-        new object[] { ResponseNumber_Min, ResponseNumber_ValMin },
-        new object[] { ResponseNumber_1, ResponseNumber_Val1 },
-        new object[] { ResponseNumber_4, ResponseNumber_Val4 },
-        new object[] { ResponseNumber_Max, ResponseNumber_ValMax },
+        new object[] { ResponseNumberMin, ResponseNumberValMin },
+        new object[] { ResponseNumber1, ResponseNumberVal1 },
+        new object[] { ResponseNumber4, ResponseNumberVal4 },
+        new object[] { ResponseNumberMax, ResponseNumberValMax },
     };
 
-    public static readonly IccNamedColor NamedColor_ValMin = new IccNamedColor(
+    public static readonly IccNamedColor NamedColorValMin = new(
         ArrayHelper.Fill('A', 31),
         new ushort[] { 0, 0, 0 },
         new ushort[] { 0, 0, 0 });
 
-    public static readonly IccNamedColor NamedColor_ValRand = new IccNamedColor(
+    public static readonly IccNamedColor NamedColorValRand = new(
         ArrayHelper.Fill('5', 31),
         new ushort[] { 10794, 10794, 10794 },
         new ushort[] { 17219, 17219, 17219, 17219, 17219 });
 
-    public static readonly IccNamedColor NamedColor_ValMax = new IccNamedColor(
+    public static readonly IccNamedColor NamedColorValMax = new(
         ArrayHelper.Fill('4', 31),
-        new ushort[] { ushort.MaxValue, ushort.MaxValue, ushort.MaxValue },
-        new ushort[] { ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue });
+        new[] { ushort.MaxValue, ushort.MaxValue, ushort.MaxValue },
+        new[] { ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue });
 
-    public static readonly byte[] NamedColor_Min = CreateNamedColor(3, 0x41, 0x00, 0x00);
-    public static readonly byte[] NamedColor_Rand = CreateNamedColor(5, 0x35, 42, 67);
-    public static readonly byte[] NamedColor_Max = CreateNamedColor(4, 0x34, 0xFF, 0xFF);
+    public static readonly byte[] NamedColorMin = CreateNamedColor(3, 0x41, 0x00, 0x00);
+    public static readonly byte[] NamedColorRand = CreateNamedColor(5, 0x35, 42, 67);
+    public static readonly byte[] NamedColorMax = CreateNamedColor(4, 0x34, 0xFF, 0xFF);
 
-    private static byte[] CreateNamedColor(int devCoordCount, byte name, byte pCS, byte device)
+    private static byte[] CreateNamedColor(int devCoordCount, byte name, byte pCs, byte device)
     {
         byte[] data = new byte[32 + 6 + (devCoordCount * 2)];
         for (int i = 0; i < data.Length; i++)
@@ -198,7 +198,7 @@ private static byte[] CreateNamedColor(int devCoordCount, byte name, byte pCS, b
             }
             else if (i < 32 + 6)
             {
-                data[i] = pCS; // PCS Coordinates
+                data[i] = pCs; // PCS Coordinates
             }
             else
             {
@@ -211,145 +211,144 @@ private static byte[] CreateNamedColor(int devCoordCount, byte name, byte pCS, b
 
     public static readonly object[][] NamedColorTestData =
     {
-        new object[] { NamedColor_Min, NamedColor_ValMin, 3u },
-        new object[] { NamedColor_Rand, NamedColor_ValRand, 5u },
-        new object[] { NamedColor_Max, NamedColor_ValMax, 4u },
+        new object[] { NamedColorMin, NamedColorValMin, 3u },
+        new object[] { NamedColorRand, NamedColorValRand, 5u },
+        new object[] { NamedColorMax, NamedColorValMax, 4u },
     };
 
-    private static readonly CultureInfo CultureEnUs = new CultureInfo("en-US");
-    private static readonly CultureInfo CultureDeAT = new CultureInfo("de-AT");
+    private static readonly CultureInfo CultureEnUs = new("en-US");
+    private static readonly CultureInfo CultureDeAt = new("de-AT");
 
-    private static readonly IccLocalizedString LocalizedString_Rand1 = new IccLocalizedString(CultureEnUs, IccTestDataPrimitives.Unicode_ValRand2);
-    private static readonly IccLocalizedString LocalizedString_Rand2 = new IccLocalizedString(CultureDeAT, IccTestDataPrimitives.Unicode_ValRand3);
+    private static readonly IccLocalizedString LocalizedStringRand1 = new(CultureEnUs, IccTestDataPrimitives.UnicodeValRand2);
+    private static readonly IccLocalizedString LocalizedStringRand2 = new(CultureDeAt, IccTestDataPrimitives.UnicodeValRand3);
 
-    private static readonly IccLocalizedString[] LocalizedString_RandArr1 = new IccLocalizedString[]
-    {
-        LocalizedString_Rand1,
-        LocalizedString_Rand2,
+    private static readonly IccLocalizedString[] LocalizedStringRandArr1 = {
+        LocalizedStringRand1,
+        LocalizedStringRand2,
     };
 
-    private static readonly IccMultiLocalizedUnicodeTagDataEntry MultiLocalizedUnicode_Val = new IccMultiLocalizedUnicodeTagDataEntry(LocalizedString_RandArr1);
-    private static readonly byte[] MultiLocalizedUnicode_Arr = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt32_2,
+    private static readonly IccMultiLocalizedUnicodeTagDataEntry MultiLocalizedUnicodeVal = new(LocalizedStringRandArr1);
+    private static readonly byte[] MultiLocalizedUnicodeArr = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt322,
         new byte[] { 0x00, 0x00, 0x00, 0x0C }, // 12
-        new byte[] { (byte)'e', (byte)'n', (byte)'U', (byte)'S' },
+        new[] { (byte)'e', (byte)'n', (byte)'U', (byte)'S' },
         new byte[] { 0x00, 0x00, 0x00, 0x0C },  // 12
         new byte[] { 0x00, 0x00, 0x00, 0x28 },  // 40
-        new byte[] { (byte)'d', (byte)'e', (byte)'A', (byte)'T' },
+        new[] { (byte)'d', (byte)'e', (byte)'A', (byte)'T' },
         new byte[] { 0x00, 0x00, 0x00, 0x0E },  // 14
         new byte[] { 0x00, 0x00, 0x00, 0x34 },  // 52
-        IccTestDataPrimitives.Unicode_Rand2,
-        IccTestDataPrimitives.Unicode_Rand3);
+        IccTestDataPrimitives.UnicodeRand2,
+        IccTestDataPrimitives.UnicodeRand3);
 
-    public static readonly IccTextDescriptionTagDataEntry TextDescription_Val1 = new IccTextDescriptionTagDataEntry(
-        IccTestDataPrimitives.Ascii_ValRand,
-        IccTestDataPrimitives.Unicode_ValRand1,
+    public static readonly IccTextDescriptionTagDataEntry TextDescriptionVal1 = new(
+        IccTestDataPrimitives.AsciiValRand,
+        IccTestDataPrimitives.UnicodeValRand1,
         ArrayHelper.Fill('A', 66),
         1701729619,
         2);
 
-    public static readonly byte[] TextDescription_Arr1 = ArrayHelper.Concat(
+    public static readonly byte[] TextDescriptionArr1 = ArrayHelper.Concat(
         new byte[] { 0x00, 0x00, 0x00, 0x0B },  // 11
-        IccTestDataPrimitives.Ascii_Rand,
+        IccTestDataPrimitives.AsciiRand,
         new byte[] { 0x00 },                    // Null terminator
-        new byte[] { (byte)'e', (byte)'n', (byte)'U', (byte)'S' },
+        new[] { (byte)'e', (byte)'n', (byte)'U', (byte)'S' },
         new byte[] { 0x00, 0x00, 0x00, 0x07 },  // 7
-        IccTestDataPrimitives.Unicode_Rand2,
+        IccTestDataPrimitives.UnicodeRand2,
         new byte[] { 0x00, 0x00 },              // Null terminator
         new byte[] { 0x00, 0x02, 0x43 },        // 2, 67
         ArrayHelper.Fill((byte)0x41, 66),
         new byte[] { 0x00 }); // Null terminator
 
-    public static readonly IccProfileDescription ProfileDescription_ValRand1 = new IccProfileDescription(
+    public static readonly IccProfileDescription ProfileDescriptionValRand1 = new(
         1,
         2,
         IccDeviceAttribute.ChromaBlackWhite | IccDeviceAttribute.ReflectivityMatte,
         IccProfileTag.ProfileDescription,
-        MultiLocalizedUnicode_Val.Texts,
-        MultiLocalizedUnicode_Val.Texts);
+        MultiLocalizedUnicodeVal.Texts,
+        MultiLocalizedUnicodeVal.Texts);
 
-    public static readonly IccProfileDescription ProfileDescription_ValRand2 = new IccProfileDescription(
+    public static readonly IccProfileDescription ProfileDescriptionValRand2 = new(
         1,
         2,
         IccDeviceAttribute.ChromaBlackWhite | IccDeviceAttribute.ReflectivityMatte,
         IccProfileTag.ProfileDescription,
-        new IccLocalizedString[] { LocalizedString_Rand1 },
-        new IccLocalizedString[] { LocalizedString_Rand1 });
+        new[] { LocalizedStringRand1 },
+        new[] { LocalizedStringRand1 });
 
-    public static readonly byte[] ProfileDescription_Rand1 = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt32_1,
-        IccTestDataPrimitives.UInt32_2,
+    public static readonly byte[] ProfileDescriptionRand1 = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt321,
+        IccTestDataPrimitives.UInt322,
         new byte[] { 0, 0, 0, 0, 0, 0, 0, 10 },
         new byte[] { 0x64, 0x65, 0x73, 0x63 },
         new byte[] { 0x6D, 0x6C, 0x75, 0x63 },
         new byte[] { 0x00, 0x00, 0x00, 0x00 },
-        MultiLocalizedUnicode_Arr,
+        MultiLocalizedUnicodeArr,
         new byte[] { 0x6D, 0x6C, 0x75, 0x63 },
         new byte[] { 0x00, 0x00, 0x00, 0x00 },
-        MultiLocalizedUnicode_Arr);
+        MultiLocalizedUnicodeArr);
 
-    public static readonly byte[] ProfileDescription_Rand2 = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt32_1,
-        IccTestDataPrimitives.UInt32_2,
+    public static readonly byte[] ProfileDescriptionRand2 = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt321,
+        IccTestDataPrimitives.UInt322,
         new byte[] { 0, 0, 0, 0, 0, 0, 0, 10 },
         new byte[] { 0x64, 0x65, 0x73, 0x63 },
         new byte[] { 0x64, 0x65, 0x73, 0x63 },
         new byte[] { 0x00, 0x00, 0x00, 0x00 },
-        TextDescription_Arr1,
+        TextDescriptionArr1,
         new byte[] { 0x64, 0x65, 0x73, 0x63 },
         new byte[] { 0x00, 0x00, 0x00, 0x00 },
-        TextDescription_Arr1);
+        TextDescriptionArr1);
 
     public static readonly object[][] ProfileDescriptionReadTestData =
     {
-        new object[] { ProfileDescription_Rand1, ProfileDescription_ValRand1 },
-        new object[] { ProfileDescription_Rand2, ProfileDescription_ValRand2 },
+        new object[] { ProfileDescriptionRand1, ProfileDescriptionValRand1 },
+        new object[] { ProfileDescriptionRand2, ProfileDescriptionValRand2 },
     };
 
     public static readonly object[][] ProfileDescriptionWriteTestData =
     {
-        new object[] { ProfileDescription_Rand1, ProfileDescription_ValRand1 },
+        new object[] { ProfileDescriptionRand1, ProfileDescriptionValRand1 },
     };
 
-    public static readonly IccColorantTableEntry ColorantTableEntry_ValRand1 = new IccColorantTableEntry(ArrayHelper.Fill('A', 31), 1, 2, 3);
-    public static readonly IccColorantTableEntry ColorantTableEntry_ValRand2 = new IccColorantTableEntry(ArrayHelper.Fill('4', 31), 4, 5, 6);
+    public static readonly IccColorantTableEntry ColorantTableEntryValRand1 = new(ArrayHelper.Fill('A', 31), 1, 2, 3);
+    public static readonly IccColorantTableEntry ColorantTableEntryValRand2 = new(ArrayHelper.Fill('4', 31), 4, 5, 6);
 
-    public static readonly byte[] ColorantTableEntry_Rand1 = ArrayHelper.Concat(
+    public static readonly byte[] ColorantTableEntryRand1 = ArrayHelper.Concat(
         ArrayHelper.Fill((byte)0x41, 31),
         new byte[1],    // null terminator
-        IccTestDataPrimitives.UInt16_1,
-        IccTestDataPrimitives.UInt16_2,
-        IccTestDataPrimitives.UInt16_3);
+        IccTestDataPrimitives.UInt161,
+        IccTestDataPrimitives.UInt162,
+        IccTestDataPrimitives.UInt163);
 
-    public static readonly byte[] ColorantTableEntry_Rand2 = ArrayHelper.Concat(
+    public static readonly byte[] ColorantTableEntryRand2 = ArrayHelper.Concat(
         ArrayHelper.Fill((byte)0x34, 31),
         new byte[1],    // null terminator
-        IccTestDataPrimitives.UInt16_4,
-        IccTestDataPrimitives.UInt16_5,
-        IccTestDataPrimitives.UInt16_6);
+        IccTestDataPrimitives.UInt164,
+        IccTestDataPrimitives.UInt165,
+        IccTestDataPrimitives.UInt166);
 
     public static readonly object[][] ColorantTableEntryTestData =
     {
-        new object[] { ColorantTableEntry_Rand1, ColorantTableEntry_ValRand1 },
-        new object[] { ColorantTableEntry_Rand2, ColorantTableEntry_ValRand2 },
+        new object[] { ColorantTableEntryRand1, ColorantTableEntryValRand1 },
+        new object[] { ColorantTableEntryRand2, ColorantTableEntryValRand2 },
     };
 
-    public static readonly IccScreeningChannel ScreeningChannel_ValRand1 = new IccScreeningChannel(4, 6, IccScreeningSpotType.Cross);
-    public static readonly IccScreeningChannel ScreeningChannel_ValRand2 = new IccScreeningChannel(8, 5, IccScreeningSpotType.Diamond);
+    public static readonly IccScreeningChannel ScreeningChannelValRand1 = new(4, 6, IccScreeningSpotType.Cross);
+    public static readonly IccScreeningChannel ScreeningChannelValRand2 = new(8, 5, IccScreeningSpotType.Diamond);
 
-    public static readonly byte[] ScreeningChannel_Rand1 = ArrayHelper.Concat(
-        IccTestDataPrimitives.Fix16_4,
-        IccTestDataPrimitives.Fix16_6,
-        IccTestDataPrimitives.Int32_7);
+    public static readonly byte[] ScreeningChannelRand1 = ArrayHelper.Concat(
+        IccTestDataPrimitives.Fix164,
+        IccTestDataPrimitives.Fix166,
+        IccTestDataPrimitives.Int327);
 
-    public static readonly byte[] ScreeningChannel_Rand2 = ArrayHelper.Concat(
-        IccTestDataPrimitives.Fix16_8,
-        IccTestDataPrimitives.Fix16_5,
-        IccTestDataPrimitives.Int32_3);
+    public static readonly byte[] ScreeningChannelRand2 = ArrayHelper.Concat(
+        IccTestDataPrimitives.Fix168,
+        IccTestDataPrimitives.Fix165,
+        IccTestDataPrimitives.Int323);
 
     public static readonly object[][] ScreeningChannelTestData =
     {
-        new object[] { ScreeningChannel_Rand1, ScreeningChannel_ValRand1 },
-        new object[] { ScreeningChannel_Rand2, ScreeningChannel_ValRand2 },
+        new object[] { ScreeningChannelRand1, ScreeningChannelValRand1 },
+        new object[] { ScreeningChannelRand2, ScreeningChannelValRand2 },
     };
 }
diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataPrimitives.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataPrimitives.cs
index f8e8717273..81cfea46fd 100644
--- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataPrimitives.cs
+++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataPrimitives.cs
@@ -1,242 +1,242 @@
 // Copyright (c) Six Labors.
 // Licensed under the Six Labors Split License.
 
-namespace SixLabors.ImageSharp.Tests;
+namespace SixLabors.ImageSharp.Tests.TestDataIcc;
 
 internal static class IccTestDataPrimitives
 {
-    public static readonly byte[] UInt16_0 = { 0x00, 0x00 };
-    public static readonly byte[] UInt16_1 = { 0x00, 0x01 };
-    public static readonly byte[] UInt16_2 = { 0x00, 0x02 };
-    public static readonly byte[] UInt16_3 = { 0x00, 0x03 };
-    public static readonly byte[] UInt16_4 = { 0x00, 0x04 };
-    public static readonly byte[] UInt16_5 = { 0x00, 0x05 };
-    public static readonly byte[] UInt16_6 = { 0x00, 0x06 };
-    public static readonly byte[] UInt16_7 = { 0x00, 0x07 };
-    public static readonly byte[] UInt16_8 = { 0x00, 0x08 };
-    public static readonly byte[] UInt16_9 = { 0x00, 0x09 };
-    public static readonly byte[] UInt16_32768 = { 0x80, 0x00 };
-    public static readonly byte[] UInt16_Max = { 0xFF, 0xFF };
-
-    public static readonly byte[] Int16_Min = { 0x80, 0x00 };
-    public static readonly byte[] Int16_0 = { 0x00, 0x00 };
-    public static readonly byte[] Int16_1 = { 0x00, 0x01 };
-    public static readonly byte[] Int16_2 = { 0x00, 0x02 };
-    public static readonly byte[] Int16_3 = { 0x00, 0x03 };
-    public static readonly byte[] Int16_4 = { 0x00, 0x04 };
-    public static readonly byte[] Int16_5 = { 0x00, 0x05 };
-    public static readonly byte[] Int16_6 = { 0x00, 0x06 };
-    public static readonly byte[] Int16_7 = { 0x00, 0x07 };
-    public static readonly byte[] Int16_8 = { 0x00, 0x08 };
-    public static readonly byte[] Int16_9 = { 0x00, 0x09 };
-    public static readonly byte[] Int16_Max = { 0x7F, 0xFF };
-
-    public static readonly byte[] UInt32_0 = { 0x00, 0x00, 0x00, 0x00 };
-    public static readonly byte[] UInt32_1 = { 0x00, 0x00, 0x00, 0x01 };
-    public static readonly byte[] UInt32_2 = { 0x00, 0x00, 0x00, 0x02 };
-    public static readonly byte[] UInt32_3 = { 0x00, 0x00, 0x00, 0x03 };
-    public static readonly byte[] UInt32_4 = { 0x00, 0x00, 0x00, 0x04 };
-    public static readonly byte[] UInt32_5 = { 0x00, 0x00, 0x00, 0x05 };
-    public static readonly byte[] UInt32_6 = { 0x00, 0x00, 0x00, 0x06 };
-    public static readonly byte[] UInt32_7 = { 0x00, 0x00, 0x00, 0x07 };
-    public static readonly byte[] UInt32_8 = { 0x00, 0x00, 0x00, 0x08 };
-    public static readonly byte[] UInt32_9 = { 0x00, 0x00, 0x00, 0x09 };
-    public static readonly byte[] UInt32_Max = { 0xFF, 0xFF, 0xFF, 0xFF };
-
-    public static readonly uint UInt32_ValRand1 = 1749014123;
-    public static readonly uint UInt32_ValRand2 = 3870560989;
-    public static readonly uint UInt32_ValRand3 = 1050090334;
-    public static readonly uint UInt32_ValRand4 = 3550252874;
-
-    public static readonly byte[] UInt32_Rand1 = { 0x68, 0x3F, 0xD6, 0x6B };
-    public static readonly byte[] UInt32_Rand2 = { 0xE6, 0xB4, 0x12, 0xDD };
-    public static readonly byte[] UInt32_Rand3 = { 0x3E, 0x97, 0x1B, 0x5E };
-    public static readonly byte[] UInt32_Rand4 = { 0xD3, 0x9C, 0x8F, 0x4A };
-
-    public static readonly byte[] Int32_Min = { 0x80, 0x00, 0x00, 0x00 };
-    public static readonly byte[] Int32_0 = { 0x00, 0x00, 0x00, 0x00 };
-    public static readonly byte[] Int32_1 = { 0x00, 0x00, 0x00, 0x01 };
-    public static readonly byte[] Int32_2 = { 0x00, 0x00, 0x00, 0x02 };
-    public static readonly byte[] Int32_3 = { 0x00, 0x00, 0x00, 0x03 };
-    public static readonly byte[] Int32_4 = { 0x00, 0x00, 0x00, 0x04 };
-    public static readonly byte[] Int32_5 = { 0x00, 0x00, 0x00, 0x05 };
-    public static readonly byte[] Int32_6 = { 0x00, 0x00, 0x00, 0x06 };
-    public static readonly byte[] Int32_7 = { 0x00, 0x00, 0x00, 0x07 };
-    public static readonly byte[] Int32_8 = { 0x00, 0x00, 0x00, 0x08 };
-    public static readonly byte[] Int32_9 = { 0x00, 0x00, 0x00, 0x09 };
-    public static readonly byte[] Int32_Max = { 0x7F, 0xFF, 0xFF, 0xFF };
-
-    public static readonly byte[] UInt64_0 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-    public static readonly byte[] UInt64_1 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
-    public static readonly byte[] UInt64_2 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 };
-    public static readonly byte[] UInt64_3 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 };
-    public static readonly byte[] UInt64_4 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 };
-    public static readonly byte[] UInt64_5 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05 };
-    public static readonly byte[] UInt64_6 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06 };
-    public static readonly byte[] UInt64_7 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07 };
-    public static readonly byte[] UInt64_8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 };
-    public static readonly byte[] UInt64_9 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 };
-    public static readonly byte[] UInt64_Max = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-
-    public static readonly byte[] Int64_Min = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-    public static readonly byte[] Int64_0 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-    public static readonly byte[] Int64_1 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
-    public static readonly byte[] Int64_2 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 };
-    public static readonly byte[] Int64_3 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 };
-    public static readonly byte[] Int64_4 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 };
-    public static readonly byte[] Int64_5 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05 };
-    public static readonly byte[] Int64_6 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06 };
-    public static readonly byte[] Int64_7 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07 };
-    public static readonly byte[] Int64_8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 };
-    public static readonly byte[] Int64_9 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 };
-    public static readonly byte[] Int64_Max = { 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-
-    public static readonly byte[] Single_Min = { 0xFF, 0x7F, 0xFF, 0xFF };
-    public static readonly byte[] Single_0 = { 0x00, 0x00, 0x00, 0x00 };
-    public static readonly byte[] Single_1 = { 0x3F, 0x80, 0x00, 0x00 };
-    public static readonly byte[] Single_2 = { 0x40, 0x00, 0x00, 0x00 };
-    public static readonly byte[] Single_3 = { 0x40, 0x40, 0x00, 0x00 };
-    public static readonly byte[] Single_4 = { 0x40, 0x80, 0x00, 0x00 };
-    public static readonly byte[] Single_5 = { 0x40, 0xA0, 0x00, 0x00 };
-    public static readonly byte[] Single_6 = { 0x40, 0xC0, 0x00, 0x00 };
-    public static readonly byte[] Single_7 = { 0x40, 0xE0, 0x00, 0x00 };
-    public static readonly byte[] Single_8 = { 0x41, 0x00, 0x00, 0x00 };
-    public static readonly byte[] Single_9 = { 0x41, 0x10, 0x00, 0x00 };
-    public static readonly byte[] Single_Max = { 0x7F, 0x7F, 0xFF, 0xFF };
-
-    public static readonly byte[] Double_Min = { 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-    public static readonly byte[] Double_0 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-    public static readonly byte[] Double_1 = { 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-    public static readonly byte[] Double_Max = { 0x7F, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-
-    public const float Fix16_ValMin = short.MinValue;
-    public const float Fix16_ValMax = short.MaxValue + (65535f / 65536f);
-
-    public static readonly byte[] Fix16_Min = { 0x80, 0x00, 0x00, 0x00 };
-    public static readonly byte[] Fix16_0 = { 0x00, 0x00, 0x00, 0x00 };
-    public static readonly byte[] Fix16_1 = { 0x00, 0x01, 0x00, 0x00 };
-    public static readonly byte[] Fix16_2 = { 0x00, 0x02, 0x00, 0x00 };
-    public static readonly byte[] Fix16_3 = { 0x00, 0x03, 0x00, 0x00 };
-    public static readonly byte[] Fix16_4 = { 0x00, 0x04, 0x00, 0x00 };
-    public static readonly byte[] Fix16_5 = { 0x00, 0x05, 0x00, 0x00 };
-    public static readonly byte[] Fix16_6 = { 0x00, 0x06, 0x00, 0x00 };
-    public static readonly byte[] Fix16_7 = { 0x00, 0x07, 0x00, 0x00 };
-    public static readonly byte[] Fix16_8 = { 0x00, 0x08, 0x00, 0x00 };
-    public static readonly byte[] Fix16_9 = { 0x00, 0x09, 0x00, 0x00 };
-    public static readonly byte[] Fix16_Max = { 0x7F, 0xFF, 0xFF, 0xFF };
+    public static readonly byte[] UInt160 = { 0x00, 0x00 };
+    public static readonly byte[] UInt161 = { 0x00, 0x01 };
+    public static readonly byte[] UInt162 = { 0x00, 0x02 };
+    public static readonly byte[] UInt163 = { 0x00, 0x03 };
+    public static readonly byte[] UInt164 = { 0x00, 0x04 };
+    public static readonly byte[] UInt165 = { 0x00, 0x05 };
+    public static readonly byte[] UInt166 = { 0x00, 0x06 };
+    public static readonly byte[] UInt167 = { 0x00, 0x07 };
+    public static readonly byte[] UInt168 = { 0x00, 0x08 };
+    public static readonly byte[] UInt169 = { 0x00, 0x09 };
+    public static readonly byte[] UInt1632768 = { 0x80, 0x00 };
+    public static readonly byte[] UInt16Max = { 0xFF, 0xFF };
+
+    public static readonly byte[] Int16Min = { 0x80, 0x00 };
+    public static readonly byte[] Int160 = { 0x00, 0x00 };
+    public static readonly byte[] Int161 = { 0x00, 0x01 };
+    public static readonly byte[] Int162 = { 0x00, 0x02 };
+    public static readonly byte[] Int163 = { 0x00, 0x03 };
+    public static readonly byte[] Int164 = { 0x00, 0x04 };
+    public static readonly byte[] Int165 = { 0x00, 0x05 };
+    public static readonly byte[] Int166 = { 0x00, 0x06 };
+    public static readonly byte[] Int167 = { 0x00, 0x07 };
+    public static readonly byte[] Int168 = { 0x00, 0x08 };
+    public static readonly byte[] Int169 = { 0x00, 0x09 };
+    public static readonly byte[] Int16Max = { 0x7F, 0xFF };
+
+    public static readonly byte[] UInt320 = { 0x00, 0x00, 0x00, 0x00 };
+    public static readonly byte[] UInt321 = { 0x00, 0x00, 0x00, 0x01 };
+    public static readonly byte[] UInt322 = { 0x00, 0x00, 0x00, 0x02 };
+    public static readonly byte[] UInt323 = { 0x00, 0x00, 0x00, 0x03 };
+    public static readonly byte[] UInt324 = { 0x00, 0x00, 0x00, 0x04 };
+    public static readonly byte[] UInt325 = { 0x00, 0x00, 0x00, 0x05 };
+    public static readonly byte[] UInt326 = { 0x00, 0x00, 0x00, 0x06 };
+    public static readonly byte[] UInt327 = { 0x00, 0x00, 0x00, 0x07 };
+    public static readonly byte[] UInt328 = { 0x00, 0x00, 0x00, 0x08 };
+    public static readonly byte[] UInt329 = { 0x00, 0x00, 0x00, 0x09 };
+    public static readonly byte[] UInt32Max = { 0xFF, 0xFF, 0xFF, 0xFF };
+
+    public static readonly uint UInt32ValRand1 = 1749014123;
+    public static readonly uint UInt32ValRand2 = 3870560989;
+    public static readonly uint UInt32ValRand3 = 1050090334;
+    public static readonly uint UInt32ValRand4 = 3550252874;
+
+    public static readonly byte[] UInt32Rand1 = { 0x68, 0x3F, 0xD6, 0x6B };
+    public static readonly byte[] UInt32Rand2 = { 0xE6, 0xB4, 0x12, 0xDD };
+    public static readonly byte[] UInt32Rand3 = { 0x3E, 0x97, 0x1B, 0x5E };
+    public static readonly byte[] UInt32Rand4 = { 0xD3, 0x9C, 0x8F, 0x4A };
+
+    public static readonly byte[] Int32Min = { 0x80, 0x00, 0x00, 0x00 };
+    public static readonly byte[] Int320 = { 0x00, 0x00, 0x00, 0x00 };
+    public static readonly byte[] Int321 = { 0x00, 0x00, 0x00, 0x01 };
+    public static readonly byte[] Int322 = { 0x00, 0x00, 0x00, 0x02 };
+    public static readonly byte[] Int323 = { 0x00, 0x00, 0x00, 0x03 };
+    public static readonly byte[] Int324 = { 0x00, 0x00, 0x00, 0x04 };
+    public static readonly byte[] Int325 = { 0x00, 0x00, 0x00, 0x05 };
+    public static readonly byte[] Int326 = { 0x00, 0x00, 0x00, 0x06 };
+    public static readonly byte[] Int327 = { 0x00, 0x00, 0x00, 0x07 };
+    public static readonly byte[] Int328 = { 0x00, 0x00, 0x00, 0x08 };
+    public static readonly byte[] Int329 = { 0x00, 0x00, 0x00, 0x09 };
+    public static readonly byte[] Int32Max = { 0x7F, 0xFF, 0xFF, 0xFF };
+
+    public static readonly byte[] UInt640 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+    public static readonly byte[] UInt641 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
+    public static readonly byte[] UInt642 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 };
+    public static readonly byte[] UInt643 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 };
+    public static readonly byte[] UInt644 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 };
+    public static readonly byte[] UInt645 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05 };
+    public static readonly byte[] UInt646 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06 };
+    public static readonly byte[] UInt647 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07 };
+    public static readonly byte[] UInt648 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 };
+    public static readonly byte[] UInt649 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 };
+    public static readonly byte[] UInt64Max = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
+    public static readonly byte[] Int64Min = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+    public static readonly byte[] Int640 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+    public static readonly byte[] Int641 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
+    public static readonly byte[] Int642 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 };
+    public static readonly byte[] Int643 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 };
+    public static readonly byte[] Int644 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 };
+    public static readonly byte[] Int645 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05 };
+    public static readonly byte[] Int646 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06 };
+    public static readonly byte[] Int647 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07 };
+    public static readonly byte[] Int648 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 };
+    public static readonly byte[] Int649 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 };
+    public static readonly byte[] Int64Max = { 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
+    public static readonly byte[] SingleMin = { 0xFF, 0x7F, 0xFF, 0xFF };
+    public static readonly byte[] Single0 = { 0x00, 0x00, 0x00, 0x00 };
+    public static readonly byte[] Single1 = { 0x3F, 0x80, 0x00, 0x00 };
+    public static readonly byte[] Single2 = { 0x40, 0x00, 0x00, 0x00 };
+    public static readonly byte[] Single3 = { 0x40, 0x40, 0x00, 0x00 };
+    public static readonly byte[] Single4 = { 0x40, 0x80, 0x00, 0x00 };
+    public static readonly byte[] Single5 = { 0x40, 0xA0, 0x00, 0x00 };
+    public static readonly byte[] Single6 = { 0x40, 0xC0, 0x00, 0x00 };
+    public static readonly byte[] Single7 = { 0x40, 0xE0, 0x00, 0x00 };
+    public static readonly byte[] Single8 = { 0x41, 0x00, 0x00, 0x00 };
+    public static readonly byte[] Single9 = { 0x41, 0x10, 0x00, 0x00 };
+    public static readonly byte[] SingleMax = { 0x7F, 0x7F, 0xFF, 0xFF };
+
+    public static readonly byte[] DoubleMin = { 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+    public static readonly byte[] Double0 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+    public static readonly byte[] Double1 = { 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+    public static readonly byte[] DoubleMax = { 0x7F, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
+    public const float Fix16ValMin = short.MinValue;
+    public const float Fix16ValMax = short.MaxValue + (65535f / 65536f);
+
+    public static readonly byte[] Fix16Min = { 0x80, 0x00, 0x00, 0x00 };
+    public static readonly byte[] Fix160 = { 0x00, 0x00, 0x00, 0x00 };
+    public static readonly byte[] Fix161 = { 0x00, 0x01, 0x00, 0x00 };
+    public static readonly byte[] Fix162 = { 0x00, 0x02, 0x00, 0x00 };
+    public static readonly byte[] Fix163 = { 0x00, 0x03, 0x00, 0x00 };
+    public static readonly byte[] Fix164 = { 0x00, 0x04, 0x00, 0x00 };
+    public static readonly byte[] Fix165 = { 0x00, 0x05, 0x00, 0x00 };
+    public static readonly byte[] Fix166 = { 0x00, 0x06, 0x00, 0x00 };
+    public static readonly byte[] Fix167 = { 0x00, 0x07, 0x00, 0x00 };
+    public static readonly byte[] Fix168 = { 0x00, 0x08, 0x00, 0x00 };
+    public static readonly byte[] Fix169 = { 0x00, 0x09, 0x00, 0x00 };
+    public static readonly byte[] Fix16Max = { 0x7F, 0xFF, 0xFF, 0xFF };
 
     public static readonly object[][] Fix16TestData =
     {
-        new object[] { Fix16_Min, Fix16_ValMin },
-        new object[] { Fix16_0, 0 },
-        new object[] { Fix16_4, 4 },
-        new object[] { Fix16_Max, Fix16_ValMax },
+        new object[] { Fix16Min, Fix16ValMin },
+        new object[] { Fix160, 0 },
+        new object[] { Fix164, 4 },
+        new object[] { Fix16Max, Fix16ValMax },
     };
 
-    public const float UFix16_ValMin = 0;
-    public const float UFix16_ValMax = ushort.MaxValue + (65535f / 65536f);
-
-    public static readonly byte[] UFix16_0 = { 0x00, 0x00, 0x00, 0x00 };
-    public static readonly byte[] UFix16_1 = { 0x00, 0x01, 0x00, 0x00 };
-    public static readonly byte[] UFix16_2 = { 0x00, 0x02, 0x00, 0x00 };
-    public static readonly byte[] UFix16_3 = { 0x00, 0x03, 0x00, 0x00 };
-    public static readonly byte[] UFix16_4 = { 0x00, 0x04, 0x00, 0x00 };
-    public static readonly byte[] UFix16_5 = { 0x00, 0x05, 0x00, 0x00 };
-    public static readonly byte[] UFix16_6 = { 0x00, 0x06, 0x00, 0x00 };
-    public static readonly byte[] UFix16_7 = { 0x00, 0x07, 0x00, 0x00 };
-    public static readonly byte[] UFix16_8 = { 0x00, 0x08, 0x00, 0x00 };
-    public static readonly byte[] UFix16_9 = { 0x00, 0x09, 0x00, 0x00 };
-    public static readonly byte[] UFix16_Max = { 0xFF, 0xFF, 0xFF, 0xFF };
+    public const float UFix16ValMin = 0;
+    public const float UFix16ValMax = ushort.MaxValue + (65535f / 65536f);
+
+    public static readonly byte[] UFix160 = { 0x00, 0x00, 0x00, 0x00 };
+    public static readonly byte[] UFix161 = { 0x00, 0x01, 0x00, 0x00 };
+    public static readonly byte[] UFix162 = { 0x00, 0x02, 0x00, 0x00 };
+    public static readonly byte[] UFix163 = { 0x00, 0x03, 0x00, 0x00 };
+    public static readonly byte[] UFix164 = { 0x00, 0x04, 0x00, 0x00 };
+    public static readonly byte[] UFix165 = { 0x00, 0x05, 0x00, 0x00 };
+    public static readonly byte[] UFix166 = { 0x00, 0x06, 0x00, 0x00 };
+    public static readonly byte[] UFix167 = { 0x00, 0x07, 0x00, 0x00 };
+    public static readonly byte[] UFix168 = { 0x00, 0x08, 0x00, 0x00 };
+    public static readonly byte[] UFix169 = { 0x00, 0x09, 0x00, 0x00 };
+    public static readonly byte[] UFix16Max = { 0xFF, 0xFF, 0xFF, 0xFF };
 
     public static readonly object[][] UFix16TestData =
     {
-        new object[] { UFix16_0, 0 },
-        new object[] { UFix16_4, 4 },
-        new object[] { UFix16_Max, UFix16_ValMax },
+        new object[] { UFix160, 0 },
+        new object[] { UFix164, 4 },
+        new object[] { UFix16Max, UFix16ValMax },
     };
 
-    public const float U1Fix15_ValMin = 0;
-    public const float U1Fix15_ValMax = 1f + (32767f / 32768f);
+    public const float U1Fix15ValMin = 0;
+    public const float U1Fix15ValMax = 1f + (32767f / 32768f);
 
-    public static readonly byte[] U1Fix15_0 = { 0x00, 0x00 };
-    public static readonly byte[] U1Fix15_1 = { 0x80, 0x00 };
-    public static readonly byte[] U1Fix15_Max = { 0xFF, 0xFF };
+    public static readonly byte[] U1Fix150 = { 0x00, 0x00 };
+    public static readonly byte[] U1Fix151 = { 0x80, 0x00 };
+    public static readonly byte[] U1Fix15Max = { 0xFF, 0xFF };
 
     public static readonly object[][] U1Fix15TestData =
     {
-        new object[] { U1Fix15_0, 0 },
-        new object[] { U1Fix15_1, 1 },
-        new object[] { U1Fix15_Max, U1Fix15_ValMax },
+        new object[] { U1Fix150, 0 },
+        new object[] { U1Fix151, 1 },
+        new object[] { U1Fix15Max, U1Fix15ValMax },
     };
 
-    public const float UFix8_ValMin = 0;
-    public const float UFix8_ValMax = byte.MaxValue + (255f / 256f);
-
-    public static readonly byte[] UFix8_0 = { 0x00, 0x00 };
-    public static readonly byte[] UFix8_1 = { 0x01, 0x00 };
-    public static readonly byte[] UFix8_2 = { 0x02, 0x00 };
-    public static readonly byte[] UFix8_3 = { 0x03, 0x00 };
-    public static readonly byte[] UFix8_4 = { 0x04, 0x00 };
-    public static readonly byte[] UFix8_5 = { 0x05, 0x00 };
-    public static readonly byte[] UFix8_6 = { 0x06, 0x00 };
-    public static readonly byte[] UFix8_7 = { 0x07, 0x00 };
-    public static readonly byte[] UFix8_8 = { 0x08, 0x00 };
-    public static readonly byte[] UFix8_9 = { 0x09, 0x00 };
-    public static readonly byte[] UFix8_Max = { 0xFF, 0xFF };
+    public const float UFix8ValMin = 0;
+    public const float UFix8ValMax = byte.MaxValue + (255f / 256f);
+
+    public static readonly byte[] UFix80 = { 0x00, 0x00 };
+    public static readonly byte[] UFix81 = { 0x01, 0x00 };
+    public static readonly byte[] UFix82 = { 0x02, 0x00 };
+    public static readonly byte[] UFix83 = { 0x03, 0x00 };
+    public static readonly byte[] UFix84 = { 0x04, 0x00 };
+    public static readonly byte[] UFix85 = { 0x05, 0x00 };
+    public static readonly byte[] UFix86 = { 0x06, 0x00 };
+    public static readonly byte[] UFix87 = { 0x07, 0x00 };
+    public static readonly byte[] UFix88 = { 0x08, 0x00 };
+    public static readonly byte[] UFix89 = { 0x09, 0x00 };
+    public static readonly byte[] UFix8Max = { 0xFF, 0xFF };
 
     public static readonly object[][] UFix8TestData =
     {
-        new object[] { UFix8_0, 0 },
-        new object[] { UFix8_4, 4 },
-        new object[] { UFix8_Max, UFix8_ValMax },
+        new object[] { UFix80, 0 },
+        new object[] { UFix84, 4 },
+        new object[] { UFix8Max, UFix8ValMax },
     };
 
-    public const string Ascii_ValRand = "aBcdEf1234";
-    public const string Ascii_ValRand1 = "Ecf3a";
-    public const string Ascii_ValRand2 = "2Bd4c";
-    public const string Ascii_ValRand3 = "cad14";
-    public const string Ascii_ValRand4 = "fd4E1";
-    public const string Ascii_ValRandLength4 = "aBcd";
-    public const string Ascii_ValNullRand = "aBcd\0Ef\0123";
-
-    public static readonly byte[] Ascii_Rand = { 97, 66, 99, 100, 69, 102, 49, 50, 51, 52 };
-    public static readonly byte[] Ascii_Rand1 = { 69, 99, 102, 51, 97 };
-    public static readonly byte[] Ascii_Rand2 = { 50, 66, 100, 52, 99 };
-    public static readonly byte[] Ascii_Rand3 = { 99, 97, 100, 49, 52 };
-    public static readonly byte[] Ascii_Rand4 = { 102, 100, 52, 69, 49 };
-    public static readonly byte[] Ascii_RandLength4 = { 97, 66, 99, 100 };
-    public static readonly byte[] Ascii_PaddedRand = { 97, 66, 99, 100, 69, 102, 49, 50, 51, 52, 0, 0, 0, 0 };
-    public static readonly byte[] Ascii_NullRand = { 97, 66, 99, 100, 0, 69, 102, 0, 49, 50, 51 };
-
-    public const int Ascii_Rand_Length = 10;
-    public const int Ascii_PaddedRand_Length = 14;
-    public const int Ascii_NullRand_Length = 11;
-    public const int Ascii_NullRand_LengthNoNull = 4;
+    public const string AsciiValRand = "aBcdEf1234";
+    public const string AsciiValRand1 = "Ecf3a";
+    public const string AsciiValRand2 = "2Bd4c";
+    public const string AsciiValRand3 = "cad14";
+    public const string AsciiValRand4 = "fd4E1";
+    public const string AsciiValRandLength4 = "aBcd";
+    public const string AsciiValNullRand = "aBcd\0Ef\0123";
+
+    public static readonly byte[] AsciiRand = { 97, 66, 99, 100, 69, 102, 49, 50, 51, 52 };
+    public static readonly byte[] AsciiRand1 = { 69, 99, 102, 51, 97 };
+    public static readonly byte[] AsciiRand2 = { 50, 66, 100, 52, 99 };
+    public static readonly byte[] AsciiRand3 = { 99, 97, 100, 49, 52 };
+    public static readonly byte[] AsciiRand4 = { 102, 100, 52, 69, 49 };
+    public static readonly byte[] AsciiRandLength4 = { 97, 66, 99, 100 };
+    public static readonly byte[] AsciiPaddedRand = { 97, 66, 99, 100, 69, 102, 49, 50, 51, 52, 0, 0, 0, 0 };
+    public static readonly byte[] AsciiNullRand = { 97, 66, 99, 100, 0, 69, 102, 0, 49, 50, 51 };
+
+    public const int AsciiRandLength = 10;
+    public const int AsciiPaddedRandLength = 14;
+    public const int AsciiNullRandLength = 11;
+    public const int AsciiNullRandLengthNoNull = 4;
 
     public static readonly object[][] AsciiTestData =
     {
-        new object[] { Ascii_Rand, Ascii_Rand_Length, Ascii_ValRand },
-        new object[] { Ascii_Rand, 4, Ascii_ValRandLength4 },
-        new object[] { Ascii_NullRand, Ascii_NullRand_LengthNoNull, Ascii_ValRandLength4 },
+        new object[] { AsciiRand, AsciiRandLength, AsciiValRand },
+        new object[] { AsciiRand, 4, AsciiValRandLength4 },
+        new object[] { AsciiNullRand, AsciiNullRandLengthNoNull, AsciiValRandLength4 },
     };
 
     public static readonly object[][] AsciiWriteTestData =
     {
-        new object[] { Ascii_Rand, Ascii_ValRand },
-        new object[] { Ascii_NullRand, Ascii_ValNullRand },
+        new object[] { AsciiRand, AsciiValRand },
+        new object[] { AsciiNullRand, AsciiValNullRand },
     };
 
     public static readonly object[][] AsciiPaddingTestData =
     {
-        new object[] { Ascii_PaddedRand, Ascii_PaddedRand_Length, Ascii_ValRand, true },
-        new object[] { Ascii_RandLength4, 4, Ascii_ValRand, false },
+        new object[] { AsciiPaddedRand, AsciiPaddedRandLength, AsciiValRand, true },
+        new object[] { AsciiRandLength4, 4, AsciiValRand, false },
     };
 
-    public const string Unicode_ValRand1 = ".6Abäñ$€β𐐷𤭢";
-    public const string Unicode_ValRand2 = ".6Abäñ";
-    public const string Unicode_ValRand3 = "$€β𐐷𤭢";
+    public const string UnicodeValRand1 = ".6Abäñ$€β𐐷𤭢";
+    public const string UnicodeValRand2 = ".6Abäñ";
+    public const string UnicodeValRand3 = "$€β𐐷𤭢";
 
-    public static readonly byte[] Unicode_Rand1 =
+    public static readonly byte[] UnicodeRand1 =
     {
         0x00, 0x2e, // .
         0x00, 0x36, // 6
@@ -251,7 +251,7 @@ internal static class IccTestDataPrimitives
         0xD8, 0x52, 0xDF, 0x62, // 𤭢
     };
 
-    public static readonly byte[] Unicode_Rand2 =
+    public static readonly byte[] UnicodeRand2 =
     {
         0x00, 0x2e, // .
         0x00, 0x36, // 6
@@ -261,7 +261,7 @@ internal static class IccTestDataPrimitives
         0x00, 0xf1, // ñ
     };
 
-    public static readonly byte[] Unicode_Rand3 =
+    public static readonly byte[] UnicodeRand3 =
     {
         0x00, 0x24, // $
         0x20, 0xAC, // €
diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs
index 8fd6f7e4ae..7441bede83 100644
--- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs
+++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs
@@ -4,59 +4,54 @@
 using System.Numerics;
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
 
-namespace SixLabors.ImageSharp.Tests;
+namespace SixLabors.ImageSharp.Tests.TestDataIcc;
 
 internal static class IccTestDataProfiles
 {
-    public static readonly IccProfileId Header_Random_Id_Value = new IccProfileId(0x84A8D460, 0xC716B6F3, 0x9B0E4C3D, 0xAB95F838);
-    public static readonly IccProfileId Profile_Random_Id_Value = new IccProfileId(0x917D6DE6, 0x84C958D1, 0x3BB0F5BB, 0xADD1134F);
+    public static readonly IccProfileId HeaderRandomIdValue = new(0x84A8D460, 0xC716B6F3, 0x9B0E4C3D, 0xAB95F838);
+    public static readonly IccProfileId ProfileRandomIdValue = new(0x917D6DE6, 0x84C958D1, 0x3BB0F5BB, 0xADD1134F);
 
-    public static readonly byte[] Header_Random_Id_Array =
+    public static readonly byte[] HeaderRandomIdArray =
     {
         0x84, 0xA8, 0xD4, 0x60, 0xC7, 0x16, 0xB6, 0xF3, 0x9B, 0x0E, 0x4C, 0x3D, 0xAB, 0x95, 0xF8, 0x38,
     };
 
-    public static readonly byte[] Profile_Random_Id_Array =
+    public static readonly byte[] ProfileRandomIdArray =
     {
         0x91, 0x7D, 0x6D, 0xE6, 0x84, 0xC9, 0x58, 0xD1, 0x3B, 0xB0, 0xF5, 0xBB, 0xAD, 0xD1, 0x13, 0x4F,
     };
 
-    public static readonly IccProfileHeader Header_Random_Write = CreateHeaderRandomValue(
+    public static readonly IccProfileHeader HeaderRandomWrite = CreateHeaderRandomValue(
         562,        // should be overwritten
         new IccProfileId(1, 2, 3, 4),   // should be overwritten
         "ijkl");    // should be overwritten to "acsp"
 
-    public static readonly IccProfileHeader Header_Random_Read = CreateHeaderRandomValue(132, Header_Random_Id_Value, "acsp");
+    public static readonly IccProfileHeader HeaderRandomRead = CreateHeaderRandomValue(132, HeaderRandomIdValue, "acsp");
 
-    public static readonly byte[] Header_Random_Array = CreateHeaderRandomArray(132, 0, Header_Random_Id_Array);
+    public static readonly byte[] HeaderRandomArray = CreateHeaderRandomArray(132, 0, HeaderRandomIdArray);
 
-    public static IccProfileHeader CreateHeaderRandomValue(uint size, IccProfileId id, string fileSignature)
+    public static IccProfileHeader CreateHeaderRandomValue(uint size, IccProfileId id, string fileSignature) => new()
     {
-        return new IccProfileHeader
-        {
-            Class = IccProfileClass.DisplayDevice,
-            CmmType = "abcd",
-            CreationDate = new DateTime(1990, 11, 26, 7, 21, 42),
-            CreatorSignature = "dcba",
-            DataColorSpace = IccColorSpaceType.Rgb,
-            DeviceAttributes = IccDeviceAttribute.ChromaBlackWhite | IccDeviceAttribute.OpacityTransparent,
-            DeviceManufacturer = 123456789u,
-            DeviceModel = 987654321u,
-            FileSignature = "acsp",
-            Flags = IccProfileFlag.Embedded | IccProfileFlag.Independent,
-            Id = id,
-            PcsIlluminant = new Vector3(4, 5, 6),
-            PrimaryPlatformSignature = IccPrimaryPlatformType.MicrosoftCorporation,
-            ProfileConnectionSpace = IccColorSpaceType.CieXyz,
-            RenderingIntent = IccRenderingIntent.AbsoluteColorimetric,
-            Size = size,
-            Version = new IccVersion(4, 3, 0),
-        };
-    }
-
-    public static byte[] CreateHeaderRandomArray(uint size, uint nrOfEntries, byte[] profileId)
-    {
-        return ArrayHelper.Concat(
+        Class = IccProfileClass.DisplayDevice,
+        CmmType = "abcd",
+        CreationDate = new DateTime(1990, 11, 26, 7, 21, 42),
+        CreatorSignature = "dcba",
+        DataColorSpace = IccColorSpaceType.Rgb,
+        DeviceAttributes = IccDeviceAttribute.ChromaBlackWhite | IccDeviceAttribute.OpacityTransparent,
+        DeviceManufacturer = 123456789u,
+        DeviceModel = 987654321u,
+        FileSignature = "acsp",
+        Flags = IccProfileFlag.Embedded | IccProfileFlag.Independent,
+        Id = id,
+        PcsIlluminant = new Vector3(4, 5, 6),
+        PrimaryPlatformSignature = IccPrimaryPlatformType.MicrosoftCorporation,
+        ProfileConnectionSpace = IccColorSpaceType.CieXyz,
+        RenderingIntent = IccRenderingIntent.AbsoluteColorimetric,
+        Size = size,
+        Version = new IccVersion(4, 3, 0),
+    };
+
+    public static byte[] CreateHeaderRandomArray(uint size, uint nrOfEntries, byte[] profileId) => ArrayHelper.Concat(
              new byte[]
              {
                 (byte)(size >> 24), (byte)(size >> 16), (byte)(size >> 8), (byte)size,     // Size
@@ -91,10 +86,9 @@ public static byte[] CreateHeaderRandomArray(uint size, uint nrOfEntries, byte[]
                 (byte)(nrOfEntries >> 8),
                 (byte)nrOfEntries
              });
-    }
 
-    public static readonly byte[] Profile_Random_Array = ArrayHelper.Concat(
-        CreateHeaderRandomArray(168, 2, Profile_Random_Id_Array),
+    public static readonly byte[] ProfileRandomArray = ArrayHelper.Concat(
+        CreateHeaderRandomArray(168, 2, ProfileRandomIdArray),
         new byte[]
         {
             0x00, 0x00, 0x00, 0x00,     // tag signature (Unknown)
@@ -104,17 +98,17 @@ public static byte[] CreateHeaderRandomArray(uint size, uint nrOfEntries, byte[]
             0x00, 0x00, 0x00, 0x9C,     // tag offset (156)
             0x00, 0x00, 0x00, 0x0C,     // tag size (12)
         },
-        IccTestDataTagDataEntry.TagDataEntryHeader_UnknownArr,
-        IccTestDataTagDataEntry.Unknown_Arr);
+        IccTestDataTagDataEntry.TagDataEntryHeaderUnknownArr,
+        IccTestDataTagDataEntry.UnknownArr);
 
-    public static readonly IccProfile Profile_Random_Val = new IccProfile(
+    public static readonly IccProfile ProfileRandomVal = new(
         CreateHeaderRandomValue(
             168,
-            Profile_Random_Id_Value,
+            ProfileRandomIdValue,
             "acsp"),
-        new IccTagDataEntry[] { IccTestDataTagDataEntry.Unknown_Val, IccTestDataTagDataEntry.Unknown_Val });
+        new IccTagDataEntry[] { IccTestDataTagDataEntry.UnknownVal, IccTestDataTagDataEntry.UnknownVal });
 
-    public static readonly byte[] Header_CorruptDataColorSpace_Array =
+    public static readonly byte[] HeaderCorruptDataColorSpaceArray =
     {
         0x00, 0x00, 0x00, 0x80,     // Size
         0x61, 0x62, 0x63, 0x64,     // CmmType
@@ -143,7 +137,7 @@ public static byte[] CreateHeaderRandomArray(uint size, uint nrOfEntries, byte[]
         0x00, 0x00, 0x00, 0x00,
     };
 
-    public static readonly byte[] Header_CorruptProfileConnectionSpace_Array =
+    public static readonly byte[] HeaderCorruptProfileConnectionSpaceArray =
     {
         0x00, 0x00, 0x00, 0x80,     // Size
         0x62, 0x63, 0x64, 0x65,     // CmmType
@@ -172,7 +166,7 @@ public static byte[] CreateHeaderRandomArray(uint size, uint nrOfEntries, byte[]
         0x00, 0x00, 0x00, 0x00,
     };
 
-    public static readonly byte[] Header_CorruptRenderingIntent_Array =
+    public static readonly byte[] HeaderCorruptRenderingIntentArray =
     {
         0x00, 0x00, 0x00, 0x80,     // Size
         0x63, 0x64, 0x65, 0x66,     // CmmType
@@ -201,29 +195,29 @@ public static byte[] CreateHeaderRandomArray(uint size, uint nrOfEntries, byte[]
         0x00, 0x00, 0x00, 0x00,
     };
 
-    public static readonly byte[] Header_DataTooSmall_Array = new byte[127];
+    public static readonly byte[] HeaderDataTooSmallArray = new byte[127];
 
-    public static readonly byte[] Header_InvalidSizeSmall_Array = CreateHeaderRandomArray(127, 0, Header_Random_Id_Array);
+    public static readonly byte[] HeaderInvalidSizeSmallArray = CreateHeaderRandomArray(127, 0, HeaderRandomIdArray);
 
-    public static readonly byte[] Header_InvalidSizeBig_Array = CreateHeaderRandomArray(50_000_000, 0, Header_Random_Id_Array);
+    public static readonly byte[] HeaderInvalidSizeBigArray = CreateHeaderRandomArray(50_000_000, 0, HeaderRandomIdArray);
 
-    public static readonly byte[] Header_SizeBiggerThanData_Array = CreateHeaderRandomArray(160, 0, Header_Random_Id_Array);
+    public static readonly byte[] HeaderSizeBiggerThanDataArray = CreateHeaderRandomArray(160, 0, HeaderRandomIdArray);
 
     public static readonly object[][] ProfileIdTestData =
     {
-        new object[] { Header_Random_Array, Header_Random_Id_Value },
-        new object[] { Profile_Random_Array, Profile_Random_Id_Value },
+        new object[] { HeaderRandomArray, HeaderRandomIdValue },
+        new object[] { ProfileRandomArray, ProfileRandomIdValue },
     };
 
     public static readonly object[][] ProfileValidityTestData =
     {
-        new object[] { Header_CorruptDataColorSpace_Array, false },
-        new object[] { Header_CorruptProfileConnectionSpace_Array, false },
-        new object[] { Header_CorruptRenderingIntent_Array, false },
-        new object[] { Header_DataTooSmall_Array, false },
-        new object[] { Header_InvalidSizeSmall_Array, false },
-        new object[] { Header_InvalidSizeBig_Array, false },
-        new object[] { Header_SizeBiggerThanData_Array, false },
-        new object[] { Header_Random_Array, true },
+        new object[] { HeaderCorruptDataColorSpaceArray, false },
+        new object[] { HeaderCorruptProfileConnectionSpaceArray, false },
+        new object[] { HeaderCorruptRenderingIntentArray, false },
+        new object[] { HeaderDataTooSmallArray, false },
+        new object[] { HeaderInvalidSizeSmallArray, false },
+        new object[] { HeaderInvalidSizeBigArray, false },
+        new object[] { HeaderSizeBiggerThanDataArray, false },
+        new object[] { HeaderRandomArray, true },
     };
 }
diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs
index 69d375cedf..a83dc3575d 100644
--- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs
+++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs
@@ -2,29 +2,28 @@
 // Licensed under the Six Labors Split License.
 
 using System.Globalization;
-using System.Numerics;
 using SixLabors.ImageSharp.Metadata.Profiles.Icc;
 
-namespace SixLabors.ImageSharp.Tests;
+namespace SixLabors.ImageSharp.Tests.TestDataIcc;
 
 internal static class IccTestDataTagDataEntry
 {
-    public static readonly IccTypeSignature TagDataEntryHeader_UnknownVal = IccTypeSignature.Unknown;
-    public static readonly byte[] TagDataEntryHeader_UnknownArr =
+    public static readonly IccTypeSignature TagDataEntryHeaderUnknownVal = IccTypeSignature.Unknown;
+    public static readonly byte[] TagDataEntryHeaderUnknownArr =
     {
         0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00,
     };
 
-    public static readonly IccTypeSignature TagDataEntryHeader_MultiLocalizedUnicodeVal = IccTypeSignature.MultiLocalizedUnicode;
-    public static readonly byte[] TagDataEntryHeader_MultiLocalizedUnicodeArr =
+    public static readonly IccTypeSignature TagDataEntryHeaderMultiLocalizedUnicodeVal = IccTypeSignature.MultiLocalizedUnicode;
+    public static readonly byte[] TagDataEntryHeaderMultiLocalizedUnicodeArr =
     {
         0x6D, 0x6C, 0x75, 0x63,
         0x00, 0x00, 0x00, 0x00,
     };
 
-    public static readonly IccTypeSignature TagDataEntryHeader_CurveVal = IccTypeSignature.Curve;
-    public static readonly byte[] TagDataEntryHeader_CurveArr =
+    public static readonly IccTypeSignature TagDataEntryHeaderCurveVal = IccTypeSignature.Curve;
+    public static readonly byte[] TagDataEntryHeaderCurveArr =
     {
         0x63, 0x75, 0x72, 0x76,
         0x00, 0x00, 0x00, 0x00,
@@ -32,24 +31,24 @@ internal static class IccTestDataTagDataEntry
 
     public static readonly object[][] TagDataEntryHeaderTestData =
     {
-        new object[] { TagDataEntryHeader_UnknownArr, TagDataEntryHeader_UnknownVal },
-        new object[] { TagDataEntryHeader_MultiLocalizedUnicodeArr, TagDataEntryHeader_MultiLocalizedUnicodeVal },
-        new object[] { TagDataEntryHeader_CurveArr, TagDataEntryHeader_CurveVal },
+        new object[] { TagDataEntryHeaderUnknownArr, TagDataEntryHeaderUnknownVal },
+        new object[] { TagDataEntryHeaderMultiLocalizedUnicodeArr, TagDataEntryHeaderMultiLocalizedUnicodeVal },
+        new object[] { TagDataEntryHeaderCurveArr, TagDataEntryHeaderCurveVal },
     };
 
-    public static readonly IccUnknownTagDataEntry Unknown_Val = new(new byte[] { 0x00, 0x01, 0x02, 0x03 });
+    public static readonly IccUnknownTagDataEntry UnknownVal = new(new byte[] { 0x00, 0x01, 0x02, 0x03 });
 
-    public static readonly byte[] Unknown_Arr = { 0x00, 0x01, 0x02, 0x03 };
+    public static readonly byte[] UnknownArr = { 0x00, 0x01, 0x02, 0x03 };
 
     public static readonly object[][] UnknownTagDataEntryTestData =
     {
-        new object[] { Unknown_Arr, Unknown_Val, 12u },
+        new object[] { UnknownArr, UnknownVal, 12u },
     };
 
-    public static readonly IccChromaticityTagDataEntry Chromaticity_Val1 = new(IccColorantEncoding.ItuRBt709_2);
-    public static readonly byte[] Chromaticity_Arr1 = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt16_3,
-        IccTestDataPrimitives.UInt16_1,
+    public static readonly IccChromaticityTagDataEntry ChromaticityVal1 = new(IccColorantEncoding.ItuRBt709_2);
+    public static readonly byte[] ChromaticityArr1 = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt163,
+        IccTestDataPrimitives.UInt161,
         new byte[] { 0x00, 0x00, 0xA3, 0xD7 },  // 0.640
         new byte[] { 0x00, 0x00, 0x54, 0x7B },  // 0.330
         new byte[] { 0x00, 0x00, 0x4C, 0xCD },  // 0.300
@@ -57,103 +56,99 @@ internal static class IccTestDataTagDataEntry
         new byte[] { 0x00, 0x00, 0x26, 0x66 },  // 0.150
         new byte[] { 0x00, 0x00, 0x0F, 0x5C }); // 0.060
 
-    public static readonly IccChromaticityTagDataEntry Chromaticity_Val2 = new(
-        new double[][]
+    public static readonly IccChromaticityTagDataEntry ChromaticityVal2 = new(
+        new[]
         {
             new double[] { 1, 2 },
             new double[] { 3, 4 },
         });
 
-    public static readonly byte[] Chromaticity_Arr2 = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt16_2,
-        IccTestDataPrimitives.UInt16_0,
-        IccTestDataPrimitives.UFix16_1,
-        IccTestDataPrimitives.UFix16_2,
-        IccTestDataPrimitives.UFix16_3,
-        IccTestDataPrimitives.UFix16_4);
+    public static readonly byte[] ChromaticityArr2 = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt162,
+        IccTestDataPrimitives.UInt160,
+        IccTestDataPrimitives.UFix161,
+        IccTestDataPrimitives.UFix162,
+        IccTestDataPrimitives.UFix163,
+        IccTestDataPrimitives.UFix164);
 
     /// <summary>
     /// <see cref="InvalidIccProfileException"/>: channel count must be 3 for any enum other than <see cref="ColorantEncoding.Unknown"/>
     /// </summary>
-    public static readonly byte[] Chromaticity_ArrInvalid1 = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt16_5,
-        IccTestDataPrimitives.UInt16_1);
+    public static readonly byte[] ChromaticityArrInvalid1 = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt165,
+        IccTestDataPrimitives.UInt161);
 
     /// <summary>
     /// <see cref="InvalidIccProfileException"/>: invalid enum value
     /// </summary>
-    public static readonly byte[] Chromaticity_ArrInvalid2 = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt16_3,
-        IccTestDataPrimitives.UInt16_9);
+    public static readonly byte[] ChromaticityArrInvalid2 = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt163,
+        IccTestDataPrimitives.UInt169);
 
     public static readonly object[][] ChromaticityTagDataEntryTestData =
     {
-        new object[] { Chromaticity_Arr1, Chromaticity_Val1 },
-        new object[] { Chromaticity_Arr2, Chromaticity_Val2 },
+        new object[] { ChromaticityArr1, ChromaticityVal1 },
+        new object[] { ChromaticityArr2, ChromaticityVal2 },
     };
 
-    public static readonly IccColorantOrderTagDataEntry ColorantOrder_Val = new(new byte[] { 0x00, 0x01, 0x02 });
-    public static readonly byte[] ColorantOrder_Arr = ArrayHelper.Concat(IccTestDataPrimitives.UInt32_3, new byte[] { 0x00, 0x01, 0x02 });
+    public static readonly IccColorantOrderTagDataEntry ColorantOrderVal = new(new byte[] { 0x00, 0x01, 0x02 });
+    public static readonly byte[] ColorantOrderArr = ArrayHelper.Concat(IccTestDataPrimitives.UInt323, new byte[] { 0x00, 0x01, 0x02 });
 
     public static readonly object[][] ColorantOrderTagDataEntryTestData =
     {
-        new object[] { ColorantOrder_Arr, ColorantOrder_Val },
+        new object[] { ColorantOrderArr, ColorantOrderVal },
     };
 
-    public static readonly IccColorantTableTagDataEntry ColorantTable_Val = new(
-        new IccColorantTableEntry[]
+    public static readonly IccColorantTableTagDataEntry ColorantTableVal = new(
+        new[]
         {
-            IccTestDataNonPrimitives.ColorantTableEntry_ValRand1,
-            IccTestDataNonPrimitives.ColorantTableEntry_ValRand2
+            IccTestDataNonPrimitives.ColorantTableEntryValRand1,
+            IccTestDataNonPrimitives.ColorantTableEntryValRand2
         });
 
-    public static readonly byte[] ColorantTable_Arr = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt32_2,
-        IccTestDataNonPrimitives.ColorantTableEntry_Rand1,
-        IccTestDataNonPrimitives.ColorantTableEntry_Rand2);
+    public static readonly byte[] ColorantTableArr = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt322,
+        IccTestDataNonPrimitives.ColorantTableEntryRand1,
+        IccTestDataNonPrimitives.ColorantTableEntryRand2);
 
     public static readonly object[][] ColorantTableTagDataEntryTestData =
     {
-        new object[] { ColorantTable_Arr, ColorantTable_Val },
+        new object[] { ColorantTableArr, ColorantTableVal },
     };
 
-    public static readonly IccCurveTagDataEntry Curve_Val_0 = new();
-    public static readonly byte[] Curve_Arr_0 = IccTestDataPrimitives.UInt32_0;
+    public static readonly IccCurveTagDataEntry CurveVal0 = new();
+    public static readonly byte[] CurveArr0 = IccTestDataPrimitives.UInt320;
 
-    public static readonly IccCurveTagDataEntry Curve_Val_1 = new(1f);
-    public static readonly byte[] Curve_Arr_1 = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt32_1,
-        IccTestDataPrimitives.UFix8_1);
+    public static readonly IccCurveTagDataEntry CurveVal1 = new(1f);
+    public static readonly byte[] CurveArr1 = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt321,
+        IccTestDataPrimitives.UFix81);
 
-    public static readonly IccCurveTagDataEntry Curve_Val_2 = new(new float[] { 1 / 65535f, 2 / 65535f, 3 / 65535f });
-    public static readonly byte[] Curve_Arr_2 = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt32_3,
-        IccTestDataPrimitives.UInt16_1,
-        IccTestDataPrimitives.UInt16_2,
-        IccTestDataPrimitives.UInt16_3);
+    public static readonly IccCurveTagDataEntry CurveVal2 = new(new float[] { 1 / 65535f, 2 / 65535f, 3 / 65535f });
+    public static readonly byte[] CurveArr2 = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt323,
+        IccTestDataPrimitives.UInt161,
+        IccTestDataPrimitives.UInt162,
+        IccTestDataPrimitives.UInt163);
 
     public static readonly object[][] CurveTagDataEntryTestData =
     {
-        new object[] { Curve_Arr_0, Curve_Val_0 },
-        new object[] { Curve_Arr_1, Curve_Val_1 },
-        new object[] { Curve_Arr_2, Curve_Val_2 },
+        new object[] { CurveArr0, CurveVal0 },
+        new object[] { CurveArr1, CurveVal1 },
+        new object[] { CurveArr2, CurveVal2 },
     };
 
-    public static readonly IccDataTagDataEntry Data_ValNoASCII = new(
-        new byte[] { 0x01, 0x02, 0x03, 0x04 },
-        false);
+    public static readonly IccDataTagDataEntry DataValNoAscii = new(new byte[] { 0x01, 0x02, 0x03, 0x04 }, false);
 
-    public static readonly byte[] Data_ArrNoASCII =
+    public static readonly byte[] DataArrNoAscii =
     {
         0x00, 0x00, 0x00, 0x00,
         0x01, 0x02, 0x03, 0x04
     };
 
-    public static readonly IccDataTagDataEntry Data_ValASCII = new(
-        new byte[] { (byte)'A', (byte)'S', (byte)'C', (byte)'I', (byte)'I' },
-        true);
+    public static readonly IccDataTagDataEntry DataValAscii = new(new[] { (byte)'A', (byte)'S', (byte)'C', (byte)'I', (byte)'I' }, true);
 
-    public static readonly byte[] Data_ArrASCII =
+    public static readonly byte[] DataArrAscii =
     {
         0x00, 0x00, 0x00, 0x01,
         (byte)'A', (byte)'S', (byte)'C', (byte)'I', (byte)'I'
@@ -161,86 +156,77 @@ internal static class IccTestDataTagDataEntry
 
     public static readonly object[][] DataTagDataEntryTestData =
     {
-        new object[] { Data_ArrNoASCII, Data_ValNoASCII, 16u },
-        new object[] { Data_ArrASCII, Data_ValASCII, 17u },
+        new object[] { DataArrNoAscii, DataValNoAscii, 16u },
+        new object[] { DataArrAscii, DataValAscii, 17u },
     };
 
-    public static readonly IccDateTimeTagDataEntry DateTime_Val = new(IccTestDataNonPrimitives.DateTime_ValRand1);
-    public static readonly byte[] DateTime_Arr = IccTestDataNonPrimitives.DateTime_Rand1;
+    public static readonly IccDateTimeTagDataEntry DateTimeVal = new(IccTestDataNonPrimitives.DateTimeValRand1);
+    public static readonly byte[] DateTimeArr = IccTestDataNonPrimitives.DateTimeRand1;
 
     public static readonly object[][] DateTimeTagDataEntryTestData =
     {
-        new object[] { DateTime_Arr, DateTime_Val },
+        new object[] { DateTimeArr, DateTimeVal },
     };
 
-    public static readonly IccLut16TagDataEntry Lut16_Val = new(
-        new IccLut[] { IccTestDataLut.LUT16_ValGrad, IccTestDataLut.LUT16_ValGrad },
-        IccTestDataLut.CLUT16_ValGrad,
-        new IccLut[] { IccTestDataLut.LUT16_ValGrad, IccTestDataLut.LUT16_ValGrad, IccTestDataLut.LUT16_ValGrad });
+    public static readonly IccLut16TagDataEntry Lut16Val = new(
+        new[] { IccTestDataLut.Lut16ValGrad, IccTestDataLut.Lut16ValGrad },
+        IccTestDataLut.Clut16ValGrad,
+        new[] { IccTestDataLut.Lut16ValGrad, IccTestDataLut.Lut16ValGrad, IccTestDataLut.Lut16ValGrad });
 
-    public static readonly byte[] Lut16_Arr = ArrayHelper.Concat(
+    public static readonly byte[] Lut16Arr = ArrayHelper.Concat(
         new byte[] { 0x02, 0x03, 0x03, 0x00 },
-        IccTestDataMatrix.Fix16_2D_Identity,
-        new byte[] { 0x00, (byte)IccTestDataLut.LUT16_ValGrad.Values.Length, 0x00, (byte)IccTestDataLut.LUT16_ValGrad.Values.Length },
-        IccTestDataLut.LUT16_Grad,
-        IccTestDataLut.LUT16_Grad,
-        IccTestDataLut.CLUT16_Grad,
-        IccTestDataLut.LUT16_Grad,
-        IccTestDataLut.LUT16_Grad,
-        IccTestDataLut.LUT16_Grad);
+        IccTestDataMatrix.Fix162DIdentity,
+        new byte[] { 0x00, (byte)IccTestDataLut.Lut16ValGrad.Values.Length, 0x00, (byte)IccTestDataLut.Lut16ValGrad.Values.Length },
+        IccTestDataLut.Lut16Grad,
+        IccTestDataLut.Lut16Grad,
+        IccTestDataLut.Clut16Grad,
+        IccTestDataLut.Lut16Grad,
+        IccTestDataLut.Lut16Grad,
+        IccTestDataLut.Lut16Grad);
 
     public static readonly object[][] Lut16TagDataEntryTestData =
     {
-        new object[] { Lut16_Arr, Lut16_Val },
+        new object[] { Lut16Arr, Lut16Val },
     };
 
-    public static readonly IccLut8TagDataEntry Lut8_Val = new(
-        new IccLut[] { IccTestDataLut.LUT8_ValGrad, IccTestDataLut.LUT8_ValGrad },
-        IccTestDataLut.CLUT8_ValGrad,
-        new IccLut[] { IccTestDataLut.LUT8_ValGrad, IccTestDataLut.LUT8_ValGrad, IccTestDataLut.LUT8_ValGrad });
+    public static readonly IccLut8TagDataEntry Lut8Val = new(
+        new IccLut[] { IccTestDataLut.Lut8ValGrad, IccTestDataLut.Lut8ValGrad },
+        IccTestDataLut.Clut8ValGrad,
+        new IccLut[] { IccTestDataLut.Lut8ValGrad, IccTestDataLut.Lut8ValGrad, IccTestDataLut.Lut8ValGrad });
 
-    public static readonly byte[] Lut8_Arr = ArrayHelper.Concat(
+    public static readonly byte[] Lut8Arr = ArrayHelper.Concat(
         new byte[] { 0x02, 0x03, 0x03, 0x00 },
-        IccTestDataMatrix.Fix16_2D_Identity,
-        IccTestDataLut.LUT8_Grad,
-        IccTestDataLut.LUT8_Grad,
-        IccTestDataLut.CLUT8_Grad,
-        IccTestDataLut.LUT8_Grad,
-        IccTestDataLut.LUT8_Grad,
-        IccTestDataLut.LUT8_Grad);
+        IccTestDataMatrix.Fix162DIdentity,
+        IccTestDataLut.Lut8Grad,
+        IccTestDataLut.Lut8Grad,
+        IccTestDataLut.Clut8Grad,
+        IccTestDataLut.Lut8Grad,
+        IccTestDataLut.Lut8Grad,
+        IccTestDataLut.Lut8Grad);
 
-    public static readonly object[][] Lut8TagDataEntryTestData =
-    {
-        new object[] { Lut8_Arr, Lut8_Val },
-    };
+    public static readonly object[][] Lut8TagDataEntryTestData = { new object[] { Lut8Arr, Lut8Val }, };
 
-    private static readonly byte[] CurveFull_0 = ArrayHelper.Concat(
-        TagDataEntryHeader_CurveArr,
-        Curve_Arr_0);
+    private static readonly byte[] CurveFull0 = ArrayHelper.Concat(TagDataEntryHeaderCurveArr, CurveArr0);
 
-    private static readonly byte[] CurveFull_1 = ArrayHelper.Concat(
-        TagDataEntryHeader_CurveArr,
-        Curve_Arr_1);
+    private static readonly byte[] CurveFull1 = ArrayHelper.Concat(TagDataEntryHeaderCurveArr, CurveArr1);
 
-    private static readonly byte[] CurveFull_2 = ArrayHelper.Concat(
-        TagDataEntryHeader_CurveArr,
-        Curve_Arr_2);
+    private static readonly byte[] CurveFull2 = ArrayHelper.Concat(TagDataEntryHeaderCurveArr, CurveArr2);
 
-    public static readonly IccLutAToBTagDataEntry LutAToB_Val
+    public static readonly IccLutAToBTagDataEntry LutAToBVal
         = new(
-            new IccCurveTagDataEntry[]
+            new[]
         {
-            Curve_Val_0,
-            Curve_Val_1,
-            Curve_Val_2,
+            CurveVal0,
+            CurveVal1,
+            CurveVal2,
         },
-            IccTestDataMatrix.Single_2DArray_ValGrad,
-            IccTestDataMatrix.Single_1DArray_ValGrad,
-            new IccCurveTagDataEntry[] { Curve_Val_1, Curve_Val_2, Curve_Val_0 },
-            IccTestDataLut.CLUT_Val16,
-            new IccCurveTagDataEntry[] { Curve_Val_2, Curve_Val_1 });
+            IccTestDataMatrix.Single2DArrayValGrad,
+            IccTestDataMatrix.Single1DArrayValGrad,
+            new[] { CurveVal1, CurveVal2, CurveVal0 },
+            IccTestDataLut.ClutVal16,
+            new[] { CurveVal2, CurveVal1 });
 
-    public static readonly byte[] LutAToB_Arr = ArrayHelper.Concat(
+    public static readonly byte[] LutAToBArr = ArrayHelper.Concat(
         new byte[] { 0x02, 0x03, 0x00, 0x00 },
         new byte[] { 0x00, 0x00, 0x00, 0x20 },  // b:        32
         new byte[] { 0x00, 0x00, 0x00, 0x50 },  // matrix:   80
@@ -249,51 +235,48 @@ public static readonly IccLutAToBTagDataEntry LutAToB_Val
         new byte[] { 0x00, 0x00, 0x00, 0xFC },  // a:        252
 
         // B
-        CurveFull_0,                // 12 bytes
-        CurveFull_1,                // 14 bytes
+        CurveFull0,                // 12 bytes
+        CurveFull1,                // 14 bytes
         new byte[] { 0x00, 0x00 },  // Padding
-        CurveFull_2,                // 18 bytes
+        CurveFull2,                // 18 bytes
         new byte[] { 0x00, 0x00 },  // Padding
 
         // Matrix
-        IccTestDataMatrix.Fix16_2D_Grad,   // 36 bytes
-        IccTestDataMatrix.Fix16_1D_Grad,   // 12 bytes
+        IccTestDataMatrix.Fix162DGrad,   // 36 bytes
+        IccTestDataMatrix.Fix161DGrad,   // 12 bytes
 
         // M
-        CurveFull_1,                // 14 bytes
+        CurveFull1,                // 14 bytes
         new byte[] { 0x00, 0x00 },  // Padding
-        CurveFull_2,                // 18 bytes
+        CurveFull2,                // 18 bytes
         new byte[] { 0x00, 0x00 },  // Padding
-        CurveFull_0,                // 12 bytes
+        CurveFull0,                // 12 bytes
 
         // CLUT
-        IccTestDataLut.CLUT_16,     // 74 bytes
+        IccTestDataLut.Clut16,     // 74 bytes
         new byte[] { 0x00, 0x00 },  // Padding
 
         // A
-        CurveFull_2,                // 18 bytes
+        CurveFull2,                // 18 bytes
         new byte[] { 0x00, 0x00 },  // Padding
-        CurveFull_1,                // 14 bytes
+        CurveFull1,                // 14 bytes
         new byte[] { 0x00, 0x00 }); // Padding
 
-    public static readonly object[][] LutAToBTagDataEntryTestData =
-    {
-        new object[] { LutAToB_Arr, LutAToB_Val },
-    };
+    public static readonly object[][] LutAToBTagDataEntryTestData = { new object[] { LutAToBArr, LutAToBVal }, };
 
-    public static readonly IccLutBToATagDataEntry LutBToA_Val = new(
+    public static readonly IccLutBToATagDataEntry LutBToAVal = new(
         new[]
         {
-            Curve_Val_0,
-            Curve_Val_1,
+            CurveVal0,
+            CurveVal1,
         },
         null,
         null,
         null,
-        IccTestDataLut.CLUT_Val16,
-        new[] { Curve_Val_2, Curve_Val_1, Curve_Val_0 });
+        IccTestDataLut.ClutVal16,
+        new[] { CurveVal2, CurveVal1, CurveVal0 });
 
-    public static readonly byte[] LutBToA_Arr = ArrayHelper.Concat(
+    public static readonly byte[] LutBToAArr = ArrayHelper.Concat(
         new byte[] { 0x02, 0x03, 0x00, 0x00 },
         new byte[] { 0x00, 0x00, 0x00, 0x20 },  // b:        32
         new byte[] { 0x00, 0x00, 0x00, 0x00 },  // matrix:   0
@@ -302,52 +285,52 @@ public static readonly IccLutAToBTagDataEntry LutAToB_Val
         new byte[] { 0x00, 0x00, 0x00, 0x88 },  // a:        136
 
         // B
-        CurveFull_0,    // 12 bytes
-        CurveFull_1,    // 14 bytes
+        CurveFull0,    // 12 bytes
+        CurveFull1,    // 14 bytes
         new byte[] { 0x00, 0x00 }, // Padding
 
         // CLUT
-        IccTestDataLut.CLUT_16,     // 74 bytes
+        IccTestDataLut.Clut16,     // 74 bytes
         new byte[] { 0x00, 0x00 },  // Padding
 
         // A
-        CurveFull_2,                // 18 bytes
+        CurveFull2,                // 18 bytes
         new byte[] { 0x00, 0x00 },  // Padding
-        CurveFull_1,                // 14 bytes
+        CurveFull1,                // 14 bytes
         new byte[] { 0x00, 0x00 },  // Padding
-        CurveFull_0); // 12 bytes
+        CurveFull0); // 12 bytes
 
     public static readonly object[][] LutBToATagDataEntryTestData =
     {
-        new object[] { LutBToA_Arr, LutBToA_Val },
+        new object[] { LutBToAArr, LutBToAVal },
     };
 
-    public static readonly IccMeasurementTagDataEntry Measurement_Val = new(
+    public static readonly IccMeasurementTagDataEntry MeasurementVal = new(
         IccStandardObserver.Cie1931Observer,
-        IccTestDataNonPrimitives.XyzNumber_ValVar1,
+        IccTestDataNonPrimitives.XyzNumberValVar1,
         IccMeasurementGeometry.Degree0ToDOrDTo0,
         1f,
         IccStandardIlluminant.D50);
 
-    public static readonly byte[] Measurement_Arr = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt32_1,
-        IccTestDataNonPrimitives.XyzNumber_Var1,
-        IccTestDataPrimitives.UInt32_2,
-        IccTestDataPrimitives.UFix16_1,
-        IccTestDataPrimitives.UInt32_1);
+    public static readonly byte[] MeasurementArr = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt321,
+        IccTestDataNonPrimitives.XyzNumberVar1,
+        IccTestDataPrimitives.UInt322,
+        IccTestDataPrimitives.UFix161,
+        IccTestDataPrimitives.UInt321);
 
     public static readonly object[][] MeasurementTagDataEntryTestData =
     {
-        new object[] { Measurement_Arr, Measurement_Val },
+        new object[] { MeasurementArr, MeasurementVal },
     };
 
-    private static readonly IccLocalizedString LocalizedString_Rand_enUS = CreateLocalizedString("en", "US", IccTestDataPrimitives.Unicode_ValRand2);
-    private static readonly IccLocalizedString LocalizedString_Rand_deDE = CreateLocalizedString("de", "DE", IccTestDataPrimitives.Unicode_ValRand3);
-    private static readonly IccLocalizedString LocalizedString_Rand2_deDE = CreateLocalizedString("de", "DE", IccTestDataPrimitives.Unicode_ValRand2);
-    private static readonly IccLocalizedString LocalizedString_Rand2_esXL = CreateLocalizedString("es", "XL", IccTestDataPrimitives.Unicode_ValRand2);
-    private static readonly IccLocalizedString LocalizedString_Rand2_xyXL = CreateLocalizedString("xy", "XL", IccTestDataPrimitives.Unicode_ValRand2);
-    private static readonly IccLocalizedString LocalizedString_Rand_en = CreateLocalizedString("en", null, IccTestDataPrimitives.Unicode_ValRand2);
-    private static readonly IccLocalizedString LocalizedString_Rand_Invariant = new(CultureInfo.InvariantCulture, IccTestDataPrimitives.Unicode_ValRand3);
+    private static readonly IccLocalizedString LocalizedStringRandEnUs = CreateLocalizedString("en", "US", IccTestDataPrimitives.UnicodeValRand2);
+    private static readonly IccLocalizedString LocalizedStringRandDeDe = CreateLocalizedString("de", "DE", IccTestDataPrimitives.UnicodeValRand3);
+    private static readonly IccLocalizedString LocalizedStringRand2DeDe = CreateLocalizedString("de", "DE", IccTestDataPrimitives.UnicodeValRand2);
+    private static readonly IccLocalizedString LocalizedStringRand2EsXl = CreateLocalizedString("es", "XL", IccTestDataPrimitives.UnicodeValRand2);
+    private static readonly IccLocalizedString LocalizedStringRand2XyXl = CreateLocalizedString("xy", "XL", IccTestDataPrimitives.UnicodeValRand2);
+    private static readonly IccLocalizedString LocalizedStringRandEn = CreateLocalizedString("en", null, IccTestDataPrimitives.UnicodeValRand2);
+    private static readonly IccLocalizedString LocalizedStringRandInvariant = new(CultureInfo.InvariantCulture, IccTestDataPrimitives.UnicodeValRand3);
 
     private static IccLocalizedString CreateLocalizedString(string language, string country, string text)
     {
@@ -378,29 +361,29 @@ private static IccLocalizedString CreateLocalizedString(string language, string
         return new IccLocalizedString(culture, text);
     }
 
-    private static readonly IccLocalizedString[] LocalizedString_RandArr_enUS_deDE = new IccLocalizedString[]
+    private static readonly IccLocalizedString[] LocalizedStringRandArrEnUsDeDe = new[]
     {
-        LocalizedString_Rand_enUS,
-        LocalizedString_Rand_deDE,
+        LocalizedStringRandEnUs,
+        LocalizedStringRandDeDe,
     };
 
-    private static readonly IccLocalizedString[] LocalizedString_RandArr_en_Invariant = new IccLocalizedString[]
+    private static readonly IccLocalizedString[] LocalizedStringRandArrEnInvariant = new[]
     {
-        LocalizedString_Rand_en,
-        LocalizedString_Rand_Invariant,
+        LocalizedStringRandEn,
+        LocalizedStringRandInvariant,
     };
 
-    private static readonly IccLocalizedString[] LocalizedString_SameArr_enUS_deDE_esXL_xyXL = new IccLocalizedString[]
+    private static readonly IccLocalizedString[] LocalizedStringSameArrEnUsDeDeEsXlXyXl = new[]
     {
-        LocalizedString_Rand_enUS,
-        LocalizedString_Rand2_deDE,
-        LocalizedString_Rand2_esXL,
-        LocalizedString_Rand2_xyXL,
+        LocalizedStringRandEnUs,
+        LocalizedStringRand2DeDe,
+        LocalizedStringRand2EsXl,
+        LocalizedStringRand2XyXl,
     };
 
-    public static readonly IccMultiLocalizedUnicodeTagDataEntry MultiLocalizedUnicode_Val = new(LocalizedString_RandArr_enUS_deDE);
-    public static readonly byte[] MultiLocalizedUnicode_Arr = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt32_2,
+    public static readonly IccMultiLocalizedUnicodeTagDataEntry MultiLocalizedUnicodeVal = new(LocalizedStringRandArrEnUsDeDe);
+    public static readonly byte[] MultiLocalizedUnicodeArr = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt322,
         new byte[] { 0x00, 0x00, 0x00, 0x0C },  // 12
         new byte[] { (byte)'e', (byte)'n', (byte)'U', (byte)'S' },
         new byte[] { 0x00, 0x00, 0x00, 0x0C },  // 12
@@ -408,12 +391,12 @@ private static IccLocalizedString CreateLocalizedString(string language, string
         new byte[] { (byte)'d', (byte)'e', (byte)'D', (byte)'E' },
         new byte[] { 0x00, 0x00, 0x00, 0x0E },  // 14
         new byte[] { 0x00, 0x00, 0x00, 0x34 },  // 52
-        IccTestDataPrimitives.Unicode_Rand2,
-        IccTestDataPrimitives.Unicode_Rand3);
+        IccTestDataPrimitives.UnicodeRand2,
+        IccTestDataPrimitives.UnicodeRand3);
 
-    public static readonly IccMultiLocalizedUnicodeTagDataEntry MultiLocalizedUnicode_Val2 = new(LocalizedString_RandArr_en_Invariant);
-    public static readonly byte[] MultiLocalizedUnicode_Arr2_Read = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt32_2,
+    public static readonly IccMultiLocalizedUnicodeTagDataEntry MultiLocalizedUnicodeVal2 = new(LocalizedStringRandArrEnInvariant);
+    public static readonly byte[] MultiLocalizedUnicodeArr2Read = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt322,
         new byte[] { 0x00, 0x00, 0x00, 0x0C },  // 12
         new byte[] { (byte)'e', (byte)'n', 0x00, 0x00 },
         new byte[] { 0x00, 0x00, 0x00, 0x0C },  // 12
@@ -421,11 +404,11 @@ private static IccLocalizedString CreateLocalizedString(string language, string
         new byte[] { 0x00, 0x00, 0x00, 0x00 },
         new byte[] { 0x00, 0x00, 0x00, 0x0E },  // 14
         new byte[] { 0x00, 0x00, 0x00, 0x34 },  // 52
-        IccTestDataPrimitives.Unicode_Rand2,
-        IccTestDataPrimitives.Unicode_Rand3);
+        IccTestDataPrimitives.UnicodeRand2,
+        IccTestDataPrimitives.UnicodeRand3);
 
-    public static readonly byte[] MultiLocalizedUnicode_Arr2_Write = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt32_2,
+    public static readonly byte[] MultiLocalizedUnicodeArr2Write = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt322,
         new byte[] { 0x00, 0x00, 0x00, 0x0C },  // 12
         new byte[] { (byte)'e', (byte)'n', 0x00, 0x00 },
         new byte[] { 0x00, 0x00, 0x00, 0x0C },  // 12
@@ -433,12 +416,12 @@ private static IccLocalizedString CreateLocalizedString(string language, string
         new byte[] { (byte)'x', (byte)'x', 0x00, 0x00 },
         new byte[] { 0x00, 0x00, 0x00, 0x0E },  // 14
         new byte[] { 0x00, 0x00, 0x00, 0x34 },  // 52
-        IccTestDataPrimitives.Unicode_Rand2,
-        IccTestDataPrimitives.Unicode_Rand3);
+        IccTestDataPrimitives.UnicodeRand2,
+        IccTestDataPrimitives.UnicodeRand3);
 
-    public static readonly IccMultiLocalizedUnicodeTagDataEntry MultiLocalizedUnicode_Val3 = new(LocalizedString_SameArr_enUS_deDE_esXL_xyXL);
-    public static readonly byte[] MultiLocalizedUnicode_Arr3 = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt32_4,
+    public static readonly IccMultiLocalizedUnicodeTagDataEntry MultiLocalizedUnicodeVal3 = new(LocalizedStringSameArrEnUsDeDeEsXlXyXl);
+    public static readonly byte[] MultiLocalizedUnicodeArr3 = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt324,
         new byte[] { 0x00, 0x00, 0x00, 0x0C },  // 12
         new byte[] { (byte)'e', (byte)'n', (byte)'U', (byte)'S' },
         new byte[] { 0x00, 0x00, 0x00, 0x0C },  // 12
@@ -452,374 +435,374 @@ private static IccLocalizedString CreateLocalizedString(string language, string
         new byte[] { (byte)'x', (byte)'y', (byte)'X', (byte)'L' },
         new byte[] { 0x00, 0x00, 0x00, 0x0C },  // 12
         new byte[] { 0x00, 0x00, 0x00, 0x40 },  // 64
-        IccTestDataPrimitives.Unicode_Rand2);
+        IccTestDataPrimitives.UnicodeRand2);
 
-    public static readonly object[][] MultiLocalizedUnicodeTagDataEntryTestData_Read =
+    public static readonly object[][] MultiLocalizedUnicodeTagDataEntryTestDataRead =
     {
-        new object[] { MultiLocalizedUnicode_Arr, MultiLocalizedUnicode_Val },
-        new object[] { MultiLocalizedUnicode_Arr2_Read, MultiLocalizedUnicode_Val2 },
-        new object[] { MultiLocalizedUnicode_Arr3, MultiLocalizedUnicode_Val3 },
+        new object[] { MultiLocalizedUnicodeArr, MultiLocalizedUnicodeVal },
+        new object[] { MultiLocalizedUnicodeArr2Read, MultiLocalizedUnicodeVal2 },
+        new object[] { MultiLocalizedUnicodeArr3, MultiLocalizedUnicodeVal3 },
     };
 
-    public static readonly object[][] MultiLocalizedUnicodeTagDataEntryTestData_Write =
+    public static readonly object[][] MultiLocalizedUnicodeTagDataEntryTestDataWrite =
     {
-        new object[] { MultiLocalizedUnicode_Arr, MultiLocalizedUnicode_Val },
-        new object[] { MultiLocalizedUnicode_Arr2_Write, MultiLocalizedUnicode_Val2 },
-        new object[] { MultiLocalizedUnicode_Arr3, MultiLocalizedUnicode_Val3 },
+        new object[] { MultiLocalizedUnicodeArr, MultiLocalizedUnicodeVal },
+        new object[] { MultiLocalizedUnicodeArr2Write, MultiLocalizedUnicodeVal2 },
+        new object[] { MultiLocalizedUnicodeArr3, MultiLocalizedUnicodeVal3 },
     };
 
-    public static readonly IccMultiProcessElementsTagDataEntry MultiProcessElements_Val = new(
+    public static readonly IccMultiProcessElementsTagDataEntry MultiProcessElementsVal = new(
         new IccMultiProcessElement[]
         {
-            IccTestDataMultiProcessElements.MPE_ValCLUT,
-            IccTestDataMultiProcessElements.MPE_ValCLUT,
+            IccTestDataMultiProcessElements.MpeValClut,
+            IccTestDataMultiProcessElements.MpeValClut,
         });
 
-    public static readonly byte[] MultiProcessElements_Arr = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt16_2,
-        IccTestDataPrimitives.UInt16_3,
-        IccTestDataPrimitives.UInt32_2,
+    public static readonly byte[] MultiProcessElementsArr = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt162,
+        IccTestDataPrimitives.UInt163,
+        IccTestDataPrimitives.UInt322,
         new byte[] { 0x00, 0x00, 0x00, 0x20 },  // 32
         new byte[] { 0x00, 0x00, 0x00, 0x84 },  // 132
         new byte[] { 0x00, 0x00, 0x00, 0xA4 },  // 164
         new byte[] { 0x00, 0x00, 0x00, 0x84 },  // 132
-        IccTestDataMultiProcessElements.MPE_CLUT,
-        IccTestDataMultiProcessElements.MPE_CLUT);
+        IccTestDataMultiProcessElements.MpeClut,
+        IccTestDataMultiProcessElements.MpeClut);
 
     public static readonly object[][] MultiProcessElementsTagDataEntryTestData =
     {
-        new object[] { MultiProcessElements_Arr, MultiProcessElements_Val },
+        new object[] { MultiProcessElementsArr, MultiProcessElementsVal },
     };
 
-    public static readonly IccNamedColor2TagDataEntry NamedColor2_Val = new(
+    public static readonly IccNamedColor2TagDataEntry NamedColor2Val = new(
         16909060,
         ArrayHelper.Fill('A', 31),
         ArrayHelper.Fill('4', 31),
-        new IccNamedColor[] { IccTestDataNonPrimitives.NamedColor_ValMin, IccTestDataNonPrimitives.NamedColor_ValMin });
+        new IccNamedColor[] { IccTestDataNonPrimitives.NamedColorValMin, IccTestDataNonPrimitives.NamedColorValMin });
 
-    public static readonly byte[] NamedColor2_Arr = ArrayHelper.Concat(
+    public static readonly byte[] NamedColor2Arr = ArrayHelper.Concat(
         new byte[] { 0x01, 0x02, 0x03, 0x04 },
-        IccTestDataPrimitives.UInt32_2,
-        IccTestDataPrimitives.UInt32_3,
+        IccTestDataPrimitives.UInt322,
+        IccTestDataPrimitives.UInt323,
         ArrayHelper.Fill((byte)0x41, 31),
         new byte[] { 0x00 },
         ArrayHelper.Fill((byte)0x34, 31),
         new byte[] { 0x00 },
-        IccTestDataNonPrimitives.NamedColor_Min,
-        IccTestDataNonPrimitives.NamedColor_Min);
+        IccTestDataNonPrimitives.NamedColorMin,
+        IccTestDataNonPrimitives.NamedColorMin);
 
     public static readonly object[][] NamedColor2TagDataEntryTestData =
     {
-        new object[] { NamedColor2_Arr, NamedColor2_Val },
+        new object[] { NamedColor2Arr, NamedColor2Val },
     };
 
-    public static readonly IccParametricCurveTagDataEntry ParametricCurve_Val = new(IccTestDataCurves.Parametric_ValVar1);
-    public static readonly byte[] ParametricCurve_Arr = IccTestDataCurves.Parametric_Var1;
+    public static readonly IccParametricCurveTagDataEntry ParametricCurveVal = new(IccTestDataCurves.ParametricValVar1);
+    public static readonly byte[] ParametricCurveArr = IccTestDataCurves.ParametricVar1;
 
     public static readonly object[][] ParametricCurveTagDataEntryTestData =
     {
-        new object[] { ParametricCurve_Arr, ParametricCurve_Val },
+        new object[] { ParametricCurveArr, ParametricCurveVal },
     };
 
-    public static readonly IccProfileSequenceDescTagDataEntry ProfileSequenceDesc_Val = new(
+    public static readonly IccProfileSequenceDescTagDataEntry ProfileSequenceDescVal = new(
         new IccProfileDescription[]
         {
-            IccTestDataNonPrimitives.ProfileDescription_ValRand1,
-            IccTestDataNonPrimitives.ProfileDescription_ValRand1
+            IccTestDataNonPrimitives.ProfileDescriptionValRand1,
+            IccTestDataNonPrimitives.ProfileDescriptionValRand1
         });
 
-    public static readonly byte[] ProfileSequenceDesc_Arr = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt32_2,
-        IccTestDataNonPrimitives.ProfileDescription_Rand1,
-        IccTestDataNonPrimitives.ProfileDescription_Rand1);
+    public static readonly byte[] ProfileSequenceDescArr = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt322,
+        IccTestDataNonPrimitives.ProfileDescriptionRand1,
+        IccTestDataNonPrimitives.ProfileDescriptionRand1);
 
     public static readonly object[][] ProfileSequenceDescTagDataEntryTestData =
     {
-        new object[] { ProfileSequenceDesc_Arr, ProfileSequenceDesc_Val },
+        new object[] { ProfileSequenceDescArr, ProfileSequenceDescVal },
     };
 
     public static readonly IccProfileSequenceIdentifierTagDataEntry ProfileSequenceIdentifier_Val = new(
-        new IccProfileSequenceIdentifier[]
+        new[]
         {
-            new IccProfileSequenceIdentifier(IccTestDataNonPrimitives.ProfileId_ValRand, LocalizedString_RandArr_enUS_deDE),
-            new IccProfileSequenceIdentifier(IccTestDataNonPrimitives.ProfileId_ValRand, LocalizedString_RandArr_enUS_deDE),
+            new IccProfileSequenceIdentifier(IccTestDataNonPrimitives.ProfileIdValRand, LocalizedStringRandArrEnUsDeDe),
+            new IccProfileSequenceIdentifier(IccTestDataNonPrimitives.ProfileIdValRand, LocalizedStringRandArrEnUsDeDe),
         });
 
-    public static readonly byte[] ProfileSequenceIdentifier_Arr = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt32_2,
+    public static readonly byte[] ProfileSequenceIdentifierArr = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt322,
         new byte[] { 0x00, 0x00, 0x00, 0x1C },  // 28
         new byte[] { 0x00, 0x00, 0x00, 0x54 },  // 84
         new byte[] { 0x00, 0x00, 0x00, 0x70 },  // 112
         new byte[] { 0x00, 0x00, 0x00, 0x54 },  // 84
-        IccTestDataNonPrimitives.ProfileId_Rand,        // 16 bytes
-        TagDataEntryHeader_MultiLocalizedUnicodeArr,    // 8  bytes
-        MultiLocalizedUnicode_Arr,                      // 58 bytes
+        IccTestDataNonPrimitives.ProfileIdRand,        // 16 bytes
+        TagDataEntryHeaderMultiLocalizedUnicodeArr,    // 8  bytes
+        MultiLocalizedUnicodeArr,                      // 58 bytes
         new byte[] { 0x00, 0x00 },                      // 2  bytes (padding)
-        IccTestDataNonPrimitives.ProfileId_Rand,
-        TagDataEntryHeader_MultiLocalizedUnicodeArr,
-        MultiLocalizedUnicode_Arr,
+        IccTestDataNonPrimitives.ProfileIdRand,
+        TagDataEntryHeaderMultiLocalizedUnicodeArr,
+        MultiLocalizedUnicodeArr,
         new byte[] { 0x00, 0x00 });
 
     public static readonly object[][] ProfileSequenceIdentifierTagDataEntryTestData =
     {
-        new object[] { ProfileSequenceIdentifier_Arr, ProfileSequenceIdentifier_Val },
+        new object[] { ProfileSequenceIdentifierArr, ProfileSequenceIdentifier_Val },
     };
 
-    public static readonly IccResponseCurveSet16TagDataEntry ResponseCurveSet16_Val = new(
-        new IccResponseCurve[]
+    public static readonly IccResponseCurveSet16TagDataEntry ResponseCurveSet16Val = new(
+        new[]
         {
-            IccTestDataCurves.Response_ValGrad,
-            IccTestDataCurves.Response_ValGrad,
+            IccTestDataCurves.ResponseValGrad,
+            IccTestDataCurves.ResponseValGrad,
         });
 
-    public static readonly byte[] ResponseCurveSet16_Arr = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt16_3,
-        IccTestDataPrimitives.UInt16_2,
+    public static readonly byte[] ResponseCurveSet16Arr = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt163,
+        IccTestDataPrimitives.UInt162,
         new byte[] { 0x00, 0x00, 0x00, 0x14 },  // 20
         new byte[] { 0x00, 0x00, 0x00, 0x6C },  // 108
-        IccTestDataCurves.Response_Grad, // 88 bytes
-        IccTestDataCurves.Response_Grad); // 88 bytes
+        IccTestDataCurves.ResponseGrad, // 88 bytes
+        IccTestDataCurves.ResponseGrad); // 88 bytes
 
     public static readonly object[][] ResponseCurveSet16TagDataEntryTestData =
     {
-        new object[] { ResponseCurveSet16_Arr, ResponseCurveSet16_Val },
+        new object[] { ResponseCurveSet16Arr, ResponseCurveSet16Val },
     };
 
-    public static readonly IccFix16ArrayTagDataEntry Fix16Array_Val = new(new float[] { 1 / 256f, 2 / 256f, 3 / 256f });
-    public static readonly byte[] Fix16Array_Arr = ArrayHelper.Concat(
-        IccTestDataPrimitives.Fix16_1,
-        IccTestDataPrimitives.Fix16_2,
-        IccTestDataPrimitives.Fix16_3);
+    public static readonly IccFix16ArrayTagDataEntry Fix16ArrayVal = new(new[] { 1 / 256f, 2 / 256f, 3 / 256f });
+    public static readonly byte[] Fix16ArrayArr = ArrayHelper.Concat(
+        IccTestDataPrimitives.Fix161,
+        IccTestDataPrimitives.Fix162,
+        IccTestDataPrimitives.Fix163);
 
     public static readonly object[][] Fix16ArrayTagDataEntryTestData =
     {
-        new object[] { Fix16Array_Arr, Fix16Array_Val, 20u },
+        new object[] { Fix16ArrayArr, Fix16ArrayVal, 20u },
     };
 
-    public static readonly IccSignatureTagDataEntry Signature_Val = new("ABCD");
-    public static readonly byte[] Signature_Arr = { 0x41, 0x42, 0x43, 0x44, };
+    public static readonly IccSignatureTagDataEntry SignatureVal = new("ABCD");
+    public static readonly byte[] SignatureArr = { 0x41, 0x42, 0x43, 0x44, };
 
     public static readonly object[][] SignatureTagDataEntryTestData =
     {
-        new object[] { Signature_Arr, Signature_Val },
+        new object[] { SignatureArr, SignatureVal },
     };
 
-    public static readonly IccTextTagDataEntry Text_Val = new("ABCD");
-    public static readonly byte[] Text_Arr = { 0x41, 0x42, 0x43, 0x44 };
+    public static readonly IccTextTagDataEntry TextVal = new("ABCD");
+    public static readonly byte[] TextArr = { 0x41, 0x42, 0x43, 0x44 };
 
     public static readonly object[][] TextTagDataEntryTestData =
     {
-        new object[] { Text_Arr, Text_Val, 12u },
+        new object[] { TextArr, TextVal, 12u },
     };
 
-    public static readonly IccUFix16ArrayTagDataEntry UFix16Array_Val = new(new float[] { 1, 2, 3 });
-    public static readonly byte[] UFix16Array_Arr = ArrayHelper.Concat(
-        IccTestDataPrimitives.UFix16_1,
-        IccTestDataPrimitives.UFix16_2,
-        IccTestDataPrimitives.UFix16_3);
+    public static readonly IccUFix16ArrayTagDataEntry UFix16ArrayVal = new(new float[] { 1, 2, 3 });
+    public static readonly byte[] UFix16ArrayArr = ArrayHelper.Concat(
+        IccTestDataPrimitives.UFix161,
+        IccTestDataPrimitives.UFix162,
+        IccTestDataPrimitives.UFix163);
 
     public static readonly object[][] UFix16ArrayTagDataEntryTestData =
     {
-        new object[] { UFix16Array_Arr, UFix16Array_Val, 20u },
+        new object[] { UFix16ArrayArr, UFix16ArrayVal, 20u },
     };
 
-    public static readonly IccUInt16ArrayTagDataEntry UInt16Array_Val = new(new ushort[] { 1, 2, 3 });
-    public static readonly byte[] UInt16Array_Arr = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt16_1,
-        IccTestDataPrimitives.UInt16_2,
-        IccTestDataPrimitives.UInt16_3);
+    public static readonly IccUInt16ArrayTagDataEntry UInt16ArrayVal = new(new ushort[] { 1, 2, 3 });
+    public static readonly byte[] UInt16ArrayArr = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt161,
+        IccTestDataPrimitives.UInt162,
+        IccTestDataPrimitives.UInt163);
 
     public static readonly object[][] UInt16ArrayTagDataEntryTestData =
     {
-        new object[] { UInt16Array_Arr, UInt16Array_Val, 14u },
+        new object[] { UInt16ArrayArr, UInt16ArrayVal, 14u },
     };
 
-    public static readonly IccUInt32ArrayTagDataEntry UInt32Array_Val = new(new uint[] { 1, 2, 3 });
-    public static readonly byte[] UInt32Array_Arr = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt32_1,
-        IccTestDataPrimitives.UInt32_2,
-        IccTestDataPrimitives.UInt32_3);
+    public static readonly IccUInt32ArrayTagDataEntry UInt32ArrayVal = new(new uint[] { 1, 2, 3 });
+    public static readonly byte[] UInt32ArrayArr = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt321,
+        IccTestDataPrimitives.UInt322,
+        IccTestDataPrimitives.UInt323);
 
     public static readonly object[][] UInt32ArrayTagDataEntryTestData =
     {
-        new object[] { UInt32Array_Arr, UInt32Array_Val, 20u },
+        new object[] { UInt32ArrayArr, UInt32ArrayVal, 20u },
     };
 
-    public static readonly IccUInt64ArrayTagDataEntry UInt64Array_Val = new(new ulong[] { 1, 2, 3 });
-    public static readonly byte[] UInt64Array_Arr = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt64_1,
-        IccTestDataPrimitives.UInt64_2,
-        IccTestDataPrimitives.UInt64_3);
+    public static readonly IccUInt64ArrayTagDataEntry UInt64ArrayVal = new(new ulong[] { 1, 2, 3 });
+    public static readonly byte[] UInt64ArrayArr = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt641,
+        IccTestDataPrimitives.UInt642,
+        IccTestDataPrimitives.UInt643);
 
     public static readonly object[][] UInt64ArrayTagDataEntryTestData =
     {
-        new object[] { UInt64Array_Arr, UInt64Array_Val, 32u },
+        new object[] { UInt64ArrayArr, UInt64ArrayVal, 32u },
     };
 
-    public static readonly IccUInt8ArrayTagDataEntry UInt8Array_Val = new(new byte[] { 1, 2, 3 });
-    public static readonly byte[] UInt8Array_Arr = { 1, 2, 3 };
+    public static readonly IccUInt8ArrayTagDataEntry UInt8ArrayVal = new(new byte[] { 1, 2, 3 });
+    public static readonly byte[] UInt8ArrayArr = { 1, 2, 3 };
 
     public static readonly object[][] UInt8ArrayTagDataEntryTestData =
     {
-        new object[] { UInt8Array_Arr, UInt8Array_Val, 11u },
+        new object[] { UInt8ArrayArr, UInt8ArrayVal, 11u },
     };
 
-    public static readonly IccViewingConditionsTagDataEntry ViewingConditions_Val = new(
-        IccTestDataNonPrimitives.XyzNumber_ValVar1,
-        IccTestDataNonPrimitives.XyzNumber_ValVar2,
+    public static readonly IccViewingConditionsTagDataEntry ViewingConditionsVal = new(
+        IccTestDataNonPrimitives.XyzNumberValVar1,
+        IccTestDataNonPrimitives.XyzNumberValVar2,
         IccStandardIlluminant.D50);
 
-    public static readonly byte[] ViewingConditions_Arr = ArrayHelper.Concat(
-        IccTestDataNonPrimitives.XyzNumber_Var1,
-        IccTestDataNonPrimitives.XyzNumber_Var2,
-        IccTestDataPrimitives.UInt32_1);
+    public static readonly byte[] ViewingConditionsArr = ArrayHelper.Concat(
+        IccTestDataNonPrimitives.XyzNumberVar1,
+        IccTestDataNonPrimitives.XyzNumberVar2,
+        IccTestDataPrimitives.UInt321);
 
     public static readonly object[][] ViewingConditionsTagDataEntryTestData =
     {
-        new object[] { ViewingConditions_Arr, ViewingConditions_Val },
+        new object[] { ViewingConditionsArr, ViewingConditionsVal },
     };
 
-    public static readonly IccXyzTagDataEntry XYZ_Val = new(new Vector3[]
+    public static readonly IccXyzTagDataEntry XyzVal = new(new[]
     {
-        IccTestDataNonPrimitives.XyzNumber_ValVar1,
-        IccTestDataNonPrimitives.XyzNumber_ValVar2,
-        IccTestDataNonPrimitives.XyzNumber_ValVar3,
+        IccTestDataNonPrimitives.XyzNumberValVar1,
+        IccTestDataNonPrimitives.XyzNumberValVar2,
+        IccTestDataNonPrimitives.XyzNumberValVar3,
     });
 
-    public static readonly byte[] XYZ_Arr = ArrayHelper.Concat(
-        IccTestDataNonPrimitives.XyzNumber_Var1,
-        IccTestDataNonPrimitives.XyzNumber_Var2,
-        IccTestDataNonPrimitives.XyzNumber_Var3);
+    public static readonly byte[] XyzArr = ArrayHelper.Concat(
+        IccTestDataNonPrimitives.XyzNumberVar1,
+        IccTestDataNonPrimitives.XyzNumberVar2,
+        IccTestDataNonPrimitives.XyzNumberVar3);
 
     public static readonly object[][] XYZTagDataEntryTestData =
     {
-        new object[] { XYZ_Arr, XYZ_Val, 44u },
+        new object[] { XyzArr, XyzVal, 44u },
     };
 
-    public static readonly IccTextDescriptionTagDataEntry TextDescription_Val1 = new(
-        IccTestDataPrimitives.Ascii_ValRand,
-        IccTestDataPrimitives.Unicode_ValRand1,
+    public static readonly IccTextDescriptionTagDataEntry TextDescriptionVal1 = new(
+        IccTestDataPrimitives.AsciiValRand,
+        IccTestDataPrimitives.UnicodeValRand1,
         ArrayHelper.Fill('A', 66),
         1701729619,
         2);
 
-    public static readonly byte[] TextDescription_Arr1 = ArrayHelper.Concat(
+    public static readonly byte[] TextDescriptionArr1 = ArrayHelper.Concat(
         new byte[] { 0x00, 0x00, 0x00, 0x0B }, // 11
-        IccTestDataPrimitives.Ascii_Rand,
+        IccTestDataPrimitives.AsciiRand,
         new byte[] { 0x00 }, // Null terminator
         new byte[] { 0x65, 0x6E, 0x55, 0x53 }, // enUS
         new byte[] { 0x00, 0x00, 0x00, 0x0E }, // 14
-        IccTestDataPrimitives.Unicode_Rand1,
+        IccTestDataPrimitives.UnicodeRand1,
         new byte[] { 0x00, 0x00 }, // Null terminator
         new byte[] { 0x00, 0x02, 0x43 }, // 2, 67
         ArrayHelper.Fill((byte)0x41, 66),
         new byte[] { 0x00 }); // Null terminator
 
-    public static readonly IccTextDescriptionTagDataEntry TextDescription_Val2 = new(IccTestDataPrimitives.Ascii_ValRand, null, null, 0, 0);
-    public static readonly byte[] TextDescription_Arr2 = ArrayHelper.Concat(
+    public static readonly IccTextDescriptionTagDataEntry TextDescriptionVal2 = new(IccTestDataPrimitives.AsciiValRand, null, null, 0, 0);
+    public static readonly byte[] TextDescriptionArr2 = ArrayHelper.Concat(
         new byte[] { 0x00, 0x00, 0x00, 0x0B },  // 11
-        IccTestDataPrimitives.Ascii_Rand,
+        IccTestDataPrimitives.AsciiRand,
         new byte[] { 0x00 },                    // Null terminator
-        IccTestDataPrimitives.UInt32_0,
-        IccTestDataPrimitives.UInt32_0,
+        IccTestDataPrimitives.UInt320,
+        IccTestDataPrimitives.UInt320,
         new byte[] { 0x00, 0x00, 0x00 },        // 0, 0
         ArrayHelper.Fill((byte)0x00, 67));
 
     public static readonly object[][] TextDescriptionTagDataEntryTestData =
     {
-        new object[] { TextDescription_Arr1, TextDescription_Val1 },
-        new object[] { TextDescription_Arr2, TextDescription_Val2 },
+        new object[] { TextDescriptionArr1, TextDescriptionVal1 },
+        new object[] { TextDescriptionArr2, TextDescriptionVal2 },
     };
 
-    public static readonly IccCrdInfoTagDataEntry CrdInfo_Val = new(
-        IccTestDataPrimitives.Ascii_ValRand4,
-        IccTestDataPrimitives.Ascii_ValRand1,
-        IccTestDataPrimitives.Ascii_ValRand2,
-        IccTestDataPrimitives.Ascii_ValRand3,
-        IccTestDataPrimitives.Ascii_ValRand4);
+    public static readonly IccCrdInfoTagDataEntry CrdInfoVal = new(
+        IccTestDataPrimitives.AsciiValRand4,
+        IccTestDataPrimitives.AsciiValRand1,
+        IccTestDataPrimitives.AsciiValRand2,
+        IccTestDataPrimitives.AsciiValRand3,
+        IccTestDataPrimitives.AsciiValRand4);
 
-    public static readonly byte[] CrdInfo_Arr = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt32_6,
-        IccTestDataPrimitives.Ascii_Rand4,
+    public static readonly byte[] CrdInfoArr = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt326,
+        IccTestDataPrimitives.AsciiRand4,
         new byte[] { 0 },
-        IccTestDataPrimitives.UInt32_6,
-        IccTestDataPrimitives.Ascii_Rand1,
+        IccTestDataPrimitives.UInt326,
+        IccTestDataPrimitives.AsciiRand1,
         new byte[] { 0 },
-        IccTestDataPrimitives.UInt32_6,
-        IccTestDataPrimitives.Ascii_Rand2,
+        IccTestDataPrimitives.UInt326,
+        IccTestDataPrimitives.AsciiRand2,
         new byte[] { 0 },
-        IccTestDataPrimitives.UInt32_6,
-        IccTestDataPrimitives.Ascii_Rand3,
+        IccTestDataPrimitives.UInt326,
+        IccTestDataPrimitives.AsciiRand3,
         new byte[] { 0 },
-        IccTestDataPrimitives.UInt32_6,
-        IccTestDataPrimitives.Ascii_Rand4,
+        IccTestDataPrimitives.UInt326,
+        IccTestDataPrimitives.AsciiRand4,
         new byte[] { 0 });
 
     public static readonly object[][] CrdInfoTagDataEntryTestData =
     {
-        new object[] { CrdInfo_Arr, CrdInfo_Val },
+        new object[] { CrdInfoArr, CrdInfoVal },
     };
 
-    public static readonly IccScreeningTagDataEntry Screening_Val = new(
+    public static readonly IccScreeningTagDataEntry ScreeningVal = new(
         IccScreeningFlag.DefaultScreens | IccScreeningFlag.UnitLinesPerCm,
-        new IccScreeningChannel[] { IccTestDataNonPrimitives.ScreeningChannel_ValRand1, IccTestDataNonPrimitives.ScreeningChannel_ValRand2 });
+        new IccScreeningChannel[] { IccTestDataNonPrimitives.ScreeningChannelValRand1, IccTestDataNonPrimitives.ScreeningChannelValRand2 });
 
-    public static readonly byte[] Screening_Arr = ArrayHelper.Concat(
-        IccTestDataPrimitives.Int32_1,
-        IccTestDataPrimitives.UInt32_2,
-        IccTestDataNonPrimitives.ScreeningChannel_Rand1,
-        IccTestDataNonPrimitives.ScreeningChannel_Rand2);
+    public static readonly byte[] ScreeningArr = ArrayHelper.Concat(
+        IccTestDataPrimitives.Int321,
+        IccTestDataPrimitives.UInt322,
+        IccTestDataNonPrimitives.ScreeningChannelRand1,
+        IccTestDataNonPrimitives.ScreeningChannelRand2);
 
     public static readonly object[][] ScreeningTagDataEntryTestData =
     {
-        new object[] { Screening_Arr, Screening_Val },
+        new object[] { ScreeningArr, ScreeningVal },
     };
 
-    public static readonly IccUcrBgTagDataEntry UcrBg_Val = new(
+    public static readonly IccUcrBgTagDataEntry UcrBgVal = new(
         new ushort[] { 3, 4, 6 },
         new ushort[] { 9, 7, 2, 5 },
-        IccTestDataPrimitives.Ascii_ValRand);
-
-    public static readonly byte[] UcrBg_Arr = ArrayHelper.Concat(
-        IccTestDataPrimitives.UInt32_3,
-        IccTestDataPrimitives.UInt16_3,
-        IccTestDataPrimitives.UInt16_4,
-        IccTestDataPrimitives.UInt16_6,
-        IccTestDataPrimitives.UInt32_4,
-        IccTestDataPrimitives.UInt16_9,
-        IccTestDataPrimitives.UInt16_7,
-        IccTestDataPrimitives.UInt16_2,
-        IccTestDataPrimitives.UInt16_5,
-        IccTestDataPrimitives.Ascii_Rand,
+        IccTestDataPrimitives.AsciiValRand);
+
+    public static readonly byte[] UcrBgArr = ArrayHelper.Concat(
+        IccTestDataPrimitives.UInt323,
+        IccTestDataPrimitives.UInt163,
+        IccTestDataPrimitives.UInt164,
+        IccTestDataPrimitives.UInt166,
+        IccTestDataPrimitives.UInt324,
+        IccTestDataPrimitives.UInt169,
+        IccTestDataPrimitives.UInt167,
+        IccTestDataPrimitives.UInt162,
+        IccTestDataPrimitives.UInt165,
+        IccTestDataPrimitives.AsciiRand,
         new byte[] { 0 });
 
     public static readonly object[][] UcrBgTagDataEntryTestData =
     {
-        new object[] { UcrBg_Arr, UcrBg_Val, 41 },
+        new object[] { UcrBgArr, UcrBgVal, 41 },
     };
 
-    public static readonly IccTagDataEntry TagDataEntry_CurveVal = Curve_Val_2;
-    public static readonly byte[] TagDataEntry_CurveArr = ArrayHelper.Concat(
-        TagDataEntryHeader_CurveArr,
-        Curve_Arr_2,
+    public static readonly IccTagDataEntry TagDataEntryCurveVal = CurveVal2;
+    public static readonly byte[] TagDataEntryCurveArr = ArrayHelper.Concat(
+        TagDataEntryHeaderCurveArr,
+        CurveArr2,
         new byte[] { 0x00, 0x00 }); // padding
 
-    public static readonly IccTagDataEntry TagDataEntry_MultiLocalizedUnicodeVal = MultiLocalizedUnicode_Val;
-    public static readonly byte[] TagDataEntry_MultiLocalizedUnicodeArr = ArrayHelper.Concat(
-        TagDataEntryHeader_MultiLocalizedUnicodeArr,
-        MultiLocalizedUnicode_Arr,
+    public static readonly IccTagDataEntry TagDataEntryMultiLocalizedUnicodeVal = MultiLocalizedUnicodeVal;
+    public static readonly byte[] TagDataEntryMultiLocalizedUnicodeArr = ArrayHelper.Concat(
+        TagDataEntryHeaderMultiLocalizedUnicodeArr,
+        MultiLocalizedUnicodeArr,
         new byte[] { 0x00, 0x00 }); // padding
 
-    public static readonly IccTagTableEntry TagDataEntry_MultiLocalizedUnicodeTable = new(
+    public static readonly IccTagTableEntry TagDataEntryMultiLocalizedUnicodeTable = new(
         IccProfileTag.Unknown,
         0,
-        (uint)TagDataEntry_MultiLocalizedUnicodeArr.Length - 2);
+        (uint)TagDataEntryMultiLocalizedUnicodeArr.Length - 2);
 
-    public static readonly IccTagTableEntry TagDataEntry_CurveTable = new(IccProfileTag.Unknown, 0, (uint)TagDataEntry_CurveArr.Length - 2);
+    public static readonly IccTagTableEntry TagDataEntryCurveTable = new(IccProfileTag.Unknown, 0, (uint)TagDataEntryCurveArr.Length - 2);
 
     public static readonly object[][] TagDataEntryTestData =
     {
-        new object[] { TagDataEntry_CurveArr, TagDataEntry_CurveVal },
-        new object[] { TagDataEntry_MultiLocalizedUnicodeArr, TagDataEntry_MultiLocalizedUnicodeVal },
+        new object[] { TagDataEntryCurveArr, TagDataEntryCurveVal },
+        new object[] { TagDataEntryMultiLocalizedUnicodeArr, TagDataEntryMultiLocalizedUnicodeVal },
     };
 }
diff --git a/tests/ImageSharp.Tests/TestDataIcc/Profiles/CGATS21_CRPC7.icc b/tests/ImageSharp.Tests/TestDataIcc/Profiles/CGATS21_CRPC7.icc
new file mode 100644
index 0000000000..c4b7084721
--- /dev/null
+++ b/tests/ImageSharp.Tests/TestDataIcc/Profiles/CGATS21_CRPC7.icc
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2b186e6dadc38883138ccd30203b2870fb71db6451d3a5d24f9590cfabd26689
+size 3462496
diff --git a/tests/ImageSharp.Tests/TestDataIcc/Profiles/Coated_Fogra39L_VIGC_300.icc b/tests/ImageSharp.Tests/TestDataIcc/Profiles/Coated_Fogra39L_VIGC_300.icc
new file mode 100644
index 0000000000..a21b7f657d
--- /dev/null
+++ b/tests/ImageSharp.Tests/TestDataIcc/Profiles/Coated_Fogra39L_VIGC_300.icc
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6df43849a84d2632e7900a125f657bd09364ed56775bc4740c1e39a5492d47e3
+size 8652444
diff --git a/tests/ImageSharp.Tests/TestDataIcc/Profiles/ISO22028-2_ROMM-RGB.icc b/tests/ImageSharp.Tests/TestDataIcc/Profiles/ISO22028-2_ROMM-RGB.icc
new file mode 100644
index 0000000000..b06abf217a
--- /dev/null
+++ b/tests/ImageSharp.Tests/TestDataIcc/Profiles/ISO22028-2_ROMM-RGB.icc
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:96b2f2987f83e2a545e607799fbfdff43ef8158fb9b215b187c574db8f145aaf
+size 864
diff --git a/tests/ImageSharp.Tests/TestDataIcc/Profiles/JapanColor2003WebCoated.icc b/tests/ImageSharp.Tests/TestDataIcc/Profiles/JapanColor2003WebCoated.icc
new file mode 100644
index 0000000000..0cc501bea1
Binary files /dev/null and b/tests/ImageSharp.Tests/TestDataIcc/Profiles/JapanColor2003WebCoated.icc differ
diff --git a/tests/ImageSharp.Tests/TestDataIcc/Profiles/JapanColor2011Coated.icc b/tests/ImageSharp.Tests/TestDataIcc/Profiles/JapanColor2011Coated.icc
new file mode 100644
index 0000000000..ee8dde35aa
--- /dev/null
+++ b/tests/ImageSharp.Tests/TestDataIcc/Profiles/JapanColor2011Coated.icc
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:73202ea802e57a63a0be05ed993fde8e4d51cc436120e6c47815ce785ff42916
+size 1979304
diff --git a/tests/ImageSharp.Tests/TestDataIcc/Profiles/SWOP2006_Coated5v2.icc b/tests/ImageSharp.Tests/TestDataIcc/Profiles/SWOP2006_Coated5v2.icc
new file mode 100644
index 0000000000..e24f272f35
--- /dev/null
+++ b/tests/ImageSharp.Tests/TestDataIcc/Profiles/SWOP2006_Coated5v2.icc
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0ac00fe6f03901bfd06ef70e72ec2c55fa3c043c6c34c0b6d70f06cc7a40a822
+size 2747952
diff --git a/tests/ImageSharp.Tests/TestDataIcc/Profiles/sRGB2014.icc b/tests/ImageSharp.Tests/TestDataIcc/Profiles/sRGB2014.icc
new file mode 100644
index 0000000000..46916dd8ce
--- /dev/null
+++ b/tests/ImageSharp.Tests/TestDataIcc/Profiles/sRGB2014.icc
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:384b832de3412066743b52a75ee906b6fb9fb8d9e09e936fc2c43223815c6e0a
+size 3024
diff --git a/tests/ImageSharp.Tests/TestDataIcc/Profiles/sRGB_v4_ICC_preference.icc b/tests/ImageSharp.Tests/TestDataIcc/Profiles/sRGB_v4_ICC_preference.icc
new file mode 100644
index 0000000000..8ddb31b2b8
--- /dev/null
+++ b/tests/ImageSharp.Tests/TestDataIcc/Profiles/sRGB_v4_ICC_preference.icc
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:83174717332326ddc198d9df188a4daec27b8979ba152cebbfc470c793d0bb11
+size 60960
diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs
index 4130474b58..022c0ed945 100644
--- a/tests/ImageSharp.Tests/TestImages.cs
+++ b/tests/ImageSharp.Tests/TestImages.cs
@@ -202,6 +202,17 @@ public static class Bad
 
     public static class Jpeg
     {
+        public static class ICC
+        {
+            public const string SRgb = "Jpg/icc-profiles/Momiji-sRGB-yes.jpg";
+            public const string AdobeRgb = "Jpg/icc-profiles/Momiji-AdobeRGB-yes.jpg";
+            public const string ColorMatch = "Jpg/icc-profiles/Momiji-ColorMatch-yes.jpg";
+            public const string ProPhoto = "Jpg/icc-profiles/Momiji-ProPhoto-yes.jpg";
+            public const string WideRGB = "Jpg/icc-profiles/Momiji-WideRGB-yes.jpg";
+            public const string AppleRGB = "Jpg/icc-profiles/Momiji-AppleRGB-yes.jpg";
+            public const string CMYK = "Jpg/icc-profiles/issue-129.jpg";
+        }
+
         public static class Progressive
         {
             public const string Fb = "Jpg/progressive/fb.jpg";
diff --git a/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs b/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs
index 78e5c90204..73777ef60a 100644
--- a/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs
@@ -50,8 +50,8 @@ private string GetTestOutputFileNameImpl(
         }
 
         string fn = appendSourceFileOrDescription
-                        ? Path.GetFileNameWithoutExtension(this.SourceFileOrDescription)
-                        : string.Empty;
+            ? Path.GetFileNameWithoutExtension(this.SourceFileOrDescription)
+            : string.Empty;
 
         if (string.IsNullOrWhiteSpace(extension))
         {
@@ -63,7 +63,7 @@ private string GetTestOutputFileNameImpl(
             extension = ".bmp";
         }
 
-        extension = extension.ToLower(CultureInfo.InvariantCulture);
+        extension = extension.ToLowerInvariant();
 
         if (extension[0] != '.')
         {
diff --git a/tests/Images/External/ReferenceOutput/IccProfileConverterTests/CanConvertToSRGB_Momiji-AdobeRGB-yes.png b/tests/Images/External/ReferenceOutput/IccProfileConverterTests/CanConvertToSRGB_Momiji-AdobeRGB-yes.png
new file mode 100644
index 0000000000..46d728c8d6
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/IccProfileConverterTests/CanConvertToSRGB_Momiji-AdobeRGB-yes.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:650256637c7039c59e135bbdabd31bee1ad99c9d9ff014562300945d41b6ac3a
+size 459515
diff --git a/tests/Images/External/ReferenceOutput/IccProfileConverterTests/CanConvertToSRGB_Momiji-AppleRGB-yes.png b/tests/Images/External/ReferenceOutput/IccProfileConverterTests/CanConvertToSRGB_Momiji-AppleRGB-yes.png
new file mode 100644
index 0000000000..3c856c2c32
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/IccProfileConverterTests/CanConvertToSRGB_Momiji-AppleRGB-yes.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4e2d477de13a3767a364260b7b54b1f2a46c833e8df7aa1fded7990a3ac60563
+size 483943
diff --git a/tests/Images/External/ReferenceOutput/IccProfileConverterTests/CanConvertToSRGB_Momiji-ColorMatch-yes.png b/tests/Images/External/ReferenceOutput/IccProfileConverterTests/CanConvertToSRGB_Momiji-ColorMatch-yes.png
new file mode 100644
index 0000000000..408f52e11e
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/IccProfileConverterTests/CanConvertToSRGB_Momiji-ColorMatch-yes.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7ee8f5c7f658b11a380e6da2130dc8563da3255f3ff5d9fd9cc98ec87bb1852b
+size 465348
diff --git a/tests/Images/External/ReferenceOutput/IccProfileConverterTests/CanConvertToSRGB_Momiji-ProPhoto-yes.png b/tests/Images/External/ReferenceOutput/IccProfileConverterTests/CanConvertToSRGB_Momiji-ProPhoto-yes.png
new file mode 100644
index 0000000000..714340ad6f
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/IccProfileConverterTests/CanConvertToSRGB_Momiji-ProPhoto-yes.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c702f52b08ac5be9eb65fd1f4e841fc46c897db45c709974954265b93d46b854
+size 478310
diff --git a/tests/Images/External/ReferenceOutput/IccProfileConverterTests/CanConvertToSRGB_Momiji-WideRGB-yes.png b/tests/Images/External/ReferenceOutput/IccProfileConverterTests/CanConvertToSRGB_Momiji-WideRGB-yes.png
new file mode 100644
index 0000000000..c678bf52b3
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/IccProfileConverterTests/CanConvertToSRGB_Momiji-WideRGB-yes.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f06f61eca4187823cfb76255caaa9f9f9d43e9ea56da3cd0fac830f6198d9d8a
+size 469400
diff --git a/tests/Images/External/ReferenceOutput/IccProfileConverterTests/CanConvertToSRGB_Momiji-sRGB-yes.png b/tests/Images/External/ReferenceOutput/IccProfileConverterTests/CanConvertToSRGB_Momiji-sRGB-yes.png
new file mode 100644
index 0000000000..786937c2bb
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/IccProfileConverterTests/CanConvertToSRGB_Momiji-sRGB-yes.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:dc3657d9aa0e36beee1d24144ace5bdd1198c0249ac661f302ae38b7d478d374
+size 436479
diff --git a/tests/Images/External/ReferenceOutput/IccProfileConverterTests/CanConvertToSRGB_issue-129.png b/tests/Images/External/ReferenceOutput/IccProfileConverterTests/CanConvertToSRGB_issue-129.png
new file mode 100644
index 0000000000..52dd0e0f3a
--- /dev/null
+++ b/tests/Images/External/ReferenceOutput/IccProfileConverterTests/CanConvertToSRGB_issue-129.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d423959ad2f5c9a3fc8df0ca1ff9b3d6d6751bb552cee65dbda29623581cb816
+size 2043144
diff --git a/tests/Images/Input/Jpg/icc-profiles/Momiji-AdobeRGB-yes.jpg b/tests/Images/Input/Jpg/icc-profiles/Momiji-AdobeRGB-yes.jpg
new file mode 100644
index 0000000000..077ee22beb
--- /dev/null
+++ b/tests/Images/Input/Jpg/icc-profiles/Momiji-AdobeRGB-yes.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:cb8bdcc137efa3e28db69e48612230b3a9fec17267de9ce29757d9bacc181d28
+size 42001
diff --git a/tests/Images/Input/Jpg/icc-profiles/Momiji-AppleRGB-yes.jpg b/tests/Images/Input/Jpg/icc-profiles/Momiji-AppleRGB-yes.jpg
new file mode 100644
index 0000000000..188faa2bdd
--- /dev/null
+++ b/tests/Images/Input/Jpg/icc-profiles/Momiji-AppleRGB-yes.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7129f5485e997b75cff143021522cc8ab94e2c3c1912689bc765ce2b3b937441
+size 72150
diff --git a/tests/Images/Input/Jpg/icc-profiles/Momiji-ColorMatch-yes.jpg b/tests/Images/Input/Jpg/icc-profiles/Momiji-ColorMatch-yes.jpg
new file mode 100644
index 0000000000..befc3d1170
--- /dev/null
+++ b/tests/Images/Input/Jpg/icc-profiles/Momiji-ColorMatch-yes.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:fe7fa60a53893836200c62f34492c7a0c931692dd073dffa4afc49fe3826e433
+size 44446
diff --git a/tests/Images/Input/Jpg/icc-profiles/Momiji-ProPhoto-yes.jpg b/tests/Images/Input/Jpg/icc-profiles/Momiji-ProPhoto-yes.jpg
new file mode 100644
index 0000000000..645ad2869a
--- /dev/null
+++ b/tests/Images/Input/Jpg/icc-profiles/Momiji-ProPhoto-yes.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bb686b44e3253143a32db890823f63c79026c9ac9badc4ad9de21f6cb2fa2f2a
+size 40703
diff --git a/tests/Images/Input/Jpg/icc-profiles/Momiji-WideRGB-yes.jpg b/tests/Images/Input/Jpg/icc-profiles/Momiji-WideRGB-yes.jpg
new file mode 100644
index 0000000000..57727aaa29
--- /dev/null
+++ b/tests/Images/Input/Jpg/icc-profiles/Momiji-WideRGB-yes.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:928b854a9629d1532d37095c4744da6bc2fc986f878a76aea373f69490f4b586
+size 40505
diff --git a/tests/Images/Input/Jpg/icc-profiles/Momiji-sRGB-yes.jpg b/tests/Images/Input/Jpg/icc-profiles/Momiji-sRGB-yes.jpg
new file mode 100644
index 0000000000..4b7b612be0
--- /dev/null
+++ b/tests/Images/Input/Jpg/icc-profiles/Momiji-sRGB-yes.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:faf67048c2b7bd3fb5fa9b69bd53943d63a216ef371c5dc9d062ac443c9d2d34
+size 47434
diff --git a/tests/Images/Input/Jpg/icc-profiles/issue-129.jpg b/tests/Images/Input/Jpg/icc-profiles/issue-129.jpg
new file mode 100644
index 0000000000..98949f43f1
--- /dev/null
+++ b/tests/Images/Input/Jpg/icc-profiles/issue-129.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e1728dd548d862ef3f960c82528716e0ad1b8eb0119a5eed4dfde51026d7bb74
+size 2903429