From 4d85b30c98ef4253108fd953eb613d85ca256046 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 31 Aug 2017 00:27:34 +1000 Subject: [PATCH] GrayScale & RGB + Tests --- .../JpegColorConverter.FromGrayScale.cs | 39 ++++++++++++++ .../Decoder/JpegColorConverter.FromRgb.cs | 43 +++++++++++++++ .../Decoder/JpegColorConverter.FromYCbCr.cs | 8 +-- .../Jpeg/Common/Decoder/JpegColorConverter.cs | 2 +- .../Formats/Jpg/JpegColorConverterTests.cs | 52 +++++++++++++++++-- 5 files changed, 132 insertions(+), 12 deletions(-) create mode 100644 src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegColorConverter.FromGrayScale.cs create mode 100644 src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegColorConverter.FromRgb.cs diff --git a/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegColorConverter.FromGrayScale.cs b/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegColorConverter.FromGrayScale.cs new file mode 100644 index 000000000..9ff263dcf --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegColorConverter.FromGrayScale.cs @@ -0,0 +1,39 @@ +using System; +using System.Numerics; + +namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder +{ + internal abstract partial class JpegColorConverter + { + private class FromGrayScale : JpegColorConverter + { + public FromGrayScale() + : base(JpegColorSpace.GrayScale) + { + } + + public override void ConvertToRGBA(ComponentValues values, Span result) + { + // TODO: We can optimize a lot here with Vector and SRCS.Unsafe()! + ReadOnlySpan yVals = values.Component0; + + var v = new Vector4(0, 0, 0, 1); + + var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); + + for (int i = 0; i < result.Length; i++) + { + float y = yVals[i]; + + v.X = y; + v.Y = y; + v.Z = y; + + v *= scale; + + result[i] = v; + } + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegColorConverter.FromRgb.cs b/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegColorConverter.FromRgb.cs new file mode 100644 index 000000000..f4a702783 --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegColorConverter.FromRgb.cs @@ -0,0 +1,43 @@ +using System; +using System.Numerics; + +namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder +{ + internal abstract partial class JpegColorConverter + { + private class FromRgb : JpegColorConverter + { + public FromRgb() + : base(JpegColorSpace.RGB) + { + } + + public override void ConvertToRGBA(ComponentValues values, Span result) + { + // TODO: We can optimize a lot here with Vector and SRCS.Unsafe()! + ReadOnlySpan rVals = values.Component0; + ReadOnlySpan gVals = values.Component1; + ReadOnlySpan bVals = values.Component2; + + var v = new Vector4(0, 0, 0, 1); + + var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); + + for (int i = 0; i < result.Length; i++) + { + float r = rVals[i]; + float g = gVals[i]; + float b = bVals[i]; + + v.X = r; + v.Y = g; + v.Z = b; + + v *= scale; + + result[i] = v; + } + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegColorConverter.FromYCbCr.cs b/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegColorConverter.FromYCbCr.cs index fdfc5ba84..24e8d753b 100644 --- a/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegColorConverter.FromYCbCr.cs +++ b/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegColorConverter.FromYCbCr.cs @@ -1,9 +1,5 @@ using System; using System.Numerics; -using System.Runtime.CompilerServices; - -using SixLabors.ImageSharp.ColorSpaces; -using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.YCbCrColorSapce; namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder { @@ -11,8 +7,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder { private class FromYCbCr : JpegColorConverter { - private static readonly YCbCrAndRgbConverter Converter = new YCbCrAndRgbConverter(); - public FromYCbCr() : base(JpegColorSpace.YCbCr) { @@ -27,7 +21,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder var v = new Vector4(0, 0, 0, 1); - Vector4 scale = new Vector4(1/255f, 1 / 255f, 1 / 255f, 1f); + var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); for (int i = 0; i < result.Length; i++) { diff --git a/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegColorConverter.cs index aaee7bcd1..b83a05c6a 100644 --- a/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegColorConverter.cs +++ b/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegColorConverter.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder { internal abstract partial class JpegColorConverter { - private static readonly JpegColorConverter[] Converters = { new FromYCbCr(), new FromYccK(), new FromCmyk() }; + private static readonly JpegColorConverter[] Converters = { new FromYCbCr(), new FromYccK(), new FromCmyk(), new FromGrayScale(), new FromRgb() }; protected JpegColorConverter(JpegColorSpace colorSpace) { diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs index 9b7a63a97..2dddb2b09 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg var rnd = new Random(42); Buffer2D[] buffers = new Buffer2D[componentCount]; for (int i = 0; i < componentCount; i++) - { + { float[] values = new float[InputBufferLength]; for (int j = 0; j < InputBufferLength; j++) @@ -59,9 +59,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg var converter = JpegColorConverter.GetConverter(JpegColorSpace.YCbCr); JpegColorConverter.ComponentValues values = CreateRandomValues(3); - + converter.ConvertToRGBA(values, this.Result); - + for (int i = 0; i < ResultBufferLength; i++) { float y = values.Component0[i]; @@ -72,7 +72,51 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg Vector4 rgba = this.Result[i]; Rgb actual = new Rgb(rgba.X, rgba.Y, rgba.Z); Rgb expected = ColorSpaceConverter.ToRgb(ycbcr); - + + Assert.True(actual.AlmostEquals(expected, Precision)); + Assert.Equal(1, rgba.W); + } + } + + [Fact] + public void ConvertFromGrayScale() + { + var converter = JpegColorConverter.GetConverter(JpegColorSpace.GrayScale); + + JpegColorConverter.ComponentValues values = CreateRandomValues(1); + + converter.ConvertToRGBA(values, this.Result); + + for (int i = 0; i < ResultBufferLength; i++) + { + float y = values.Component0[i]; + Vector4 rgba = this.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); + } + } + + [Fact] + public void ConvertFromRgb() + { + var converter = JpegColorConverter.GetConverter(JpegColorSpace.RGB); + + JpegColorConverter.ComponentValues values = CreateRandomValues(3); + + converter.ConvertToRGBA(values, this.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 = this.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); }