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/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
index 435c629bc6..cb90793e04 100644
--- a/.github/workflows/build-and-test.yml
+++ b/.github/workflows/build-and-test.yml
@@ -73,8 +73,10 @@ jobs:
steps:
- name: Install libgdi+, which is required for tests running on ubuntu
- if: ${{ matrix.options.os == 'buildjet-4vcpu-ubuntu-2204-arm' }}
- run: sudo apt-get -y install libgdiplus libgif-dev libglib2.0-dev libcairo2-dev libtiff-dev libexif-dev
+ if: ${{ contains(matrix.options.os, 'ubuntu') }}
+ run: |
+ sudo apt-get update
+ sudo apt-get -y install libgdiplus libgif-dev libglib2.0-dev libcairo2-dev libtiff-dev libexif-dev
- name: Git Config
shell: bash
diff --git a/.github/workflows/code-coverage.yml b/.github/workflows/code-coverage.yml
index cd22fe5e58..b4965795c3 100644
--- a/.github/workflows/code-coverage.yml
+++ b/.github/workflows/code-coverage.yml
@@ -17,6 +17,13 @@ jobs:
runs-on: ${{matrix.options.os}}
steps:
+
+ - name: Install libgdi+, which is required for tests running on ubuntu
+ if: ${{ contains(matrix.options.os, 'ubuntu') }}
+ run: |
+ sudo apt-get update
+ sudo apt-get -y install libgdiplus libgif-dev libglib2.0-dev libcairo2-dev libtiff-dev libexif-dev
+
- name: Git Config
shell: bash
run: |
diff --git a/Directory.Build.props b/Directory.Build.props
index 26b3cc5afc..755cbe3b30 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -21,9 +21,8 @@
-
-
- preview
+
+ 12.0
+
+
- CA1822
+
+
+
+ CA1822;CA1416;CA1001;CS0029;CA1861;CA2201
+
+
+
+
+
+
+
+
+
diff --git a/tests/ImageSharp.Benchmarks/LoadResizeSave/LoadResizeSaveStressRunner.cs b/tests/ImageSharp.Benchmarks/LoadResizeSave/LoadResizeSaveStressRunner.cs
index e7d240acd3..44c248dc98 100644
--- a/tests/ImageSharp.Benchmarks/LoadResizeSave/LoadResizeSaveStressRunner.cs
+++ b/tests/ImageSharp.Benchmarks/LoadResizeSave/LoadResizeSaveStressRunner.cs
@@ -40,7 +40,7 @@ public class LoadResizeSaveStressRunner
public double TotalProcessedMegapixels { get; private set; }
- public Size LastProcessedImageSize { get; private set; }
+ public ImageSharpSize LastProcessedImageSize { get; private set; }
private string outputDirectory;
diff --git a/tests/ImageSharp.Benchmarks/Processing/Crop.cs b/tests/ImageSharp.Benchmarks/Processing/Crop.cs
index 0432b76249..e14366bfde 100644
--- a/tests/ImageSharp.Benchmarks/Processing/Crop.cs
+++ b/tests/ImageSharp.Benchmarks/Processing/Crop.cs
@@ -17,9 +17,9 @@ public class Crop
[Benchmark(Baseline = true, Description = "System.Drawing Crop")]
public SDSize CropSystemDrawing()
{
- using var source = new Bitmap(800, 800);
- using var destination = new Bitmap(100, 100);
- using var graphics = Graphics.FromImage(destination);
+ using Bitmap source = new(800, 800);
+ using Bitmap destination = new(100, 100);
+ using Graphics graphics = Graphics.FromImage(destination);
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
@@ -32,7 +32,7 @@ public class Crop
[Benchmark(Description = "ImageSharp Crop")]
public Size CropImageSharp()
{
- using var image = new Image(800, 800);
+ using Image image = new(800, 800);
image.Mutate(x => x.Crop(100, 100));
return new Size(image.Width, image.Height);
}
diff --git a/tests/ImageSharp.Benchmarks/Processing/Resize.cs b/tests/ImageSharp.Benchmarks/Processing/Resize.cs
index 05baceb6a0..09673cb96a 100644
--- a/tests/ImageSharp.Benchmarks/Processing/Resize.cs
+++ b/tests/ImageSharp.Benchmarks/Processing/Resize.cs
@@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Benchmarks;
public abstract class Resize
where TPixel : unmanaged, IPixel
{
- private byte[] bytes = null;
+ private byte[] bytes;
private Image sourceImage;
@@ -35,7 +35,7 @@ public abstract class Resize
this.sourceImage = Image.Load(this.bytes);
- var ms1 = new MemoryStream(this.bytes);
+ MemoryStream ms1 = new(this.bytes);
this.sourceBitmap = SDImage.FromStream(ms1);
this.DestSize = this.sourceBitmap.Width / 2;
}
@@ -52,21 +52,19 @@ public abstract class Resize
[Benchmark(Baseline = true)]
public int SystemDrawing()
{
- using (var destination = new Bitmap(this.DestSize, this.DestSize))
+ using Bitmap destination = new(this.DestSize, this.DestSize);
+ using (Graphics g = Graphics.FromImage(destination))
{
- using (var g = Graphics.FromImage(destination))
- {
- g.CompositingMode = CompositingMode.SourceCopy;
- g.InterpolationMode = InterpolationMode.HighQualityBicubic;
- g.PixelOffsetMode = PixelOffsetMode.HighQuality;
- g.CompositingQuality = CompositingQuality.HighQuality;
- g.SmoothingMode = SmoothingMode.HighQuality;
-
- g.DrawImage(this.sourceBitmap, 0, 0, this.DestSize, this.DestSize);
- }
-
- return destination.Width;
+ g.CompositingMode = CompositingMode.SourceCopy;
+ g.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ g.PixelOffsetMode = PixelOffsetMode.HighQuality;
+ g.CompositingQuality = CompositingQuality.HighQuality;
+ g.SmoothingMode = SmoothingMode.HighQuality;
+
+ g.DrawImage(this.sourceBitmap, 0, 0, this.DestSize, this.DestSize);
}
+
+ return destination.Width;
}
[Benchmark(Description = "ImageSharp, MaxDegreeOfParallelism = 1")]
@@ -87,10 +85,8 @@ public abstract class Resize
{
this.Configuration.MaxDegreeOfParallelism = maxDegreeOfParallelism;
- using (Image clone = this.sourceImage.Clone(this.ExecuteResizeOperation))
- {
- return clone.Width;
- }
+ using Image clone = this.sourceImage.Clone(this.ExecuteResizeOperation);
+ return clone.Width;
}
protected abstract void ExecuteResizeOperation(IImageProcessingContext ctx);
diff --git a/tests/ImageSharp.Tests/ColorProfiles/ApproximateColorProfileComparer.cs b/tests/ImageSharp.Tests/ColorProfiles/ApproximateColorProfileComparer.cs
index 56d495a87a..f4078887c7 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/ApproximateColorProfileComparer.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/ApproximateColorProfileComparer.cs
@@ -22,7 +22,9 @@ internal readonly struct ApproximateColorProfileComparer :
IEqualityComparer,
IEqualityComparer,
IEqualityComparer,
- IEqualityComparer
+ IEqualityComparer,
+ IEqualityComparer,
+ IEqualityComparer
{
private readonly float epsilon;
@@ -58,6 +60,10 @@ internal readonly struct ApproximateColorProfileComparer :
public bool Equals(HunterLab x, HunterLab y) => this.Equals(x.L, y.L) && this.Equals(x.A, y.A) && this.Equals(x.B, y.B);
+ public bool Equals(Y x, Y y) => this.Equals(x.L, y.L);
+
+ public bool Equals(YccK x, YccK y) => this.Equals(x.Y, y.Y) && this.Equals(x.Cb, y.Cb) && this.Equals(x.Cr, y.Cr) && this.Equals(x.K, y.K);
+
public int GetHashCode([DisallowNull] CieLab obj) => obj.GetHashCode();
public int GetHashCode([DisallowNull] CieXyz obj) => obj.GetHashCode();
@@ -84,6 +90,10 @@ internal readonly struct ApproximateColorProfileComparer :
public int GetHashCode([DisallowNull] HunterLab obj) => obj.GetHashCode();
+ public int GetHashCode([DisallowNull] Y obj) => obj.GetHashCode();
+
+ public int GetHashCode([DisallowNull] YccK obj) => obj.GetHashCode();
+
private bool Equals(float x, float y)
{
float d = x - y;
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:
///
///
+[Trait("Color", "Conversion")]
public class CieLabAndCieLchConversionTests
{
private static readonly ApproximateColorProfileComparer Comparer = new(.0001f);
@@ -30,7 +31,7 @@ public class CieLabAndCieLchConversionTests
// 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 inputSpan = new CieLch[5];
@@ -65,7 +66,7 @@ public class CieLabAndCieLchConversionTests
// 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 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 class CieLabAndCieLchuvConversionTests
// 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 inputSpan = new CieLchuv[5];
@@ -53,7 +53,7 @@ public class CieLabAndCieLchuvConversionTests
// 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 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 class CieLabAndCieLuvConversionTests
// 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 inputSpan = new CieLuv[5];
@@ -53,7 +53,7 @@ public class CieLabAndCieLuvConversionTests
// 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 inputSpan = new CieLab[5];
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieLabAndYCbCrConversionTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieLabAndYCbCrConversionTests.cs
index 9a29b15398..15677c46f0 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieLabAndYCbCrConversionTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieLabAndYCbCrConversionTests.cs
@@ -13,8 +13,9 @@ public class CieLabAndYCbCrConversionTests
private static readonly ApproximateColorProfileComparer Comparer = new(.0002F);
[Theory]
- [InlineData(0, 128, 128, 0, 0, 0)]
- [InlineData(87.4179, 133.9763, 247.5308, 55.06287, 82.54838, 23.1697)]
+ [InlineData(1, .5F, .5F, 100, 0, 0)]
+ [InlineData(0, .5F, .5F, 0, 0, 0)]
+ [InlineData(.5F, .5F, .5F, 53.38897F, 0, 0)]
public void Convert_YCbCr_to_CieLab(float y, float cb, float cr, float l, float a, float b)
{
// Arrange
@@ -41,8 +42,9 @@ public class CieLabAndYCbCrConversionTests
}
[Theory]
- [InlineData(0, 0, 0, 0, 128, 128)]
- [InlineData(55.06287, 82.54838, 23.1697, 87.41701, 133.97232, 247.5314)]
+ [InlineData(100, 0, 0, 1, .5F, .5F)]
+ [InlineData(0, 0, 0, 0, .5F, .5F)]
+ [InlineData(53.38897F, 0, 0, .5F, .5F, .5F)]
public void Convert_CieLab_to_YCbCr(float l, float a, float b, float y, float cb, float cr)
{
// Arrange
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;
///
/// Tests the struct.
///
+[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 class CieLchAndCieLuvConversionTests
// 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 inputSpan = new CieLch[5];
@@ -48,7 +48,7 @@ public class CieLchAndCieLuvConversionTests
// 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 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 class CieLchuvAndCieLchConversionTests
// 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 inputSpan = new CieLch[5];
@@ -48,7 +48,7 @@ public class CieLchuvAndCieLchConversionTests
// 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 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:
///
///
+[Trait("Color", "Conversion")]
public class CieLchuvAndCieLuvConversionTests
{
private static readonly ApproximateColorProfileComparer Comparer = new(.0001F);
@@ -30,7 +31,7 @@ public class CieLchuvAndCieLuvConversionTests
// 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 inputSpan = new CieLchuv[5];
@@ -66,7 +67,7 @@ public class CieLchuvAndCieLuvConversionTests
// 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 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 class CieLchuvAndCmykConversionTests
// 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 inputSpan = new Cmyk[5];
@@ -49,7 +49,7 @@ public class CieLchuvAndCmykConversionTests
// 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 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;
///
/// Tests the struct.
///
+[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 class CieLuvAndCieXyyConversionTests
// 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 inputSpan = new CieLuv[5];
@@ -49,7 +49,7 @@ public class CieLuvAndCieXyyConversionTests
// 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 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 class CieLuvAndHslConversionTests
// 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 inputSpan = new CieLuv[5];
@@ -49,7 +49,7 @@ public class CieLuvAndHslConversionTests
// 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 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 class CieLuvAndHsvConversionTests
// 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 inputSpan = new CieLuv[5];
@@ -49,7 +49,7 @@ public class CieLuvAndHsvConversionTests
// 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 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 class CieLuvAndHunterLabConversionTests
// 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 inputSpan = new CieLuv[5];
@@ -49,7 +49,7 @@ public class CieLuvAndHunterLabConversionTests
// 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 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 class CieLuvAndLmsConversionTests
// 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 inputSpan = new CieLuv[5];
@@ -49,7 +49,7 @@ public class CieLuvAndLmsConversionTests
// 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 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 class CieLuvAndRgbConversionTests
// 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 inputSpan = new CieLuv[5];
@@ -49,7 +49,7 @@ public class CieLuvAndRgbConversionTests
// 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 inputSpan = new Rgb[5];
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndYCbCrConversionTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndYCbCrConversionTests.cs
index fa7e2ece3f..62b276a1f1 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndYCbCrConversionTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieLuvAndYCbCrConversionTests.cs
@@ -13,14 +13,15 @@ public class CieLuvAndYCbCrConversionTests
private static readonly ApproximateColorProfileComparer Comparer = new(.0002F);
[Theory]
- [InlineData(0, 0, 0, 0, 128, 128)]
- [InlineData(36.0555, 93.6901, 10.01514, 71.8283, 119.3174, 193.9839)]
+ [InlineData(100, 0, 0, 1, .5F, .5F)]
+ [InlineData(0, 0, 0, 0, .5F, .5F)]
+ [InlineData(53.38897F, 0, 0, .5F, .5F, .5F)]
public void Convert_CieLuv_to_YCbCr(float l, float u, float v, float y, float cb, float cr)
{
// 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 inputSpan = new CieLuv[5];
@@ -42,14 +43,15 @@ public class CieLuvAndYCbCrConversionTests
}
[Theory]
- [InlineData(0, 128, 128, 0, 0, 0)]
- [InlineData(71.8283, 119.3174, 193.9839, 36.00565, 93.44593, 10.2234)]
+ [InlineData(1, .5F, .5F, 100, 0, 0)]
+ [InlineData(0, .5F, .5F, 0, 0, 0)]
+ [InlineData(.5F, .5F, .5F, 53.38897F, 0, 0)]
public void Convert_YCbCr_to_CieLuv(float y, float cb, float cr, float l, float u, float v)
{
// 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 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;
///
/// Tests the struct.
///
+[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;
///
/// Tests the struct.
///
+[Trait("Color", "Conversion")]
public class CieXyChromaticityCoordinatesTests
{
[Fact]
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieXyyAndYCbCrConversionTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieXyyAndYCbCrConversionTests.cs
index 1fe3596036..f9d571e036 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieXyyAndYCbCrConversionTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieXyyAndYCbCrConversionTests.cs
@@ -13,8 +13,9 @@ public class CieXyyAndYCbCrConversionTests
private static readonly ApproximateColorProfileComparer Comparer = new(.0002f);
[Theory]
- [InlineData(0, 0, 0, 0, 128, 128)]
- [InlineData(0.360555, 0.936901, 0.1001514, 64.0204849, 91.87107, 82.33627)]
+ [InlineData(.34566915F, .358496159F, .99999994F, 1, .5F, .5F)]
+ [InlineData(0, 0, 0, 0, .5F, .5F)]
+ [InlineData(.34566915F, .358496159F, .214041144F, .5F, .5F, .5F)]
public void Convert_CieXyy_to_YCbCr(float x, float y, float yl, float y2, float cb, float cr)
{
// Arrange
@@ -41,8 +42,9 @@ public class CieXyyAndYCbCrConversionTests
}
[Theory]
- [InlineData(0, 128, 128, 0, 0, 0)]
- [InlineData(64.0204849, 91.87107, 82.33627, 0.32114, 0.59787, 0.10976)]
+ [InlineData(1, .5F, .5F, .34566915F, .358496159F, .99999994F)]
+ [InlineData(0, .5F, .5F, 0, 0, 0)]
+ [InlineData(.5F, .5F, .5F, .34566915F, .358496159F, .214041144F)]
public void Convert_YCbCr_to_CieXyy(float y2, float cb, float cr, float x, float y, float yl)
{
// Arrange
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;
///
/// Tests the struct.
///
+[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:
///
///
+[Trait("Color", "Conversion")]
public class CieXyzAndCieLabConversionTest
{
private static readonly ApproximateColorProfileComparer Comparer = new(.0001f);
@@ -29,7 +30,7 @@ public class CieXyzAndCieLabConversionTest
{
// 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 class CieXyzAndCieLabConversionTest
{
// 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 class CieXyzAndCieLuvConversionTest
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 inputSpan = new CieXyz[5];
@@ -64,7 +64,7 @@ public class CieXyzAndCieLuvConversionTest
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 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:
///
///
+[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;
///
/// Test data generated using original colorful library.
///
+[Trait("Color", "Conversion")]
public class CieXyzAndLmsConversionTest
{
private static readonly ApproximateColorProfileComparer Comparer = new(.0001f);
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CieXyzAndYCbCrConversionTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CieXyzAndYCbCrConversionTests.cs
index 475673da84..90175a0585 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CieXyzAndYCbCrConversionTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CieXyzAndYCbCrConversionTests.cs
@@ -13,8 +13,8 @@ public class CieXyzAndYCbCrConversionTests
private static readonly ApproximateColorProfileComparer Comparer = new(.0002f);
[Theory]
- [InlineData(0, 0, 0, 0, 128, 128)]
- [InlineData(0.360555, 0.936901, 0.1001514, 149.685, 43.52769, 21.23457)]
+ [InlineData(0, 0, 0, 0, .5F, .5F)]
+ [InlineData(.206382737F, .214041144F, .176628917F, .5F, .5F, .5F)]
public void Convert_CieXyz_to_YCbCr(float x, float y, float z, float y2, float cb, float cr)
{
// Arrange
@@ -41,8 +41,8 @@ public class CieXyzAndYCbCrConversionTests
}
[Theory]
- [InlineData(0, 128, 128, 0, 0, 0)]
- [InlineData(149.685, 43.52769, 21.23457, 0.38506496, 0.716878653, 0.0971045)]
+ [InlineData(0, .5F, .5F, 0, 0, 0)]
+ [InlineData(.5F, .5F, .5F, .206382737F, .214041144F, .176628917F)]
public void Convert_YCbCr_to_CieXyz(float y2, float cb, float cr, float x, float y, float z)
{
// Arrange
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;
///
/// Tests the struct.
///
+[Trait("Color", "Conversion")]
public class CieXyzTests
{
[Fact]
diff --git a/tests/ImageSharp.Tests/ColorProfiles/CmykAndYCbCrConversionTests.cs b/tests/ImageSharp.Tests/ColorProfiles/CmykAndYCbCrConversionTests.cs
index 64b47e2b97..3a5fe7c15c 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/CmykAndYCbCrConversionTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/CmykAndYCbCrConversionTests.cs
@@ -13,8 +13,9 @@ public class CmykAndYCbCrConversionTests
private static readonly ApproximateColorProfileComparer Comparer = new(.0002F);
[Theory]
- [InlineData(0, 0, 0, 0, 255, 128, 128)]
- [InlineData(0.360555, 0.1036901, 0.818514, 0.274615, 136.5134, 69.90555, 114.9948)]
+ [InlineData(0, 0, 0, 1, 0, .5F, .5F)]
+ [InlineData(0, 0, 0, 0, 1, .5F, .5F)]
+ [InlineData(0, .8570679F, .49999997F, 0, .439901F, .5339159F, .899500132F)]
public void Convert_Cmyk_To_YCbCr(float c, float m, float y, float k, float y2, float cb, float cr)
{
// Arrange
@@ -41,8 +42,9 @@ public class CmykAndYCbCrConversionTests
}
[Theory]
- [InlineData(255, 128, 128, 0, 0, 0, 5.960464E-08)]
- [InlineData(136.5134, 69.90555, 114.9948, 0.2891567, 0, 0.7951807, 0.3490196)]
+ [InlineData(0, .5F, .5F, 0, 0, 0, 1)]
+ [InlineData(1, .5F, .5F, 0, 0, 0, 0)]
+ [InlineData(.5F, .5F, 1F, 0, .8570679F, .49999997F, 0)]
public void Convert_YCbCr_To_Cmyk(float y2, float cb, float cr, float c, float m, float y, float k)
{
// Arrange
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;
///
/// Tests the struct.
///
+[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 class ColorProfileConverterChomaticAdaptationTests
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 class ColorProfileConverterChomaticAdaptationTests
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 class ColorProfileConverterChomaticAdaptationTests
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 class ColorProfileConverterChomaticAdaptationTests
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 class ColorProfileConverterChomaticAdaptationTests
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 class ColorProfileConverterChomaticAdaptationTests
HunterLab expected = new(l2, a2, b2);
ColorConversionOptions options = new()
{
- WhitePoint = KnownIlluminants.D65,
+ SourceWhitePoint = KnownIlluminants.D65,
TargetWhitePoint = KnownIlluminants.D50,
};
@@ -164,7 +164,7 @@ public class ColorProfileConverterChomaticAdaptationTests
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 class ColorProfileConverterChomaticAdaptationTests
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;
///
/// Tests the struct.
///
+[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;
///
/// Tests the struct.
///
+[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;
///
/// Tests the struct.
///
+[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;
+
+///
+/// Tests ICC
+///
+[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..8f48277d6c
--- /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.ColorProfiles.Conversion.Icc;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc.Conversion;
+
+namespace SixLabors.ImageSharp.Tests.ColorProfiles.Icc.Calculators;
+
+///
+/// Tests ICC
+///
+[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..de2b4f5fae
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/LutABCalculatorTests.cs
@@ -0,0 +1,38 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using System.Numerics;
+using SixLabors.ImageSharp.ColorProfiles.Conversion.Icc;
+using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc.Conversion;
+
+namespace SixLabors.ImageSharp.Tests.ColorProfiles.Icc.Calculators;
+
+///
+/// Tests ICC
+///
+[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..6cc77247a9
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/LutCalculatorTests.cs
@@ -0,0 +1,25 @@
+// 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;
+
+///
+/// Tests ICC
+///
+[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..14f1386eb8
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/LutEntryCalculatorTests.cs
@@ -0,0 +1,38 @@
+// 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;
+
+///
+/// Tests ICC
+///
+[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..f56bf5873e
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/MatrixCalculatorTests.cs
@@ -0,0 +1,26 @@
+// 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;
+
+///
+/// Tests ICC
+///
+[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..aac3f42c9b
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/ParametricCurveCalculatorTests.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.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Tests.TestDataIcc.Conversion;
+
+namespace SixLabors.ImageSharp.Tests.ColorProfiles.Icc.Calculators;
+
+///
+/// Tests ICC
+///
+[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..65f02c3fb7
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/Icc/Calculators/TrcCalculatorTests.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;
+
+///
+/// Tests ICC
+///
+[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..6c56dc682d
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/Icc/ColorProfileConverterTests.Icc.cs
@@ -0,0 +1,263 @@
+// 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)
+{
+ // for 3-channel spaces, 4th item is ignored
+ private static readonly List 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()]
+ ];
+
+ [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)
+ {
+ List actual = Inputs.ConvertAll(input => GetActualTargetValues(input, sourceProfile, targetProfile));
+ AssertConversion(sourceProfile, targetProfile, actual, tolerance, 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)
+ [InlineData(TestIccProfiles.Issue129, TestIccProfiles.StandardRgbV4)] // CMYK -> LAB -> -> XYZ -> RGB
+ public void CanBulkConvertIccProfiles(string sourceProfile, string targetProfile, double tolerance = 0.00005)
+ {
+ List actual = GetBulkActualTargetValues(Inputs, sourceProfile, targetProfile);
+ AssertConversion(sourceProfile, targetProfile, actual, tolerance, testOutputHelper);
+ }
+
+ private static void AssertConversion(string sourceProfile, string targetProfile, List actual, double tolerance, ITestOutputHelper testOutputHelper)
+ {
+ List expected = Inputs.ConvertAll(input => GetExpectedTargetValues(sourceProfile, targetProfile, input, testOutputHelper));
+ Assert.Equal(expected.Count, actual.Count);
+
+ for (int i = 0; i < expected.Count; i++)
+ {
+ Log(testOutputHelper, Inputs[i], expected[i], actual[i]);
+ for (int j = 0; j < expected[i].Length; j++)
+ {
+ Assert.Equal(expected[i][j], actual[i][j], tolerance);
+ }
+ }
+ }
+
+ private static double[] GetExpectedTargetValues(string sourceProfile, string targetProfile, float[] input, ITestOutputHelper testOutputHelper)
+ {
+ 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)]);
+ Unicolour source = new(sourceConfig, channels);
+ Unicolour target = source.ConvertToConfiguration(targetConfig);
+ if (target.Icc.Error != null)
+ {
+ testOutputHelper.WriteLine($"Error during Unicolour ICC conversion of supported profile: {target.Icc.Error}");
+ }
+
+ 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(new Cmyk(new Vector4(input))).ToScaledVector4(),
+ IccColorSpaceType.Cmyk when targetDataSpace == IccColorSpaceType.Rgb
+ => converter.Convert(new Cmyk(new Vector4(input))).ToScaledVector4(),
+ IccColorSpaceType.Rgb when targetDataSpace == IccColorSpaceType.Cmyk
+ => converter.Convert(new Rgb(new Vector3(input))).ToScaledVector4(),
+ IccColorSpaceType.Rgb when targetDataSpace == IccColorSpaceType.Rgb
+ => converter.Convert(new Rgb(new Vector3(input))).ToScaledVector4(),
+ _ => throw new NotSupportedException($"Unsupported ICC profile data color space conversion: {sourceDataSpace} -> {targetDataSpace}")
+ };
+ }
+
+ private static List GetBulkActualTargetValues(List inputs, 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;
+
+ switch (sourceDataSpace)
+ {
+ case IccColorSpaceType.Cmyk:
+ {
+ Span inputSpan = inputs.Select(x => new Cmyk(new Vector4(x))).ToArray();
+
+ switch (targetDataSpace)
+ {
+ case IccColorSpaceType.Cmyk:
+ {
+ Span outputSpan = stackalloc Cmyk[inputs.Count];
+ converter.Convert(inputSpan, outputSpan);
+ return [.. outputSpan.ToArray().Select(x => x.ToScaledVector4())];
+ }
+
+ case IccColorSpaceType.Rgb:
+ {
+ Span outputSpan = stackalloc Rgb[inputs.Count];
+ converter.Convert(inputSpan, outputSpan);
+ return [.. outputSpan.ToArray().Select(x => x.ToScaledVector4())];
+ }
+
+ default:
+ throw new NotSupportedException($"Unsupported ICC profile data color space conversion: {sourceDataSpace} -> {targetDataSpace}");
+ }
+ }
+
+ case IccColorSpaceType.Rgb:
+ {
+ Span inputSpan = inputs.Select(x => new Rgb(new Vector3(x))).ToArray();
+
+ switch (targetDataSpace)
+ {
+ case IccColorSpaceType.Cmyk:
+ {
+ Span outputSpan = stackalloc Cmyk[inputs.Count];
+ converter.Convert(inputSpan, outputSpan);
+ return [.. outputSpan.ToArray().Select(x => x.ToScaledVector4())];
+ }
+
+ case IccColorSpaceType.Rgb:
+ {
+ Span outputSpan = stackalloc Rgb[inputs.Count];
+ converter.Convert(inputSpan, outputSpan);
+ return [.. outputSpan.ToArray().Select(x => x.ToScaledVector4())];
+ }
+
+ default:
+ throw new NotSupportedException($"Unsupported ICC profile data color space conversion: {sourceDataSpace} -> {targetDataSpace}");
+ }
+ }
+
+ default:
+ 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);
+ }
+
+ private static void Log(ITestOutputHelper testOutputHelper, float[] input, double[] expected, Vector4 actual)
+ {
+ string inputText = string.Join(", ", input);
+ string expectedText = string.Join(", ", expected.Select(x => $"{x:f8}"));
+ testOutputHelper.WriteLine($"Input {inputText} · Expected output {expectedText} · Actual output {actual}");
+ }
+}
diff --git a/tests/ImageSharp.Tests/ColorProfiles/Icc/TestIccProfiles.cs b/tests/ImageSharp.Tests/ColorProfiles/Icc/TestIccProfiles.cs
new file mode 100644
index 0000000000..3e3bb4d498
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/Icc/TestIccProfiles.cs
@@ -0,0 +1,73 @@
+// 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 ProfileCache = new();
+ private static readonly ConcurrentDictionary UnicolourConfigurationCache = new();
+
+ ///
+ /// v2 CMYK -> LAB, output, lut16
+ ///
+ public const string Fogra39 = "Coated_Fogra39L_VIGC_300.icc";
+
+ ///
+ /// v2 CMYK -> LAB, output, lut16
+ ///
+ public const string Swop2006 = "SWOP2006_Coated5v2.icc";
+
+ ///
+ /// v2 CMYK -> LAB, output, lut8 (A2B tags)
+ ///
+ public const string JapanColor2011 = "JapanColor2011Coated.icc";
+
+ ///
+ /// v2 CMYK -> LAB, output, lut8 (B2A tags)
+ ///
+ public const string JapanColor2003 = "JapanColor2003WebCoated.icc";
+
+ ///
+ /// v4 CMYK -> LAB, output, lutAToB: B-CLUT-A
+ ///
+ public const string Cgats21 = "CGATS21_CRPC7.icc";
+
+ ///
+ /// v4 RGB -> XYZ, colorspace, lutAToB: B-Matrix-M [only intent 0]
+ ///
+ public const string RommRgb = "ISO22028-2_ROMM-RGB.icc";
+
+ ///
+ /// v4 RGB -> LAB, colorspace, lutAToB: B-Matrix-M-CLUT-A [only intent 0 & 1]
+ ///
+ public const string StandardRgbV4 = "sRGB_v4_ICC_preference.icc";
+
+ ///
+ /// v2 CMYK -> LAB, output
+ ///
+ public const string Issue129 = "issue-129.icc";
+
+ ///
+ /// v2 RGB -> XYZ, display, TRCs
+ ///
+ 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;
///
/// Tests the struct.
///
+[Trait("Color", "Conversion")]
public class LmsTests
{
[Fact]
diff --git a/tests/ImageSharp.Tests/ColorProfiles/RbgAndYConversionTests.cs b/tests/ImageSharp.Tests/ColorProfiles/RbgAndYConversionTests.cs
new file mode 100644
index 0000000000..017ba78d0b
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/RbgAndYConversionTests.cs
@@ -0,0 +1,84 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using SixLabors.ImageSharp.ColorProfiles;
+
+namespace SixLabors.ImageSharp.Tests.ColorProfiles;
+
+///
+/// Tests - conversions.
+///
+///
+/// Test data generated mathematically
+///
+public class RbgAndYConversionTests
+{
+ private static readonly ApproximateColorProfileComparer Comparer = new(.001F);
+
+ [Theory]
+ [InlineData(0F, 0F, 0F, 0F)]
+ [InlineData(0.5F, 0.5F, 0.5F, 0.5F)]
+ [InlineData(1F, 1F, 1F, 1F)]
+ public void Convert_Rgb_To_Y_BT601(float r, float g, float b, float y)
+ {
+ ColorConversionOptions options = new()
+ {
+ YCbCrTransform = KnownYCbCrMatrices.BT601
+ };
+
+ Convert_Rgb_To_Y_Core(r, g, b, y, options);
+ }
+
+ [Theory]
+ [InlineData(0F, 0F, 0F, 0F)]
+ [InlineData(0.5F, 0.5F, 0.5F, 0.5F)]
+ [InlineData(1F, 1F, 1F, 1F)]
+ public void Convert_Rgb_To_Y_BT709(float r, float g, float b, float y)
+ {
+ ColorConversionOptions options = new()
+ {
+ YCbCrTransform = KnownYCbCrMatrices.BT709
+ };
+
+ Convert_Rgb_To_Y_Core(r, g, b, y, options);
+ }
+
+ [Theory]
+ [InlineData(0F, 0F, 0F, 0F)]
+ [InlineData(0.5F, 0.5F, 0.5F, 0.49999997F)]
+ [InlineData(1F, 1F, 1F, 0.99999994F)]
+ public void Convert_Rgb_To_Y_BT2020(float r, float g, float b, float y)
+ {
+ ColorConversionOptions options = new()
+ {
+ YCbCrTransform = KnownYCbCrMatrices.BT2020
+ };
+
+ Convert_Rgb_To_Y_Core(r, g, b, y, options);
+ }
+
+ private static void Convert_Rgb_To_Y_Core(float r, float g, float b, float y, ColorConversionOptions options)
+ {
+ // Arrange
+ Rgb input = new(r, g, b);
+ Y expected = new(y);
+ ColorProfileConverter converter = new(options);
+
+ Span inputSpan = new Rgb[5];
+ inputSpan.Fill(input);
+
+ Span actualSpan = new Y[5];
+
+ // Act
+ Y actual = converter.Convert(input);
+ converter.Convert(inputSpan, actualSpan);
+
+ // Assert
+ Assert.Equal(expected, actual, Comparer);
+
+ for (int i = 0; i < actualSpan.Length; i++)
+ {
+ Assert.Equal(expected, actualSpan[i], Comparer);
+ }
+ }
+}
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 class RgbAndCieXyzConversionTest
{
// 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 class RgbAndCieXyzConversionTest
{
// 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 class RgbAndCieXyzConversionTest
{
// 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 class RgbAndCieXyzConversionTest
{
// 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;
///
///
///
+[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;
///
///
///
+[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:
///
///
+[Trait("Color", "Conversion")]
public class RgbAndHsvConversionTest
{
private static readonly ApproximateColorProfileComparer Comparer = new(.0001f);
diff --git a/tests/ImageSharp.Tests/ColorProfiles/RgbAndYCbCrConversionTest.cs b/tests/ImageSharp.Tests/ColorProfiles/RgbAndYCbCrConversionTest.cs
index 91f7fc08ee..ede8226e40 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/RgbAndYCbCrConversionTest.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/RgbAndYCbCrConversionTest.cs
@@ -16,9 +16,9 @@ public class RgbAndYCbCrConversionTest
private static readonly ApproximateColorProfileComparer Comparer = new(.001F);
[Theory]
- [InlineData(255, 128, 128, 1, 1, 1)]
- [InlineData(0, 128, 128, 0, 0, 0)]
- [InlineData(128, 128, 128, 0.502, 0.502, 0.502)]
+ [InlineData(1, .5F, .5F, 1, 1, 1)]
+ [InlineData(0, .5F, .5F, 0, 0, 0)]
+ [InlineData(.5F, .5F, .5F, .5F, .5F, .5F)]
public void Convert_YCbCr_To_Rgb(float y, float cb, float cr, float r, float g, float b)
{
// Arrange
@@ -45,10 +45,9 @@ public class RgbAndYCbCrConversionTest
}
[Theory]
- [InlineData(0, 0, 0, 0, 128, 128)]
- [InlineData(1, 1, 1, 255, 128, 128)]
- [InlineData(0.5, 0.5, 0.5, 127.5, 128, 128)]
- [InlineData(1, 0, 0, 76.245, 84.972, 255)]
+ [InlineData(1, 1, 1, 1, .5F, .5F)]
+ [InlineData(0, 0, 0, 0, .5F, .5F)]
+ [InlineData(.5F, .5F, .5F, .5F, .5F, .5F)]
public void Convert_Rgb_To_YCbCr(float r, float g, float b, float y, float cb, float cr)
{
// Arrange
diff --git a/tests/ImageSharp.Tests/ColorProfiles/RgbAndYccKConversionTests.cs b/tests/ImageSharp.Tests/ColorProfiles/RgbAndYccKConversionTests.cs
new file mode 100644
index 0000000000..78f424cc28
--- /dev/null
+++ b/tests/ImageSharp.Tests/ColorProfiles/RgbAndYccKConversionTests.cs
@@ -0,0 +1,80 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using SixLabors.ImageSharp.ColorProfiles;
+
+namespace SixLabors.ImageSharp.Tests.ColorProfiles;
+
+///
+/// Tests - conversions.
+///
+///
+/// Test data generated mathematically
+///
+public class RgbAndYccKConversionTests
+{
+ private static readonly ApproximateColorProfileComparer Comparer = new(.001F);
+
+ [Theory]
+ [InlineData(1, .5F, .5F, 0, 1, 1, 1)]
+ [InlineData(0, .5F, .5F, 1, 0, 0, 0)]
+ [InlineData(.5F, .5F, .5F, 0, .5F, .5F, .5F)]
+ public void Convert_YccK_To_Rgb(float y, float cb, float cr, float k, float r, float g, float b)
+ {
+ // Arrange
+ YccK input = new(y, cb, cr, k);
+ Rgb expected = new(r, g, b);
+ ColorProfileConverter converter = new();
+
+ Span inputSpan = new YccK[5];
+ inputSpan.Fill(input);
+
+ Span actualSpan = new Rgb[5];
+
+ // Act
+ Rgb actual = converter.Convert(input);
+ converter.Convert(inputSpan, actualSpan);
+
+ // Assert
+ Assert.Equal(expected, actual, Comparer);
+
+ for (int i = 0; i < actualSpan.Length; i++)
+ {
+ Assert.Equal(expected, actualSpan[i], Comparer);
+ }
+ }
+
+ [Theory]
+ [InlineData(1, 1, 1, 1, .5F, .5F, 0)]
+ [InlineData(0, 0, 0, 0, .5F, .5F, 1)]
+ [InlineData(.5F, .5F, .5F, 1, .5F, .5F, .5F)]
+ public void Convert_Rgb_To_YccK(float r, float g, float b, float y, float cb, float cr, float k)
+ {
+ // Multiple YccK representations can decode to the same RGB value.
+ // For example, (Y=1.0, Cb=0.5, Cr=0.5, K=0.5) and (Y=0.5, Cb=0.5, Cr=0.5, K=0.0) both yield RGB (0.5, 0.5, 0.5).
+ // This is expected because YccK is not a unique encoding — K modulates RGB after YCbCr decoding.
+ // Round-tripping RGB -> YccK -> RGB is stable, but YccK -> RGB -> YccK is not injective.
+
+ // Arrange
+ Rgb input = new(r, g, b);
+ YccK expected = new(y, cb, cr, k);
+ ColorProfileConverter converter = new();
+
+ Span inputSpan = new Rgb[5];
+ inputSpan.Fill(input);
+
+ Span actualSpan = new YccK[5];
+
+ // Act
+ YccK actual = converter.Convert(input);
+ converter.Convert(inputSpan, actualSpan);
+
+ // Assert
+ Assert.Equal(expected, actual, Comparer);
+
+ for (int i = 0; i < actualSpan.Length; i++)
+ {
+ Assert.Equal(expected, actualSpan[i], Comparer);
+ }
+ }
+}
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;
///
/// Tests the struct.
///
+[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..f61124d8f5 100644
--- a/tests/ImageSharp.Tests/ColorProfiles/StringRepresentationTests.cs
+++ b/tests/ImageSharp.Tests/ColorProfiles/StringRepresentationTests.cs
@@ -6,11 +6,13 @@ using SixLabors.ImageSharp.ColorProfiles;
namespace SixLabors.ImageSharp.Tests.ColorProfiles;
+[Trait("Color", "Conversion")]
public class StringRepresentationTests
{
private static readonly Vector3 One = new(1);
private static readonly Vector3 Zero = new(0);
private static readonly Vector3 Random = new(42.4F, 94.5F, 83.4F);
+ private static readonly Vector4 Random4 = new(42.4F, 94.5F, 83.4F, 1);
public static readonly TheoryData