From 7b6d6a6579940fb3c743005a993510c471a0dce9 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 6 Feb 2018 13:18:38 +1100 Subject: [PATCH 01/19] Replace CoreCompat.System.Drawing with System.Drawing.Common --- .../ImageSharp.Benchmarks.csproj | 13 ++++--------- tests/ImageSharp.Tests/ImageSharp.Tests.csproj | 10 +++++----- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj index 417e849be1..2e0b935155 100644 --- a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj +++ b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj @@ -1,6 +1,6 @@  - netcoreapp1.1;net461 + netcoreapp2.0;net461 Exe True SixLabors.ImageSharp.Benchmarks @@ -15,17 +15,12 @@ + - + - - - - - - - + diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index 4f214fd85c..16f062c6ef 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -1,6 +1,6 @@  - netcoreapp1.1 + netcoreapp2.0 True full portable @@ -16,14 +16,14 @@ - + - - - + + + From ad4704855508067f065e83807609bdfffdc27747 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 6 Feb 2018 13:29:50 +1100 Subject: [PATCH 02/19] Update dotnet sdk version --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 70501a484b..740107f49d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ matrix: - os: linux # Ubuntu 14.04 dist: trusty sudo: required - dotnet: 1.0.4 + dotnet: 2.1.4 mono: latest # - os: osx # OSX 10.11 # osx_image: xcode7.3.1 From 375a7ea70616115b9512d7c2864d08cf29f7fda3 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 6 Feb 2018 13:46:38 +1100 Subject: [PATCH 03/19] Fix non-netcore2.0 compatible unit test --- tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj | 4 ++-- tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj b/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj index b186ff4df9..7d56686eb4 100644 --- a/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj +++ b/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj @@ -18,8 +18,8 @@ - - + + diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs index 0fde67d28e..945a4f502f 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs @@ -387,13 +387,13 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats internal static void TestOperation( TSource[] source, TDest[] expected, - Action, Buffer> action) + Action, Buffer> action) where TSource : struct where TDest : struct { - using (TestBuffers buffers = new TestBuffers(source, expected)) + using (var buffers = new TestBuffers(source, expected)) { - action(buffers.Source, buffers.ActualDestBuffer); + action(buffers.SourceBuffer, buffers.ActualDestBuffer); buffers.Verify(); } } From 080db8529b577494b2bf3683e5157ac29c897652 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 6 Feb 2018 13:53:14 +1100 Subject: [PATCH 04/19] Bump test version target --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 740107f49d..54e4dee2f8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,7 +21,7 @@ branches: script: - git submodule -q update --init - dotnet restore - - dotnet test tests/ImageSharp.Tests/ImageSharp.Tests.csproj -c Release -f "netcoreapp1.1" + - dotnet test tests/ImageSharp.Tests/ImageSharp.Tests.csproj -c Release -f "netcoreapp2.0" env: global: From e91863e2f7aa3064db8f39445796a49e98d559c8 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 6 Feb 2018 16:16:49 +1100 Subject: [PATCH 05/19] Fix all failing tests --- .../Drawing/FillRegionProcessorTests.cs | 65 +++-- .../Formats/Jpg/JpegColorConverterTests.cs | 260 +++++++++--------- .../Image/ImageDiscoverMimeType.cs | 32 +-- .../ImageSharp.Tests/Image/ImageLoadTests.cs | 13 +- .../ImageSharp.Tests/Image/ImageSaveTests.cs | 23 +- .../Image/MockImageFormatDetector.cs | 28 ++ 6 files changed, 217 insertions(+), 204 deletions(-) create mode 100644 tests/ImageSharp.Tests/Image/MockImageFormatDetector.cs diff --git a/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs b/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs index db6c1157c4..79ebf47787 100644 --- a/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs @@ -1,16 +1,14 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; using System.Numerics; -using SixLabors.ImageSharp; using SixLabors.ImageSharp.Drawing; using SixLabors.ImageSharp.Drawing.Pens; using SixLabors.ImageSharp.Drawing.Processors; -using SixLabors.ImageSharp.PixelFormats; using Moq; using Xunit; using SixLabors.ImageSharp.Drawing.Brushes; +using SixLabors.Primitives; namespace SixLabors.ImageSharp.Tests.Drawing { @@ -25,18 +23,18 @@ namespace SixLabors.ImageSharp.Tests.Drawing [InlineData(false, 16, 4)] // we always do 4 sub=pixels when antialising is off. public void MinimumAntialiasSubpixelDepth(bool antialias, int antialiasSubpixelDepth, int expectedAntialiasSubpixelDepth) { - SixLabors.Primitives.Rectangle bounds = new SixLabors.Primitives.Rectangle(0, 0, 1, 1); + var bounds = new SixLabors.Primitives.Rectangle(0, 0, 1, 1); - Mock> brush = new Mock>(); - Mock region = new Mock(); + var brush = new Mock>(); + var region = new Mock(); region.Setup(x => x.Bounds).Returns(bounds); - GraphicsOptions options = new GraphicsOptions(antialias) + var options = new GraphicsOptions(antialias) { AntialiasSubpixelDepth = 1 }; - FillRegionProcessor processor = new FillRegionProcessor(brush.Object, region.Object, options); - Image img = new Image(1, 1); + var processor = new FillRegionProcessor(brush.Object, region.Object, options); + var img = new Image(1, 1); processor.Apply(img, bounds); region.Verify(x => x.Scan(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(4)); @@ -45,31 +43,11 @@ namespace SixLabors.ImageSharp.Tests.Drawing [Fact] public void FillOffCanvas() { - - SixLabors.Primitives.Rectangle bounds = new SixLabors.Primitives.Rectangle(-100, -10, 10, 10); - - Mock> brush = new Mock>(); - Mock region = new Mock(); - region.Setup(x => x.Bounds).Returns(bounds); - - region.Setup(x => x.MaxIntersections).Returns(10); - region.Setup(x => x.Scan(It.IsAny(), It.IsAny(), It.IsAny())) - .Returns>((y, span) => - { - if (y < 5) - { - span[0] = -10f; - span[1] = 100f; - return 2; - } - return 0; - }); - - GraphicsOptions options = new GraphicsOptions(true) - { - }; - FillRegionProcessor processor = new FillRegionProcessor(brush.Object, region.Object, options); - Image img = new Image(10, 10); + var bounds = new Rectangle(-100, -10, 10, 10); + var brush = new Mock>(); + var options = new GraphicsOptions(true); + var processor = new FillRegionProcessor(brush.Object, new MockRegion(), options); + var img = new Image(10, 10); processor.Apply(img, bounds); } @@ -85,5 +63,24 @@ namespace SixLabors.ImageSharp.Tests.Drawing })); } } + + // Mocking the region throws an error in netcore2.0 + private class MockRegion : Region + { + public override Rectangle Bounds => new Rectangle(-100, -10, 10, 10); + + public override int MaxIntersections => 10; + + public override int Scan(float y, float[] buffer, int offset) + { + if (y < 5) + { + buffer[0] = -10f; + buffer[1] = 100f; + return 2; + } + return 0; + } + } } } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs index 7e0dc915ce..f141905efd 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs @@ -39,10 +39,15 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [MemberData(nameof(CommonConversionData))] public void ConvertFromYCbCrBasic(int inputBufferLength, int resultBufferLength, int seed) { - ValidateConversion(new JpegColorConverter.FromYCbCrBasic(), 3, inputBufferLength, resultBufferLength, seed, ValidateYCbCr); + ValidateRgbToYCbCrConversion( + new JpegColorConverter.FromYCbCrBasic(), + 3, + inputBufferLength, + resultBufferLength, + seed); } - private static void ValidateYCbCr(JpegColorConverter.ComponentValues values, Span result, int i) + private static void ValidateYCbCr(JpegColorConverter.ComponentValues values, Vector4[] result, int i) { float y = values.Component0[i]; float cb = values.Component1[i]; @@ -63,20 +68,27 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [InlineData(8, 3)] public void FromYCbCrSimd_ConvertCore(int size, int seed) { - ValidateConversion(JpegColorConverter.FromYCbCrSimd.ConvertCore, 3, size, size, seed, ValidateYCbCr); + JpegColorConverter.ComponentValues values = CreateRandomValues(3, size, seed); + Vector4[] result = new Vector4[size]; + + JpegColorConverter.FromYCbCrSimd.ConvertCore(values, result); + + for (int i = 0; i < size; i++) + { + ValidateYCbCr(values, result, i); + } } [Theory] [MemberData(nameof(CommonConversionData))] public void FromYCbCrSimd(int inputBufferLength, int resultBufferLength, int seed) { - ValidateConversion( + ValidateRgbToYCbCrConversion( new JpegColorConverter.FromYCbCrSimd(), 3, inputBufferLength, resultBufferLength, - seed, - ValidateYCbCr); + seed); } [Theory] @@ -91,13 +103,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg //JpegColorConverter.FromYCbCrSimdAvx2.LogPlz = s => this.Output.WriteLine(s); - ValidateConversion( + ValidateRgbToYCbCrConversion( new JpegColorConverter.FromYCbCrSimdAvx2(), 3, inputBufferLength, resultBufferLength, - seed, - ValidateYCbCr); + seed); } @@ -105,10 +116,15 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [MemberData(nameof(CommonConversionData))] public void ConvertFromYCbCr_WithDefaultConverter(int inputBufferLength, int resultBufferLength, int seed) { - ValidateConversion(JpegColorSpace.YCbCr, 3, inputBufferLength, resultBufferLength, seed, ValidateYCbCr); + ValidateConversion( + JpegColorSpace.YCbCr, + 3, + inputBufferLength, + resultBufferLength, + seed); } - // Becnhmark, for local execution only + // Benchmark, for local execution only //[Theory] //[InlineData(false)] //[InlineData(true)] @@ -120,11 +136,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg JpegColorConverter.ComponentValues values = CreateRandomValues(3, count, 1); Vector4[] result = new Vector4[count]; - JpegColorConverter converter = simd ? (JpegColorConverter)new JpegColorConverter.FromYCbCrSimd() : new JpegColorConverter.FromYCbCrBasic(); - + JpegColorConverter converter = simd ? (JpegColorConverter)new JpegColorConverter.FromYCbCrSimd() : new JpegColorConverter.FromYCbCrBasic(); + // Warm up: converter.ConvertToRGBA(values, result); - + using (new MeasureGuard(this.Output, $"{converter.GetType().Name} x {times}")) { for (int i = 0; i < times; i++) @@ -141,79 +157,79 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg var v = new Vector4(0, 0, 0, 1F); var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); - ValidateConversion( - JpegColorSpace.Cmyk, - 4, - inputBufferLength, - resultBufferLength, - seed, - (values, result, i) => - { - float c = values.Component0[i]; - float m = values.Component1[i]; - float y = values.Component2[i]; - float k = values.Component3[i] / 255F; - - v.X = c * k; - v.Y = m * k; - v.Z = y * k; - v.W = 1F; - - v *= scale; - - Vector4 rgba = result[i]; - var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); - var expected = new Rgb(v.X, v.Y, v.Z); - - Assert.True(actual.AlmostEquals(expected, Precision)); - Assert.Equal(1, rgba.W); - }); + var converter = JpegColorConverter.GetConverter(JpegColorSpace.Cmyk); + JpegColorConverter.ComponentValues values = CreateRandomValues(4, inputBufferLength, seed); + Vector4[] result = new Vector4[resultBufferLength]; + + converter.ConvertToRGBA(values, result); + + for (int i = 0; i < resultBufferLength; i++) + { + float c = values.Component0[i]; + float m = values.Component1[i]; + float y = values.Component2[i]; + float k = values.Component3[i] / 255F; + + v.X = c * k; + v.Y = m * k; + v.Z = y * k; + v.W = 1F; + + v *= scale; + + Vector4 rgba = result[i]; + var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); + var expected = new Rgb(v.X, v.Y, v.Z); + + Assert.True(actual.AlmostEquals(expected, Precision)); + Assert.Equal(1, rgba.W); + } } [Theory] [MemberData(nameof(CommonConversionData))] public void ConvertFromGrayScale(int inputBufferLength, int resultBufferLength, int seed) { - ValidateConversion( - JpegColorSpace.GrayScale, - 1, - inputBufferLength, - resultBufferLength, - seed, - (values, result, i) => - { - float y = values.Component0[i]; - Vector4 rgba = result[i]; - var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); - var expected = new Rgb(y / 255F, y / 255F, y / 255F); - - Assert.True(actual.AlmostEquals(expected, Precision)); - Assert.Equal(1, rgba.W); - }); + var converter = JpegColorConverter.GetConverter(JpegColorSpace.GrayScale); + JpegColorConverter.ComponentValues values = CreateRandomValues(1, inputBufferLength, seed); + Vector4[] result = new Vector4[resultBufferLength]; + + converter.ConvertToRGBA(values, result); + + for (int i = 0; i < resultBufferLength; i++) + { + float y = values.Component0[i]; + Vector4 rgba = result[i]; + var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); + var expected = new Rgb(y / 255F, y / 255F, y / 255F); + + Assert.True(actual.AlmostEquals(expected, Precision)); + Assert.Equal(1, rgba.W); + } } [Theory] [MemberData(nameof(CommonConversionData))] public void ConvertFromRgb(int inputBufferLength, int resultBufferLength, int seed) { - ValidateConversion( - JpegColorSpace.RGB, - 3, - inputBufferLength, - resultBufferLength, - seed, - (values, result, i) => - { - float r = values.Component0[i]; - float g = values.Component1[i]; - float b = values.Component2[i]; - Vector4 rgba = result[i]; - var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); - var expected = new Rgb(r / 255F, g / 255F, b / 255F); - - Assert.True(actual.AlmostEquals(expected, Precision)); - Assert.Equal(1, rgba.W); - }); + var converter = JpegColorConverter.GetConverter(JpegColorSpace.RGB); + JpegColorConverter.ComponentValues values = CreateRandomValues(3, inputBufferLength, seed); + Vector4[] result = new Vector4[resultBufferLength]; + + converter.ConvertToRGBA(values, result); + + for (int i = 0; i < resultBufferLength; i++) + { + float r = values.Component0[i]; + float g = values.Component1[i]; + float b = values.Component2[i]; + Vector4 rgba = result[i]; + var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); + var expected = new Rgb(r / 255F, g / 255F, b / 255F); + + Assert.True(actual.AlmostEquals(expected, Precision)); + Assert.Equal(1, rgba.W); + } } [Theory] @@ -223,35 +239,35 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg var v = new Vector4(0, 0, 0, 1F); var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); - ValidateConversion( - JpegColorSpace.Ycck, - 4, - inputBufferLength, - resultBufferLength, - seed, - (values, result, i) => - { - float y = values.Component0[i]; - float cb = values.Component1[i] - 128F; - float cr = values.Component2[i] - 128F; - float k = values.Component3[i] / 255F; - - v.X = (255F - (float)Math.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero)) * k; - v.Y = (255F - (float)Math.Round( - y - (0.344136F * cb) - (0.714136F * cr), - MidpointRounding.AwayFromZero)) * k; - v.Z = (255F - (float)Math.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero)) * k; - v.W = 1F; - - v *= scale; - - Vector4 rgba = result[i]; - var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); - var expected = new Rgb(v.X, v.Y, v.Z); - - Assert.True(actual.AlmostEquals(expected, Precision)); - Assert.Equal(1, rgba.W); - }); + var converter = JpegColorConverter.GetConverter(JpegColorSpace.Ycck); + JpegColorConverter.ComponentValues values = CreateRandomValues(4, inputBufferLength, seed); + Vector4[] result = new Vector4[resultBufferLength]; + + converter.ConvertToRGBA(values, result); + + for (int i = 0; i < resultBufferLength; i++) + { + float y = values.Component0[i]; + float cb = values.Component1[i] - 128F; + float cr = values.Component2[i] - 128F; + float k = values.Component3[i] / 255F; + + v.X = (255F - (float)Math.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero)) * k; + v.Y = (255F - (float)Math.Round( + y - (0.344136F * cb) - (0.714136F * cr), + MidpointRounding.AwayFromZero)) * k; + v.Z = (255F - (float)Math.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero)) * k; + v.W = 1F; + + v *= scale; + + Vector4 rgba = result[i]; + var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); + var expected = new Rgb(v.X, v.Y, v.Z); + + Assert.True(actual.AlmostEquals(expected, Precision)); + Assert.Equal(1, rgba.W); + } } private static JpegColorConverter.ComponentValues CreateRandomValues( @@ -269,7 +285,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg for (int j = 0; j < inputBufferLength; j++) { - values[j] = (float)rnd.NextDouble() * (maxVal-minVal)+minVal; + values[j] = (float)rnd.NextDouble() * (maxVal - minVal) + minVal; } // no need to dispose when buffer is not array owner @@ -283,51 +299,31 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg int componentCount, int inputBufferLength, int resultBufferLength, - int seed, - Action, int> validatePixelValue) + int seed) { - ValidateConversion( + ValidateRgbToYCbCrConversion( JpegColorConverter.GetConverter(colorSpace), componentCount, inputBufferLength, resultBufferLength, - seed, - validatePixelValue); + seed); } - private static void ValidateConversion( + private static void ValidateRgbToYCbCrConversion( JpegColorConverter converter, int componentCount, int inputBufferLength, int resultBufferLength, - int seed, - Action, int> validatePixelValue) - { - ValidateConversion( - converter.ConvertToRGBA, - componentCount, - inputBufferLength, - resultBufferLength, - seed, - validatePixelValue); - } - - private static void ValidateConversion( - Action> doConvert, - int componentCount, - int inputBufferLength, - int resultBufferLength, - int seed, - Action, int> validatePixelValue) + int seed) { JpegColorConverter.ComponentValues values = CreateRandomValues(componentCount, inputBufferLength, seed); Vector4[] result = new Vector4[resultBufferLength]; - doConvert(values, result); + converter.ConvertToRGBA(values, result); for (int i = 0; i < resultBufferLength; i++) { - validatePixelValue(values, result, i); + ValidateYCbCr(values, result, i); } } } diff --git a/tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs b/tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs index aefa32f469..f19fa1990c 100644 --- a/tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs +++ b/tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs @@ -5,7 +5,6 @@ using System; using System.IO; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.IO; -using SixLabors.ImageSharp.PixelFormats; using Moq; using Xunit; @@ -18,10 +17,10 @@ namespace SixLabors.ImageSharp.Tests { private readonly Mock fileSystem; private readonly string FilePath; - private readonly Mock localMimeTypeDetector; + private readonly IImageFormatDetector localMimeTypeDetector; private readonly Mock localImageFormatMock; - public IImageFormat localImageFormat => localImageFormatMock.Object; + public IImageFormat localImageFormat => this.localImageFormatMock.Object; public Configuration LocalConfiguration { get; private set; } public byte[] Marker { get; private set; } public MemoryStream DataStream { get; private set; } @@ -32,9 +31,7 @@ namespace SixLabors.ImageSharp.Tests { this.localImageFormatMock = new Mock(); - this.localMimeTypeDetector = new Mock(); - this.localMimeTypeDetector.Setup(x => x.HeaderSize).Returns(1); - this.localMimeTypeDetector.Setup(x => x.DetectFormat(It.IsAny>())).Returns(localImageFormatMock.Object); + this.localMimeTypeDetector = new MockImageFormatDetector(this.localImageFormatMock.Object); this.fileSystem = new Mock(); @@ -42,7 +39,8 @@ namespace SixLabors.ImageSharp.Tests { FileSystem = this.fileSystem.Object }; - this.LocalConfiguration.AddImageFormatDetector(this.localMimeTypeDetector.Object); + + this.LocalConfiguration.AddImageFormatDetector(this.localMimeTypeDetector); TestFormat.RegisterGlobalTestFormat(); this.Marker = Guid.NewGuid().ToByteArray(); @@ -58,49 +56,49 @@ namespace SixLabors.ImageSharp.Tests [Fact] public void DiscoverImageFormatByteArray() { - var type = Image.DetectFormat(DataStream.ToArray()); + IImageFormat type = Image.DetectFormat(this.DataStream.ToArray()); Assert.Equal(TestFormat.GlobalTestFormat, type); } [Fact] public void DiscoverImageFormatByteArray_WithConfig() { - var type = Image.DetectFormat(this.LocalConfiguration, DataStream.ToArray()); - Assert.Equal(localImageFormat, type); + IImageFormat type = Image.DetectFormat(this.LocalConfiguration, this.DataStream.ToArray()); + Assert.Equal(this.localImageFormat, type); } [Fact] public void DiscoverImageFormatFile() { - var type = Image.DetectFormat(this.FilePath); + IImageFormat type = Image.DetectFormat(this.FilePath); Assert.Equal(TestFormat.GlobalTestFormat, type); } [Fact] public void DiscoverImageFormatFilePath_WithConfig() { - var type = Image.DetectFormat(this.LocalConfiguration, FilePath); - Assert.Equal(localImageFormat, type); + IImageFormat type = Image.DetectFormat(this.LocalConfiguration, this.FilePath); + Assert.Equal(this.localImageFormat, type); } [Fact] public void DiscoverImageFormatStream() { - var type = Image.DetectFormat(this.DataStream); + IImageFormat type = Image.DetectFormat(this.DataStream); Assert.Equal(TestFormat.GlobalTestFormat, type); } [Fact] public void DiscoverImageFormatFileStream_WithConfig() { - var type = Image.DetectFormat(this.LocalConfiguration, DataStream); - Assert.Equal(localImageFormat, type); + IImageFormat type = Image.DetectFormat(this.LocalConfiguration, this.DataStream); + Assert.Equal(this.localImageFormat, type); } [Fact] public void DiscoverImageFormatNoDetectorsRegisterdShouldReturnNull() { - var type = Image.DetectFormat(new Configuration(), DataStream); + IImageFormat type = Image.DetectFormat(new Configuration(), this.DataStream); Assert.Null(type); } } diff --git a/tests/ImageSharp.Tests/Image/ImageLoadTests.cs b/tests/ImageSharp.Tests/Image/ImageLoadTests.cs index 2c0a30b154..de18714e2b 100644 --- a/tests/ImageSharp.Tests/Image/ImageLoadTests.cs +++ b/tests/ImageSharp.Tests/Image/ImageLoadTests.cs @@ -14,13 +14,13 @@ namespace SixLabors.ImageSharp.Tests /// /// Tests the class. /// - public class ImageLoadTests : IDisposable + public partial class ImageLoadTests : IDisposable { private readonly Mock fileSystem; private Image returnImage; private Mock localDecoder; private readonly string FilePath; - private readonly Mock localMimeTypeDetector; + private readonly IImageFormatDetector localMimeTypeDetector; private readonly Mock localImageFormatMock; public Configuration LocalConfiguration { get; private set; } @@ -35,10 +35,7 @@ namespace SixLabors.ImageSharp.Tests this.localImageFormatMock = new Mock(); this.localDecoder = new Mock(); - this.localMimeTypeDetector = new Mock(); - this.localMimeTypeDetector.Setup(x => x.HeaderSize).Returns(1); - this.localMimeTypeDetector.Setup(x => x.DetectFormat(It.IsAny>())).Returns(localImageFormatMock.Object); - + this.localMimeTypeDetector = new MockImageFormatDetector(this.localImageFormatMock.Object); this.localDecoder.Setup(x => x.Decode(It.IsAny(), It.IsAny())) .Callback((c, s) => @@ -57,8 +54,8 @@ namespace SixLabors.ImageSharp.Tests { FileSystem = this.fileSystem.Object }; - this.LocalConfiguration.AddImageFormatDetector(this.localMimeTypeDetector.Object); - this.LocalConfiguration.SetDecoder(localImageFormatMock.Object, this.localDecoder.Object); + this.LocalConfiguration.AddImageFormatDetector(this.localMimeTypeDetector); + this.LocalConfiguration.SetDecoder(this.localImageFormatMock.Object, this.localDecoder.Object); TestFormat.RegisterGlobalTestFormat(); this.Marker = Guid.NewGuid().ToByteArray(); diff --git a/tests/ImageSharp.Tests/Image/ImageSaveTests.cs b/tests/ImageSharp.Tests/Image/ImageSaveTests.cs index 5b672059c2..7f6e3b7dac 100644 --- a/tests/ImageSharp.Tests/Image/ImageSaveTests.cs +++ b/tests/ImageSharp.Tests/Image/ImageSaveTests.cs @@ -24,17 +24,14 @@ namespace SixLabors.ImageSharp.Tests private readonly Mock fileSystem; private readonly Mock encoder; private readonly Mock encoderNotInFormat; - private Mock localMimeTypeDetector; + private IImageFormatDetector localMimeTypeDetector; private Mock localImageFormat; public ImageSaveTests() { this.localImageFormat = new Mock(); this.localImageFormat.Setup(x => x.FileExtensions).Returns(new[] { "png" }); - - this.localMimeTypeDetector = new Mock(); - this.localMimeTypeDetector.Setup(x => x.HeaderSize).Returns(1); - this.localMimeTypeDetector.Setup(x => x.DetectFormat(It.IsAny>())).Returns(localImageFormat.Object); + this.localMimeTypeDetector = new MockImageFormatDetector(this.localImageFormat.Object); this.encoder = new Mock(); @@ -45,8 +42,8 @@ namespace SixLabors.ImageSharp.Tests { FileSystem = this.fileSystem.Object }; - config.AddImageFormatDetector(this.localMimeTypeDetector.Object); - config.SetEncoder(localImageFormat.Object, this.encoder.Object); + config.AddImageFormatDetector(this.localMimeTypeDetector); + config.SetEncoder(this.localImageFormat.Object, this.encoder.Object); this.Image = new Image(config, 1, 1); } @@ -57,7 +54,7 @@ namespace SixLabors.ImageSharp.Tests { using (Image image = provider.GetImage()) { - TPixel[] buffer = new TPixel[image.Width*image.Height]; + TPixel[] buffer = new TPixel[image.Width * image.Height]; image.SavePixelData(buffer); image.ComparePixelBufferTo(buffer); @@ -73,14 +70,14 @@ namespace SixLabors.ImageSharp.Tests { using (Image image = provider.GetImage()) { - byte[] buffer = new byte[image.Width*image.Height*Unsafe.SizeOf()]; + byte[] buffer = new byte[image.Width * image.Height * Unsafe.SizeOf()]; image.SavePixelData(buffer); image.ComparePixelBufferTo(buffer.AsSpan().NonPortableCast()); } } - + [Fact] public void SavePixelData_Rgba32_WhenBufferIsTooSmall_Throws() { @@ -91,7 +88,7 @@ namespace SixLabors.ImageSharp.Tests img[0, 1] = Rgba32.Red; img[1, 1] = Rgba32.Blue; - var buffer = new byte[2 * 2]; // width * height * bytes per pixel + byte[] buffer = new byte[2 * 2]; // width * height * bytes per pixel Assert.Throws(() => { @@ -125,7 +122,7 @@ namespace SixLabors.ImageSharp.Tests [Fact] public void ToBase64String() { - var str = this.Image.ToBase64String(localImageFormat.Object); + string str = this.Image.ToBase64String(this.localImageFormat.Object); this.encoder.Verify(x => x.Encode(this.Image, It.IsAny())); } @@ -134,7 +131,7 @@ namespace SixLabors.ImageSharp.Tests public void SaveStreamWithMime() { Stream stream = new MemoryStream(); - this.Image.Save(stream, localImageFormat.Object); + this.Image.Save(stream, this.localImageFormat.Object); this.encoder.Verify(x => x.Encode(this.Image, stream)); } diff --git a/tests/ImageSharp.Tests/Image/MockImageFormatDetector.cs b/tests/ImageSharp.Tests/Image/MockImageFormatDetector.cs new file mode 100644 index 0000000000..cb09fa010c --- /dev/null +++ b/tests/ImageSharp.Tests/Image/MockImageFormatDetector.cs @@ -0,0 +1,28 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using SixLabors.ImageSharp.Formats; + +namespace SixLabors.ImageSharp.Tests +{ + /// + /// You can't mock the "DetectFormat" method due to the ReadOnlySpan{byte} parameter. + /// + public class MockImageFormatDetector : IImageFormatDetector + { + private IImageFormat localImageFormatMock; + + public MockImageFormatDetector(IImageFormat imageFormat) + { + this.localImageFormatMock = imageFormat; + } + + public int HeaderSize => 1; + + public IImageFormat DetectFormat(ReadOnlySpan header) + { + return this.localImageFormatMock; + } + } +} From f657f41cea167a6d59bc4e20cefdc393f4e0d6bb Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 6 Feb 2018 17:02:53 +1100 Subject: [PATCH 06/19] Fix equality operators --- .../Conversion/Implementation/Rgb/RgbWorkingSpace.cs | 4 ++-- src/ImageSharp/MetaData/ImageProperty.cs | 9 +++++++-- src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs | 9 +++++++-- src/ImageSharp/MetaData/Profiles/Exif/Rational.cs | 4 ++-- .../MetaData/Profiles/Exif/SignedRational.cs | 4 ++-- .../Formats/Jpg/Utils/LibJpegTools.SpectralData.cs | 11 ++++++++--- 6 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs index 8a2c66a80c..8bcc311af0 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs @@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap /// public static bool operator ==(RgbWorkingSpace left, RgbWorkingSpace right) { - return Equals(left, right); + return left.Equals(right); } /// @@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap /// public static bool operator !=(RgbWorkingSpace left, RgbWorkingSpace right) { - return !Equals(left, right); + return !left.Equals(right); } /// diff --git a/src/ImageSharp/MetaData/ImageProperty.cs b/src/ImageSharp/MetaData/ImageProperty.cs index 62ae9d4790..c60aaecfba 100644 --- a/src/ImageSharp/MetaData/ImageProperty.cs +++ b/src/ImageSharp/MetaData/ImageProperty.cs @@ -71,7 +71,12 @@ namespace SixLabors.ImageSharp.MetaData /// public static bool operator ==(ImageProperty left, ImageProperty right) { - return Equals(left, right); + if (ReferenceEquals(left, right)) + { + return true; + } + + return left.Equals(right); } /// @@ -90,7 +95,7 @@ namespace SixLabors.ImageSharp.MetaData /// public static bool operator !=(ImageProperty left, ImageProperty right) { - return !Equals(left, right); + return !(left == right); } /// diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs index 64508137b4..7ffe9d48fe 100644 --- a/src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs +++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs @@ -188,7 +188,12 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif /// public static bool operator ==(ExifValue left, ExifValue right) { - return ExifValue.Equals(left, right); + if (ReferenceEquals(left, right)) + { + return true; + } + + return left.Equals(right); } /// @@ -205,7 +210,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif /// public static bool operator !=(ExifValue left, ExifValue right) { - return !ExifValue.Equals(left, right); + return !(left == right); } /// diff --git a/src/ImageSharp/MetaData/Profiles/Exif/Rational.cs b/src/ImageSharp/MetaData/Profiles/Exif/Rational.cs index 6d62a623f9..0f47870d24 100644 --- a/src/ImageSharp/MetaData/Profiles/Exif/Rational.cs +++ b/src/ImageSharp/MetaData/Profiles/Exif/Rational.cs @@ -87,7 +87,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif /// The public static bool operator ==(Rational left, Rational right) { - return Rational.Equals(left, right); + return left.Equals(right); } /// @@ -98,7 +98,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif /// The public static bool operator !=(Rational left, Rational right) { - return !Rational.Equals(left, right); + return !left.Equals(right); } /// diff --git a/src/ImageSharp/MetaData/Profiles/Exif/SignedRational.cs b/src/ImageSharp/MetaData/Profiles/Exif/SignedRational.cs index f2fe359242..17f1b568b3 100644 --- a/src/ImageSharp/MetaData/Profiles/Exif/SignedRational.cs +++ b/src/ImageSharp/MetaData/Profiles/Exif/SignedRational.cs @@ -87,7 +87,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif /// The public static bool operator ==(SignedRational left, SignedRational right) { - return SignedRational.Equals(left, right); + return left.Equals(right); } /// @@ -98,7 +98,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif /// The public static bool operator !=(SignedRational left, SignedRational right) { - return !SignedRational.Equals(left, right); + return !left.Equals(right); } /// diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Utils/LibJpegTools.SpectralData.cs b/tests/ImageSharp.Tests/Formats/Jpg/Utils/LibJpegTools.SpectralData.cs index ae7a9c046f..5a4db87b9b 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/Utils/LibJpegTools.SpectralData.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/Utils/LibJpegTools.SpectralData.cs @@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils this.ComponentCount = components.Length; this.Components = components; } - + public static SpectralData LoadFromImageSharpDecoder(PdfJsJpegDecoderCore decoder) { PdfJsFrameComponent[] srcComponents = decoder.Frame.Components; @@ -137,12 +137,17 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils public static bool operator ==(SpectralData left, SpectralData right) { - return Object.Equals(left, right); + if (ReferenceEquals(left, right)) + { + return true; + } + + return left.Equals(right); } public static bool operator !=(SpectralData left, SpectralData right) { - return !Object.Equals(left, right); + return !(left == right); } } } From 454270f51dd3c7c040da95bc1012ff3729e1e5e6 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 6 Feb 2018 17:28:28 +1100 Subject: [PATCH 07/19] Temp disable RgbColorspace asserts, AppVeyor fails, works locally and on Travis --- .../Rgb/RGBPrimariesChromaticityCoordinates.cs | 12 ++++++------ src/ImageSharp/ColorSpaces/IRgbWorkingSpace.cs | 2 +- .../Colorspaces/RgbAndCieXyzConversionTest.cs | 6 ++++-- .../Colorspaces/RgbAndCmykConversionTest.cs | 3 ++- .../Colorspaces/RgbAndHslConversionTest.cs | 3 ++- .../Colorspaces/RgbAndHsvConversionTest.cs | 3 ++- .../Colorspaces/RgbAndYCbCrConversionTest.cs | 3 ++- 7 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs index d279aba850..d5b9b3cbe5 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs @@ -14,9 +14,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap /// /// Initializes a new instance of the struct. /// - /// The chomaticity coordinates of the red channel. - /// The chomaticity coordinates of the green channel. - /// The chomaticity coordinates of the blue channel. + /// The chromaticity coordinates of the red channel. + /// The chromaticity coordinates of the green channel. + /// The chromaticity coordinates of the blue channel. public RgbPrimariesChromaticityCoordinates(CieXyChromaticityCoordinates r, CieXyChromaticityCoordinates g, CieXyChromaticityCoordinates b) { this.R = r; @@ -25,17 +25,17 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap } /// - /// Gets the chomaticity coordinates of the red channel. + /// Gets the chromaticity coordinates of the red channel. /// public CieXyChromaticityCoordinates R { get; } /// - /// Gets the chomaticity coordinates of the green channel. + /// Gets the chromaticity coordinates of the green channel. /// public CieXyChromaticityCoordinates G { get; } /// - /// Gets the chomaticity coordinates of the blue channel. + /// Gets the chromaticity coordinates of the blue channel. /// public CieXyChromaticityCoordinates B { get; } diff --git a/src/ImageSharp/ColorSpaces/IRgbWorkingSpace.cs b/src/ImageSharp/ColorSpaces/IRgbWorkingSpace.cs index 156e94ed3c..bd31fd61a4 100644 --- a/src/ImageSharp/ColorSpaces/IRgbWorkingSpace.cs +++ b/src/ImageSharp/ColorSpaces/IRgbWorkingSpace.cs @@ -7,7 +7,7 @@ using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce; namespace SixLabors.ImageSharp.ColorSpaces { /// - /// Encasulates the RGB working color space + /// Encapsulates the RGB working color space /// internal interface IRgbWorkingSpace : IEquatable { diff --git a/tests/ImageSharp.Tests/Colorspaces/RgbAndCieXyzConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/RgbAndCieXyzConversionTest.cs index ee71eefc17..24958e375a 100644 --- a/tests/ImageSharp.Tests/Colorspaces/RgbAndCieXyzConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/RgbAndCieXyzConversionTest.cs @@ -40,7 +40,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces Rgb output = converter.ToRgb(input); // Assert - Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); + // TODO: Enable next line + // Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); Assert.Equal(r, output.R, FloatRoundingComparer); Assert.Equal(g, output.G, FloatRoundingComparer); Assert.Equal(b, output.B, FloatRoundingComparer); @@ -68,7 +69,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces Rgb output = converter.ToRgb(input); // Assert - Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); + // TODO: Enable next line + // Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); Assert.Equal(r, output.R, FloatRoundingComparer); Assert.Equal(g, output.G, FloatRoundingComparer); Assert.Equal(b, output.B, FloatRoundingComparer); diff --git a/tests/ImageSharp.Tests/Colorspaces/RgbAndCmykConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/RgbAndCmykConversionTest.cs index 6c3d579b4e..b08071dc76 100644 --- a/tests/ImageSharp.Tests/Colorspaces/RgbAndCmykConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/RgbAndCmykConversionTest.cs @@ -38,7 +38,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces Rgb output = Converter.ToRgb(input); // Assert - Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); + // TODO: Enable next line + // Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); Assert.Equal(r, output.R, FloatRoundingComparer); Assert.Equal(g, output.G, FloatRoundingComparer); Assert.Equal(b, output.B, FloatRoundingComparer); diff --git a/tests/ImageSharp.Tests/Colorspaces/RgbAndHslConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/RgbAndHslConversionTest.cs index a7071e883d..e1f32e5c57 100644 --- a/tests/ImageSharp.Tests/Colorspaces/RgbAndHslConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/RgbAndHslConversionTest.cs @@ -41,7 +41,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces Rgb output = Converter.ToRgb(input); // Assert - Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); + // TODO: Enable next line + // Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); Assert.Equal(r, output.R, FloatRoundingComparer); Assert.Equal(g, output.G, FloatRoundingComparer); Assert.Equal(b, output.B, FloatRoundingComparer); diff --git a/tests/ImageSharp.Tests/Colorspaces/RgbAndHsvConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/RgbAndHsvConversionTest.cs index 0dc58a0a3e..2d9f2fa0f3 100644 --- a/tests/ImageSharp.Tests/Colorspaces/RgbAndHsvConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/RgbAndHsvConversionTest.cs @@ -40,7 +40,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces Rgb output = Converter.ToRgb(input); // Assert - Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); + // TODO: Enable next line + // Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); Assert.Equal(r, output.R, FloatRoundingComparer); Assert.Equal(g, output.G, FloatRoundingComparer); Assert.Equal(b, output.B, FloatRoundingComparer); diff --git a/tests/ImageSharp.Tests/Colorspaces/RgbAndYCbCrConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/RgbAndYCbCrConversionTest.cs index 0eb1f620bf..eb29c6b1e5 100644 --- a/tests/ImageSharp.Tests/Colorspaces/RgbAndYCbCrConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/RgbAndYCbCrConversionTest.cs @@ -36,7 +36,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces Rgb output = Converter.ToRgb(input); // Assert - Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); + // TODO: Enable next line + // Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); Assert.Equal(r, output.R, FloatRoundingComparer); Assert.Equal(g, output.G, FloatRoundingComparer); Assert.Equal(b, output.B, FloatRoundingComparer); From 109315240d2f08fd79b0ce47005c2fdc9e16693c Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 6 Feb 2018 17:58:28 +1100 Subject: [PATCH 08/19] Disable that funcky object.Equals --- .../Conversion/Implementation/Rgb/RgbWorkingSpace.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs index 8bcc311af0..8283201b50 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs @@ -84,10 +84,11 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap /// public bool Equals(IRgbWorkingSpace other) { - // TODO: Object.Equals for ICompanding will be slow. return this.WhitePoint.Equals(other.WhitePoint) - && this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates) - && Equals(this.Companding, other.Companding); + && this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates); + + // TODO: This should be refactored as separate classes with different companding implementations. + // && Equals(this.Companding, other.Companding); } /// From 279d79092df6dbfe8c4dc258b35001ffabbf5f51 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 6 Feb 2018 18:46:11 +1100 Subject: [PATCH 09/19] Use classes --- .../Conversion/Implementation/Rgb/RgbWorkingSpace.cs | 11 +++++------ .../Colorspaces/RgbAndCieXyzConversionTest.cs | 3 +-- .../Colorspaces/RgbAndCmykConversionTest.cs | 3 +-- .../Colorspaces/RgbAndHslConversionTest.cs | 3 +-- .../Colorspaces/RgbAndHsvConversionTest.cs | 3 +-- .../Colorspaces/RgbAndYCbCrConversionTest.cs | 3 +-- 6 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs index 8283201b50..a7b63d657e 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs @@ -6,10 +6,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap /// /// Trivial implementation of /// - internal struct RgbWorkingSpace : IRgbWorkingSpace + internal class RgbWorkingSpace : IRgbWorkingSpace { /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the class. /// /// The reference white point. /// The function pair for converting to and back. @@ -84,11 +84,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap /// public bool Equals(IRgbWorkingSpace other) { + // This should be refactored as separate classes with different companding implementations. return this.WhitePoint.Equals(other.WhitePoint) - && this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates); - - // TODO: This should be refactored as separate classes with different companding implementations. - // && Equals(this.Companding, other.Companding); + && this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates) + && Equals(this.Companding, other.Companding); } /// diff --git a/tests/ImageSharp.Tests/Colorspaces/RgbAndCieXyzConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/RgbAndCieXyzConversionTest.cs index 24958e375a..0293811fbd 100644 --- a/tests/ImageSharp.Tests/Colorspaces/RgbAndCieXyzConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/RgbAndCieXyzConversionTest.cs @@ -40,8 +40,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces Rgb output = converter.ToRgb(input); // Assert - // TODO: Enable next line - // Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); + Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); Assert.Equal(r, output.R, FloatRoundingComparer); Assert.Equal(g, output.G, FloatRoundingComparer); Assert.Equal(b, output.B, FloatRoundingComparer); diff --git a/tests/ImageSharp.Tests/Colorspaces/RgbAndCmykConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/RgbAndCmykConversionTest.cs index b08071dc76..6c3d579b4e 100644 --- a/tests/ImageSharp.Tests/Colorspaces/RgbAndCmykConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/RgbAndCmykConversionTest.cs @@ -38,8 +38,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces Rgb output = Converter.ToRgb(input); // Assert - // TODO: Enable next line - // Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); + Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); Assert.Equal(r, output.R, FloatRoundingComparer); Assert.Equal(g, output.G, FloatRoundingComparer); Assert.Equal(b, output.B, FloatRoundingComparer); diff --git a/tests/ImageSharp.Tests/Colorspaces/RgbAndHslConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/RgbAndHslConversionTest.cs index e1f32e5c57..a7071e883d 100644 --- a/tests/ImageSharp.Tests/Colorspaces/RgbAndHslConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/RgbAndHslConversionTest.cs @@ -41,8 +41,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces Rgb output = Converter.ToRgb(input); // Assert - // TODO: Enable next line - // Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); + Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); Assert.Equal(r, output.R, FloatRoundingComparer); Assert.Equal(g, output.G, FloatRoundingComparer); Assert.Equal(b, output.B, FloatRoundingComparer); diff --git a/tests/ImageSharp.Tests/Colorspaces/RgbAndHsvConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/RgbAndHsvConversionTest.cs index 2d9f2fa0f3..0dc58a0a3e 100644 --- a/tests/ImageSharp.Tests/Colorspaces/RgbAndHsvConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/RgbAndHsvConversionTest.cs @@ -40,8 +40,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces Rgb output = Converter.ToRgb(input); // Assert - // TODO: Enable next line - // Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); + Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); Assert.Equal(r, output.R, FloatRoundingComparer); Assert.Equal(g, output.G, FloatRoundingComparer); Assert.Equal(b, output.B, FloatRoundingComparer); diff --git a/tests/ImageSharp.Tests/Colorspaces/RgbAndYCbCrConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/RgbAndYCbCrConversionTest.cs index eb29c6b1e5..0eb1f620bf 100644 --- a/tests/ImageSharp.Tests/Colorspaces/RgbAndYCbCrConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/RgbAndYCbCrConversionTest.cs @@ -36,8 +36,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces Rgb output = Converter.ToRgb(input); // Assert - // TODO: Enable next line - // Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); + Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); Assert.Equal(r, output.R, FloatRoundingComparer); Assert.Equal(g, output.G, FloatRoundingComparer); Assert.Equal(b, output.B, FloatRoundingComparer); From 2aa21a705e4c81feee0ae0f8be56442d176e28d9 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 6 Feb 2018 19:08:14 +1100 Subject: [PATCH 10/19] Remove adaptation --- .../ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs index de13b97eb8..f3803b9bd5 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs @@ -181,11 +181,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion Guard.NotNull(color, nameof(color)); // Conversion - Rgb rgb = YCbCrAndRgbConverter.Convert(color); - - // Adaptation - // TODO: Check this! - return rgb.WorkingSpace.Equals(this.TargetRgbWorkingSpace) ? rgb : this.Adapt(rgb); + return YCbCrAndRgbConverter.Convert(color); } } } \ No newline at end of file From edb75e1be029a416b520cdf286dec1dcd039708b Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 6 Feb 2018 21:13:48 +1100 Subject: [PATCH 11/19] Refactor RgbWorkingSpace --- .../Implementation/Rgb/GammaCompanding.cs | 46 ----- .../Implementation/Rgb/LCompanding.cs | 35 ---- .../Rgb/LinearRgbToRgbConverter.cs | 6 +- .../Implementation/Rgb/Rec2020Companding.cs | 32 ---- .../Implementation/Rgb/Rec709Companding.cs | 31 ---- .../Rgb/RgbGammaWorkingSpace.cs | 89 +++++++++ .../Implementation/Rgb/RgbLWorkingSpace.cs | 82 +++++++++ .../Rgb/RgbRec2020WorkingSpace.cs | 79 ++++++++ .../Rgb/RgbRec709WorkingSpace.cs | 78 ++++++++ .../Implementation/Rgb/RgbSRgbWorkingSpace.cs | 80 +++++++++ .../Rgb/RgbToLinearRgbConverter.cs | 6 +- .../Implementation/Rgb/RgbWorkingSpace.cs | 105 ----------- .../Implementation/Rgb/SRgbCompanding.cs | 33 ---- src/ImageSharp/ColorSpaces/ICompanding.cs | 35 ---- .../ColorSpaces/IRgbWorkingSpace.cs | 21 ++- .../ColorSpaces/RgbWorkingSpaces.cs | 169 +++++++++++++++--- 16 files changed, 581 insertions(+), 346 deletions(-) delete mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/GammaCompanding.cs delete mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LCompanding.cs delete mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec2020Companding.cs delete mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec709Companding.cs create mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbGammaWorkingSpace.cs create mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbLWorkingSpace.cs create mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbRec2020WorkingSpace.cs create mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbRec709WorkingSpace.cs create mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbSRgbWorkingSpace.cs delete mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs delete mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/SRgbCompanding.cs delete mode 100644 src/ImageSharp/ColorSpaces/ICompanding.cs diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/GammaCompanding.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/GammaCompanding.cs deleted file mode 100644 index 21a80225ee..0000000000 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/GammaCompanding.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Runtime.CompilerServices; - -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce -{ - /// - /// Implements gamma companding - /// - /// - /// - /// - /// - public class GammaCompanding : ICompanding - { - /// - /// Initializes a new instance of the class. - /// - /// The gamma value. - public GammaCompanding(float gamma) - { - this.Gamma = gamma; - } - - /// - /// Gets the gamma value - /// - public float Gamma { get; } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float Expand(float channel) - { - return MathF.Pow(channel, this.Gamma); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float Compress(float channel) - { - return MathF.Pow(channel, 1 / this.Gamma); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LCompanding.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LCompanding.cs deleted file mode 100644 index 132861b476..0000000000 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LCompanding.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Runtime.CompilerServices; - -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce -{ - /// - /// Implements L* companding - /// - /// - /// For more info see: - /// - /// - /// - public class LCompanding : ICompanding - { - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float Expand(float channel) - { - return channel <= 0.08 ? 100 * channel / CieConstants.Kappa : MathF.Pow((channel + 0.16F) / 1.16F, 3); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float Compress(float channel) - { - return channel <= CieConstants.Epsilon - ? channel * CieConstants.Kappa / 100F - : MathF.Pow(1.16F * channel, 0.3333333F) - 0.16F; - } - } -} diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs index 29ea0f3148..25dbc746b0 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs @@ -16,9 +16,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap DebugGuard.NotNull(input, nameof(input)); Vector3 vector = input.Vector; - vector.X = input.WorkingSpace.Companding.Compress(vector.X); - vector.Y = input.WorkingSpace.Companding.Compress(vector.Y); - vector.Z = input.WorkingSpace.Companding.Compress(vector.Z); + vector.X = input.WorkingSpace.Compress(vector.X); + vector.Y = input.WorkingSpace.Compress(vector.Y); + vector.Z = input.WorkingSpace.Compress(vector.Z); return new Rgb(vector, input.WorkingSpace); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec2020Companding.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec2020Companding.cs deleted file mode 100644 index 11761f0e4d..0000000000 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec2020Companding.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Runtime.CompilerServices; - -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce -{ - /// - /// Implements Rec. 2020 companding function (for 12-bits). - /// - /// - /// - /// For 10-bits, companding is identical to - /// - public class Rec2020Companding : ICompanding - { - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float Expand(float channel) - { - return channel < 0.08145F ? channel / 4.5F : MathF.Pow((channel + 0.0993F) / 1.0993F, 2.222222F); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float Compress(float channel) - { - return channel < 0.0181F ? 4500F * channel : (1.0993F * channel) - 0.0993F; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec709Companding.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec709Companding.cs deleted file mode 100644 index ccda6bf521..0000000000 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec709Companding.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Runtime.CompilerServices; - -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce -{ - /// - /// Implements the Rec. 709 companding function - /// - /// - /// http://en.wikipedia.org/wiki/Rec._709 - /// - public class Rec709Companding : ICompanding - { - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float Expand(float channel) - { - return channel < 0.081F ? channel / 4.5F : MathF.Pow((channel + 0.099F) / 1.099F, 2.222222F); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float Compress(float channel) - { - return channel < 0.018F ? 4500F * channel : (1.099F * channel) - 0.099F; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbGammaWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbGammaWorkingSpace.cs new file mode 100644 index 0000000000..891beba1ac --- /dev/null +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbGammaWorkingSpace.cs @@ -0,0 +1,89 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce +{ + /// + /// Represents an that implements gamma companding + /// + /// + /// + /// + /// + internal class RgbGammaWorkingSpace : IRgbWorkingSpace, IEquatable + { + /// + /// Initializes a new instance of the class. + /// + /// The reference white point. + /// The gamma value. + /// The chromaticity of the rgb primaries. + public RgbGammaWorkingSpace(CieXyz referenceWhite, float gamma, RgbPrimariesChromaticityCoordinates chromaticityCoordinates) + { + this.WhitePoint = referenceWhite; + this.Gamma = gamma; + this.ChromaticityCoordinates = chromaticityCoordinates; + } + + /// + public CieXyz WhitePoint { get; } + + /// + public RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; } + + /// + /// Gets the gamma value + /// + public float Gamma { get; } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float Expand(float channel) + { + return MathF.Pow(channel, this.Gamma); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float Compress(float channel) + { + return MathF.Pow(channel, 1 / this.Gamma); + } + + /// + public override bool Equals(object obj) + { + return obj is RgbGammaWorkingSpace space && this.Equals(space); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(IRgbWorkingSpace other) + { + return other is RgbGammaWorkingSpace space && this.Equals(space); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(RgbGammaWorkingSpace other) + { + return other != null && + this.WhitePoint.Equals(other.WhitePoint) && + this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates) && + this.Gamma == other.Gamma; + } + + /// + public override int GetHashCode() + { + return HashHelpers.Combine( + this.WhitePoint.GetHashCode(), + HashHelpers.Combine( + this.ChromaticityCoordinates.GetHashCode(), + this.Gamma.GetHashCode())); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbLWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbLWorkingSpace.cs new file mode 100644 index 0000000000..c2d75cd90b --- /dev/null +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbLWorkingSpace.cs @@ -0,0 +1,82 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce +{ + /// + /// Represents an that implements L* companding + /// + /// + /// For more info see: + /// + /// + /// + internal class RgbLWorkingSpace : IRgbWorkingSpace, IEquatable + { + /// + /// Initializes a new instance of the class. + /// + /// The reference white point. + /// The chromaticity of the rgb primaries. + public RgbLWorkingSpace(CieXyz referenceWhite, RgbPrimariesChromaticityCoordinates chromaticityCoordinates) + { + this.WhitePoint = referenceWhite; + this.ChromaticityCoordinates = chromaticityCoordinates; + } + + /// + public CieXyz WhitePoint { get; } + + /// + public RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float Expand(float channel) + { + return channel <= 0.08 ? 100 * channel / CieConstants.Kappa : MathF.Pow((channel + 0.16F) / 1.16F, 3); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float Compress(float channel) + { + return channel <= CieConstants.Epsilon + ? channel * CieConstants.Kappa / 100F + : MathF.Pow(1.16F * channel, 0.3333333F) - 0.16F; + } + + /// + public override bool Equals(object obj) + { + return obj is RgbLWorkingSpace space && this.Equals(space); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(IRgbWorkingSpace other) + { + return other is RgbLWorkingSpace space && this.Equals(space); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(RgbLWorkingSpace other) + { + return other != null && + this.WhitePoint.Equals(other.WhitePoint) && + this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates); + } + + /// + public override int GetHashCode() + { + return HashHelpers.Combine( + this.WhitePoint.GetHashCode(), + this.ChromaticityCoordinates.GetHashCode()); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbRec2020WorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbRec2020WorkingSpace.cs new file mode 100644 index 0000000000..cc814e9b31 --- /dev/null +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbRec2020WorkingSpace.cs @@ -0,0 +1,79 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce +{ + /// + /// Represents an that implements Rec. 2020 companding (for 12-bits). + /// + /// + /// + /// For 10-bits, companding is identical to + /// + internal class RgbRec2020WorkingSpace : IRgbWorkingSpace, IEquatable + { + /// + /// Initializes a new instance of the class. + /// + /// The reference white point. + /// The chromaticity of the rgb primaries. + public RgbRec2020WorkingSpace(CieXyz referenceWhite, RgbPrimariesChromaticityCoordinates chromaticityCoordinates) + { + this.WhitePoint = referenceWhite; + this.ChromaticityCoordinates = chromaticityCoordinates; + } + + /// + public CieXyz WhitePoint { get; } + + /// + public RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float Expand(float channel) + { + return channel < 0.08145F ? channel / 4.5F : MathF.Pow((channel + 0.0993F) / 1.0993F, 2.222222F); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float Compress(float channel) + { + return channel < 0.0181F ? 4500F * channel : (1.0993F * channel) - 0.0993F; + } + + /// + public override bool Equals(object obj) + { + return obj is RgbRec2020WorkingSpace space && this.Equals(space); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(IRgbWorkingSpace other) + { + return other is RgbRec2020WorkingSpace space && this.Equals(space); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(RgbRec2020WorkingSpace other) + { + return other != null && + this.WhitePoint.Equals(other.WhitePoint) && + this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates); + } + + /// + public override int GetHashCode() + { + return HashHelpers.Combine( + this.WhitePoint.GetHashCode(), + this.ChromaticityCoordinates.GetHashCode()); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbRec709WorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbRec709WorkingSpace.cs new file mode 100644 index 0000000000..87301dd657 --- /dev/null +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbRec709WorkingSpace.cs @@ -0,0 +1,78 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce +{ + /// + /// Represents an that implements Rec. 709 companding. + /// + /// + /// + /// + internal class RgbRec709WorkingSpace : IRgbWorkingSpace, IEquatable + { + /// + /// Initializes a new instance of the class. + /// + /// The reference white point. + /// The chromaticity of the rgb primaries. + public RgbRec709WorkingSpace(CieXyz referenceWhite, RgbPrimariesChromaticityCoordinates chromaticityCoordinates) + { + this.WhitePoint = referenceWhite; + this.ChromaticityCoordinates = chromaticityCoordinates; + } + + /// + public CieXyz WhitePoint { get; } + + /// + public RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float Expand(float channel) + { + return channel < 0.081F ? channel / 4.5F : MathF.Pow((channel + 0.099F) / 1.099F, 2.222222F); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float Compress(float channel) + { + return channel < 0.018F ? 4500F * channel : (1.099F * channel) - 0.099F; + } + + /// + public override bool Equals(object obj) + { + return obj is RgbRec709WorkingSpace space && this.Equals(space); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(IRgbWorkingSpace other) + { + return other is RgbRec709WorkingSpace space && this.Equals(space); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(RgbRec709WorkingSpace other) + { + return other != null && + this.WhitePoint.Equals(other.WhitePoint) && + this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates); + } + + /// + public override int GetHashCode() + { + return HashHelpers.Combine( + this.WhitePoint.GetHashCode(), + this.ChromaticityCoordinates.GetHashCode()); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbSRgbWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbSRgbWorkingSpace.cs new file mode 100644 index 0000000000..98edaa0b37 --- /dev/null +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbSRgbWorkingSpace.cs @@ -0,0 +1,80 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce +{ + /// + /// Represents an that implements sRGB companding + /// + /// + /// For more info see: + /// + /// + /// + internal class RgbSRgbWorkingSpace : IRgbWorkingSpace, IEquatable + { + /// + /// Initializes a new instance of the class. + /// + /// The reference white point. + /// The chromaticity of the rgb primaries. + public RgbSRgbWorkingSpace(CieXyz referenceWhite, RgbPrimariesChromaticityCoordinates chromaticityCoordinates) + { + this.WhitePoint = referenceWhite; + this.ChromaticityCoordinates = chromaticityCoordinates; + } + + /// + public CieXyz WhitePoint { get; } + + /// + public RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float Expand(float channel) + { + return channel <= 0.04045F ? channel / 12.92F : MathF.Pow((channel + 0.055F) / 1.055F, 2.4F); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float Compress(float channel) + { + return channel <= 0.0031308F ? 12.92F * channel : (1.055F * MathF.Pow(channel, 0.416666666666667F)) - 0.055F; + } + + /// + public override bool Equals(object obj) + { + return obj is RgbSRgbWorkingSpace space && this.Equals(space); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(IRgbWorkingSpace other) + { + return other is RgbSRgbWorkingSpace space && this.Equals(space); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(RgbSRgbWorkingSpace other) + { + return other != null && + this.WhitePoint.Equals(other.WhitePoint) && + this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates); + } + + /// + public override int GetHashCode() + { + return HashHelpers.Combine( + this.WhitePoint.GetHashCode(), + this.ChromaticityCoordinates.GetHashCode()); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs index e40ecc192e..89a57051f7 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs @@ -16,9 +16,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap Guard.NotNull(input, nameof(input)); Vector3 vector = input.Vector; - vector.X = input.WorkingSpace.Companding.Expand(vector.X); - vector.Y = input.WorkingSpace.Companding.Expand(vector.Y); - vector.Z = input.WorkingSpace.Companding.Expand(vector.Z); + vector.X = input.WorkingSpace.Expand(vector.X); + vector.Y = input.WorkingSpace.Expand(vector.Y); + vector.Z = input.WorkingSpace.Expand(vector.Z); return new LinearRgb(vector, input.WorkingSpace); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs deleted file mode 100644 index a7b63d657e..0000000000 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce -{ - /// - /// Trivial implementation of - /// - internal class RgbWorkingSpace : IRgbWorkingSpace - { - /// - /// Initializes a new instance of the class. - /// - /// The reference white point. - /// The function pair for converting to and back. - /// The chromaticity of the rgb primaries. - public RgbWorkingSpace(CieXyz referenceWhite, ICompanding companding, RgbPrimariesChromaticityCoordinates chromaticityCoordinates) - { - this.WhitePoint = referenceWhite; - this.Companding = companding; - this.ChromaticityCoordinates = chromaticityCoordinates; - } - - /// - /// Gets the reference white point - /// - public CieXyz WhitePoint { get; } - - /// - /// Gets the function pair for converting to and back. - /// - public ICompanding Companding { get; } - - /// - /// Gets the chromaticity of the rgb primaries. - /// - public RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; } - - /// - /// Compares two objects for equality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - public static bool operator ==(RgbWorkingSpace left, RgbWorkingSpace right) - { - return left.Equals(right); - } - - /// - /// Compares two objects for inequality - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - public static bool operator !=(RgbWorkingSpace left, RgbWorkingSpace right) - { - return !left.Equals(right); - } - - /// - public override bool Equals(object obj) - { - if (obj is RgbWorkingSpace) - { - return this.Equals((RgbWorkingSpace)obj); - } - - return false; - } - - /// - public bool Equals(IRgbWorkingSpace other) - { - // This should be refactored as separate classes with different companding implementations. - return this.WhitePoint.Equals(other.WhitePoint) - && this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates) - && Equals(this.Companding, other.Companding); - } - - /// - public override int GetHashCode() - { - unchecked - { - int hashCode = this.WhitePoint.GetHashCode(); - hashCode = (hashCode * 397) ^ this.ChromaticityCoordinates.GetHashCode(); - hashCode = (hashCode * 397) ^ (this.Companding?.GetHashCode() ?? 0); - return hashCode; - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/SRgbCompanding.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/SRgbCompanding.cs deleted file mode 100644 index ce8ea7c6e5..0000000000 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/SRgbCompanding.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Runtime.CompilerServices; - -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce -{ - /// - /// Implements sRGB companding - /// - /// - /// For more info see: - /// - /// - /// - public class SRgbCompanding : ICompanding - { - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float Expand(float channel) - { - return channel <= 0.04045F ? channel / 12.92F : MathF.Pow((channel + 0.055F) / 1.055F, 2.4F); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float Compress(float channel) - { - return channel <= 0.0031308F ? 12.92F * channel : (1.055F * MathF.Pow(channel, 0.416666666666667F)) - 0.055F; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/ICompanding.cs b/src/ImageSharp/ColorSpaces/ICompanding.cs deleted file mode 100644 index 2dfa575ed9..0000000000 --- a/src/ImageSharp/ColorSpaces/ICompanding.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.ColorSpaces -{ - /// - /// Pair of companding functions for . - /// Used for conversion to and backwards. - /// See also: - /// - internal interface ICompanding - { - /// - /// Expands a companded channel to its linear equivalent with respect to the energy. - /// - /// - /// For more info see: - /// - /// - /// The channel value - /// The linear channel value - float Expand(float channel); - - /// - /// Compresses an uncompanded channel (linear) to its nonlinear equivalent (depends on the RGB color system). - /// - /// - /// For more info see: - /// - /// - /// The channel value - /// The nonlinear channel value - float Compress(float channel); - } -} diff --git a/src/ImageSharp/ColorSpaces/IRgbWorkingSpace.cs b/src/ImageSharp/ColorSpaces/IRgbWorkingSpace.cs index bd31fd61a4..1af3a219d6 100644 --- a/src/ImageSharp/ColorSpaces/IRgbWorkingSpace.cs +++ b/src/ImageSharp/ColorSpaces/IRgbWorkingSpace.cs @@ -22,10 +22,25 @@ namespace SixLabors.ImageSharp.ColorSpaces RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; } /// - /// Gets the companding function associated with the RGB color system. Used for conversion to XYZ and backwards. + /// Expands a compressed channel to its linear equivalent with respect to the energy. + /// + /// + /// For more info see: /// - /// + /// + /// The channel value + /// The linear channel value + float Expand(float channel); + + /// + /// Compresses an expanded channel (linear) to its nonlinear equivalent (depends on the RGB color system). /// - ICompanding Companding { get; } + /// + /// For more info see: + /// + /// + /// The channel value + /// The nonlinear channel value + float Compress(float channel); } } \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs b/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs index 098ca9a4a4..93557154d9 100644 --- a/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs +++ b/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs @@ -19,97 +19,226 @@ namespace SixLabors.ImageSharp.ColorSpaces /// Uses proper companding function, according to: /// /// - public static readonly IRgbWorkingSpace SRgb = new RgbWorkingSpace(Illuminants.D65, new SRgbCompanding(), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.3000F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); + public static readonly IRgbWorkingSpace SRgb = + new RgbSRgbWorkingSpace( + Illuminants.D65, + new RgbPrimariesChromaticityCoordinates( + new CieXyChromaticityCoordinates(0.6400F, 0.3300F), + new CieXyChromaticityCoordinates(0.3000F, 0.6000F), + new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); /// - /// Simplified sRgb working space (uses gamma companding instead of ). + /// Simplified sRgb working space that uses gamma companding instead of srgb companding. /// See also . /// - public static readonly IRgbWorkingSpace SRgbSimplified = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.3000F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); + public static readonly IRgbWorkingSpace SRgbSimplified = + new RgbGammaWorkingSpace( + Illuminants.D65, + 2.2F, + new RgbPrimariesChromaticityCoordinates( + new CieXyChromaticityCoordinates(0.6400F, 0.3300F), + new CieXyChromaticityCoordinates(0.3000F, 0.6000F), + new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); /// /// Rec. 709 (ITU-R Recommendation BT.709) working space /// - public static readonly IRgbWorkingSpace Rec709 = new RgbWorkingSpace(Illuminants.D65, new Rec709Companding(), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.64F, 0.33F), new CieXyChromaticityCoordinates(0.30F, 0.60F), new CieXyChromaticityCoordinates(0.15F, 0.06F))); + public static readonly IRgbWorkingSpace Rec709 = + new RgbRec709WorkingSpace( + Illuminants.D65, + new RgbPrimariesChromaticityCoordinates( + new CieXyChromaticityCoordinates(0.64F, 0.33F), + new CieXyChromaticityCoordinates(0.30F, 0.60F), + new CieXyChromaticityCoordinates(0.15F, 0.06F))); /// /// Rec. 2020 (ITU-R Recommendation BT.2020F) working space /// - public static readonly IRgbWorkingSpace Rec2020 = new RgbWorkingSpace(Illuminants.D65, new Rec2020Companding(), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.708F, 0.292F), new CieXyChromaticityCoordinates(0.170F, 0.797F), new CieXyChromaticityCoordinates(0.131F, 0.046F))); + public static readonly IRgbWorkingSpace Rec2020 = + new RgbRec2020WorkingSpace( + Illuminants.D65, + new RgbPrimariesChromaticityCoordinates( + new CieXyChromaticityCoordinates(0.708F, 0.292F), + new CieXyChromaticityCoordinates(0.170F, 0.797F), + new CieXyChromaticityCoordinates(0.131F, 0.046F))); /// /// ECI Rgb v2 working space /// - public static readonly IRgbWorkingSpace ECIRgbv2 = new RgbWorkingSpace(Illuminants.D50, new LCompanding(), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6700F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1400F, 0.0800F))); + public static readonly IRgbWorkingSpace ECIRgbv2 = + new RgbLWorkingSpace( + Illuminants.D50, + new RgbPrimariesChromaticityCoordinates( + new CieXyChromaticityCoordinates(0.6700F, 0.3300F), + new CieXyChromaticityCoordinates(0.2100F, 0.7100F), + new CieXyChromaticityCoordinates(0.1400F, 0.0800F))); /// /// Adobe Rgb (1998) working space /// - public static readonly IRgbWorkingSpace AdobeRgb1998 = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); + public static readonly IRgbWorkingSpace AdobeRgb1998 = + new RgbGammaWorkingSpace( + Illuminants.D65, + 2.2F, + new RgbPrimariesChromaticityCoordinates( + new CieXyChromaticityCoordinates(0.6400F, 0.3300F), + new CieXyChromaticityCoordinates(0.2100F, 0.7100F), + new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); /// /// Apple sRgb working space /// - public static readonly IRgbWorkingSpace ApplesRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(1.8F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6250F, 0.3400F), new CieXyChromaticityCoordinates(0.2800F, 0.5950F), new CieXyChromaticityCoordinates(0.1550F, 0.0700F))); + public static readonly IRgbWorkingSpace ApplesRgb = + new RgbGammaWorkingSpace( + Illuminants.D65, + 1.8F, + new RgbPrimariesChromaticityCoordinates( + new CieXyChromaticityCoordinates(0.6250F, 0.3400F), + new CieXyChromaticityCoordinates(0.2800F, 0.5950F), + new CieXyChromaticityCoordinates(0.1550F, 0.0700F))); /// /// Best Rgb working space /// - public static readonly IRgbWorkingSpace BestRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7347F, 0.2653F), new CieXyChromaticityCoordinates(0.2150F, 0.7750F), new CieXyChromaticityCoordinates(0.1300F, 0.0350F))); + public static readonly IRgbWorkingSpace BestRgb = + new RgbGammaWorkingSpace( + Illuminants.D50, + 2.2F, + new RgbPrimariesChromaticityCoordinates( + new CieXyChromaticityCoordinates(0.7347F, 0.2653F), + new CieXyChromaticityCoordinates(0.2150F, 0.7750F), + new CieXyChromaticityCoordinates(0.1300F, 0.0350F))); /// /// Beta Rgb working space /// - public static readonly IRgbWorkingSpace BetaRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6888F, 0.3112F), new CieXyChromaticityCoordinates(0.1986F, 0.7551F), new CieXyChromaticityCoordinates(0.1265F, 0.0352F))); + public static readonly IRgbWorkingSpace BetaRgb = + new RgbGammaWorkingSpace( + Illuminants.D50, + 2.2F, + new RgbPrimariesChromaticityCoordinates( + new CieXyChromaticityCoordinates(0.6888F, 0.3112F), + new CieXyChromaticityCoordinates(0.1986F, 0.7551F), + new CieXyChromaticityCoordinates(0.1265F, 0.0352F))); /// /// Bruce Rgb working space /// - public static readonly IRgbWorkingSpace BruceRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2800F, 0.6500F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); + public static readonly IRgbWorkingSpace BruceRgb = + new RgbGammaWorkingSpace( + Illuminants.D65, + 2.2F, + new RgbPrimariesChromaticityCoordinates( + new CieXyChromaticityCoordinates(0.6400F, 0.3300F), + new CieXyChromaticityCoordinates(0.2800F, 0.6500F), + new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); /// /// CIE Rgb working space /// - public static readonly IRgbWorkingSpace CIERgb = new RgbWorkingSpace(Illuminants.E, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7350F, 0.2650F), new CieXyChromaticityCoordinates(0.2740F, 0.7170F), new CieXyChromaticityCoordinates(0.1670F, 0.0090F))); + public static readonly IRgbWorkingSpace CIERgb = + new RgbGammaWorkingSpace( + Illuminants.E, + 2.2F, + new RgbPrimariesChromaticityCoordinates( + new CieXyChromaticityCoordinates(0.7350F, 0.2650F), + new CieXyChromaticityCoordinates(0.2740F, 0.7170F), + new CieXyChromaticityCoordinates(0.1670F, 0.0090F))); /// /// ColorMatch Rgb working space /// - public static readonly IRgbWorkingSpace ColorMatchRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(1.8F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6300F, 0.3400F), new CieXyChromaticityCoordinates(0.2950F, 0.6050F), new CieXyChromaticityCoordinates(0.1500F, 0.0750F))); + public static readonly IRgbWorkingSpace ColorMatchRgb = + new RgbGammaWorkingSpace( + Illuminants.D50, + 1.8F, + new RgbPrimariesChromaticityCoordinates( + new CieXyChromaticityCoordinates(0.6300F, 0.3400F), + new CieXyChromaticityCoordinates(0.2950F, 0.6050F), + new CieXyChromaticityCoordinates(0.1500F, 0.0750F))); /// /// Don Rgb 4 working space /// - public static readonly IRgbWorkingSpace DonRgb4 = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6960F, 0.3000F), new CieXyChromaticityCoordinates(0.2150F, 0.7650F), new CieXyChromaticityCoordinates(0.1300F, 0.0350F))); + public static readonly IRgbWorkingSpace DonRgb4 = + new RgbGammaWorkingSpace( + Illuminants.D50, + 2.2F, + new RgbPrimariesChromaticityCoordinates( + new CieXyChromaticityCoordinates(0.6960F, 0.3000F), + new CieXyChromaticityCoordinates(0.2150F, 0.7650F), + new CieXyChromaticityCoordinates(0.1300F, 0.0350F))); /// /// Ekta Space PS5 working space /// - public static readonly IRgbWorkingSpace EktaSpacePS5 = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6950F, 0.3050F), new CieXyChromaticityCoordinates(0.2600F, 0.7000F), new CieXyChromaticityCoordinates(0.1100F, 0.0050F))); + public static readonly IRgbWorkingSpace EktaSpacePS5 = + new RgbGammaWorkingSpace( + Illuminants.D50, + 2.2F, + new RgbPrimariesChromaticityCoordinates( + new CieXyChromaticityCoordinates(0.6950F, 0.3050F), + new CieXyChromaticityCoordinates(0.2600F, 0.7000F), + new CieXyChromaticityCoordinates(0.1100F, 0.0050F))); /// /// NTSC Rgb working space /// - public static readonly IRgbWorkingSpace NTSCRgb = new RgbWorkingSpace(Illuminants.C, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6700F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1400F, 0.0800F))); + public static readonly IRgbWorkingSpace NTSCRgb = + new RgbGammaWorkingSpace( + Illuminants.C, + 2.2F, + new RgbPrimariesChromaticityCoordinates( + new CieXyChromaticityCoordinates(0.6700F, 0.3300F), + new CieXyChromaticityCoordinates(0.2100F, 0.7100F), + new CieXyChromaticityCoordinates(0.1400F, 0.0800F))); /// /// PAL/SECAM Rgb working space /// - public static readonly IRgbWorkingSpace PALSECAMRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2900F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); + public static readonly IRgbWorkingSpace PALSECAMRgb = + new RgbGammaWorkingSpace( + Illuminants.D65, + 2.2F, + new RgbPrimariesChromaticityCoordinates( + new CieXyChromaticityCoordinates(0.6400F, 0.3300F), + new CieXyChromaticityCoordinates(0.2900F, 0.6000F), + new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); /// /// ProPhoto Rgb working space /// - public static readonly IRgbWorkingSpace ProPhotoRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(1.8F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7347F, 0.2653F), new CieXyChromaticityCoordinates(0.1596F, 0.8404F), new CieXyChromaticityCoordinates(0.0366F, 0.0001F))); + public static readonly IRgbWorkingSpace ProPhotoRgb = + new RgbGammaWorkingSpace( + Illuminants.D50, + 1.8F, + new RgbPrimariesChromaticityCoordinates( + new CieXyChromaticityCoordinates(0.7347F, 0.2653F), + new CieXyChromaticityCoordinates(0.1596F, 0.8404F), + new CieXyChromaticityCoordinates(0.0366F, 0.0001F))); /// /// SMPTE-C Rgb working space /// - public static readonly IRgbWorkingSpace SMPTECRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6300F, 0.3400F), new CieXyChromaticityCoordinates(0.3100F, 0.5950F), new CieXyChromaticityCoordinates(0.1550F, 0.0700F))); + public static readonly IRgbWorkingSpace SMPTECRgb = + new RgbGammaWorkingSpace( + Illuminants.D65, + 2.2F, + new RgbPrimariesChromaticityCoordinates( + new CieXyChromaticityCoordinates(0.6300F, 0.3400F), + new CieXyChromaticityCoordinates(0.3100F, 0.5950F), + new CieXyChromaticityCoordinates(0.1550F, 0.0700F))); /// /// Wide Gamut Rgb working space /// - public static readonly IRgbWorkingSpace WideGamutRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7350F, 0.2650F), new CieXyChromaticityCoordinates(0.1150F, 0.8260F), new CieXyChromaticityCoordinates(0.1570F, 0.0180F))); + public static readonly IRgbWorkingSpace WideGamutRgb = + new RgbGammaWorkingSpace( + Illuminants.D50, + 2.2F, + new RgbPrimariesChromaticityCoordinates( + new CieXyChromaticityCoordinates(0.7350F, 0.2650F), + new CieXyChromaticityCoordinates(0.1150F, 0.8260F), + new CieXyChromaticityCoordinates(0.1570F, 0.0180F))); } } \ No newline at end of file From 1191d322bd7fa11b760d0a4ed6385a65e78b4ad6 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 6 Feb 2018 22:06:33 +1100 Subject: [PATCH 12/19] Update ToString so we can see full output. --- .../ColorSpaces/CieXyChromaticityCoordinates.cs | 9 ++------- .../Rgb/RGBPrimariesChromaticityCoordinates.cs | 13 +++++++------ 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs index d9767d45ea..94ba6de782 100644 --- a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs +++ b/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs @@ -124,19 +124,14 @@ namespace SixLabors.ImageSharp.ColorSpaces return "CieXyChromaticityCoordinates [Empty]"; } - return $"CieXyChromaticityCoordinates [ X={this.X:#0.##}, Y={this.Y:#0.##}]"; + return $"CieXyChromaticityCoordinates [ X={this.X}, Y={this.Y}]"; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public override bool Equals(object obj) { - if (obj is CieXyChromaticityCoordinates) - { - return this.Equals((CieXyChromaticityCoordinates)obj); - } - - return false; + return obj is CieXyChromaticityCoordinates coordinates && this.Equals(coordinates); } /// diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs index d5b9b3cbe5..062398f94e 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs @@ -76,12 +76,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap /// public override bool Equals(object obj) { - if (obj is RgbPrimariesChromaticityCoordinates) - { - return this.Equals((RgbPrimariesChromaticityCoordinates)obj); - } - - return false; + return obj is RgbPrimariesChromaticityCoordinates coordinates && this.Equals(coordinates); } /// @@ -90,6 +85,12 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap return this.R.Equals(other.R) && this.G.Equals(other.G) && this.B.Equals(other.B); } + /// + public override string ToString() + { + return $"RgbPrimariesChromaticityCoordinates [ R={this.R}, G={this.G}, B={this.B}]"; + } + /// public override int GetHashCode() { From 6cf6ea497fe3e873b07ee8e7656e85d12dd17928 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 6 Feb 2018 23:11:57 +1100 Subject: [PATCH 13/19] Use custom comparer --- .../Colorspaces/RgbAndCieXyzConversionTest.cs | 7 ++- .../Colorspaces/RgbAndHslConversionTest.cs | 4 +- .../Colorspaces/RgbAndHsvConversionTest.cs | 4 +- .../Colorspaces/RgbAndYCbCrConversionTest.cs | 4 +- .../TestUtilities/ApproximateFloatComparer.cs | 57 ++++++++++++++++++- 5 files changed, 69 insertions(+), 7 deletions(-) diff --git a/tests/ImageSharp.Tests/Colorspaces/RgbAndCieXyzConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/RgbAndCieXyzConversionTest.cs index 0293811fbd..48c91dd6d0 100644 --- a/tests/ImageSharp.Tests/Colorspaces/RgbAndCieXyzConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/RgbAndCieXyzConversionTest.cs @@ -19,6 +19,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces { private static readonly IEqualityComparer FloatRoundingComparer = new FloatRoundingComparer(6); + private static readonly ApproximateFloatComparer ApproximateComparer = new ApproximateFloatComparer(0.0001F); + /// /// Tests conversion from () /// to (default sRGB working space). @@ -40,7 +42,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces Rgb output = converter.ToRgb(input); // Assert - Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); + Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace, ApproximateComparer); Assert.Equal(r, output.R, FloatRoundingComparer); Assert.Equal(g, output.G, FloatRoundingComparer); Assert.Equal(b, output.B, FloatRoundingComparer); @@ -68,8 +70,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces Rgb output = converter.ToRgb(input); // Assert - // TODO: Enable next line - // Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); + Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace, ApproximateComparer); Assert.Equal(r, output.R, FloatRoundingComparer); Assert.Equal(g, output.G, FloatRoundingComparer); Assert.Equal(b, output.B, FloatRoundingComparer); diff --git a/tests/ImageSharp.Tests/Colorspaces/RgbAndHslConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/RgbAndHslConversionTest.cs index a7071e883d..f658ddaae5 100644 --- a/tests/ImageSharp.Tests/Colorspaces/RgbAndHslConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/RgbAndHslConversionTest.cs @@ -22,6 +22,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces private static readonly ColorSpaceConverter Converter = new ColorSpaceConverter(); + private static readonly ApproximateFloatComparer ApproximateComparer = new ApproximateFloatComparer(0.0001F); + /// /// Tests conversion from to . /// @@ -41,7 +43,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces Rgb output = Converter.ToRgb(input); // Assert - Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); + Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace, ApproximateComparer); Assert.Equal(r, output.R, FloatRoundingComparer); Assert.Equal(g, output.G, FloatRoundingComparer); Assert.Equal(b, output.B, FloatRoundingComparer); diff --git a/tests/ImageSharp.Tests/Colorspaces/RgbAndHsvConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/RgbAndHsvConversionTest.cs index 0dc58a0a3e..63b3d9b749 100644 --- a/tests/ImageSharp.Tests/Colorspaces/RgbAndHsvConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/RgbAndHsvConversionTest.cs @@ -21,6 +21,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces private static readonly ColorSpaceConverter Converter = new ColorSpaceConverter(); + private static readonly ApproximateFloatComparer ApproximateComparer = new ApproximateFloatComparer(0.0001F); + /// /// Tests conversion from to . /// @@ -40,7 +42,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces Rgb output = Converter.ToRgb(input); // Assert - Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); + Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace, ApproximateComparer); Assert.Equal(r, output.R, FloatRoundingComparer); Assert.Equal(g, output.G, FloatRoundingComparer); Assert.Equal(b, output.B, FloatRoundingComparer); diff --git a/tests/ImageSharp.Tests/Colorspaces/RgbAndYCbCrConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/RgbAndYCbCrConversionTest.cs index 0eb1f620bf..96c302e25b 100644 --- a/tests/ImageSharp.Tests/Colorspaces/RgbAndYCbCrConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/RgbAndYCbCrConversionTest.cs @@ -20,6 +20,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces private static readonly ColorSpaceConverter Converter = new ColorSpaceConverter(); + private static readonly ApproximateFloatComparer ApproximateComparer = new ApproximateFloatComparer(0.0001F); + /// /// Tests conversion from to . /// @@ -36,7 +38,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces Rgb output = Converter.ToRgb(input); // Assert - Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); + Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace, ApproximateComparer); Assert.Equal(r, output.R, FloatRoundingComparer); Assert.Equal(g, output.G, FloatRoundingComparer); Assert.Equal(b, output.B, FloatRoundingComparer); diff --git a/tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs b/tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs index 70d4df273e..1bd80073e5 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs @@ -4,10 +4,18 @@ using System; using System.Collections.Generic; using System.Numerics; +using SixLabors.ImageSharp.ColorSpaces; +using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce; namespace SixLabors.ImageSharp.Tests { - internal struct ApproximateFloatComparer : IEqualityComparer, IEqualityComparer + internal struct ApproximateFloatComparer : + IEqualityComparer, + IEqualityComparer, + IEqualityComparer, + IEqualityComparer, + IEqualityComparer, + IEqualityComparer { private readonly float Eps; @@ -37,5 +45,52 @@ namespace SixLabors.ImageSharp.Tests { throw new InvalidOperationException(); } + + public bool Equals(CieXyChromaticityCoordinates x, CieXyChromaticityCoordinates y) + { + return this.Equals(x.X, y.X) && this.Equals(x.Y, y.Y); + } + + public int GetHashCode(CieXyChromaticityCoordinates obj) + { + throw new NotImplementedException(); + } + + public bool Equals(RgbPrimariesChromaticityCoordinates x, RgbPrimariesChromaticityCoordinates y) + { + return this.Equals(x.R, y.R) && this.Equals(x.G, y.G) && this.Equals(x.B, y.B); + } + + public int GetHashCode(RgbPrimariesChromaticityCoordinates obj) + { + throw new NotImplementedException(); + } + + public bool Equals(CieXyz x, CieXyz y) + { + return this.Equals(x.X, y.X) && this.Equals(x.Y, y.Y) && this.Equals(x.Z, y.Z); + } + + public int GetHashCode(CieXyz obj) + { + throw new NotImplementedException(); + } + + public bool Equals(IRgbWorkingSpace x, IRgbWorkingSpace y) + { + if (x is RgbGammaWorkingSpace g1 && y is RgbGammaWorkingSpace g2) + { + return this.Equals(g1.WhitePoint, g2.WhitePoint) + && this.Equals(g1.ChromaticityCoordinates, g2.ChromaticityCoordinates); + } + + return this.Equals(x.WhitePoint, y.WhitePoint) + && this.Equals(x.ChromaticityCoordinates, y.ChromaticityCoordinates); + } + + public int GetHashCode(IRgbWorkingSpace obj) + { + throw new NotImplementedException(); + } } } \ No newline at end of file From de04ff60955c2a5217fe72636ac6a5fb3ad17169 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 6 Feb 2018 23:38:42 +1100 Subject: [PATCH 14/19] DebugGuard + missing ApproximateComparer --- .../Implementation/Rgb/LinearRgbAndCieXyzConverterBase.cs | 4 ++-- .../Implementation/Rgb/LinearRgbToCieXyzConverter.cs | 2 +- .../ImageSharp.Tests/Colorspaces/RgbAndCmykConversionTest.cs | 4 +++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbAndCieXyzConverterBase.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbAndCieXyzConverterBase.cs index 2ec79b353b..b40a02af76 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbAndCieXyzConverterBase.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbAndCieXyzConverterBase.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap internal abstract class LinearRgbAndCieXyzConverterBase { /// - /// Geturns the correct matrix to convert between the Rgb and CieXyz color space. + /// Returns the correct matrix to convert between the Rgb and CieXyz color space. /// /// The Rgb working space. /// The based on the chromaticity and working space. @@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap Vector3 vector = Vector3.Transform(workingSpace.WhitePoint.Vector, inverseXyzMatrix); - // Use transposed Rows/Coloumns + // Use transposed Rows/Columns // TODO: Is there a built in method for this multiplication? return new Matrix4x4 { diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs index 19d4130373..bf36e252a2 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap public CieXyz Convert(LinearRgb input) { DebugGuard.NotNull(input, nameof(input)); - Guard.IsTrue(input.WorkingSpace.Equals(this.SourceWorkingSpace), nameof(input.WorkingSpace), "Input and source working spaces must be equal."); + DebugGuard.IsTrue(input.WorkingSpace.Equals(this.SourceWorkingSpace), nameof(input.WorkingSpace), "Input and source working spaces must be equal."); Vector3 vector = Vector3.Transform(input.Vector, this.conversionMatrix); return new CieXyz(vector); diff --git a/tests/ImageSharp.Tests/Colorspaces/RgbAndCmykConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/RgbAndCmykConversionTest.cs index 6c3d579b4e..aa1f9c5743 100644 --- a/tests/ImageSharp.Tests/Colorspaces/RgbAndCmykConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/RgbAndCmykConversionTest.cs @@ -22,6 +22,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces private static readonly ColorSpaceConverter Converter = new ColorSpaceConverter(); + private static readonly ApproximateFloatComparer ApproximateComparer = new ApproximateFloatComparer(0.0001F); + /// /// Tests conversion from to . /// @@ -38,7 +40,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces Rgb output = Converter.ToRgb(input); // Assert - Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace); + Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace, ApproximateComparer); Assert.Equal(r, output.R, FloatRoundingComparer); Assert.Equal(g, output.G, FloatRoundingComparer); Assert.Equal(b, output.B, FloatRoundingComparer); From 4d41c235af478e590b5a79672634541c60fc78b7 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 7 Feb 2018 00:00:34 +1100 Subject: [PATCH 15/19] Should be last missing ApproximateComparer --- .../ImageSharp.Tests/Colorspaces/ColorConverterAdaptTest.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/ImageSharp.Tests/Colorspaces/ColorConverterAdaptTest.cs b/tests/ImageSharp.Tests/Colorspaces/ColorConverterAdaptTest.cs index 87dc59907b..6cb32be47b 100644 --- a/tests/ImageSharp.Tests/Colorspaces/ColorConverterAdaptTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/ColorConverterAdaptTest.cs @@ -19,6 +19,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces { private static readonly IEqualityComparer FloatRoundingComparer = new FloatRoundingComparer(3); + private static readonly ApproximateFloatComparer ApproximateComparer = new ApproximateFloatComparer(0.0001F); + [Theory] [InlineData(0, 0, 0, 0, 0, 0)] [InlineData(1, 1, 1, 1, 1, 1)] @@ -34,7 +36,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces Rgb output = converter.Adapt(input); // Assert - Assert.Equal(expectedOutput.WorkingSpace, output.WorkingSpace); + Assert.Equal(expectedOutput.WorkingSpace, output.WorkingSpace, ApproximateComparer); Assert.Equal(expectedOutput.R, output.R, FloatRoundingComparer); Assert.Equal(expectedOutput.G, output.G, FloatRoundingComparer); Assert.Equal(expectedOutput.B, output.B, FloatRoundingComparer); @@ -55,7 +57,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces Rgb output = converter.Adapt(input); // Assert - Assert.Equal(expectedOutput.WorkingSpace, output.WorkingSpace); + Assert.Equal(expectedOutput.WorkingSpace, output.WorkingSpace, ApproximateComparer); Assert.Equal(expectedOutput.R, output.R, FloatRoundingComparer); Assert.Equal(expectedOutput.G, output.G, FloatRoundingComparer); Assert.Equal(expectedOutput.B, output.B, FloatRoundingComparer); From 96dbbd62d9a38db71e0761227be2cb1747971f98 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 15 Feb 2018 23:54:02 +1100 Subject: [PATCH 16/19] Revert most colorspace changes. --- .../CieXyChromaticityCoordinates.cs | 9 +- .../Conversion/ColorSpaceConverter.Rgb.cs | 5 +- .../Implementation/Rgb/GammaCompanding.cs | 46 +++++ .../Implementation/Rgb/LCompanding.cs | 35 ++++ .../Rgb/LinearRgbToRgbConverter.cs | 6 +- .../RGBPrimariesChromaticityCoordinates.cs | 25 ++- .../Implementation/Rgb/Rec2020Companding.cs | 32 ++++ .../Implementation/Rgb/Rec709Companding.cs | 31 ++++ .../Rgb/RgbGammaWorkingSpace.cs | 89 --------- .../Implementation/Rgb/RgbLWorkingSpace.cs | 82 --------- .../Rgb/RgbRec2020WorkingSpace.cs | 79 -------- .../Rgb/RgbRec709WorkingSpace.cs | 78 -------- .../Implementation/Rgb/RgbSRgbWorkingSpace.cs | 80 --------- .../Rgb/RgbToLinearRgbConverter.cs | 6 +- .../Implementation/Rgb/RgbWorkingSpace.cs | 105 +++++++++++ .../Implementation/Rgb/SRgbCompanding.cs | 33 ++++ src/ImageSharp/ColorSpaces/ICompanding.cs | 35 ++++ .../ColorSpaces/IRgbWorkingSpace.cs | 23 +-- .../ColorSpaces/RgbWorkingSpaces.cs | 169 +++--------------- .../TestUtilities/ApproximateFloatComparer.cs | 2 +- 20 files changed, 371 insertions(+), 599 deletions(-) create mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/GammaCompanding.cs create mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LCompanding.cs create mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec2020Companding.cs create mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec709Companding.cs delete mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbGammaWorkingSpace.cs delete mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbLWorkingSpace.cs delete mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbRec2020WorkingSpace.cs delete mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbRec709WorkingSpace.cs delete mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbSRgbWorkingSpace.cs create mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs create mode 100644 src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/SRgbCompanding.cs create mode 100644 src/ImageSharp/ColorSpaces/ICompanding.cs diff --git a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs index 94ba6de782..d9767d45ea 100644 --- a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs +++ b/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs @@ -124,14 +124,19 @@ namespace SixLabors.ImageSharp.ColorSpaces return "CieXyChromaticityCoordinates [Empty]"; } - return $"CieXyChromaticityCoordinates [ X={this.X}, Y={this.Y}]"; + return $"CieXyChromaticityCoordinates [ X={this.X:#0.##}, Y={this.Y:#0.##}]"; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public override bool Equals(object obj) { - return obj is CieXyChromaticityCoordinates coordinates && this.Equals(coordinates); + if (obj is CieXyChromaticityCoordinates) + { + return this.Equals((CieXyChromaticityCoordinates)obj); + } + + return false; } /// diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs index f3803b9bd5..6844e3a3ca 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs @@ -181,7 +181,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion Guard.NotNull(color, nameof(color)); // Conversion - return YCbCrAndRgbConverter.Convert(color); + Rgb rgb = YCbCrAndRgbConverter.Convert(color); + + // Adaptation + return this.Adapt(rgb); } } } \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/GammaCompanding.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/GammaCompanding.cs new file mode 100644 index 0000000000..21a80225ee --- /dev/null +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/GammaCompanding.cs @@ -0,0 +1,46 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce +{ + /// + /// Implements gamma companding + /// + /// + /// + /// + /// + public class GammaCompanding : ICompanding + { + /// + /// Initializes a new instance of the class. + /// + /// The gamma value. + public GammaCompanding(float gamma) + { + this.Gamma = gamma; + } + + /// + /// Gets the gamma value + /// + public float Gamma { get; } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float Expand(float channel) + { + return MathF.Pow(channel, this.Gamma); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float Compress(float channel) + { + return MathF.Pow(channel, 1 / this.Gamma); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LCompanding.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LCompanding.cs new file mode 100644 index 0000000000..132861b476 --- /dev/null +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LCompanding.cs @@ -0,0 +1,35 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce +{ + /// + /// Implements L* companding + /// + /// + /// For more info see: + /// + /// + /// + public class LCompanding : ICompanding + { + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float Expand(float channel) + { + return channel <= 0.08 ? 100 * channel / CieConstants.Kappa : MathF.Pow((channel + 0.16F) / 1.16F, 3); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float Compress(float channel) + { + return channel <= CieConstants.Epsilon + ? channel * CieConstants.Kappa / 100F + : MathF.Pow(1.16F * channel, 0.3333333F) - 0.16F; + } + } +} diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs index 25dbc746b0..29ea0f3148 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs @@ -16,9 +16,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap DebugGuard.NotNull(input, nameof(input)); Vector3 vector = input.Vector; - vector.X = input.WorkingSpace.Compress(vector.X); - vector.Y = input.WorkingSpace.Compress(vector.Y); - vector.Z = input.WorkingSpace.Compress(vector.Z); + vector.X = input.WorkingSpace.Companding.Compress(vector.X); + vector.Y = input.WorkingSpace.Companding.Compress(vector.Y); + vector.Z = input.WorkingSpace.Companding.Compress(vector.Z); return new Rgb(vector, input.WorkingSpace); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs index 062398f94e..d279aba850 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs @@ -14,9 +14,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap /// /// Initializes a new instance of the struct. /// - /// The chromaticity coordinates of the red channel. - /// The chromaticity coordinates of the green channel. - /// The chromaticity coordinates of the blue channel. + /// The chomaticity coordinates of the red channel. + /// The chomaticity coordinates of the green channel. + /// The chomaticity coordinates of the blue channel. public RgbPrimariesChromaticityCoordinates(CieXyChromaticityCoordinates r, CieXyChromaticityCoordinates g, CieXyChromaticityCoordinates b) { this.R = r; @@ -25,17 +25,17 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap } /// - /// Gets the chromaticity coordinates of the red channel. + /// Gets the chomaticity coordinates of the red channel. /// public CieXyChromaticityCoordinates R { get; } /// - /// Gets the chromaticity coordinates of the green channel. + /// Gets the chomaticity coordinates of the green channel. /// public CieXyChromaticityCoordinates G { get; } /// - /// Gets the chromaticity coordinates of the blue channel. + /// Gets the chomaticity coordinates of the blue channel. /// public CieXyChromaticityCoordinates B { get; } @@ -76,7 +76,12 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap /// public override bool Equals(object obj) { - return obj is RgbPrimariesChromaticityCoordinates coordinates && this.Equals(coordinates); + if (obj is RgbPrimariesChromaticityCoordinates) + { + return this.Equals((RgbPrimariesChromaticityCoordinates)obj); + } + + return false; } /// @@ -85,12 +90,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap return this.R.Equals(other.R) && this.G.Equals(other.G) && this.B.Equals(other.B); } - /// - public override string ToString() - { - return $"RgbPrimariesChromaticityCoordinates [ R={this.R}, G={this.G}, B={this.B}]"; - } - /// public override int GetHashCode() { diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec2020Companding.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec2020Companding.cs new file mode 100644 index 0000000000..11761f0e4d --- /dev/null +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec2020Companding.cs @@ -0,0 +1,32 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce +{ + /// + /// Implements Rec. 2020 companding function (for 12-bits). + /// + /// + /// + /// For 10-bits, companding is identical to + /// + public class Rec2020Companding : ICompanding + { + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float Expand(float channel) + { + return channel < 0.08145F ? channel / 4.5F : MathF.Pow((channel + 0.0993F) / 1.0993F, 2.222222F); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float Compress(float channel) + { + return channel < 0.0181F ? 4500F * channel : (1.0993F * channel) - 0.0993F; + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec709Companding.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec709Companding.cs new file mode 100644 index 0000000000..ccda6bf521 --- /dev/null +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec709Companding.cs @@ -0,0 +1,31 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce +{ + /// + /// Implements the Rec. 709 companding function + /// + /// + /// http://en.wikipedia.org/wiki/Rec._709 + /// + public class Rec709Companding : ICompanding + { + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float Expand(float channel) + { + return channel < 0.081F ? channel / 4.5F : MathF.Pow((channel + 0.099F) / 1.099F, 2.222222F); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float Compress(float channel) + { + return channel < 0.018F ? 4500F * channel : (1.099F * channel) - 0.099F; + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbGammaWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbGammaWorkingSpace.cs deleted file mode 100644 index 891beba1ac..0000000000 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbGammaWorkingSpace.cs +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Runtime.CompilerServices; - -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce -{ - /// - /// Represents an that implements gamma companding - /// - /// - /// - /// - /// - internal class RgbGammaWorkingSpace : IRgbWorkingSpace, IEquatable - { - /// - /// Initializes a new instance of the class. - /// - /// The reference white point. - /// The gamma value. - /// The chromaticity of the rgb primaries. - public RgbGammaWorkingSpace(CieXyz referenceWhite, float gamma, RgbPrimariesChromaticityCoordinates chromaticityCoordinates) - { - this.WhitePoint = referenceWhite; - this.Gamma = gamma; - this.ChromaticityCoordinates = chromaticityCoordinates; - } - - /// - public CieXyz WhitePoint { get; } - - /// - public RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; } - - /// - /// Gets the gamma value - /// - public float Gamma { get; } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float Expand(float channel) - { - return MathF.Pow(channel, this.Gamma); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float Compress(float channel) - { - return MathF.Pow(channel, 1 / this.Gamma); - } - - /// - public override bool Equals(object obj) - { - return obj is RgbGammaWorkingSpace space && this.Equals(space); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(IRgbWorkingSpace other) - { - return other is RgbGammaWorkingSpace space && this.Equals(space); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(RgbGammaWorkingSpace other) - { - return other != null && - this.WhitePoint.Equals(other.WhitePoint) && - this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates) && - this.Gamma == other.Gamma; - } - - /// - public override int GetHashCode() - { - return HashHelpers.Combine( - this.WhitePoint.GetHashCode(), - HashHelpers.Combine( - this.ChromaticityCoordinates.GetHashCode(), - this.Gamma.GetHashCode())); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbLWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbLWorkingSpace.cs deleted file mode 100644 index c2d75cd90b..0000000000 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbLWorkingSpace.cs +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Runtime.CompilerServices; - -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce -{ - /// - /// Represents an that implements L* companding - /// - /// - /// For more info see: - /// - /// - /// - internal class RgbLWorkingSpace : IRgbWorkingSpace, IEquatable - { - /// - /// Initializes a new instance of the class. - /// - /// The reference white point. - /// The chromaticity of the rgb primaries. - public RgbLWorkingSpace(CieXyz referenceWhite, RgbPrimariesChromaticityCoordinates chromaticityCoordinates) - { - this.WhitePoint = referenceWhite; - this.ChromaticityCoordinates = chromaticityCoordinates; - } - - /// - public CieXyz WhitePoint { get; } - - /// - public RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float Expand(float channel) - { - return channel <= 0.08 ? 100 * channel / CieConstants.Kappa : MathF.Pow((channel + 0.16F) / 1.16F, 3); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float Compress(float channel) - { - return channel <= CieConstants.Epsilon - ? channel * CieConstants.Kappa / 100F - : MathF.Pow(1.16F * channel, 0.3333333F) - 0.16F; - } - - /// - public override bool Equals(object obj) - { - return obj is RgbLWorkingSpace space && this.Equals(space); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(IRgbWorkingSpace other) - { - return other is RgbLWorkingSpace space && this.Equals(space); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(RgbLWorkingSpace other) - { - return other != null && - this.WhitePoint.Equals(other.WhitePoint) && - this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates); - } - - /// - public override int GetHashCode() - { - return HashHelpers.Combine( - this.WhitePoint.GetHashCode(), - this.ChromaticityCoordinates.GetHashCode()); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbRec2020WorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbRec2020WorkingSpace.cs deleted file mode 100644 index cc814e9b31..0000000000 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbRec2020WorkingSpace.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Runtime.CompilerServices; - -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce -{ - /// - /// Represents an that implements Rec. 2020 companding (for 12-bits). - /// - /// - /// - /// For 10-bits, companding is identical to - /// - internal class RgbRec2020WorkingSpace : IRgbWorkingSpace, IEquatable - { - /// - /// Initializes a new instance of the class. - /// - /// The reference white point. - /// The chromaticity of the rgb primaries. - public RgbRec2020WorkingSpace(CieXyz referenceWhite, RgbPrimariesChromaticityCoordinates chromaticityCoordinates) - { - this.WhitePoint = referenceWhite; - this.ChromaticityCoordinates = chromaticityCoordinates; - } - - /// - public CieXyz WhitePoint { get; } - - /// - public RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float Expand(float channel) - { - return channel < 0.08145F ? channel / 4.5F : MathF.Pow((channel + 0.0993F) / 1.0993F, 2.222222F); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float Compress(float channel) - { - return channel < 0.0181F ? 4500F * channel : (1.0993F * channel) - 0.0993F; - } - - /// - public override bool Equals(object obj) - { - return obj is RgbRec2020WorkingSpace space && this.Equals(space); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(IRgbWorkingSpace other) - { - return other is RgbRec2020WorkingSpace space && this.Equals(space); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(RgbRec2020WorkingSpace other) - { - return other != null && - this.WhitePoint.Equals(other.WhitePoint) && - this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates); - } - - /// - public override int GetHashCode() - { - return HashHelpers.Combine( - this.WhitePoint.GetHashCode(), - this.ChromaticityCoordinates.GetHashCode()); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbRec709WorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbRec709WorkingSpace.cs deleted file mode 100644 index 87301dd657..0000000000 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbRec709WorkingSpace.cs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Runtime.CompilerServices; - -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce -{ - /// - /// Represents an that implements Rec. 709 companding. - /// - /// - /// - /// - internal class RgbRec709WorkingSpace : IRgbWorkingSpace, IEquatable - { - /// - /// Initializes a new instance of the class. - /// - /// The reference white point. - /// The chromaticity of the rgb primaries. - public RgbRec709WorkingSpace(CieXyz referenceWhite, RgbPrimariesChromaticityCoordinates chromaticityCoordinates) - { - this.WhitePoint = referenceWhite; - this.ChromaticityCoordinates = chromaticityCoordinates; - } - - /// - public CieXyz WhitePoint { get; } - - /// - public RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float Expand(float channel) - { - return channel < 0.081F ? channel / 4.5F : MathF.Pow((channel + 0.099F) / 1.099F, 2.222222F); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float Compress(float channel) - { - return channel < 0.018F ? 4500F * channel : (1.099F * channel) - 0.099F; - } - - /// - public override bool Equals(object obj) - { - return obj is RgbRec709WorkingSpace space && this.Equals(space); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(IRgbWorkingSpace other) - { - return other is RgbRec709WorkingSpace space && this.Equals(space); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(RgbRec709WorkingSpace other) - { - return other != null && - this.WhitePoint.Equals(other.WhitePoint) && - this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates); - } - - /// - public override int GetHashCode() - { - return HashHelpers.Combine( - this.WhitePoint.GetHashCode(), - this.ChromaticityCoordinates.GetHashCode()); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbSRgbWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbSRgbWorkingSpace.cs deleted file mode 100644 index 98edaa0b37..0000000000 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbSRgbWorkingSpace.cs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Runtime.CompilerServices; - -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce -{ - /// - /// Represents an that implements sRGB companding - /// - /// - /// For more info see: - /// - /// - /// - internal class RgbSRgbWorkingSpace : IRgbWorkingSpace, IEquatable - { - /// - /// Initializes a new instance of the class. - /// - /// The reference white point. - /// The chromaticity of the rgb primaries. - public RgbSRgbWorkingSpace(CieXyz referenceWhite, RgbPrimariesChromaticityCoordinates chromaticityCoordinates) - { - this.WhitePoint = referenceWhite; - this.ChromaticityCoordinates = chromaticityCoordinates; - } - - /// - public CieXyz WhitePoint { get; } - - /// - public RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float Expand(float channel) - { - return channel <= 0.04045F ? channel / 12.92F : MathF.Pow((channel + 0.055F) / 1.055F, 2.4F); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float Compress(float channel) - { - return channel <= 0.0031308F ? 12.92F * channel : (1.055F * MathF.Pow(channel, 0.416666666666667F)) - 0.055F; - } - - /// - public override bool Equals(object obj) - { - return obj is RgbSRgbWorkingSpace space && this.Equals(space); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(IRgbWorkingSpace other) - { - return other is RgbSRgbWorkingSpace space && this.Equals(space); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(RgbSRgbWorkingSpace other) - { - return other != null && - this.WhitePoint.Equals(other.WhitePoint) && - this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates); - } - - /// - public override int GetHashCode() - { - return HashHelpers.Combine( - this.WhitePoint.GetHashCode(), - this.ChromaticityCoordinates.GetHashCode()); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs index 89a57051f7..e40ecc192e 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs @@ -16,9 +16,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap Guard.NotNull(input, nameof(input)); Vector3 vector = input.Vector; - vector.X = input.WorkingSpace.Expand(vector.X); - vector.Y = input.WorkingSpace.Expand(vector.Y); - vector.Z = input.WorkingSpace.Expand(vector.Z); + vector.X = input.WorkingSpace.Companding.Expand(vector.X); + vector.Y = input.WorkingSpace.Companding.Expand(vector.Y); + vector.Z = input.WorkingSpace.Companding.Expand(vector.Z); return new LinearRgb(vector, input.WorkingSpace); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs new file mode 100644 index 0000000000..8a2c66a80c --- /dev/null +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs @@ -0,0 +1,105 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce +{ + /// + /// Trivial implementation of + /// + internal struct RgbWorkingSpace : IRgbWorkingSpace + { + /// + /// Initializes a new instance of the struct. + /// + /// The reference white point. + /// The function pair for converting to and back. + /// The chromaticity of the rgb primaries. + public RgbWorkingSpace(CieXyz referenceWhite, ICompanding companding, RgbPrimariesChromaticityCoordinates chromaticityCoordinates) + { + this.WhitePoint = referenceWhite; + this.Companding = companding; + this.ChromaticityCoordinates = chromaticityCoordinates; + } + + /// + /// Gets the reference white point + /// + public CieXyz WhitePoint { get; } + + /// + /// Gets the function pair for converting to and back. + /// + public ICompanding Companding { get; } + + /// + /// Gets the chromaticity of the rgb primaries. + /// + public RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; } + + /// + /// Compares two objects for equality. + /// + /// + /// The on the left side of the operand. + /// + /// + /// The on the right side of the operand. + /// + /// + /// True if the current left is equal to the parameter; otherwise, false. + /// + public static bool operator ==(RgbWorkingSpace left, RgbWorkingSpace right) + { + return Equals(left, right); + } + + /// + /// Compares two objects for inequality + /// + /// + /// The on the left side of the operand. + /// + /// + /// The on the right side of the operand. + /// + /// + /// True if the current left is unequal to the parameter; otherwise, false. + /// + public static bool operator !=(RgbWorkingSpace left, RgbWorkingSpace right) + { + return !Equals(left, right); + } + + /// + public override bool Equals(object obj) + { + if (obj is RgbWorkingSpace) + { + return this.Equals((RgbWorkingSpace)obj); + } + + return false; + } + + /// + public bool Equals(IRgbWorkingSpace other) + { + // TODO: Object.Equals for ICompanding will be slow. + return this.WhitePoint.Equals(other.WhitePoint) + && this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates) + && Equals(this.Companding, other.Companding); + } + + /// + public override int GetHashCode() + { + unchecked + { + int hashCode = this.WhitePoint.GetHashCode(); + hashCode = (hashCode * 397) ^ this.ChromaticityCoordinates.GetHashCode(); + hashCode = (hashCode * 397) ^ (this.Companding?.GetHashCode() ?? 0); + return hashCode; + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/SRgbCompanding.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/SRgbCompanding.cs new file mode 100644 index 0000000000..ce8ea7c6e5 --- /dev/null +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/SRgbCompanding.cs @@ -0,0 +1,33 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce +{ + /// + /// Implements sRGB companding + /// + /// + /// For more info see: + /// + /// + /// + public class SRgbCompanding : ICompanding + { + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float Expand(float channel) + { + return channel <= 0.04045F ? channel / 12.92F : MathF.Pow((channel + 0.055F) / 1.055F, 2.4F); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float Compress(float channel) + { + return channel <= 0.0031308F ? 12.92F * channel : (1.055F * MathF.Pow(channel, 0.416666666666667F)) - 0.055F; + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/ICompanding.cs b/src/ImageSharp/ColorSpaces/ICompanding.cs new file mode 100644 index 0000000000..2dfa575ed9 --- /dev/null +++ b/src/ImageSharp/ColorSpaces/ICompanding.cs @@ -0,0 +1,35 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.ColorSpaces +{ + /// + /// Pair of companding functions for . + /// Used for conversion to and backwards. + /// See also: + /// + internal interface ICompanding + { + /// + /// Expands a companded channel to its linear equivalent with respect to the energy. + /// + /// + /// For more info see: + /// + /// + /// The channel value + /// The linear channel value + float Expand(float channel); + + /// + /// Compresses an uncompanded channel (linear) to its nonlinear equivalent (depends on the RGB color system). + /// + /// + /// For more info see: + /// + /// + /// The channel value + /// The nonlinear channel value + float Compress(float channel); + } +} diff --git a/src/ImageSharp/ColorSpaces/IRgbWorkingSpace.cs b/src/ImageSharp/ColorSpaces/IRgbWorkingSpace.cs index 1af3a219d6..156e94ed3c 100644 --- a/src/ImageSharp/ColorSpaces/IRgbWorkingSpace.cs +++ b/src/ImageSharp/ColorSpaces/IRgbWorkingSpace.cs @@ -7,7 +7,7 @@ using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce; namespace SixLabors.ImageSharp.ColorSpaces { /// - /// Encapsulates the RGB working color space + /// Encasulates the RGB working color space /// internal interface IRgbWorkingSpace : IEquatable { @@ -22,25 +22,10 @@ namespace SixLabors.ImageSharp.ColorSpaces RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; } /// - /// Expands a compressed channel to its linear equivalent with respect to the energy. - /// - /// - /// For more info see: + /// Gets the companding function associated with the RGB color system. Used for conversion to XYZ and backwards. /// - /// - /// The channel value - /// The linear channel value - float Expand(float channel); - - /// - /// Compresses an expanded channel (linear) to its nonlinear equivalent (depends on the RGB color system). - /// - /// - /// For more info see: /// - /// - /// The channel value - /// The nonlinear channel value - float Compress(float channel); + /// + ICompanding Companding { get; } } } \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs b/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs index 93557154d9..098ca9a4a4 100644 --- a/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs +++ b/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs @@ -19,226 +19,97 @@ namespace SixLabors.ImageSharp.ColorSpaces /// Uses proper companding function, according to: /// /// - public static readonly IRgbWorkingSpace SRgb = - new RgbSRgbWorkingSpace( - Illuminants.D65, - new RgbPrimariesChromaticityCoordinates( - new CieXyChromaticityCoordinates(0.6400F, 0.3300F), - new CieXyChromaticityCoordinates(0.3000F, 0.6000F), - new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); + public static readonly IRgbWorkingSpace SRgb = new RgbWorkingSpace(Illuminants.D65, new SRgbCompanding(), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.3000F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); /// - /// Simplified sRgb working space that uses gamma companding instead of srgb companding. + /// Simplified sRgb working space (uses gamma companding instead of ). /// See also . /// - public static readonly IRgbWorkingSpace SRgbSimplified = - new RgbGammaWorkingSpace( - Illuminants.D65, - 2.2F, - new RgbPrimariesChromaticityCoordinates( - new CieXyChromaticityCoordinates(0.6400F, 0.3300F), - new CieXyChromaticityCoordinates(0.3000F, 0.6000F), - new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); + public static readonly IRgbWorkingSpace SRgbSimplified = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.3000F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); /// /// Rec. 709 (ITU-R Recommendation BT.709) working space /// - public static readonly IRgbWorkingSpace Rec709 = - new RgbRec709WorkingSpace( - Illuminants.D65, - new RgbPrimariesChromaticityCoordinates( - new CieXyChromaticityCoordinates(0.64F, 0.33F), - new CieXyChromaticityCoordinates(0.30F, 0.60F), - new CieXyChromaticityCoordinates(0.15F, 0.06F))); + public static readonly IRgbWorkingSpace Rec709 = new RgbWorkingSpace(Illuminants.D65, new Rec709Companding(), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.64F, 0.33F), new CieXyChromaticityCoordinates(0.30F, 0.60F), new CieXyChromaticityCoordinates(0.15F, 0.06F))); /// /// Rec. 2020 (ITU-R Recommendation BT.2020F) working space /// - public static readonly IRgbWorkingSpace Rec2020 = - new RgbRec2020WorkingSpace( - Illuminants.D65, - new RgbPrimariesChromaticityCoordinates( - new CieXyChromaticityCoordinates(0.708F, 0.292F), - new CieXyChromaticityCoordinates(0.170F, 0.797F), - new CieXyChromaticityCoordinates(0.131F, 0.046F))); + public static readonly IRgbWorkingSpace Rec2020 = new RgbWorkingSpace(Illuminants.D65, new Rec2020Companding(), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.708F, 0.292F), new CieXyChromaticityCoordinates(0.170F, 0.797F), new CieXyChromaticityCoordinates(0.131F, 0.046F))); /// /// ECI Rgb v2 working space /// - public static readonly IRgbWorkingSpace ECIRgbv2 = - new RgbLWorkingSpace( - Illuminants.D50, - new RgbPrimariesChromaticityCoordinates( - new CieXyChromaticityCoordinates(0.6700F, 0.3300F), - new CieXyChromaticityCoordinates(0.2100F, 0.7100F), - new CieXyChromaticityCoordinates(0.1400F, 0.0800F))); + public static readonly IRgbWorkingSpace ECIRgbv2 = new RgbWorkingSpace(Illuminants.D50, new LCompanding(), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6700F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1400F, 0.0800F))); /// /// Adobe Rgb (1998) working space /// - public static readonly IRgbWorkingSpace AdobeRgb1998 = - new RgbGammaWorkingSpace( - Illuminants.D65, - 2.2F, - new RgbPrimariesChromaticityCoordinates( - new CieXyChromaticityCoordinates(0.6400F, 0.3300F), - new CieXyChromaticityCoordinates(0.2100F, 0.7100F), - new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); + public static readonly IRgbWorkingSpace AdobeRgb1998 = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); /// /// Apple sRgb working space /// - public static readonly IRgbWorkingSpace ApplesRgb = - new RgbGammaWorkingSpace( - Illuminants.D65, - 1.8F, - new RgbPrimariesChromaticityCoordinates( - new CieXyChromaticityCoordinates(0.6250F, 0.3400F), - new CieXyChromaticityCoordinates(0.2800F, 0.5950F), - new CieXyChromaticityCoordinates(0.1550F, 0.0700F))); + public static readonly IRgbWorkingSpace ApplesRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(1.8F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6250F, 0.3400F), new CieXyChromaticityCoordinates(0.2800F, 0.5950F), new CieXyChromaticityCoordinates(0.1550F, 0.0700F))); /// /// Best Rgb working space /// - public static readonly IRgbWorkingSpace BestRgb = - new RgbGammaWorkingSpace( - Illuminants.D50, - 2.2F, - new RgbPrimariesChromaticityCoordinates( - new CieXyChromaticityCoordinates(0.7347F, 0.2653F), - new CieXyChromaticityCoordinates(0.2150F, 0.7750F), - new CieXyChromaticityCoordinates(0.1300F, 0.0350F))); + public static readonly IRgbWorkingSpace BestRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7347F, 0.2653F), new CieXyChromaticityCoordinates(0.2150F, 0.7750F), new CieXyChromaticityCoordinates(0.1300F, 0.0350F))); /// /// Beta Rgb working space /// - public static readonly IRgbWorkingSpace BetaRgb = - new RgbGammaWorkingSpace( - Illuminants.D50, - 2.2F, - new RgbPrimariesChromaticityCoordinates( - new CieXyChromaticityCoordinates(0.6888F, 0.3112F), - new CieXyChromaticityCoordinates(0.1986F, 0.7551F), - new CieXyChromaticityCoordinates(0.1265F, 0.0352F))); + public static readonly IRgbWorkingSpace BetaRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6888F, 0.3112F), new CieXyChromaticityCoordinates(0.1986F, 0.7551F), new CieXyChromaticityCoordinates(0.1265F, 0.0352F))); /// /// Bruce Rgb working space /// - public static readonly IRgbWorkingSpace BruceRgb = - new RgbGammaWorkingSpace( - Illuminants.D65, - 2.2F, - new RgbPrimariesChromaticityCoordinates( - new CieXyChromaticityCoordinates(0.6400F, 0.3300F), - new CieXyChromaticityCoordinates(0.2800F, 0.6500F), - new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); + public static readonly IRgbWorkingSpace BruceRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2800F, 0.6500F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); /// /// CIE Rgb working space /// - public static readonly IRgbWorkingSpace CIERgb = - new RgbGammaWorkingSpace( - Illuminants.E, - 2.2F, - new RgbPrimariesChromaticityCoordinates( - new CieXyChromaticityCoordinates(0.7350F, 0.2650F), - new CieXyChromaticityCoordinates(0.2740F, 0.7170F), - new CieXyChromaticityCoordinates(0.1670F, 0.0090F))); + public static readonly IRgbWorkingSpace CIERgb = new RgbWorkingSpace(Illuminants.E, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7350F, 0.2650F), new CieXyChromaticityCoordinates(0.2740F, 0.7170F), new CieXyChromaticityCoordinates(0.1670F, 0.0090F))); /// /// ColorMatch Rgb working space /// - public static readonly IRgbWorkingSpace ColorMatchRgb = - new RgbGammaWorkingSpace( - Illuminants.D50, - 1.8F, - new RgbPrimariesChromaticityCoordinates( - new CieXyChromaticityCoordinates(0.6300F, 0.3400F), - new CieXyChromaticityCoordinates(0.2950F, 0.6050F), - new CieXyChromaticityCoordinates(0.1500F, 0.0750F))); + public static readonly IRgbWorkingSpace ColorMatchRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(1.8F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6300F, 0.3400F), new CieXyChromaticityCoordinates(0.2950F, 0.6050F), new CieXyChromaticityCoordinates(0.1500F, 0.0750F))); /// /// Don Rgb 4 working space /// - public static readonly IRgbWorkingSpace DonRgb4 = - new RgbGammaWorkingSpace( - Illuminants.D50, - 2.2F, - new RgbPrimariesChromaticityCoordinates( - new CieXyChromaticityCoordinates(0.6960F, 0.3000F), - new CieXyChromaticityCoordinates(0.2150F, 0.7650F), - new CieXyChromaticityCoordinates(0.1300F, 0.0350F))); + public static readonly IRgbWorkingSpace DonRgb4 = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6960F, 0.3000F), new CieXyChromaticityCoordinates(0.2150F, 0.7650F), new CieXyChromaticityCoordinates(0.1300F, 0.0350F))); /// /// Ekta Space PS5 working space /// - public static readonly IRgbWorkingSpace EktaSpacePS5 = - new RgbGammaWorkingSpace( - Illuminants.D50, - 2.2F, - new RgbPrimariesChromaticityCoordinates( - new CieXyChromaticityCoordinates(0.6950F, 0.3050F), - new CieXyChromaticityCoordinates(0.2600F, 0.7000F), - new CieXyChromaticityCoordinates(0.1100F, 0.0050F))); + public static readonly IRgbWorkingSpace EktaSpacePS5 = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6950F, 0.3050F), new CieXyChromaticityCoordinates(0.2600F, 0.7000F), new CieXyChromaticityCoordinates(0.1100F, 0.0050F))); /// /// NTSC Rgb working space /// - public static readonly IRgbWorkingSpace NTSCRgb = - new RgbGammaWorkingSpace( - Illuminants.C, - 2.2F, - new RgbPrimariesChromaticityCoordinates( - new CieXyChromaticityCoordinates(0.6700F, 0.3300F), - new CieXyChromaticityCoordinates(0.2100F, 0.7100F), - new CieXyChromaticityCoordinates(0.1400F, 0.0800F))); + public static readonly IRgbWorkingSpace NTSCRgb = new RgbWorkingSpace(Illuminants.C, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6700F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1400F, 0.0800F))); /// /// PAL/SECAM Rgb working space /// - public static readonly IRgbWorkingSpace PALSECAMRgb = - new RgbGammaWorkingSpace( - Illuminants.D65, - 2.2F, - new RgbPrimariesChromaticityCoordinates( - new CieXyChromaticityCoordinates(0.6400F, 0.3300F), - new CieXyChromaticityCoordinates(0.2900F, 0.6000F), - new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); + public static readonly IRgbWorkingSpace PALSECAMRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2900F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); /// /// ProPhoto Rgb working space /// - public static readonly IRgbWorkingSpace ProPhotoRgb = - new RgbGammaWorkingSpace( - Illuminants.D50, - 1.8F, - new RgbPrimariesChromaticityCoordinates( - new CieXyChromaticityCoordinates(0.7347F, 0.2653F), - new CieXyChromaticityCoordinates(0.1596F, 0.8404F), - new CieXyChromaticityCoordinates(0.0366F, 0.0001F))); + public static readonly IRgbWorkingSpace ProPhotoRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(1.8F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7347F, 0.2653F), new CieXyChromaticityCoordinates(0.1596F, 0.8404F), new CieXyChromaticityCoordinates(0.0366F, 0.0001F))); /// /// SMPTE-C Rgb working space /// - public static readonly IRgbWorkingSpace SMPTECRgb = - new RgbGammaWorkingSpace( - Illuminants.D65, - 2.2F, - new RgbPrimariesChromaticityCoordinates( - new CieXyChromaticityCoordinates(0.6300F, 0.3400F), - new CieXyChromaticityCoordinates(0.3100F, 0.5950F), - new CieXyChromaticityCoordinates(0.1550F, 0.0700F))); + public static readonly IRgbWorkingSpace SMPTECRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6300F, 0.3400F), new CieXyChromaticityCoordinates(0.3100F, 0.5950F), new CieXyChromaticityCoordinates(0.1550F, 0.0700F))); /// /// Wide Gamut Rgb working space /// - public static readonly IRgbWorkingSpace WideGamutRgb = - new RgbGammaWorkingSpace( - Illuminants.D50, - 2.2F, - new RgbPrimariesChromaticityCoordinates( - new CieXyChromaticityCoordinates(0.7350F, 0.2650F), - new CieXyChromaticityCoordinates(0.1150F, 0.8260F), - new CieXyChromaticityCoordinates(0.1570F, 0.0180F))); + public static readonly IRgbWorkingSpace WideGamutRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7350F, 0.2650F), new CieXyChromaticityCoordinates(0.1150F, 0.8260F), new CieXyChromaticityCoordinates(0.1570F, 0.0180F))); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs b/tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs index 1bd80073e5..24363173ae 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs @@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp.Tests public bool Equals(IRgbWorkingSpace x, IRgbWorkingSpace y) { - if (x is RgbGammaWorkingSpace g1 && y is RgbGammaWorkingSpace g2) + if (x is IRgbWorkingSpace g1 && y is IRgbWorkingSpace g2) { return this.Equals(g1.WhitePoint, g2.WhitePoint) && this.Equals(g1.ChromaticityCoordinates, g2.ChromaticityCoordinates); From 37928d7b10985626f8c6bc7da422725e331ceb38 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 16 Feb 2018 23:01:53 +0100 Subject: [PATCH 17/19] fix benchmark.sh --- tests/ImageSharp.Benchmarks/benchmark.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ImageSharp.Benchmarks/benchmark.sh b/tests/ImageSharp.Benchmarks/benchmark.sh index 1966475bca..f51a9833aa 100755 --- a/tests/ImageSharp.Benchmarks/benchmark.sh +++ b/tests/ImageSharp.Benchmarks/benchmark.sh @@ -1,7 +1,7 @@ #!/bin/bash # Build in release mode -dotnet build -c Release -f netcoreapp1.1 +dotnet build -c Release -f netcoreapp2.0 # Run benchmarks -dotnet bin/Release/netcoreapp1.1/ImageSharp.Benchmarks.dll \ No newline at end of file +dotnet bin/Release/netcoreapp2.0/ImageSharp.Benchmarks.dll \ No newline at end of file From ba9584725fa8a8c8e29da90a9ab45c6b8acb59fe Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 16 Feb 2018 23:17:01 +0100 Subject: [PATCH 18/19] removing samples --- ImageSharp.sln | 32 ----- .../AvatarWithRoundedCorner.csproj | 12 -- samples/AvatarWithRoundedCorner/Program.cs | 111 ------------------ samples/AvatarWithRoundedCorner/fb.jpg | Bin 15787 -> 0 bytes .../ChangeDefaultEncoderOptions.csproj | 12 -- .../ChangeDefaultEncoderOptions/Program.cs | 23 ---- 6 files changed, 190 deletions(-) delete mode 100644 samples/AvatarWithRoundedCorner/AvatarWithRoundedCorner.csproj delete mode 100644 samples/AvatarWithRoundedCorner/Program.cs delete mode 100644 samples/AvatarWithRoundedCorner/fb.jpg delete mode 100644 samples/ChangeDefaultEncoderOptions/ChangeDefaultEncoderOptions.csproj delete mode 100644 samples/ChangeDefaultEncoderOptions/Program.cs diff --git a/ImageSharp.sln b/ImageSharp.sln index 4ea89dd450..3ff5b09d41 100644 --- a/ImageSharp.sln +++ b/ImageSharp.sln @@ -43,12 +43,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp.Tests", "tests\I EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp.Benchmarks", "tests\ImageSharp.Benchmarks\ImageSharp.Benchmarks.csproj", "{2BF743D8-2A06-412D-96D7-F448F00C5EA5}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{7CC6D57E-B916-43B8-B315-A0BB92F260A2}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AvatarWithRoundedCorner", "samples\AvatarWithRoundedCorner\AvatarWithRoundedCorner.csproj", "{844FC582-4E78-4371-847D-EFD4D1103578}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChangeDefaultEncoderOptions", "samples\ChangeDefaultEncoderOptions\ChangeDefaultEncoderOptions.csproj", "{07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp.Sandbox46", "tests\ImageSharp.Sandbox46\ImageSharp.Sandbox46.csproj", "{561B880A-D9EE-44EF-90F5-817C54A9D9AB}" EndProject Global @@ -112,30 +106,6 @@ Global {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Release|x64.Build.0 = Release|Any CPU {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Release|x86.ActiveCfg = Release|Any CPU {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Release|x86.Build.0 = Release|Any CPU - {844FC582-4E78-4371-847D-EFD4D1103578}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {844FC582-4E78-4371-847D-EFD4D1103578}.Debug|Any CPU.Build.0 = Debug|Any CPU - {844FC582-4E78-4371-847D-EFD4D1103578}.Debug|x64.ActiveCfg = Debug|Any CPU - {844FC582-4E78-4371-847D-EFD4D1103578}.Debug|x64.Build.0 = Debug|Any CPU - {844FC582-4E78-4371-847D-EFD4D1103578}.Debug|x86.ActiveCfg = Debug|Any CPU - {844FC582-4E78-4371-847D-EFD4D1103578}.Debug|x86.Build.0 = Debug|Any CPU - {844FC582-4E78-4371-847D-EFD4D1103578}.Release|Any CPU.ActiveCfg = Release|Any CPU - {844FC582-4E78-4371-847D-EFD4D1103578}.Release|Any CPU.Build.0 = Release|Any CPU - {844FC582-4E78-4371-847D-EFD4D1103578}.Release|x64.ActiveCfg = Release|Any CPU - {844FC582-4E78-4371-847D-EFD4D1103578}.Release|x64.Build.0 = Release|Any CPU - {844FC582-4E78-4371-847D-EFD4D1103578}.Release|x86.ActiveCfg = Release|Any CPU - {844FC582-4E78-4371-847D-EFD4D1103578}.Release|x86.Build.0 = Release|Any CPU - {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Debug|x64.ActiveCfg = Debug|Any CPU - {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Debug|x64.Build.0 = Debug|Any CPU - {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Debug|x86.ActiveCfg = Debug|Any CPU - {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Debug|x86.Build.0 = Debug|Any CPU - {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Release|Any CPU.Build.0 = Release|Any CPU - {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Release|x64.ActiveCfg = Release|Any CPU - {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Release|x64.Build.0 = Release|Any CPU - {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Release|x86.ActiveCfg = Release|Any CPU - {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Release|x86.Build.0 = Release|Any CPU {561B880A-D9EE-44EF-90F5-817C54A9D9AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {561B880A-D9EE-44EF-90F5-817C54A9D9AB}.Debug|Any CPU.Build.0 = Debug|Any CPU {561B880A-D9EE-44EF-90F5-817C54A9D9AB}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -158,8 +128,6 @@ Global {2E33181E-6E28-4662-A801-E2E7DC206029} = {815C0625-CD3D-440F-9F80-2D83856AB7AE} {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC} {2BF743D8-2A06-412D-96D7-F448F00C5EA5} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC} - {844FC582-4E78-4371-847D-EFD4D1103578} = {7CC6D57E-B916-43B8-B315-A0BB92F260A2} - {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0} = {7CC6D57E-B916-43B8-B315-A0BB92F260A2} {561B880A-D9EE-44EF-90F5-817C54A9D9AB} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/samples/AvatarWithRoundedCorner/AvatarWithRoundedCorner.csproj b/samples/AvatarWithRoundedCorner/AvatarWithRoundedCorner.csproj deleted file mode 100644 index e000aacf10..0000000000 --- a/samples/AvatarWithRoundedCorner/AvatarWithRoundedCorner.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - Exe - netcoreapp1.1 - - - - - - - \ No newline at end of file diff --git a/samples/AvatarWithRoundedCorner/Program.cs b/samples/AvatarWithRoundedCorner/Program.cs deleted file mode 100644 index 087bbc29d5..0000000000 --- a/samples/AvatarWithRoundedCorner/Program.cs +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Numerics; -using SixLabors.ImageSharp; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.Primitives; -using SixLabors.Shapes; - -namespace AvatarWithRoundedCorner -{ - static class Program - { - static void Main(string[] args) - { - System.IO.Directory.CreateDirectory("output"); - using (var img = Image.Load("fb.jpg")) - { - // as generate returns a new IImage make sure we dispose of it - using (Image destRound = img.Clone(x => x.ConvertToAvatar(new Size(200, 200), 20))) - { - destRound.Save("output/fb.png"); - } - - using (Image destRound = img.Clone(x => x.ConvertToAvatar(new Size(200, 200), 100))) - { - destRound.Save("output/fb-round.png"); - } - - using (Image destRound = img.Clone(x => x.ConvertToAvatar(new Size(200, 200), 150))) - { - destRound.Save("output/fb-rounder.png"); - } - - using (Image destRound = img.CloneAndConvertToAvatarWithoutApply(new Size(200, 200), 150)) - { - destRound.Save("output/fb-rounder-without-apply.png"); - } - - // the original `img` object has not been altered at all. - } - } - - // 1. The short way: - // Implements a full image mutating pipeline operating on IImageProcessingContext - // We need the dimensions of the resized image to deduce 'IPathCollection' needed to build the corners, - // so we implement an "inline" image processor by utilizing 'ImageExtensions.Apply()' - private static IImageProcessingContext ConvertToAvatar(this IImageProcessingContext processingContext, Size size, float cornerRadius) - { - return processingContext.Resize(new ResizeOptions - { - Size = size, - Mode = ResizeMode.Crop - }).Apply(i => ApplyRoundedCorners(i, cornerRadius)); - } - - // 2. A more verbose way, avoiding 'Apply()': - // First we create a resized clone of the image, then we draw the corners on that instance with Mutate(). - private static Image CloneAndConvertToAvatarWithoutApply(this Image image, Size size, float cornerRadius) - { - Image result = image.Clone( - ctx => ctx.Resize( - new ResizeOptions - { - Size = size, - Mode = ResizeMode.Crop - })); - - ApplyRoundedCorners(result, cornerRadius); - return result; - } - - // This method can be seen as an inline implementation of an `IImageProcessor`: - // (The combination of `IImageOperations.Apply()` + this could be replaced with an `IImageProcessor`) - public static void ApplyRoundedCorners(Image img, float cornerRadius) - { - IPathCollection corners = BuildCorners(img.Width, img.Height, cornerRadius); - - // mutating in here as we already have a cloned original - img.Mutate(x => x.Fill(Rgba32.Transparent, corners, new GraphicsOptions(true) - { - BlenderMode = PixelBlenderMode.Src // enforces that any part of this shape that has color is punched out of the background - })); - } - - public static IPathCollection BuildCorners(int imageWidth, int imageHeight, float cornerRadius) - { - // first create a square - var rect = new RectangularePolygon(-0.5f, -0.5f, cornerRadius, cornerRadius); - - // then cut out of the square a circle so we are left with a corner - IPath cornerToptLeft = rect.Clip(new EllipsePolygon(cornerRadius - 0.5f, cornerRadius - 0.5f, cornerRadius)); - - // corner is now a corner shape positions top left - //lets make 3 more positioned correctly, we can do that by translating the orgional artound the center of the image - var center = new Vector2(imageWidth / 2F, imageHeight / 2F); - - float rightPos = imageWidth - cornerToptLeft.Bounds.Width + 1; - float bottomPos = imageHeight - cornerToptLeft.Bounds.Height + 1; - - // move it across the widthof the image - the width of the shape - IPath cornerTopRight = cornerToptLeft.RotateDegree(90).Translate(rightPos, 0); - IPath cornerBottomLeft = cornerToptLeft.RotateDegree(-90).Translate(0, bottomPos); - IPath cornerBottomRight = cornerToptLeft.RotateDegree(180).Translate(rightPos, bottomPos); - - return new PathCollection(cornerToptLeft, cornerBottomLeft, cornerTopRight, cornerBottomRight); - } - } -} \ No newline at end of file diff --git a/samples/AvatarWithRoundedCorner/fb.jpg b/samples/AvatarWithRoundedCorner/fb.jpg deleted file mode 100644 index 305294f47eee72bcc7fe5ec3fce0d33d39d0b293..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15787 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 - - - Exe - netcoreapp1.1 - - - - - - - \ No newline at end of file diff --git a/samples/ChangeDefaultEncoderOptions/Program.cs b/samples/ChangeDefaultEncoderOptions/Program.cs deleted file mode 100644 index a8fbd75993..0000000000 --- a/samples/ChangeDefaultEncoderOptions/Program.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using SixLabors.ImageSharp; -using SixLabors.ImageSharp.Formats.Jpeg; - -namespace ChangeDefaultEncoderOptions -{ - class Program - { - static void Main(string[] args) - { - // lets switch out the default encoder for jpeg to one - // that saves at 90 quality and ignores the matadata - Configuration.Default.SetEncoder(ImageFormats.Jpeg, new JpegEncoder() - { - Quality = 90, - IgnoreMetadata = true - }); - } - } -} \ No newline at end of file From 9bbab229ff0249a6056c9bd7ae0dae190fa5e7df Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sun, 18 Feb 2018 18:04:12 +1100 Subject: [PATCH 19/19] Update .vscode files --- .vscode/launch.json | 2 +- .vscode/tasks.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index c9c7453f64..c772e647ce 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,7 +10,7 @@ "request": "launch", "preLaunchTask": "build", // If you have changed target frameworks, make sure to update the program path. - "program": "${workspaceRoot}/samples/AvatarWithRoundedCorner/bin/Debug/netcoreapp1.1/AvatarWithRoundedCorner.dll", + "program": "${workspaceRoot}/tests/ImageSharp.Benchmarks/bin/Debug/netcoreapp2.0/ImageSharp.Benchmarks.dll", "args": [], "cwd": "${workspaceRoot}/samples/AvatarWithRoundedCorner", // For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 4a7b35ac2c..82aaa2f8d0 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -16,13 +16,13 @@ { "taskName": "build benchmark", "suppressTaskName": true, - "args": [ "build", "tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj", "-f", "netcoreapp1.1", "-c", "Release" ], + "args": [ "build", "tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj", "-f", "netcoreapp2.0", "-c", "Release" ], "showOutput": "always", "problemMatcher": "$msCompile" }, { "taskName": "test", - "args": ["tests/ImageSharp.Tests/ImageSharp.Tests.csproj", "-c", "release", "-f", "netcoreapp1.1"], + "args": ["tests/ImageSharp.Tests/ImageSharp.Tests.csproj", "-c", "release", "-f", "netcoreapp2.0"], "isTestCommand": true, "showOutput": "always", "problemMatcher": "$msCompile"