From c6ac54a936751abc6ad3cfdc86a02111a10d0664 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Thu, 18 Jul 2024 23:09:49 +0200 Subject: [PATCH] Added additional tests and some small fixes and improvements --- HPPH.Reference/PixelHelper.Average.cs | 24 ++ HPPH.Reference/PixelHelper.MinMax.cs | 22 ++ HPPH.Reference/PixelHelper.Sum.cs | 16 ++ HPPH.Test/Colors/ColorFormatTests.cs | 90 ++++++++ HPPH.Test/Colors/ColorTests.cs | 183 +++++++++++++++ HPPH.Test/Colors/MinMaxStructTests.cs | 176 ++++++++++++++ HPPH.Test/Colors/SumStructTests.cs | 183 +++++++++++++++ HPPH.Test/HPPH.Test.csproj | 1 + HPPH.Test/Image/ImageTest.cs | 305 +++++++++++++++++++++++++ HPPH.Test/ImageHelper.cs | 36 +-- HPPH.Test/PixelHelper/AverageTests.cs | 164 +++++++++---- HPPH.Test/PixelHelper/ConvertTests.cs | 18 +- HPPH.Test/PixelHelper/MinMaxTests.cs | 234 ++++++++++++++----- HPPH.Test/PixelHelper/QuantizeTests.cs | 12 +- HPPH.Test/PixelHelper/SortTests.cs | 14 +- HPPH.Test/PixelHelper/SumTests.cs | 164 +++++++++---- HPPH.Test/TestDataHelper.cs | 8 +- HPPH/Images/Image.cs | 2 +- HPPH/Images/ImageColumn.cs | 10 +- HPPH/Images/ImageRow.cs | 2 +- HPPH/Images/RefImage.cs | 3 +- HPPH/PixelHelper.Average.cs | 15 +- HPPH/PixelHelper.Quantize.cs | 2 +- HPPH/PixelHelper.Sum.cs | 6 +- 24 files changed, 1503 insertions(+), 187 deletions(-) create mode 100644 HPPH.Test/Colors/ColorFormatTests.cs create mode 100644 HPPH.Test/Colors/ColorTests.cs create mode 100644 HPPH.Test/Colors/MinMaxStructTests.cs create mode 100644 HPPH.Test/Colors/SumStructTests.cs diff --git a/HPPH.Reference/PixelHelper.Average.cs b/HPPH.Reference/PixelHelper.Average.cs index 43b8f9c..2553764 100644 --- a/HPPH.Reference/PixelHelper.Average.cs +++ b/HPPH.Reference/PixelHelper.Average.cs @@ -15,6 +15,18 @@ public static partial class ReferencePixelHelper (byte)(sum.A / count)); } + public static T Average(IImage image) + where T : struct, IColor + { + float count = image.Width * image.Height; + + ISum sum = Sum(image); + return (T)T.Create((byte)(sum.R / count), + (byte)(sum.G / count), + (byte)(sum.B / count), + (byte)(sum.A / count)); + } + public static T Average(RefImage image) where T : struct, IColor { @@ -27,6 +39,18 @@ public static partial class ReferencePixelHelper (byte)(sum.A / count)); } + public static T Average(Span colors) + where T : struct, IColor + { + float count = colors.Length; + + ISum sum = Sum(colors); + return (T)T.Create((byte)(sum.R / count), + (byte)(sum.G / count), + (byte)(sum.B / count), + (byte)(sum.A / count)); + } + public static T Average(ReadOnlySpan colors) where T : struct, IColor { diff --git a/HPPH.Reference/PixelHelper.MinMax.cs b/HPPH.Reference/PixelHelper.MinMax.cs index 80ce107..140cb85 100644 --- a/HPPH.Reference/PixelHelper.MinMax.cs +++ b/HPPH.Reference/PixelHelper.MinMax.cs @@ -47,6 +47,28 @@ public static partial class ReferencePixelHelper return new MinMaxRGBA(minR, maxR, minG, maxG, minB, maxB, minA, maxA); } + public static IMinMax MinMax(Span colors) + where T : struct, IColor + { + byte minR = byte.MaxValue, minG = byte.MaxValue, minB = byte.MaxValue, minA = byte.MaxValue; + byte maxR = byte.MinValue, maxG = byte.MinValue, maxB = byte.MinValue, maxA = byte.MinValue; + + foreach (T color in colors) + { + minR = Math.Min(minR, color.R); + minG = Math.Min(minG, color.G); + minB = Math.Min(minB, color.B); + minA = Math.Min(minA, color.A); + + maxR = Math.Max(maxR, color.R); + maxG = Math.Max(maxG, color.G); + maxB = Math.Max(maxB, color.B); + maxA = Math.Max(maxA, color.A); + } + + return new MinMaxRGBA(minR, maxR, minG, maxG, minB, maxB, minA, maxA); + } + public static IMinMax MinMax(ReadOnlySpan colors) where T : struct, IColor { diff --git a/HPPH.Reference/PixelHelper.Sum.cs b/HPPH.Reference/PixelHelper.Sum.cs index 6ea5e38..47ddc14 100644 --- a/HPPH.Reference/PixelHelper.Sum.cs +++ b/HPPH.Reference/PixelHelper.Sum.cs @@ -35,6 +35,22 @@ public static partial class ReferencePixelHelper return new SumRGBA(sumR, sumG, sumB, sumA); } + public static ISum Sum(Span colors) + where T : struct, IColor + { + long sumR = 0, sumG = 0, sumB = 0, sumA = 0; + + foreach (T color in colors) + { + sumR += color.R; + sumG += color.G; + sumB += color.B; + sumA += color.A; + } + + return new SumRGBA(sumR, sumG, sumB, sumA); + } + public static ISum Sum(ReadOnlySpan colors) where T : struct, IColor { diff --git a/HPPH.Test/Colors/ColorFormatTests.cs b/HPPH.Test/Colors/ColorFormatTests.cs new file mode 100644 index 0000000..cb94b0c --- /dev/null +++ b/HPPH.Test/Colors/ColorFormatTests.cs @@ -0,0 +1,90 @@ +namespace HPPH.Test.Colors; + +[TestClass] +public class ColorFormatTests +{ + [TestMethod] + public void ColorFormatRGBName() + { + Assert.AreEqual("RGB", IColorFormat.RGB.Name); + Assert.AreEqual("RGB", ColorRGB.ColorFormat.Name); + } + + [TestMethod] + public void ColorFormatBGRName() + { + Assert.AreEqual("BGR", IColorFormat.BGR.Name); + Assert.AreEqual("BGR", ColorBGR.ColorFormat.Name); + } + + [TestMethod] + public void ColorFormatRGBAName() + { + Assert.AreEqual("RGBA", IColorFormat.RGBA.Name); + Assert.AreEqual("RGBA", ColorRGBA.ColorFormat.Name); + } + + [TestMethod] + public void ColorFormatBGRAName() + { + Assert.AreEqual("BGRA", IColorFormat.BGRA.Name); + Assert.AreEqual("BGRA", ColorBGRA.ColorFormat.Name); + } + + [TestMethod] + public void ColorFormatARGBName() + { + Assert.AreEqual("ARGB", IColorFormat.ARGB.Name); + Assert.AreEqual("ARGB", ColorARGB.ColorFormat.Name); + } + + [TestMethod] + public void ColorFormatABGRName() + { + Assert.AreEqual("ABGR", IColorFormat.ABGR.Name); + Assert.AreEqual("ABGR", ColorABGR.ColorFormat.Name); + } + + + [TestMethod] + public void ColorFormatRGBBPP() + { + Assert.AreEqual(3, IColorFormat.RGB.BytesPerPixel); + Assert.AreEqual(3, ColorRGB.ColorFormat.BytesPerPixel); + } + + [TestMethod] + public void ColorFormatBGRBPP() + { + Assert.AreEqual(3, IColorFormat.BGR.BytesPerPixel); + Assert.AreEqual(3, ColorBGR.ColorFormat.BytesPerPixel); + } + + [TestMethod] + public void ColorFormatRGBABPP() + { + Assert.AreEqual(4, IColorFormat.RGBA.BytesPerPixel); + Assert.AreEqual(4, ColorRGBA.ColorFormat.BytesPerPixel); + } + + [TestMethod] + public void ColorFormatBGRABPP() + { + Assert.AreEqual(4, IColorFormat.BGRA.BytesPerPixel); + Assert.AreEqual(4, ColorBGRA.ColorFormat.BytesPerPixel); + } + + [TestMethod] + public void ColorFormatARGBBPP() + { + Assert.AreEqual(4, IColorFormat.ARGB.BytesPerPixel); + Assert.AreEqual(4, ColorARGB.ColorFormat.BytesPerPixel); + } + + [TestMethod] + public void ColorFormatABGRBPP() + { + Assert.AreEqual(4, IColorFormat.ABGR.BytesPerPixel); + Assert.AreEqual(4, ColorABGR.ColorFormat.BytesPerPixel); + } +} \ No newline at end of file diff --git a/HPPH.Test/Colors/ColorTests.cs b/HPPH.Test/Colors/ColorTests.cs new file mode 100644 index 0000000..f07dbac --- /dev/null +++ b/HPPH.Test/Colors/ColorTests.cs @@ -0,0 +1,183 @@ +using System.Runtime.InteropServices; + +namespace HPPH.Test.Colors; + +[TestClass] +public class ColorTests +{ + [TestMethod] + public void ColorRGBLayout() + { + Span data = [1, 2, 3, 4]; + ColorRGB color = MemoryMarshal.Cast(data)[0]; + + Assert.AreEqual(data[0], color.R); + Assert.AreEqual(data[1], color.G); + Assert.AreEqual(data[2], color.B); + Assert.AreEqual(byte.MaxValue, color.A); + } + + [TestMethod] + public void ColorBGRLayout() + { + Span data = [1, 2, 3, 4]; + ColorBGR color = MemoryMarshal.Cast(data)[0]; + + Assert.AreEqual(data[0], color.B); + Assert.AreEqual(data[1], color.G); + Assert.AreEqual(data[2], color.R); + Assert.AreEqual(byte.MaxValue, color.A); + } + + [TestMethod] + public void ColorRGBALayout() + { + Span data = [1, 2, 3, 4]; + ColorRGBA color = MemoryMarshal.Cast(data)[0]; + + Assert.AreEqual(data[0], color.R); + Assert.AreEqual(data[1], color.G); + Assert.AreEqual(data[2], color.B); + Assert.AreEqual(data[3], color.A); + } + + [TestMethod] + public void ColorBGRALayout() + { + Span data = [1, 2, 3, 4]; + ColorBGRA color = MemoryMarshal.Cast(data)[0]; + + Assert.AreEqual(data[0], color.B); + Assert.AreEqual(data[1], color.G); + Assert.AreEqual(data[2], color.R); + Assert.AreEqual(data[3], color.A); + } + + [TestMethod] + public void ColorARGBLayout() + { + Span data = [1, 2, 3, 4]; + ColorARGB color = MemoryMarshal.Cast(data)[0]; + + Assert.AreEqual(data[0], color.A); + Assert.AreEqual(data[1], color.R); + Assert.AreEqual(data[2], color.G); + Assert.AreEqual(data[3], color.B); + } + + [TestMethod] + public void ColorABGRLayout() + { + Span data = [1, 2, 3, 4]; + ColorABGR color = MemoryMarshal.Cast(data)[0]; + + Assert.AreEqual(data[0], color.A); + Assert.AreEqual(data[1], color.B); + Assert.AreEqual(data[2], color.G); + Assert.AreEqual(data[3], color.R); + } + + + [TestMethod] + public void ColorRGBCreate() + { + IColor color = ColorRGB.Create(1, 2, 3, 4); + + Assert.AreEqual(1, color.R); + Assert.AreEqual(2, color.G); + Assert.AreEqual(3, color.B); + Assert.AreEqual(byte.MaxValue, color.A); + } + + [TestMethod] + public void ColorBGRCreate() + { + IColor color = ColorBGR.Create(1, 2, 3, 4); + + Assert.AreEqual(1, color.R); + Assert.AreEqual(2, color.G); + Assert.AreEqual(3, color.B); + Assert.AreEqual(byte.MaxValue, color.A); + } + + [TestMethod] + public void ColorRGBACreate() + { + IColor color = ColorRGBA.Create(1, 2, 3, 4); + + Assert.AreEqual(1, color.R); + Assert.AreEqual(2, color.G); + Assert.AreEqual(3, color.B); + Assert.AreEqual(4, color.A); + } + + [TestMethod] + public void ColorBGRACreate() + { + IColor color = ColorBGRA.Create(1, 2, 3, 4); + + Assert.AreEqual(1, color.R); + Assert.AreEqual(2, color.G); + Assert.AreEqual(3, color.B); + Assert.AreEqual(4, color.A); + } + + [TestMethod] + public void ColorARGBCreate() + { + IColor color = ColorARGB.Create(1, 2, 3, 4); + + Assert.AreEqual(1, color.R); + Assert.AreEqual(2, color.G); + Assert.AreEqual(3, color.B); + Assert.AreEqual(4, color.A); + } + + [TestMethod] + public void ColorABGRCreate() + { + IColor color = ColorABGR.Create(1, 2, 3, 4); + + Assert.AreEqual(1, color.R); + Assert.AreEqual(2, color.G); + Assert.AreEqual(3, color.B); + Assert.AreEqual(4, color.A); + } + + + [TestMethod] + public void ColorRGBToString() + { + Assert.AreEqual("[A: 255, R: 1, G: 2, B: 3]", new ColorRGB(1, 2, 3).ToString()); + } + + [TestMethod] + public void ColorBGRToString() + { + Assert.AreEqual("[A: 255, R: 1, G: 2, B: 3]", new ColorBGR(3, 2, 1).ToString()); + } + + [TestMethod] + public void ColorRGBAToString() + { + Assert.AreEqual("[A: 4, R: 1, G: 2, B: 3]", new ColorRGBA(1, 2, 3, 4).ToString()); + } + + [TestMethod] + public void ColorBGRAToString() + { + Assert.AreEqual("[A: 4, R: 1, G: 2, B: 3]", new ColorBGRA(3, 2, 1, 4).ToString()); + } + + [TestMethod] + public void ColorARGBToString() + { + Assert.AreEqual("[A: 4, R: 1, G: 2, B: 3]", new ColorARGB(4, 1, 2, 3).ToString()); + } + + [TestMethod] + public void ColorABGRToString() + { + Assert.AreEqual("[A: 4, R: 1, G: 2, B: 3]", new ColorABGR(4, 3, 2, 1).ToString()); + } +} \ No newline at end of file diff --git a/HPPH.Test/Colors/MinMaxStructTests.cs b/HPPH.Test/Colors/MinMaxStructTests.cs new file mode 100644 index 0000000..81cdfe3 --- /dev/null +++ b/HPPH.Test/Colors/MinMaxStructTests.cs @@ -0,0 +1,176 @@ +using System.Runtime.InteropServices; + +namespace HPPH.Test.Colors; + +[TestClass] +public class MinMaxStructTests +{ + [TestMethod] + public void MinMaxRGBCreate() + { + IMinMax color = new MinMaxRGB(1, 3, 4, 7, 16, 31); + + Assert.AreEqual(1, color.RedMin); + Assert.AreEqual(3, color.RedMax); + Assert.AreEqual(2, color.RedRange); + + Assert.AreEqual(4, color.GreenMin); + Assert.AreEqual(7, color.GreenMax); + Assert.AreEqual(3, color.GreenRange); + + Assert.AreEqual(16, color.BlueMin); + Assert.AreEqual(31, color.BlueMax); + Assert.AreEqual(15, color.BlueRange); + + Assert.AreEqual(byte.MaxValue, color.AlphaMin); + Assert.AreEqual(byte.MaxValue, color.AlphaMax); + Assert.AreEqual(0, color.AlphaRange); + } + + [TestMethod] + public void MinMaxBGRCreate() + { + IMinMax color = new MinMaxBGR(1, 3, 4, 7, 16, 31); + + Assert.AreEqual(1, color.BlueMin); + Assert.AreEqual(3, color.BlueMax); + Assert.AreEqual(2, color.BlueRange); + + Assert.AreEqual(4, color.GreenMin); + Assert.AreEqual(7, color.GreenMax); + Assert.AreEqual(3, color.GreenRange); + + Assert.AreEqual(16, color.RedMin); + Assert.AreEqual(31, color.RedMax); + Assert.AreEqual(15, color.RedRange); + + Assert.AreEqual(byte.MaxValue, color.AlphaMin); + Assert.AreEqual(byte.MaxValue, color.AlphaMax); + Assert.AreEqual(0, color.AlphaRange); + } + + [TestMethod] + public void MinMaxRGBACreate() + { + IMinMax color = new MinMaxRGBA(1, 3, 4, 7, 16, 31, 64, 127); + + Assert.AreEqual(1, color.RedMin); + Assert.AreEqual(3, color.RedMax); + Assert.AreEqual(2, color.RedRange); + + Assert.AreEqual(4, color.GreenMin); + Assert.AreEqual(7, color.GreenMax); + Assert.AreEqual(3, color.GreenRange); + + Assert.AreEqual(16, color.BlueMin); + Assert.AreEqual(31, color.BlueMax); + Assert.AreEqual(15, color.BlueRange); + + Assert.AreEqual(64, color.AlphaMin); + Assert.AreEqual(127, color.AlphaMax); + Assert.AreEqual(63, color.AlphaRange); + } + + [TestMethod] + public void MinMaxBGRACreate() + { + IMinMax color = new MinMaxBGRA(1, 3, 4, 7, 16, 31, 64, 127); + + Assert.AreEqual(1, color.BlueMin); + Assert.AreEqual(3, color.BlueMax); + Assert.AreEqual(2, color.BlueRange); + + Assert.AreEqual(4, color.GreenMin); + Assert.AreEqual(7, color.GreenMax); + Assert.AreEqual(3, color.GreenRange); + + Assert.AreEqual(16, color.RedMin); + Assert.AreEqual(31, color.RedMax); + Assert.AreEqual(15, color.RedRange); + + Assert.AreEqual(64, color.AlphaMin); + Assert.AreEqual(127, color.AlphaMax); + Assert.AreEqual(63, color.AlphaRange); + } + + [TestMethod] + public void MinMaxARGBCreate() + { + IMinMax color = new MinMaxARGB(1, 3, 4, 7, 16, 31, 64, 127); + + Assert.AreEqual(1, color.AlphaMin); + Assert.AreEqual(3, color.AlphaMax); + Assert.AreEqual(2, color.AlphaRange); + + Assert.AreEqual(4, color.RedMin); + Assert.AreEqual(7, color.RedMax); + Assert.AreEqual(3, color.RedRange); + + Assert.AreEqual(16, color.GreenMin); + Assert.AreEqual(31, color.GreenMax); + Assert.AreEqual(15, color.GreenRange); + + Assert.AreEqual(64, color.BlueMin); + Assert.AreEqual(127, color.BlueMax); + Assert.AreEqual(63, color.BlueRange); + } + + [TestMethod] + public void MinMaxABGRCreate() + { + IMinMax color = new MinMaxABGR(1, 3, 4, 7, 16, 31, 64, 127); + + Assert.AreEqual(1, color.AlphaMin); + Assert.AreEqual(3, color.AlphaMax); + Assert.AreEqual(2, color.AlphaRange); + + Assert.AreEqual(4, color.BlueMin); + Assert.AreEqual(7, color.BlueMax); + Assert.AreEqual(3, color.BlueRange); + + Assert.AreEqual(16, color.GreenMin); + Assert.AreEqual(31, color.GreenMax); + Assert.AreEqual(15, color.GreenRange); + + Assert.AreEqual(64, color.RedMin); + Assert.AreEqual(127, color.RedMax); + Assert.AreEqual(63, color.RedRange); + } + + + [TestMethod] + public void MinMaxRGBToString() + { + Assert.AreEqual("[A: 255-255, R: 1-3, G: 4-7, B: 16-31]", new MinMaxRGB(1, 3, 4, 7, 16, 31).ToString()); + } + + [TestMethod] + public void MinMaxBGRToString() + { + Assert.AreEqual("[A: 255-255, R: 16-31, G: 4-7, B: 1-3]", new MinMaxBGR(1, 3, 4, 7, 16, 31).ToString()); + } + + [TestMethod] + public void MinMaxRGBAToString() + { + Assert.AreEqual("[A: 64-127, R: 1-3, G: 4-7, B: 16-31]", new MinMaxRGBA(1, 3, 4, 7, 16, 31, 64, 127).ToString()); + } + + [TestMethod] + public void MinMaxBGRAToString() + { + Assert.AreEqual("[A: 64-127, R: 16-31, G: 4-7, B: 1-3]", new MinMaxBGRA(1, 3, 4, 7, 16, 31, 64, 127).ToString()); + } + + [TestMethod] + public void MinMaxARGBToString() + { + Assert.AreEqual("[A: 1-3, R: 4-7, G: 16-31, B: 64-127]", new MinMaxARGB(1, 3, 4, 7, 16, 31, 64, 127).ToString()); + } + + [TestMethod] + public void MinMaxABGRToString() + { + Assert.AreEqual("[A: 1-3, R: 64-127, G: 16-31, B: 4-7]", new MinMaxABGR(1, 3, 4, 7, 16, 31, 64, 127).ToString()); + } +} \ No newline at end of file diff --git a/HPPH.Test/Colors/SumStructTests.cs b/HPPH.Test/Colors/SumStructTests.cs new file mode 100644 index 0000000..b7bdaa5 --- /dev/null +++ b/HPPH.Test/Colors/SumStructTests.cs @@ -0,0 +1,183 @@ +using System.Runtime.InteropServices; + +namespace HPPH.Test.Colors; + +[TestClass] +public class SumStructTests +{ + [TestMethod] + public void SumRGBLayout() + { + Span data = [1, 2, 3, 4]; + SumRGB color = MemoryMarshal.Cast(data)[0]; + + Assert.AreEqual(data[0], color.R); + Assert.AreEqual(data[1], color.G); + Assert.AreEqual(data[2], color.B); + Assert.AreEqual(data[3], color.A); + } + + [TestMethod] + public void SumBGRLayout() + { + Span data = [1, 2, 3, 4]; + SumBGR color = MemoryMarshal.Cast(data)[0]; + + Assert.AreEqual(data[0], color.B); + Assert.AreEqual(data[1], color.G); + Assert.AreEqual(data[2], color.R); + Assert.AreEqual(data[3], color.A); + } + + [TestMethod] + public void SumRGBALayout() + { + Span data = [1, 2, 3, 4]; + SumRGBA color = MemoryMarshal.Cast(data)[0]; + + Assert.AreEqual(data[0], color.R); + Assert.AreEqual(data[1], color.G); + Assert.AreEqual(data[2], color.B); + Assert.AreEqual(data[3], color.A); + } + + [TestMethod] + public void SumBGRALayout() + { + Span data = [1, 2, 3, 4]; + SumBGRA color = MemoryMarshal.Cast(data)[0]; + + Assert.AreEqual(data[0], color.B); + Assert.AreEqual(data[1], color.G); + Assert.AreEqual(data[2], color.R); + Assert.AreEqual(data[3], color.A); + } + + [TestMethod] + public void SumARGBLayout() + { + Span data = [1, 2, 3, 4]; + SumARGB color = MemoryMarshal.Cast(data)[0]; + + Assert.AreEqual(data[0], color.A); + Assert.AreEqual(data[1], color.R); + Assert.AreEqual(data[2], color.G); + Assert.AreEqual(data[3], color.B); + } + + [TestMethod] + public void SumABGRLayout() + { + Span data = [1, 2, 3, 4]; + SumABGR color = MemoryMarshal.Cast(data)[0]; + + Assert.AreEqual(data[0], color.A); + Assert.AreEqual(data[1], color.B); + Assert.AreEqual(data[2], color.G); + Assert.AreEqual(data[3], color.R); + } + + + [TestMethod] + public void SumRGBCreate() + { + ISum color = new SumRGB(1, 2, 3, 4); + + Assert.AreEqual(1, color.R); + Assert.AreEqual(2, color.G); + Assert.AreEqual(3, color.B); + Assert.AreEqual(4, color.A); + } + + [TestMethod] + public void SumBGRCreate() + { + ISum color = new SumBGR(3, 2, 1, 4); + + Assert.AreEqual(1, color.R); + Assert.AreEqual(2, color.G); + Assert.AreEqual(3, color.B); + Assert.AreEqual(4, color.A); + } + + [TestMethod] + public void SumRGBACreate() + { + ISum color = new SumRGBA(1, 2, 3, 4); + + Assert.AreEqual(1, color.R); + Assert.AreEqual(2, color.G); + Assert.AreEqual(3, color.B); + Assert.AreEqual(4, color.A); + } + + [TestMethod] + public void SumBGRACreate() + { + ISum color = new SumBGRA(3, 2, 1, 4); + + Assert.AreEqual(1, color.R); + Assert.AreEqual(2, color.G); + Assert.AreEqual(3, color.B); + Assert.AreEqual(4, color.A); + } + + [TestMethod] + public void SumARGBCreate() + { + ISum color = new SumARGB(4, 1, 2, 3); + + Assert.AreEqual(1, color.R); + Assert.AreEqual(2, color.G); + Assert.AreEqual(3, color.B); + Assert.AreEqual(4, color.A); + } + + [TestMethod] + public void SumABGRCreate() + { + ISum color = new SumABGR(4, 3, 2, 1); + + Assert.AreEqual(1, color.R); + Assert.AreEqual(2, color.G); + Assert.AreEqual(3, color.B); + Assert.AreEqual(4, color.A); + } + + + [TestMethod] + public void SumRGBToString() + { + Assert.AreEqual("[A: 4, R: 1, G: 2, B: 3]", new SumRGB(1, 2, 3, 4).ToString()); + } + + [TestMethod] + public void SumBGRToString() + { + Assert.AreEqual("[A: 4, R: 1, G: 2, B: 3]", new SumBGR(3, 2, 1, 4).ToString()); + } + + [TestMethod] + public void SumRGBAToString() + { + Assert.AreEqual("[A: 4, R: 1, G: 2, B: 3]", new SumRGBA(1, 2, 3, 4).ToString()); + } + + [TestMethod] + public void SumBGRAToString() + { + Assert.AreEqual("[A: 4, R: 1, G: 2, B: 3]", new SumBGRA(3, 2, 1, 4).ToString()); + } + + [TestMethod] + public void SumARGBToString() + { + Assert.AreEqual("[A: 4, R: 1, G: 2, B: 3]", new SumARGB(4, 1, 2, 3).ToString()); + } + + [TestMethod] + public void SumABGRToString() + { + Assert.AreEqual("[A: 4, R: 1, G: 2, B: 3]", new SumABGR(4, 3, 2, 1).ToString()); + } +} \ No newline at end of file diff --git a/HPPH.Test/HPPH.Test.csproj b/HPPH.Test/HPPH.Test.csproj index 9ff21f8..ea0f934 100644 --- a/HPPH.Test/HPPH.Test.csproj +++ b/HPPH.Test/HPPH.Test.csproj @@ -7,6 +7,7 @@ false true + true diff --git a/HPPH.Test/Image/ImageTest.cs b/HPPH.Test/Image/ImageTest.cs index c0ad725..59d7ac9 100644 --- a/HPPH.Test/Image/ImageTest.cs +++ b/HPPH.Test/Image/ImageTest.cs @@ -1,3 +1,5 @@ +using System.Collections; + namespace HPPH.Test.Image; [TestClass] @@ -204,5 +206,308 @@ public class ImageTest } } + [TestMethod] + public void ToArray() + { + Image image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); + ColorARGB[] testData = image.ToArray(); + + for (int y = 0; y < TEST_HEIGHT; y++) + for (int x = 0; x < TEST_WIDTH; x++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), testData[(y * TEST_WIDTH) + x]); + } + + [TestMethod] + public void CopyTo() + { + Image image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); + ColorARGB[] testData = new ColorARGB[TEST_WIDTH * TEST_HEIGHT]; + image.CopyTo(testData); + + for (int y = 0; y < TEST_HEIGHT; y++) + for (int x = 0; x < TEST_WIDTH; x++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), testData[(y * TEST_WIDTH) + x]); + } + + [TestMethod] + public void SubImage() + { + Image image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); + RefImage subImage = image[10, 20, 100, 200]; + + for (int y = 0; y < 200; y++) + for (int x = 0; x < 100; x++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(10 + x, 20 + y), subImage[x, y]); + } + + [TestMethod] + public void GenericRowsIterate() + { + Image image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); + + int y = 0; + foreach (ImageRow row in image.Rows) + { + int x = 0; + foreach (ColorARGB color in row) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x++, y), color); + + y++; + } + } + + [TestMethod] + public void GenericRowsCopyTo() + { + + Image image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); + + int y = 0; + foreach (ImageRow row in image.Rows) + { + ColorARGB[] colors = new ColorARGB[TEST_WIDTH]; + byte[] bytes = new byte[TEST_WIDTH * 4]; + row.CopyTo(colors); + row.CopyTo(bytes); + + int x = 0; + foreach (ColorARGB color in colors) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x++, y), color); + + for (x = 0; x < TEST_WIDTH; x++) + { + ColorARGB reference = TestDataHelper.GetColorFromLocation(x, y); + + Assert.AreEqual(reference.A, bytes[(x * 4) + 0]); + Assert.AreEqual(reference.R, bytes[(x * 4) + 1]); + Assert.AreEqual(reference.G, bytes[(x * 4) + 2]); + Assert.AreEqual(reference.B, bytes[(x * 4) + 3]); + } + + y++; + } + } + + [TestMethod] + public void GenericRowsToArray() + { + Image image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); + + int y = 0; + foreach (ImageRow row in image.Rows) + { + ColorARGB[] data = row.ToArray(); + + for (int x = 0; x < TEST_WIDTH; x++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), data[x]); + + y++; + } + } + + [TestMethod] + public void GenericColumnsIterate() + { + Image image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); + + int x = 0; + foreach (ImageColumn column in image.Columns) + { + int y = 0; + foreach (ColorARGB color in column) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y++), color); + + x++; + } + } + + [TestMethod] + public void GenericColumnsCopyTo() + { + Image image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); + + int x = 0; + foreach (ImageColumn column in image.Columns) + { + ColorARGB[] colors = new ColorARGB[TEST_HEIGHT]; + byte[] bytes = new byte[TEST_HEIGHT * 4]; + column.CopyTo(colors); + column.CopyTo(bytes); + + int y = 0; + foreach (ColorARGB color in colors) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y++), color); + + for (y = 0; y < TEST_HEIGHT; y++) + { + ColorARGB reference = TestDataHelper.GetColorFromLocation(x, y); + + Assert.AreEqual(reference.A, bytes[(y * 4) + 0]); + Assert.AreEqual(reference.R, bytes[(y * 4) + 1]); + Assert.AreEqual(reference.G, bytes[(y * 4) + 2]); + Assert.AreEqual(reference.B, bytes[(y * 4) + 3]); + } + + x++; + } + } + + [TestMethod] + public void GenericColumnsToArray() + { + Image image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); + + int x = 0; + foreach (ImageColumn column in image.Columns) + { + ColorARGB[] data = column.ToArray(); + + for (int y = 0; y < TEST_HEIGHT; y++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), data[y]); + + x++; + } + } + + [TestMethod] + public void GenericEnumerate() + { + Image image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); + ColorARGB[] reference = TestDataHelper.GetPixelData(TEST_WIDTH, TEST_HEIGHT); + + int i = 0; + foreach (ColorARGB color in image) + Assert.AreEqual(reference[i++], color); + + IEnumerable enumerable = image; + i = 0; + foreach (ColorARGB color in enumerable) + Assert.AreEqual(reference[i++], color); + } + + [TestMethod] + public unsafe void Pin() + { + Image image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); + ColorARGB[] reference = TestDataHelper.GetPixelData(TEST_WIDTH, TEST_HEIGHT); + + fixed (byte* ptr = image) + { + for (int i = 0; i < reference.Length; i++) + { + Assert.AreEqual(reference[i].A, ptr[(i * 4) + 0]); + Assert.AreEqual(reference[i].R, ptr[(i * 4) + 1]); + Assert.AreEqual(reference[i].G, ptr[(i * 4) + 2]); + Assert.AreEqual(reference[i].B, ptr[(i * 4) + 3]); + } + } + } + + [TestMethod] + public void InterfaceRowsIterate() + { + IImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); + + int y = 0; + foreach (IImageRow row in image.Rows) + { + int x = 0; + foreach (IColor color in row) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x++, y), color); + + y++; + } + } + + [TestMethod] + public void InterfaceColumnsIterate() + { + IImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); + + int x = 0; + foreach (IImageColumn column in image.Columns) + { + int y = 0; + foreach (IColor color in column) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y++), color); + + x++; + } + + x = 0; + foreach (IImageColumn column in (IEnumerable)image.Columns) + { + int y = 0; + foreach (IColor color in (IEnumerable)column) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y++), color); + + x++; + } + } + + [TestMethod] + public void InterfaceEnumerate() + { + IImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); + ColorARGB[] reference = TestDataHelper.GetPixelData(TEST_WIDTH, TEST_HEIGHT); + + int i = 0; + foreach (IColor color in image) + Assert.AreEqual(reference[i++], color); + + IEnumerable enumerable = image; + i = 0; + foreach (IColor color in enumerable) + Assert.AreEqual(reference[i++], color); + } + + [TestMethod] + public void InterfaceColumnsCopyTo() + { + IImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); + + int x = 0; + foreach (IImageColumn column in image.Columns) + { + IColor[] colors = new IColor[TEST_HEIGHT]; + byte[] bytes = new byte[TEST_HEIGHT * 4]; + column.CopyTo(colors); + column.CopyTo(bytes); + + int y = 0; + foreach (IColor color in colors) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y++), color); + + for (y = 0; y < TEST_HEIGHT; y++) + { + IColor reference = TestDataHelper.GetColorFromLocation(x, y); + + Assert.AreEqual(reference.A, bytes[(y * 4) + 0]); + Assert.AreEqual(reference.R, bytes[(y * 4) + 1]); + Assert.AreEqual(reference.G, bytes[(y * 4) + 2]); + Assert.AreEqual(reference.B, bytes[(y * 4) + 3]); + } + + x++; + } + } + + [TestMethod] + public void InterfaceColumnsToArray() + { + IImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); + + int x = 0; + foreach (IImageColumn column in image.Columns) + { + IColor[] data = column.ToArray(); + + for (int y = 0; y < TEST_HEIGHT; y++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), data[y]); + + x++; + } + } + #endregion } \ No newline at end of file diff --git a/HPPH.Test/ImageHelper.cs b/HPPH.Test/ImageHelper.cs index f779dd7..663d7d2 100644 --- a/HPPH.Test/ImageHelper.cs +++ b/HPPH.Test/ImageHelper.cs @@ -6,35 +6,43 @@ internal static class ImageHelper { #region Methods - public static ColorRGB[] Get3ByteColorsFromImage(string file) + public static T[] GetColorsFromImage(string file) + where T : struct, IColor { using FileStream stream = File.OpenRead(file); using Bitmap bmp = new(stream); - ColorRGB[] colors = new ColorRGB[bmp.Width * bmp.Height]; - int i = 0; - for (int x = 0; x < bmp.Width; x++) - for (int y = 0; y < bmp.Height; y++) - { - Color color = bmp.GetPixel(x, y); - colors[i++] = new ColorRGB(color.R, color.G, color.B); - } - - return colors; + return GetColors(bmp); } - public static ColorRGBA[] Get4ByteColorsFromImage(string file) + public static Image GetImage(string file) + where T : struct, IColor { using FileStream stream = File.OpenRead(file); using Bitmap bmp = new(stream); - ColorRGBA[] colors = new ColorRGBA[bmp.Width * bmp.Height]; + T[] colors = new T[bmp.Width * bmp.Height]; int i = 0; for (int x = 0; x < bmp.Width; x++) for (int y = 0; y < bmp.Height; y++) { Color color = bmp.GetPixel(x, y); - colors[i++] = new ColorRGBA(color.R, color.G, color.B, color.A); + colors[i++] = (T)T.Create(color.R, color.G, color.B, color.A); + } + + return Image.Create(GetColors(bmp), bmp.Width, bmp.Height); + } + + private static T[] GetColors(Bitmap bmp) + where T : struct, IColor + { + T[] colors = new T[bmp.Width * bmp.Height]; + int i = 0; + for (int x = 0; x < bmp.Width; x++) + for (int y = 0; y < bmp.Height; y++) + { + Color color = bmp.GetPixel(x, y); + colors[i++] = (T)T.Create(color.R, color.G, color.B, color.A); } return colors; diff --git a/HPPH.Test/PixelHelper/AverageTests.cs b/HPPH.Test/PixelHelper/AverageTests.cs index ab09d85..d732dfd 100644 --- a/HPPH.Test/PixelHelper/AverageTests.cs +++ b/HPPH.Test/PixelHelper/AverageTests.cs @@ -8,58 +8,144 @@ public class AverageTests private static IEnumerable GetTestImages() => Directory.EnumerateFiles(@"..\..\..\..\sample_data", "*.png", SearchOption.AllDirectories); [TestMethod] - public void AverageImage3Byte() - { - } - - [TestMethod] - public void AverageRefImage3Byte() - { - } - - [TestMethod] - public void AverageReadOnlySpan3Byte() + public void AverageRefImage() { foreach (string image in GetTestImages()) { - ColorRGB[] data = ImageHelper.Get3ByteColorsFromImage(image); - ReadOnlySpan span = data; - - ColorRGB reference = ReferencePixelHelper.Average(span); - ColorRGB test = span.Average(); - - Assert.AreEqual(reference.R, test.R, "R differs"); - Assert.AreEqual(reference.G, test.G, "G differs"); - Assert.AreEqual(reference.B, test.B, "B differs"); - Assert.AreEqual(reference.A, test.A, "A differs"); + AverageRefImage(image); + AverageRefImage(image); + AverageRefImage(image); + AverageRefImage(image); + AverageRefImage(image); + AverageRefImage(image); } } - [TestMethod] - public void AverageImage4Byte() + private static void AverageRefImage(string image) + where T : struct, IColor { + RefImage data = ImageHelper.GetImage(image).AsRefImage(); + + T reference = ReferencePixelHelper.Average(data); + T test = data.Average(); + + Assert.AreEqual(reference.R, test.R, $"R differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.G, test.G, $"G differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.B, test.B, $"B differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.A, test.A, $"A differs in type '{T.ColorFormat.Name}'"); } [TestMethod] - public void AverageRefImage4Byte() - { - } - - [TestMethod] - public void AverageReadOnlySpan4Byte() + public void AverageGenericImage() { foreach (string image in GetTestImages()) { - ColorRGBA[] data = ImageHelper.Get4ByteColorsFromImage(image); - ReadOnlySpan span = data; - - ColorRGBA reference = ReferencePixelHelper.Average(span); - ColorRGBA test = span.Average(); - - Assert.AreEqual(reference.R, test.R, "R differs"); - Assert.AreEqual(reference.G, test.G, "G differs"); - Assert.AreEqual(reference.B, test.B, "B differs"); - Assert.AreEqual(reference.A, test.A, "A differs"); + AverageGenericImage(image); + AverageGenericImage(image); + AverageGenericImage(image); + AverageGenericImage(image); + AverageGenericImage(image); + AverageGenericImage(image); } } + + private static void AverageGenericImage(string image) + where T : struct, IColor + { + Image data = ImageHelper.GetImage(image); + + IColor reference = ReferencePixelHelper.Average(data); + T test = data.Average(); + + Assert.AreEqual(reference.R, test.R, $"R differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.G, test.G, $"G differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.B, test.B, $"B differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.A, test.A, $"A differs in type '{T.ColorFormat.Name}'"); + } + + [TestMethod] + public void AverageImage() + { + foreach (string image in GetTestImages()) + { + AverageImage(image); + AverageImage(image); + AverageImage(image); + AverageImage(image); + AverageImage(image); + AverageImage(image); + } + } + + private static void AverageImage(string image) + where T : struct, IColor + { + IImage data = ImageHelper.GetImage(image); + + IColor reference = ReferencePixelHelper.Average(data); + IColor test = data.Average(); + + Assert.AreEqual(reference.R, test.R, $"R differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.G, test.G, $"G differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.B, test.B, $"B differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.A, test.A, $"A differs in type '{T.ColorFormat.Name}'"); + } + + [TestMethod] + public void AverageSpan() + { + foreach (string image in GetTestImages()) + { + AverageSpan(image); + AverageSpan(image); + AverageSpan(image); + AverageSpan(image); + AverageSpan(image); + AverageSpan(image); + } + } + + private static void AverageSpan(string image) + where T : struct, IColor + { + T[] data = ImageHelper.GetColorsFromImage(image); + Span span = data; + + T reference = ReferencePixelHelper.Average(span); + T test = span.Average(); + + Assert.AreEqual(reference.R, test.R, $"R differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.G, test.G, $"G differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.B, test.B, $"B differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.A, test.A, $"A differs in type '{T.ColorFormat.Name}'"); + } + + [TestMethod] + public void AverageReadOnlySpan() + { + foreach (string image in GetTestImages()) + { + AverageReadOnlySpan(image); + AverageReadOnlySpan(image); + AverageReadOnlySpan(image); + AverageReadOnlySpan(image); + AverageReadOnlySpan(image); + AverageReadOnlySpan(image); + } + } + + private static void AverageReadOnlySpan(string image) + where T : struct, IColor + { + T[] data = ImageHelper.GetColorsFromImage(image); + ReadOnlySpan span = data; + + T reference = ReferencePixelHelper.Average(span); + T test = span.Average(); + + Assert.AreEqual(reference.R, test.R, $"R differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.G, test.G, $"G differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.B, test.B, $"B differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.A, test.A, $"A differs in type '{T.ColorFormat.Name}'"); + } } \ No newline at end of file diff --git a/HPPH.Test/PixelHelper/ConvertTests.cs b/HPPH.Test/PixelHelper/ConvertTests.cs index 3180114..3a31004 100644 --- a/HPPH.Test/PixelHelper/ConvertTests.cs +++ b/HPPH.Test/PixelHelper/ConvertTests.cs @@ -12,7 +12,7 @@ public class ConvertTests { for (int skip = 0; skip < 4; skip++) { - ColorRGB[] data = ImageHelper.Get3ByteColorsFromImage(image).SkipLast(skip).ToArray(); + ColorRGB[] data = ImageHelper.GetColorsFromImage(image).SkipLast(skip).ToArray(); ReadOnlySpan referenceData = data; Span sourceData = new ColorRGB[referenceData.Length]; @@ -42,7 +42,7 @@ public class ConvertTests { for (int skip = 0; skip < 4; skip++) { - ColorRGBA[] data = ImageHelper.Get4ByteColorsFromImage(image).SkipLast(skip).ToArray(); + ColorRGBA[] data = ImageHelper.GetColorsFromImage(image).SkipLast(skip).ToArray(); ReadOnlySpan referenceData = data; Span sourceData = new ColorRGBA[referenceData.Length]; @@ -72,7 +72,7 @@ public class ConvertTests { for (int skip = 0; skip < 4; skip++) { - ColorRGBA[] data = ImageHelper.Get4ByteColorsFromImage(image).SkipLast(skip).ToArray(); + ColorRGBA[] data = ImageHelper.GetColorsFromImage(image).SkipLast(skip).ToArray(); ReadOnlySpan referenceData = data; Span sourceData = new ColorRGBA[referenceData.Length]; @@ -102,7 +102,7 @@ public class ConvertTests { for (int skip = 0; skip < 4; skip++) { - ColorRGBA[] data = ImageHelper.Get4ByteColorsFromImage(image).SkipLast(skip).ToArray(); + ColorRGBA[] data = ImageHelper.GetColorsFromImage(image).SkipLast(skip).ToArray(); ReadOnlySpan referenceData = data; Span sourceData = new ColorRGBA[referenceData.Length]; @@ -132,7 +132,7 @@ public class ConvertTests { for (int skip = 0; skip < 4; skip++) { - ColorRGBA[] data = ImageHelper.Get4ByteColorsFromImage(image).SkipLast(skip).ToArray(); + ColorRGBA[] data = ImageHelper.GetColorsFromImage(image).SkipLast(skip).ToArray(); ReadOnlySpan referenceData = data; Span sourceData = new ColorRGBA[referenceData.Length]; @@ -162,7 +162,7 @@ public class ConvertTests { for (int skip = 0; skip < 4; skip++) { - ColorRGB[] data = ImageHelper.Get3ByteColorsFromImage(image).SkipLast(skip).ToArray(); + ColorRGB[] data = ImageHelper.GetColorsFromImage(image).SkipLast(skip).ToArray(); ReadOnlySpan referenceData = data; Span sourceData = new ColorRGB[referenceData.Length]; @@ -192,7 +192,7 @@ public class ConvertTests { for (int skip = 0; skip < 4; skip++) { - ColorRGB[] data = ImageHelper.Get3ByteColorsFromImage(image).SkipLast(skip).ToArray(); + ColorRGB[] data = ImageHelper.GetColorsFromImage(image).SkipLast(skip).ToArray(); ReadOnlySpan referenceData = data; Span sourceData = new ColorRGB[referenceData.Length]; @@ -222,7 +222,7 @@ public class ConvertTests { for (int skip = 0; skip < 4; skip++) { - ColorRGB[] data = ImageHelper.Get3ByteColorsFromImage(image).SkipLast(skip).ToArray(); + ColorRGB[] data = ImageHelper.GetColorsFromImage(image).SkipLast(skip).ToArray(); ReadOnlySpan referenceData = data; Span sourceData = new ColorRGB[referenceData.Length]; @@ -252,7 +252,7 @@ public class ConvertTests { for (int skip = 0; skip < 4; skip++) { - ColorRGB[] data = ImageHelper.Get3ByteColorsFromImage(image).SkipLast(skip).ToArray(); + ColorRGB[] data = ImageHelper.GetColorsFromImage(image).SkipLast(skip).ToArray(); ReadOnlySpan referenceData = data; Span sourceData = new ColorRGB[referenceData.Length]; diff --git a/HPPH.Test/PixelHelper/MinMaxTests.cs b/HPPH.Test/PixelHelper/MinMaxTests.cs index 2c4f877..eab7631 100644 --- a/HPPH.Test/PixelHelper/MinMaxTests.cs +++ b/HPPH.Test/PixelHelper/MinMaxTests.cs @@ -8,78 +8,194 @@ public class MinMaxTests private static IEnumerable GetTestImages() => Directory.EnumerateFiles(@"..\..\..\..\sample_data", "*.png", SearchOption.AllDirectories); [TestMethod] - public void MinMaxImage3Byte() - { - } - - [TestMethod] - public void MinMaxRefImage3Byte() - { - } - - [TestMethod] - public void MinMaxReadOnlySpan3Byte() + public void MinMaxRefImage() { foreach (string image in GetTestImages()) { - ColorRGB[] data = ImageHelper.Get3ByteColorsFromImage(image); - ReadOnlySpan span = data; - - IMinMax reference = ReferencePixelHelper.MinMax(span); - IMinMax test = span.MinMax(); - - Assert.AreEqual(reference.RedMin, test.RedMin, "RedMin differs"); - Assert.AreEqual(reference.GreenMin, test.GreenMin, "GreenMin differs"); - Assert.AreEqual(reference.BlueMin, test.BlueMin, "BlueMin differs"); - Assert.AreEqual(reference.AlphaMin, test.AlphaMin, "AlphaMin differs"); - - Assert.AreEqual(reference.RedMax, test.RedMax, "RedMax differs"); - Assert.AreEqual(reference.GreenMax, test.GreenMax, "GreenMax differs"); - Assert.AreEqual(reference.BlueMax, test.BlueMax, "BlueMax differs"); - Assert.AreEqual(reference.AlphaMax, test.AlphaMax, "AlphaMax differs"); - - Assert.AreEqual(reference.RedRange, test.RedRange, "RedRange differs"); - Assert.AreEqual(reference.GreenRange, test.GreenRange, "GreenRange differs"); - Assert.AreEqual(reference.BlueRange, test.BlueRange, "BlueRange differs"); - Assert.AreEqual(reference.AlphaRange, test.AlphaRange, "AlphaRange differs"); + MinMaxRefImage(image); + MinMaxRefImage(image); + MinMaxRefImage(image); + MinMaxRefImage(image); + MinMaxRefImage(image); + MinMaxRefImage(image); } } - [TestMethod] - public void MinMaxImage4Byte() + private static void MinMaxRefImage(string image) + where T : struct, IColor { + RefImage data = ImageHelper.GetImage(image).AsRefImage(); + + IMinMax reference = ReferencePixelHelper.MinMax(data); + IMinMax test = data.MinMax(); + + Assert.AreEqual(reference.RedMin, test.RedMin, $"RedMin differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.GreenMin, test.GreenMin, $"GreenMin differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.BlueMin, test.BlueMin, $"BlueMin differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.AlphaMin, test.AlphaMin, $"AlphaMin differs in type '{T.ColorFormat.Name}'"); + + Assert.AreEqual(reference.RedMax, test.RedMax, $"RedMax differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.GreenMax, test.GreenMax, $"GreenMax differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.BlueMax, test.BlueMax, $"BlueMax differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.AlphaMax, test.AlphaMax, $"AlphaMax differs in type '{T.ColorFormat.Name}'"); + + Assert.AreEqual(reference.RedRange, test.RedRange, $"RedRange differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.GreenRange, test.GreenRange, $"GreenRange differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.BlueRange, test.BlueRange, $"BlueRange differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.AlphaRange, test.AlphaRange, $"AlphaRange differs in type '{T.ColorFormat.Name}'"); } [TestMethod] - public void MinMaxRefImage4Byte() - { - } - - [TestMethod] - public void MinMaxReadOnlySpan4Byte() + public void MinMaxGenericImage() { foreach (string image in GetTestImages()) { - ColorRGBA[] data = ImageHelper.Get4ByteColorsFromImage(image); - ReadOnlySpan span = data; - - IMinMax reference = ReferencePixelHelper.MinMax(span); - IMinMax test = span.MinMax(); - - Assert.AreEqual(reference.RedMin, test.RedMin, "RedMin differs"); - Assert.AreEqual(reference.GreenMin, test.GreenMin, "GreenMin differs"); - Assert.AreEqual(reference.BlueMin, test.BlueMin, "BlueMin differs"); - Assert.AreEqual(reference.AlphaMin, test.AlphaMin, "AlphaMin differs"); - - Assert.AreEqual(reference.RedMax, test.RedMax, "RedMax differs"); - Assert.AreEqual(reference.GreenMax, test.GreenMax, "GreenMax differs"); - Assert.AreEqual(reference.BlueMax, test.BlueMax, "BlueMax differs"); - Assert.AreEqual(reference.AlphaMax, test.AlphaMax, "AlphaMax differs"); - - Assert.AreEqual(reference.RedRange, test.RedRange, "RedRange differs"); - Assert.AreEqual(reference.GreenRange, test.GreenRange, "GreenRange differs"); - Assert.AreEqual(reference.BlueRange, test.BlueRange, "BlueRange differs"); - Assert.AreEqual(reference.AlphaRange, test.AlphaRange, "AlphaRange differs"); + MinMaxGenericImage(image); + MinMaxGenericImage(image); + MinMaxGenericImage(image); + MinMaxGenericImage(image); + MinMaxGenericImage(image); + MinMaxGenericImage(image); } } + + private static void MinMaxGenericImage(string image) + where T : struct, IColor + { + Image data = ImageHelper.GetImage(image); + + IMinMax reference = ReferencePixelHelper.MinMax(data); + IMinMax test = data.MinMax(); + + Assert.AreEqual(reference.RedMin, test.RedMin, $"RedMin differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.GreenMin, test.GreenMin, $"GreenMin differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.BlueMin, test.BlueMin, $"BlueMin differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.AlphaMin, test.AlphaMin, $"AlphaMin differs in type '{T.ColorFormat.Name}'"); + + Assert.AreEqual(reference.RedMax, test.RedMax, $"RedMax differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.GreenMax, test.GreenMax, $"GreenMax differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.BlueMax, test.BlueMax, $"BlueMax differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.AlphaMax, test.AlphaMax, $"AlphaMax differs in type '{T.ColorFormat.Name}'"); + + Assert.AreEqual(reference.RedRange, test.RedRange, $"RedRange differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.GreenRange, test.GreenRange, $"GreenRange differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.BlueRange, test.BlueRange, $"BlueRange differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.AlphaRange, test.AlphaRange, $"AlphaRange differs in type '{T.ColorFormat.Name}'"); + } + + [TestMethod] + public void MinMaxImage() + { + foreach (string image in GetTestImages()) + { + MinMaxImage(image); + MinMaxImage(image); + MinMaxImage(image); + MinMaxImage(image); + MinMaxImage(image); + MinMaxImage(image); + } + } + + private static void MinMaxImage(string image) + where T : struct, IColor + { + IImage data = ImageHelper.GetImage(image); + + IMinMax reference = ReferencePixelHelper.MinMax(data); + IMinMax test = data.MinMax(); + + Assert.AreEqual(reference.RedMin, test.RedMin, $"RedMin differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.GreenMin, test.GreenMin, $"GreenMin differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.BlueMin, test.BlueMin, $"BlueMin differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.AlphaMin, test.AlphaMin, $"AlphaMin differs in type '{T.ColorFormat.Name}'"); + + Assert.AreEqual(reference.RedMax, test.RedMax, $"RedMax differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.GreenMax, test.GreenMax, $"GreenMax differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.BlueMax, test.BlueMax, $"BlueMax differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.AlphaMax, test.AlphaMax, $"AlphaMax differs in type '{T.ColorFormat.Name}'"); + + Assert.AreEqual(reference.RedRange, test.RedRange, $"RedRange differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.GreenRange, test.GreenRange, $"GreenRange differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.BlueRange, test.BlueRange, $"BlueRange differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.AlphaRange, test.AlphaRange, $"AlphaRange differs in type '{T.ColorFormat.Name}'"); + } + + [TestMethod] + public void MinMaxSpan() + { + foreach (string image in GetTestImages()) + { + MinMaxSpan(image); + MinMaxSpan(image); + MinMaxSpan(image); + MinMaxSpan(image); + MinMaxSpan(image); + MinMaxSpan(image); + } + } + + private static void MinMaxSpan(string image) + where T : struct, IColor + { + T[] data = ImageHelper.GetColorsFromImage(image); + Span span = data; + + IMinMax reference = ReferencePixelHelper.MinMax(span); + IMinMax test = span.MinMax(); + + Assert.AreEqual(reference.RedMin, test.RedMin, $"RedMin differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.GreenMin, test.GreenMin, $"GreenMin differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.BlueMin, test.BlueMin, $"BlueMin differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.AlphaMin, test.AlphaMin, $"AlphaMin differs in type '{T.ColorFormat.Name}'"); + + Assert.AreEqual(reference.RedMax, test.RedMax, $"RedMax differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.GreenMax, test.GreenMax, $"GreenMax differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.BlueMax, test.BlueMax, $"BlueMax differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.AlphaMax, test.AlphaMax, $"AlphaMax differs in type '{T.ColorFormat.Name}'"); + + Assert.AreEqual(reference.RedRange, test.RedRange, $"RedRange differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.GreenRange, test.GreenRange, $"GreenRange differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.BlueRange, test.BlueRange, $"BlueRange differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.AlphaRange, test.AlphaRange, $"AlphaRange differs in type '{T.ColorFormat.Name}'"); + } + + [TestMethod] + public void MinMaxReadOnlySpan() + { + foreach (string image in GetTestImages()) + { + MinMaxReadOnlySpan(image); + MinMaxReadOnlySpan(image); + MinMaxReadOnlySpan(image); + MinMaxReadOnlySpan(image); + MinMaxReadOnlySpan(image); + MinMaxReadOnlySpan(image); + } + } + + private static void MinMaxReadOnlySpan(string image) + where T : struct, IColor + { + T[] data = ImageHelper.GetColorsFromImage(image); + ReadOnlySpan span = data; + + IMinMax reference = ReferencePixelHelper.MinMax(span); + IMinMax test = span.MinMax(); + + Assert.AreEqual(reference.RedMin, test.RedMin, $"RedMin differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.GreenMin, test.GreenMin, $"GreenMin differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.BlueMin, test.BlueMin, $"BlueMin differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.AlphaMin, test.AlphaMin, $"AlphaMin differs in type '{T.ColorFormat.Name}'"); + + Assert.AreEqual(reference.RedMax, test.RedMax, $"RedMax differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.GreenMax, test.GreenMax, $"GreenMax differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.BlueMax, test.BlueMax, $"BlueMax differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.AlphaMax, test.AlphaMax, $"AlphaMax differs in type '{T.ColorFormat.Name}'"); + + Assert.AreEqual(reference.RedRange, test.RedRange, $"RedRange differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.GreenRange, test.GreenRange, $"GreenRange differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.BlueRange, test.BlueRange, $"BlueRange differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.AlphaRange, test.AlphaRange, $"AlphaRange differs in type '{T.ColorFormat.Name}'"); + } } \ No newline at end of file diff --git a/HPPH.Test/PixelHelper/QuantizeTests.cs b/HPPH.Test/PixelHelper/QuantizeTests.cs index 94134a1..d081189 100644 --- a/HPPH.Test/PixelHelper/QuantizeTests.cs +++ b/HPPH.Test/PixelHelper/QuantizeTests.cs @@ -12,7 +12,7 @@ public class CreateColorPaletteTests { foreach (string image in GetTestImages()) { - ColorRGB[] data = ImageHelper.Get3ByteColorsFromImage(image); + ColorRGB[] data = ImageHelper.GetColorsFromImage(image); Span span = data; ColorRGB[] reference = [.. ReferencePixelHelper.CreateColorPalette(span, 1).OrderBy(x => x.R).ThenBy(x => x.G).ThenBy(x => x.B).ThenBy(x => x.A)]; @@ -30,7 +30,7 @@ public class CreateColorPaletteTests { foreach (string image in GetTestImages()) { - ColorRGB[] data = ImageHelper.Get3ByteColorsFromImage(image); + ColorRGB[] data = ImageHelper.GetColorsFromImage(image); Span span = data; ColorRGB[] reference = [.. ReferencePixelHelper.CreateColorPalette(span, 2).OrderBy(x => x.R).ThenBy(x => x.G).ThenBy(x => x.B).ThenBy(x => x.A)]; @@ -48,7 +48,7 @@ public class CreateColorPaletteTests { foreach (string image in GetTestImages()) { - ColorRGB[] data = ImageHelper.Get3ByteColorsFromImage(image); + ColorRGB[] data = ImageHelper.GetColorsFromImage(image); Span span = data; ColorRGB[] reference = [.. ReferencePixelHelper.CreateColorPalette(span, 16).OrderBy(x => x.R).ThenBy(x => x.G).ThenBy(x => x.B).ThenBy(x => x.A)]; @@ -66,7 +66,7 @@ public class CreateColorPaletteTests { foreach (string image in GetTestImages()) { - ColorRGBA[] data = ImageHelper.Get4ByteColorsFromImage(image); + ColorRGBA[] data = ImageHelper.GetColorsFromImage(image); Span span = data; ColorRGBA[] reference = [.. ReferencePixelHelper.CreateColorPalette(span, 1).OrderBy(x => x.R).ThenBy(x => x.G).ThenBy(x => x.B).ThenBy(x => x.A)]; @@ -84,7 +84,7 @@ public class CreateColorPaletteTests { foreach (string image in GetTestImages()) { - ColorRGBA[] data = ImageHelper.Get4ByteColorsFromImage(image); + ColorRGBA[] data = ImageHelper.GetColorsFromImage(image); Span span = data; ColorRGBA[] reference = [.. ReferencePixelHelper.CreateColorPalette(span, 2).OrderBy(x => x.R).ThenBy(x => x.G).ThenBy(x => x.B).ThenBy(x => x.A)]; @@ -102,7 +102,7 @@ public class CreateColorPaletteTests { foreach (string image in GetTestImages()) { - ColorRGBA[] data = ImageHelper.Get4ByteColorsFromImage(image); + ColorRGBA[] data = ImageHelper.GetColorsFromImage(image); Span span = data; ColorRGBA[] reference = [.. ReferencePixelHelper.CreateColorPalette(span, 16).OrderBy(x => x.R).ThenBy(x => x.G).ThenBy(x => x.B).ThenBy(x => x.A)]; diff --git a/HPPH.Test/PixelHelper/SortTests.cs b/HPPH.Test/PixelHelper/SortTests.cs index 1d5f271..bfeb9d6 100644 --- a/HPPH.Test/PixelHelper/SortTests.cs +++ b/HPPH.Test/PixelHelper/SortTests.cs @@ -13,7 +13,7 @@ public class SortTests { foreach (string image in GetTestImages()) { - ColorRGB[] referenceData = ImageHelper.Get3ByteColorsFromImage(image); + ColorRGB[] referenceData = ImageHelper.GetColorsFromImage(image); ColorRGB[] testData = new ColorRGB[referenceData.Length]; Span referenceSpan = referenceData; Span testSpan = testData; @@ -32,7 +32,7 @@ public class SortTests { foreach (string image in GetTestImages()) { - ColorRGB[] referenceData = ImageHelper.Get3ByteColorsFromImage(image); + ColorRGB[] referenceData = ImageHelper.GetColorsFromImage(image); ColorRGB[] testData = new ColorRGB[referenceData.Length]; Span referenceSpan = referenceData; Span testSpan = testData; @@ -51,7 +51,7 @@ public class SortTests { foreach (string image in GetTestImages()) { - ColorRGB[] referenceData = ImageHelper.Get3ByteColorsFromImage(image); + ColorRGB[] referenceData = ImageHelper.GetColorsFromImage(image); ColorRGB[] testData = new ColorRGB[referenceData.Length]; Span referenceSpan = referenceData; Span testSpan = testData; @@ -70,7 +70,7 @@ public class SortTests { foreach (string image in GetTestImages()) { - ColorRGBA[] referenceData = ImageHelper.Get4ByteColorsFromImage(image); + ColorRGBA[] referenceData = ImageHelper.GetColorsFromImage(image); ColorRGBA[] testData = new ColorRGBA[referenceData.Length]; Span referenceSpan = referenceData; Span testSpan = testData; @@ -89,7 +89,7 @@ public class SortTests { foreach (string image in GetTestImages()) { - ColorRGBA[] referenceData = ImageHelper.Get4ByteColorsFromImage(image); + ColorRGBA[] referenceData = ImageHelper.GetColorsFromImage(image); ColorRGBA[] testData = new ColorRGBA[referenceData.Length]; Span referenceSpan = referenceData; Span testSpan = testData; @@ -108,7 +108,7 @@ public class SortTests { foreach (string image in GetTestImages()) { - ColorRGBA[] referenceData = ImageHelper.Get4ByteColorsFromImage(image); + ColorRGBA[] referenceData = ImageHelper.GetColorsFromImage(image); ColorRGBA[] testData = new ColorRGBA[referenceData.Length]; Span referenceSpan = referenceData; Span testSpan = testData; @@ -127,7 +127,7 @@ public class SortTests { foreach (string image in GetTestImages()) { - ColorRGBA[] referenceData = ImageHelper.Get4ByteColorsFromImage(image); + ColorRGBA[] referenceData = ImageHelper.GetColorsFromImage(image); ColorRGBA[] testData = new ColorRGBA[referenceData.Length]; Span referenceSpan = referenceData; Span testSpan = testData; diff --git a/HPPH.Test/PixelHelper/SumTests.cs b/HPPH.Test/PixelHelper/SumTests.cs index bb1f27a..58e3c8f 100644 --- a/HPPH.Test/PixelHelper/SumTests.cs +++ b/HPPH.Test/PixelHelper/SumTests.cs @@ -8,58 +8,144 @@ public class SumTests private static IEnumerable GetTestImages() => Directory.EnumerateFiles(@"..\..\..\..\sample_data", "*.png", SearchOption.AllDirectories); [TestMethod] - public void SumImage3Byte() - { - } - - [TestMethod] - public void SumRefImage3Byte() - { - } - - [TestMethod] - public void SumReadOnlySpan3Byte() + public void SumRefImage() { foreach (string image in GetTestImages()) { - ColorRGB[] data = ImageHelper.Get3ByteColorsFromImage(image); - ReadOnlySpan span = data; - - ISum reference = ReferencePixelHelper.Sum(span); - ISum test = span.Sum(); - - Assert.AreEqual(reference.R, test.R, "R differs"); - Assert.AreEqual(reference.G, test.G, "G differs"); - Assert.AreEqual(reference.B, test.B, "B differs"); - Assert.AreEqual(reference.A, test.A, "A differs"); + SumRefImage(image); + SumRefImage(image); + SumRefImage(image); + SumRefImage(image); + SumRefImage(image); + SumRefImage(image); } } - [TestMethod] - public void SumImage4Byte() + private static void SumRefImage(string image) + where T : struct, IColor { + RefImage data = ImageHelper.GetImage(image).AsRefImage(); + + ISum reference = ReferencePixelHelper.Sum(data); + ISum test = data.Sum(); + + Assert.AreEqual(reference.R, test.R, $"R differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.G, test.G, $"G differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.B, test.B, $"B differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.A, test.A, $"A differs in type '{T.ColorFormat.Name}'"); } [TestMethod] - public void SumRefImage4Byte() - { - } - - [TestMethod] - public void SumReadOnlySpan4Byte() + public void SumGenericImage() { foreach (string image in GetTestImages()) { - ColorRGBA[] data = ImageHelper.Get4ByteColorsFromImage(image); - ReadOnlySpan span = data; - - ISum reference = ReferencePixelHelper.Sum(span); - ISum test = span.Sum(); - - Assert.AreEqual(reference.R, test.R, "R differs"); - Assert.AreEqual(reference.G, test.G, "G differs"); - Assert.AreEqual(reference.B, test.B, "B differs"); - Assert.AreEqual(reference.A, test.A, "A differs"); + SumGenericImage(image); + SumGenericImage(image); + SumGenericImage(image); + SumGenericImage(image); + SumGenericImage(image); + SumGenericImage(image); } } + + private static void SumGenericImage(string image) + where T : struct, IColor + { + Image data = ImageHelper.GetImage(image); + + ISum reference = ReferencePixelHelper.Sum(data); + ISum test = data.Sum(); + + Assert.AreEqual(reference.R, test.R, $"R differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.G, test.G, $"G differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.B, test.B, $"B differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.A, test.A, $"A differs in type '{T.ColorFormat.Name}'"); + } + + [TestMethod] + public void SumImage() + { + foreach (string image in GetTestImages()) + { + SumImage(image); + SumImage(image); + SumImage(image); + SumImage(image); + SumImage(image); + SumImage(image); + } + } + + private static void SumImage(string image) + where T : struct, IColor + { + IImage data = ImageHelper.GetImage(image); + + ISum reference = ReferencePixelHelper.Sum(data); + ISum test = data.Sum(); + + Assert.AreEqual(reference.R, test.R, $"R differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.G, test.G, $"G differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.B, test.B, $"B differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.A, test.A, $"A differs in type '{T.ColorFormat.Name}'"); + } + + [TestMethod] + public void SumSpan() + { + foreach (string image in GetTestImages()) + { + SumSpan(image); + SumSpan(image); + SumSpan(image); + SumSpan(image); + SumSpan(image); + SumSpan(image); + } + } + + private static void SumSpan(string image) + where T : struct, IColor + { + T[] data = ImageHelper.GetColorsFromImage(image); + Span span = data; + + ISum reference = ReferencePixelHelper.Sum(span); + ISum test = span.Sum(); + + Assert.AreEqual(reference.R, test.R, $"R differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.G, test.G, $"G differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.B, test.B, $"B differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.A, test.A, $"A differs in type '{T.ColorFormat.Name}'"); + } + + [TestMethod] + public void SumReadOnlySpan() + { + foreach (string image in GetTestImages()) + { + SumReadOnlySpan(image); + SumReadOnlySpan(image); + SumReadOnlySpan(image); + SumReadOnlySpan(image); + SumReadOnlySpan(image); + SumReadOnlySpan(image); + } + } + + private static void SumReadOnlySpan(string image) + where T : struct, IColor + { + T[] data = ImageHelper.GetColorsFromImage(image); + ReadOnlySpan span = data; + + ISum reference = ReferencePixelHelper.Sum(span); + ISum test = span.Sum(); + + Assert.AreEqual(reference.R, test.R, $"R differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.G, test.G, $"G differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.B, test.B, $"B differs in type '{T.ColorFormat.Name}'"); + Assert.AreEqual(reference.A, test.A, $"A differs in type '{T.ColorFormat.Name}'"); + } } \ No newline at end of file diff --git a/HPPH.Test/TestDataHelper.cs b/HPPH.Test/TestDataHelper.cs index 2351ff1..782e4d5 100644 --- a/HPPH.Test/TestDataHelper.cs +++ b/HPPH.Test/TestDataHelper.cs @@ -10,7 +10,7 @@ internal static class TestDataHelper return (T)T.Create(xBytes[0], xBytes[1], yBytes[0], yBytes[1]); } - public static Image CreateTestImage(int width, int height) + public static T[] GetPixelData(int width, int height) where T : struct, IColor { T[] buffer = new T[width * height]; @@ -19,6 +19,10 @@ internal static class TestDataHelper for (int x = 0; x < width; x++) buffer[(y * width) + x] = GetColorFromLocation(x, y); - return Image.Create(buffer, width, height); + return buffer; } + + public static Image CreateTestImage(int width, int height) + where T : struct, IColor + => Image.Create(GetPixelData(width, height), width, height); } \ No newline at end of file diff --git a/HPPH/Images/Image.cs b/HPPH/Images/Image.cs index 2d6f8f2..a92d82d 100644 --- a/HPPH/Images/Image.cs +++ b/HPPH/Images/Image.cs @@ -205,7 +205,7 @@ public sealed class Image : IImage if (_buffer.Length == 0) return ref Unsafe.NullRef(); - return ref MemoryMarshal.GetReference(new ReadOnlySpan(_buffer)[((_y * _stride) + (_x * ColorFormat.BytesPerPixel))..]); + return ref Unsafe.Add(ref MemoryMarshal.GetReference(_buffer.AsSpan()), (_y * _stride) + (_x * ColorFormat.BytesPerPixel)); } public IEnumerator GetEnumerator() diff --git a/HPPH/Images/ImageColumn.cs b/HPPH/Images/ImageColumn.cs index 7ee3a8a..85792e9 100644 --- a/HPPH/Images/ImageColumn.cs +++ b/HPPH/Images/ImageColumn.cs @@ -60,10 +60,10 @@ public readonly ref struct ImageColumn _buffer.Slice(_start, SizeInBytes).CopyTo(destination); else { - ReadOnlySpan data = MemoryMarshal.Cast(_buffer[_start..]); + ref byte dataRef = ref Unsafe.Add(ref MemoryMarshal.GetReference(_buffer), _start); Span target = MemoryMarshal.Cast(destination); for (int i = 0; i < Length; i++) - target[i] = data[i * _step]; + target[i] = Unsafe.As(ref Unsafe.Add(ref dataRef, i * _step)); } } @@ -143,7 +143,7 @@ internal class IColorImageColumn : IImageColumn { if ((y < 0) || (y >= _length)) throw new IndexOutOfRangeException(); - return MemoryMarshal.Cast(_buffer.AsSpan()[(_start + (y * _step))..])[0]; + return Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetReference(_buffer.AsSpan()), _start + (y * _step))); } } @@ -181,10 +181,10 @@ internal class IColorImageColumn : IImageColumn _buffer.AsSpan().Slice(_start, SizeInBytes).CopyTo(destination); else { - ReadOnlySpan data = MemoryMarshal.Cast(_buffer.AsSpan()[_start..]); + ref byte dataRef = ref Unsafe.Add(ref MemoryMarshal.GetReference(_buffer.AsSpan()), _start); Span target = MemoryMarshal.Cast(destination); for (int i = 0; i < Length; i++) - target[i] = data[i * _step]; + target[i] = Unsafe.As(ref Unsafe.Add(ref dataRef, i * _step)); } } diff --git a/HPPH/Images/ImageRow.cs b/HPPH/Images/ImageRow.cs index 793e3f5..9b553c4 100644 --- a/HPPH/Images/ImageRow.cs +++ b/HPPH/Images/ImageRow.cs @@ -131,7 +131,7 @@ internal class IColorImageRow : IImageRow { if ((x < 0) || (x >= _length)) throw new IndexOutOfRangeException(); - return MemoryMarshal.Cast(_buffer.AsSpan()[_start..])[x]; + return Unsafe.Add(ref Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetReference(_buffer.AsSpan()), (nint)(uint)_start)), (nint)(uint)x); } } diff --git a/HPPH/Images/RefImage.cs b/HPPH/Images/RefImage.cs index 54129a7..60c74ce 100644 --- a/HPPH/Images/RefImage.cs +++ b/HPPH/Images/RefImage.cs @@ -126,8 +126,7 @@ public readonly ref struct RefImage if (_data.Length == 0) return ref Unsafe.NullRef(); - int offset = (_y * RawStride) + (_x * T.ColorFormat.BytesPerPixel); - return ref MemoryMarshal.GetReference(_data[offset..]); + return ref Unsafe.Add(ref MemoryMarshal.GetReference(_data), (_y * RawStride) + (_x * T.ColorFormat.BytesPerPixel)); } /// diff --git a/HPPH/PixelHelper.Average.cs b/HPPH/PixelHelper.Average.cs index 2df9e23..054a519 100644 --- a/HPPH/PixelHelper.Average.cs +++ b/HPPH/PixelHelper.Average.cs @@ -39,7 +39,7 @@ public static partial class PixelHelper try { image.CopyTo(buffer); - return Average(buffer); + return Average(buffer); } finally { @@ -47,6 +47,19 @@ public static partial class PixelHelper } } + public static T Average(this Span colors) + where T : struct, IColor + { + if (colors == null) throw new ArgumentNullException(nameof(colors)); + + return T.ColorFormat.BytesPerPixel switch + { + 3 => Unsafe.BitCast(Average(MemoryMarshal.Cast(colors))), + 4 => Unsafe.BitCast(Average(MemoryMarshal.Cast(colors))), + _ => throw new NotSupportedException("Data is not of a supported valid color-type.") + }; + } + public static T Average(this ReadOnlySpan colors) where T : struct, IColor { diff --git a/HPPH/PixelHelper.Quantize.cs b/HPPH/PixelHelper.Quantize.cs index 89854a2..1bfdc12 100644 --- a/HPPH/PixelHelper.Quantize.cs +++ b/HPPH/PixelHelper.Quantize.cs @@ -86,7 +86,7 @@ public static partial class PixelHelper T[] result = new T[cubes.Length]; for (int i = 0; i < cubes.Length; i++) - result[i] = Average(cubes[i].Slice(colors)); + result[i] = Average(cubes[i].Slice(colors)); return result; } diff --git a/HPPH/PixelHelper.Sum.cs b/HPPH/PixelHelper.Sum.cs index f0fe454..a33e5ee 100644 --- a/HPPH/PixelHelper.Sum.cs +++ b/HPPH/PixelHelper.Sum.cs @@ -41,7 +41,7 @@ public static unsafe partial class PixelHelper try { image.CopyTo(buffer); - return Sum(buffer); + return Sum(buffer); } finally { @@ -53,6 +53,10 @@ public static unsafe partial class PixelHelper where T : struct, IColor => T.ColorFormat.Sum(MemoryMarshal.AsBytes(colors)); + public static ISum Sum(this Span colors) + where T : struct, IColor + => T.ColorFormat.Sum(MemoryMarshal.AsBytes(colors)); + internal static ISum Sum(ReadOnlySpan colors) where T : struct, IColor where TSum : struct, ISum