From efc4cf55ab700a2ac9d27ad422c5b558f8f3350c Mon Sep 17 00:00:00 2001 From: Wacton Date: Thu, 18 Sep 2025 12:40:55 +0100 Subject: [PATCH] Enforce ICC D50 PCS illuminant --- .../ColorProfiles/ColorProfileConverterExtensionsIcc.cs | 8 ++++---- src/ImageSharp/ColorProfiles/KnownIlluminants.cs | 8 +++++++- .../ColorProfiles/Icc/ColorProfileConverterTests.Icc.cs | 4 ++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsIcc.cs b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsIcc.cs index c33f40001a..3ddbf93b58 100644 --- a/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsIcc.cs +++ b/src/ImageSharp/ColorProfiles/ColorProfileConverterExtensionsIcc.cs @@ -60,8 +60,8 @@ internal static class ColorProfileConverterExtensionsIcc 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), + SourceWhitePoint = KnownIlluminants.D50Icc, + TargetWhitePoint = KnownIlluminants.D50Icc }); // Normalize the source, then convert to the PCS space. @@ -104,8 +104,8 @@ internal static class ColorProfileConverterExtensionsIcc 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), + SourceWhitePoint = KnownIlluminants.D50Icc, + TargetWhitePoint = KnownIlluminants.D50Icc }); using IMemoryOwner pcsBuffer = converter.Options.MemoryAllocator.Allocate(source.Length); diff --git a/src/ImageSharp/ColorProfiles/KnownIlluminants.cs b/src/ImageSharp/ColorProfiles/KnownIlluminants.cs index b9236497fe..20ba445ecc 100644 --- a/src/ImageSharp/ColorProfiles/KnownIlluminants.cs +++ b/src/ImageSharp/ColorProfiles/KnownIlluminants.cs @@ -9,6 +9,7 @@ namespace SixLabors.ImageSharp.ColorProfiles; /// /// /// Coefficients taken from: http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html +/// and https://color.org/specification/ICC.1-2022-05.pdf ///
/// Descriptions taken from: http://en.wikipedia.org/wiki/Standard_illuminant ///
@@ -30,10 +31,15 @@ public static class KnownIlluminants public static CieXyz C { get; } = new(0.98074F, 1F, 1.18232F); /// - /// Gets the Horizon Light. ICC profile PCS illuminant. + /// Gets the Horizon Light. /// public static CieXyz D50 { get; } = new(0.96422F, 1F, 0.82521F); + /// + /// Gets the D50 illuminant used in the ICC profile specification. + /// + public static CieXyz D50Icc { get; } = new(0.9642F, 1F, 0.8249F); + /// /// Gets the Mid-morning / Mid-afternoon Daylight illuminant. /// diff --git a/tests/ImageSharp.Tests/ColorProfiles/Icc/ColorProfileConverterTests.Icc.cs b/tests/ImageSharp.Tests/ColorProfiles/Icc/ColorProfileConverterTests.Icc.cs index 6c56dc682d..cb349af96a 100644 --- a/tests/ImageSharp.Tests/ColorProfiles/Icc/ColorProfileConverterTests.Icc.cs +++ b/tests/ImageSharp.Tests/ColorProfiles/Icc/ColorProfileConverterTests.Icc.cs @@ -42,7 +42,7 @@ public class ColorProfileConverterTests(ITestOutputHelper testOutputHelper) [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) + public void CanConvertIccProfiles(string sourceProfile, string targetProfile, double tolerance = 0.000005) { List actual = Inputs.ConvertAll(input => GetActualTargetValues(input, sourceProfile, targetProfile)); AssertConversion(sourceProfile, targetProfile, actual, tolerance, testOutputHelper); @@ -63,7 +63,7 @@ public class ColorProfileConverterTests(ITestOutputHelper testOutputHelper) [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) [InlineData(TestIccProfiles.Issue129, TestIccProfiles.StandardRgbV4)] // CMYK -> LAB -> -> XYZ -> RGB - public void CanBulkConvertIccProfiles(string sourceProfile, string targetProfile, double tolerance = 0.00005) + public void CanBulkConvertIccProfiles(string sourceProfile, string targetProfile, double tolerance = 0.000005) { List actual = GetBulkActualTargetValues(Inputs, sourceProfile, targetProfile); AssertConversion(sourceProfile, targetProfile, actual, tolerance, testOutputHelper);