From 9f3fbc7473375ff049bf2d6157f951e4e411b8af Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Sat, 20 Jul 2024 22:09:34 +0200 Subject: [PATCH] More tests and small fixes --- HPPH.Test/HPPH.Test.csproj | 3 +- HPPH.Test/Image/ImageTest.cs | 1096 ++++++++++++----- HPPH.Test/Image/RefImageTest.cs | 419 +++++-- HPPH.Test/PixelHelper/ConvertTests.cs | 30 + HPPH.Test/Skia/SkiaTests.cs | 52 + HPPH.Test/SystemDrawing/SystemDrawingTests.cs | 52 + HPPH/Images/Image.cs | 46 +- HPPH/Images/ImageColumn.cs | 26 +- HPPH/Images/ImageColumns.cs | 4 +- HPPH/Images/ImageRow.cs | 3 + HPPH/Images/ImageRows.cs | 4 +- HPPH/Images/Interfaces/IImage.cs | 6 +- 12 files changed, 1345 insertions(+), 396 deletions(-) create mode 100644 HPPH.Test/Skia/SkiaTests.cs create mode 100644 HPPH.Test/SystemDrawing/SystemDrawingTests.cs diff --git a/HPPH.Test/HPPH.Test.csproj b/HPPH.Test/HPPH.Test.csproj index ea0f934..4493a2a 100644 --- a/HPPH.Test/HPPH.Test.csproj +++ b/HPPH.Test/HPPH.Test.csproj @@ -15,11 +15,12 @@ - + + diff --git a/HPPH.Test/Image/ImageTest.cs b/HPPH.Test/Image/ImageTest.cs index b2ee5c1..34fa2ca 100644 --- a/HPPH.Test/Image/ImageTest.cs +++ b/HPPH.Test/Image/ImageTest.cs @@ -1,4 +1,6 @@ +using System; using System.Collections; +using System.Runtime.CompilerServices; namespace HPPH.Test.Image; @@ -7,8 +9,7 @@ public class ImageTest { #region Constants - private const int TEST_WIDTH = 1920; - private const int TEST_HEIGHT = 1080; + private readonly List<(int width, int height)> SIZES = [(1920, 1080), (1920, 1), (1, 1080), (200, 500), (1, 1)]; #endregion @@ -17,48 +18,59 @@ public class ImageTest [TestMethod] public void ImageCreation() { - IImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); + foreach ((int width, int height) in SIZES) + { + IImage image = TestDataHelper.CreateTestImage(width, height); - Assert.AreEqual(TEST_WIDTH, image.Width); - Assert.AreEqual(TEST_HEIGHT, image.Height); + Assert.AreEqual(width, image.Width); + Assert.AreEqual(height, image.Height); - for (int y = 0; y < image.Height; y++) - for (int x = 0; x < image.Width; x++) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), image[x, y]); + for (int y = 0; y < image.Height; y++) + for (int x = 0; x < image.Width; x++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), image[x, y]); + } } [TestMethod] public void ImageInnerFull() { - IImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); - image = image[0, 0, image.Width, image.Height]; + foreach ((int width, int height) in SIZES) + { + IImage image = TestDataHelper.CreateTestImage(width, height); + image = image[0, 0, image.Width, image.Height]; - for (int y = 0; y < image.Height; y++) - for (int x = 0; x < image.Width; x++) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), image[x, y]); + for (int y = 0; y < image.Height; y++) + for (int x = 0; x < image.Width; x++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), image[x, y]); + } } [TestMethod] public void ImageEnumerator() { - IImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); - - int counter = 0; - foreach (IColor color in image) + foreach ((int width, int height) in SIZES) { - int x = counter % image.Width; - int y = counter / image.Width; + IImage image = TestDataHelper.CreateTestImage(width, height); - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), color); + int counter = 0; + foreach (IColor color in image) + { + int x = counter % image.Width; + int y = counter / image.Width; - counter++; + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), color); + + counter++; + } } } [TestMethod] public void ImageInnerPartial() { - IImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); + (int width, int height) = SIZES[0]; + + IImage image = TestDataHelper.CreateTestImage(width, height); image = image[163, 280, 720, 13]; Assert.AreEqual(720, image.Width); @@ -72,7 +84,9 @@ public class ImageTest [TestMethod] public void ImageInnerInnerPartial() { - IImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); + (int width, int height) = SIZES[0]; + + IImage image = TestDataHelper.CreateTestImage(width, height); image = image[163, 280, 720, 13]; image = image[15, 2, 47, 8]; @@ -87,152 +101,179 @@ public class ImageTest [TestMethod] public void ImageRowIndexer() { - IImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); - - Assert.AreEqual(image.Height, image.Rows.Count); - - for (int y = 0; y < image.Height; y++) + foreach ((int width, int height) in SIZES) { - IImageRow row = image.Rows[y]; - Assert.AreEqual(image.Width, row.Length); - for (int x = 0; x < row.Length; x++) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), row[x]); + IImage image = TestDataHelper.CreateTestImage(width, height); + + Assert.AreEqual(image.Height, image.Rows.Count); + + for (int y = 0; y < image.Height; y++) + { + IImageRow row = image.Rows[y]; + Assert.AreEqual(image.Width, row.Length); + for (int x = 0; x < row.Length; x++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), row[x]); + } } } [TestMethod] public void ImageRowEnumerator() { - IImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); - - int y = 0; - foreach (IImageRow row in image.Rows) + foreach ((int width, int height) in SIZES) { - for (int x = 0; x < row.Length; x++) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), row[x]); + IImage image = TestDataHelper.CreateTestImage(width, height); - y++; + int y = 0; + foreach (IImageRow row in image.Rows) + { + for (int x = 0; x < row.Length; x++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), row[x]); + + y++; + } } } [TestMethod] public void ImageColumnIndexer() { - IImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); - - Assert.AreEqual(image.Width, image.Columns.Count); - - for (int x = 0; x < image.Width; x++) + foreach ((int width, int height) in SIZES) { - IImageColumn column = image.Columns[x]; - Assert.AreEqual(image.Height, column.Length); - for (int y = 0; y < column.Length; y++) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), column[y]); + IImage image = TestDataHelper.CreateTestImage(width, height); + + Assert.AreEqual(image.Width, image.Columns.Count); + + for (int x = 0; x < image.Width; x++) + { + IImageColumn column = image.Columns[x]; + Assert.AreEqual(image.Height, column.Length); + for (int y = 0; y < column.Length; y++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), column[y]); + } } } [TestMethod] public void ImageColumnEnumerator() { - IImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); - - int x = 0; - foreach (IImageColumn column in image.Columns) + foreach ((int width, int height) in SIZES) { - for (int y = 0; y < column.Length; y++) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), column[y]); + IImage image = TestDataHelper.CreateTestImage(width, height); - x++; + int x = 0; + foreach (IImageColumn column in image.Columns) + { + for (int y = 0; y < column.Length; y++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), column[y]); + + x++; + } } } [TestMethod] public void AsRefImage() { - IImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); - image = image[163, 280, 720, 13]; - image = image[15, 2, 47, 8]; + foreach ((int width, int height) in SIZES) + { + IImage image = TestDataHelper.CreateTestImage(width, height); - RefImage refImage = image.AsRefImage(); + RefImage refImage = image.AsRefImage(); - for (int y = 0; y < image.Height; y++) - for (int x = 0; x < image.Width; x++) - Assert.AreEqual(image[x, y], refImage[x, y]); + for (int y = 0; y < image.Height; y++) + for (int x = 0; x < image.Width; x++) + Assert.AreEqual(image[x, y], refImage[x, y]); + } } [TestMethod] public void ConvertToInPlace() { - IImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); - - IColor[] referenceData = image.ToArray(); - - image.ConvertTo(); - IColor[] testData = image.ToArray(); - - Assert.AreEqual(referenceData.Length, testData.Length); - for (int i = 0; i < referenceData.Length; i++) + foreach ((int width, int height) in SIZES) { - IColor reference = referenceData[i]; - IColor test = testData[i]; + IImage image = TestDataHelper.CreateTestImage(width, height); - Assert.AreEqual(reference.R, test.R, $"R differs at index {i}"); - Assert.AreEqual(reference.G, test.G, $"G differs at index {i}"); - Assert.AreEqual(reference.B, test.B, $"B differs at index {i}"); - Assert.AreEqual(reference.A, test.A, $"A differs at index {i}"); + IColor[] referenceData = image.ToArray(); + + image.ConvertTo(); + IColor[] testData = image.ToArray(); + + Assert.AreEqual(referenceData.Length, testData.Length); + for (int i = 0; i < referenceData.Length; i++) + { + IColor reference = referenceData[i]; + IColor test = testData[i]; + + Assert.AreEqual(reference.R, test.R, $"R differs at index {i}"); + Assert.AreEqual(reference.G, test.G, $"G differs at index {i}"); + Assert.AreEqual(reference.B, test.B, $"B differs at index {i}"); + Assert.AreEqual(reference.A, test.A, $"A differs at index {i}"); + } } } [TestMethod] public void ConvertToCopy() { - IImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); - - IColor[] referenceData = image.ToArray(); - - image.ConvertTo(); - IColor[] testData = image.ToArray(); - - Assert.AreEqual(referenceData.Length, testData.Length); - for (int i = 0; i < referenceData.Length; i++) + foreach ((int width, int height) in SIZES) { - IColor reference = referenceData[i]; - IColor test = testData[i]; + IImage image = TestDataHelper.CreateTestImage(width, height); - Assert.AreEqual(reference.R, test.R, $"R differs at index {i}"); - Assert.AreEqual(reference.G, test.G, $"G differs at index {i}"); - Assert.AreEqual(reference.B, test.B, $"B differs at index {i}"); - Assert.AreEqual(reference.A, test.A, $"A differs at index {i}"); + IColor[] referenceData = image.ToArray(); + + image.ConvertTo(); + IColor[] testData = image.ToArray(); + + Assert.AreEqual(referenceData.Length, testData.Length); + for (int i = 0; i < referenceData.Length; i++) + { + IColor reference = referenceData[i]; + IColor test = testData[i]; + + Assert.AreEqual(reference.R, test.R, $"R differs at index {i}"); + Assert.AreEqual(reference.G, test.G, $"G differs at index {i}"); + Assert.AreEqual(reference.B, test.B, $"B differs at index {i}"); + Assert.AreEqual(reference.A, test.A, $"A differs at index {i}"); + } } } [TestMethod] public void ToArray() { - Image image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); - ColorARGB[] testData = image.ToArray(); + foreach ((int width, int height) in SIZES) + { + Image image = TestDataHelper.CreateTestImage(width, 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]); + for (int y = 0; y < height; y++) + for (int x = 0; x < width; x++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), testData[(y * 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); + foreach ((int width, int height) in SIZES) + { + Image image = TestDataHelper.CreateTestImage(width, height); + ColorARGB[] testData = new ColorARGB[width * 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]); + for (int y = 0; y < height; y++) + for (int x = 0; x < width; x++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), testData[(y * width) + x]); + } } [TestMethod] public void SubImage() { - Image image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); + (int width, int height) = SIZES[0]; + + Image image = TestDataHelper.CreateTestImage(width, height); RefImage subImage = image[10, 20, 100, 200]; for (int y = 0; y < 200; y++) @@ -243,162 +284,185 @@ public class ImageTest [TestMethod] public void GenericRowsIterate() { - Image image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); - - int y = 0; - foreach (ImageRow row in image.Rows) + foreach ((int width, int height) in SIZES) { - int x = 0; - foreach (ColorARGB color in row) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x++, y), color); + Image image = TestDataHelper.CreateTestImage(width, height); - y++; + 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) + foreach ((int width, int height) in SIZES) { - ColorARGB[] colors = new ColorARGB[TEST_WIDTH]; - byte[] bytes = new byte[TEST_WIDTH * 4]; - row.CopyTo(colors); - row.CopyTo(bytes); + Image image = TestDataHelper.CreateTestImage(width, height); - int x = 0; - foreach (ColorARGB color in colors) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x++, y), color); - - for (x = 0; x < TEST_WIDTH; x++) + int y = 0; + foreach (ImageRow row in image.Rows) { - ColorARGB reference = TestDataHelper.GetColorFromLocation(x, y); + ColorARGB[] colors = new ColorARGB[width]; + byte[] bytes = new byte[width * 4]; + row.CopyTo(colors); + row.CopyTo(bytes); - 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]); + int x = 0; + foreach (ColorARGB color in colors) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x++, y), color); + + for (x = 0; x < 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++; } - - y++; } } [TestMethod] public void GenericRowsToArray() { - Image image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); - - int y = 0; - foreach (ImageRow row in image.Rows) + foreach ((int width, int height) in SIZES) { - ColorARGB[] data = row.ToArray(); + Image image = TestDataHelper.CreateTestImage(width, height); - for (int x = 0; x < TEST_WIDTH; x++) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), data[x]); + int y = 0; + foreach (ImageRow row in image.Rows) + { + ColorARGB[] data = row.ToArray(); - y++; + for (int x = 0; x < 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) + foreach ((int width, int height) in SIZES) { - int y = 0; - foreach (ColorARGB color in column) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y++), color); + Image image = TestDataHelper.CreateTestImage(width, height); - x++; + 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) + foreach ((int width, int height) in SIZES) { - ColorARGB[] colors = new ColorARGB[TEST_HEIGHT]; - byte[] bytes = new byte[TEST_HEIGHT * 4]; - column.CopyTo(colors); - column.CopyTo(bytes); + Image image = TestDataHelper.CreateTestImage(width, height); - int y = 0; - foreach (ColorARGB color in colors) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y++), color); - - for (y = 0; y < TEST_HEIGHT; y++) + int x = 0; + foreach (ImageColumn column in image.Columns) { - ColorARGB reference = TestDataHelper.GetColorFromLocation(x, y); + ColorARGB[] colors = new ColorARGB[height]; + byte[] bytes = new byte[height * 4]; + column.CopyTo(colors); + column.CopyTo(bytes); - 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]); + int y = 0; + foreach (ColorARGB color in colors) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y++), color); + + for (y = 0; y < 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++; } - - x++; } } [TestMethod] public void GenericColumnsToArray() { - Image image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); - - int x = 0; - foreach (ImageColumn column in image.Columns) + foreach ((int width, int height) in SIZES) { - ColorARGB[] data = column.ToArray(); + Image image = TestDataHelper.CreateTestImage(width, height); - for (int y = 0; y < TEST_HEIGHT; y++) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), data[y]); + int x = 0; + foreach (ImageColumn column in image.Columns) + { + ColorARGB[] data = column.ToArray(); - x++; + for (int y = 0; y < 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); + foreach ((int width, int height) in SIZES) + { + Image image = TestDataHelper.CreateTestImage(width, height); + ColorARGB[] reference = TestDataHelper.GetPixelData(width, height); - int i = 0; - foreach (ColorARGB color in image) - Assert.AreEqual(reference[i++], color); + 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); + 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) + foreach ((int width, int height) in SIZES) { - for (int i = 0; i < reference.Length; i++) + Image image = TestDataHelper.CreateTestImage(width, height); + ColorARGB[] reference = TestDataHelper.GetPixelData(width, height); + + fixed (byte* ptr = image) { - 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]); + 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]); + } } } } @@ -406,166 +470,614 @@ public class ImageTest [TestMethod] public void InterfaceRowsIterate() { - IImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); - - int y = 0; - foreach (IImageRow row in image.Rows) + foreach ((int width, int height) in SIZES) { - int x = 0; - foreach (IColor color in row) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x++, y), color); + IImage image = TestDataHelper.CreateTestImage(width, height); - y++; - } + 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 = 0; - foreach (IImageRow row in (IEnumerable)image.Rows) - { - int x = 0; - foreach (IColor color in (IEnumerable)row) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x++, y), color); + y++; + } - y++; + y = 0; + foreach (IImageRow row in (IEnumerable)image.Rows) + { + int x = 0; + foreach (IColor color in (IEnumerable)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) + foreach ((int width, int height) in SIZES) { - int y = 0; - foreach (IColor color in column) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y++), color); + IImage image = TestDataHelper.CreateTestImage(width, height); - x++; - } + 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 = 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++; + } - 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); + foreach ((int width, int height) in SIZES) + { + IImage image = TestDataHelper.CreateTestImage(width, height); + ColorARGB[] reference = TestDataHelper.GetPixelData(width, height); - int i = 0; - foreach (IColor color in image) - Assert.AreEqual(reference[i++], color); + 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); + 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) + foreach ((int width, int height) in SIZES) { - IColor[] colors = new IColor[TEST_HEIGHT]; - byte[] bytes = new byte[TEST_HEIGHT * 4]; - column.CopyTo(colors); - column.CopyTo(bytes); + IImage image = TestDataHelper.CreateTestImage(width, height); - int y = 0; - foreach (IColor color in colors) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y++), color); - - for (y = 0; y < TEST_HEIGHT; y++) + int x = 0; + foreach (IImageColumn column in image.Columns) { - IColor reference = TestDataHelper.GetColorFromLocation(x, y); + IColor[] colors = new IColor[height]; + byte[] bytes = new byte[height * 4]; + column.CopyTo(colors); + column.CopyTo(bytes); - 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]); + int y = 0; + foreach (IColor color in colors) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y++), color); + + for (y = 0; y < 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++; } - - x++; } } [TestMethod] public void InterfaceColumnsToArray() { - IImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); - - int x = 0; - foreach (IImageColumn column in image.Columns) + foreach ((int width, int height) in SIZES) { - IColor[] data = column.ToArray(); + IImage image = TestDataHelper.CreateTestImage(width, height); - for (int y = 0; y < TEST_HEIGHT; y++) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), data[y]); + int x = 0; + foreach (IImageColumn column in image.Columns) + { + IColor[] data = column.ToArray(); - x++; + for (int y = 0; y < height; y++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), data[y]); + + x++; + } } } [TestMethod] public void InterfaceRowsCopyTo() { - IImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); - - int y = 0; - foreach (IImageRow row in image.Rows) + foreach ((int width, int height) in SIZES) { - IColor[] colors = new IColor[TEST_WIDTH]; - byte[] bytes = new byte[TEST_WIDTH * 4]; - row.CopyTo(colors); - row.CopyTo(bytes); + IImage image = TestDataHelper.CreateTestImage(width, height); - int x = 0; - foreach (IColor color in colors) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x++, y), color); - - for (x = 0; x < TEST_WIDTH; x++) + int y = 0; + foreach (IImageRow row in image.Rows) { - IColor reference = TestDataHelper.GetColorFromLocation(x, y); + IColor[] colors = new IColor[width]; + byte[] bytes = new byte[width * 4]; + row.CopyTo(colors); + row.CopyTo(bytes); - 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]); + int x = 0; + foreach (IColor color in colors) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x++, y), color); + + for (x = 0; x < width; x++) + { + IColor 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++; } - - y++; } } [TestMethod] public void InterfaceRowsToArray() { - IImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT); - - int y = 0; - foreach (IImageRow row in image.Rows) + foreach ((int width, int height) in SIZES) { - IColor[] data = row.ToArray(); + IImage image = TestDataHelper.CreateTestImage(width, height); - for (int x = 0; x < TEST_WIDTH; x++) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), data[x]); + int y = 0; + foreach (IImageRow row in image.Rows) + { + IColor[] data = row.ToArray(); - y++; + for (int x = 0; x < width; x++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), data[x]); + + y++; + } } } + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void CreateWrongStride() + { + Image.Create([], 10, 20, 9); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void CreateWrongBufferSize() + { + Image.Create(new byte[299], 10, 10, 30); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void CopyToByteNull() + { + TestDataHelper.CreateTestImage(10, 10).CopyTo((Span)null); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void CopyToColorNull() + { + TestDataHelper.CreateTestImage(10, 10).CopyTo((Span)null); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void CopyToByteWrongSize() + { + TestDataHelper.CreateTestImage(10, 10).CopyTo(new byte[(10 * 10 * 3) - 1]); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void CopyToColorWrongSize() + { + TestDataHelper.CreateTestImage(10, 10).CopyTo(new ColorRGB[(10 * 10) - 1]); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void AsRefImageWrongType() + { + IImage image = TestDataHelper.CreateTestImage(10, 10); + RefImage refImage = image.AsRefImage(); + } + + [TestMethod] + public void PinEmpty() + { + Image image = TestDataHelper.CreateTestImage(0, 0); + Assert.IsTrue(Unsafe.IsNullRef(in image.GetPinnableReference())); + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void IndexerWrongXBig() + { + Image image = TestDataHelper.CreateTestImage(10, 20); + ColorRGB test = image[10, 19]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void IndexerWrongYBig() + { + Image image = TestDataHelper.CreateTestImage(10, 20); + ColorRGB test = image[9, 20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void IndexerWrongXSmall() + { + Image image = TestDataHelper.CreateTestImage(10, 20); + ColorRGB test = image[-1, 19]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void IndexerWrongYSmall() + { + Image image = TestDataHelper.CreateTestImage(10, 20); + ColorRGB test = image[9, -1]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void SubImageWrongX() + { + Image image = TestDataHelper.CreateTestImage(10, 20); + RefImage test = image[-1, 0, 10, 20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void SubImageWrongY() + { + Image image = TestDataHelper.CreateTestImage(10, 20); + RefImage test = image[0, -1, 10, 20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void SubImageWrongWidth() + { + Image image = TestDataHelper.CreateTestImage(10, 20); + RefImage test = image[0, 0, 0, 20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void SubImageWrongHeight() + { + Image image = TestDataHelper.CreateTestImage(10, 20); + RefImage test = image[0, 0, 10, 0]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void SubImageInvalidSizeWidth() + { + Image image = TestDataHelper.CreateTestImage(10, 20); + RefImage test = image[1, 0, 10, 20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void SubImageInvalidSizeHeight() + { + Image image = TestDataHelper.CreateTestImage(10, 20); + RefImage test = image[0, 1, 10, 20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void SubImageInterfaceWrongX() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + IImage test = image[-1, 0, 10, 20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void SubImageInterfaceWrongY() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + IImage test = image[0, -1, 10, 20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void SubImageInterfaceWrongWidth() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + IImage test = image[0, 0, 0, 20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void SubImageInterfaceWrongHeight() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + IImage test = image[0, 0, 10, 0]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void SubImageInterfaceInvalidSizeWidth() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + IImage test = image[1, 0, 10, 20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void SubImageInterfaceInvalidSizeHeight() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + IImage test = image[0, 1, 10, 20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void ColumnsIndexerToBig() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + IImageColumn test = image.Columns[20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void ColumnsIndexerToSmall() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + IImageColumn test = image.Columns[-1]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void RowsIndexerToBig() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + IImageRow test = image.Rows[20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void RowsIndexerToSmall() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + IImageRow test = image.Rows[-1]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void ColumnIndexerToBig() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + IColor test = image.Columns[1][20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void ColumnIndexerToSmall() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + IColor test = image.Columns[1][-1]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void RowIndexerToBig() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + IColor test = image.Rows[1][10]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void RowIndexerToSmall() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + IColor test = image.Rows[1][-1]; + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void ColumnCopyToByteNull() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + image.Columns[1].CopyTo((Span)null); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void ColumnCopyToColorNull() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + image.Columns[1].CopyTo((Span)null); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void ColumnCopyToByteToSmall() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + image.Columns[1].CopyTo(new byte[(20 * 3) - 1]); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void ColumnCopyToColorToSmall() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + image.Columns[1].CopyTo(new IColor[19]); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void RowCopyToByteNull() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + image.Rows[1].CopyTo((Span)null); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void RowCopyToColorNull() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + image.Rows[1].CopyTo((Span)null); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void RowCopyToByteToSmall() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + image.Rows[1].CopyTo(new byte[(10 * 3) - 1]); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void RowCopyToColorToSmall() + { + IImage image = TestDataHelper.CreateTestImage(10, 20); + image.Rows[1].CopyTo(new IColor[9]); + } + + [TestMethod] + public void EqualsIImage() + { + Image image = TestDataHelper.CreateTestImage(10, 20); + + IImage image2 = TestDataHelper.CreateTestImage(10, 20); + Assert.AreEqual(image, image2); + + Assert.IsFalse(image.Equals((IImage?)null)); + } + + [TestMethod] + public void EqualsGenericIImage() + { + Image image = TestDataHelper.CreateTestImage(10, 20); + + IImage image2 = TestDataHelper.CreateTestImage(10, 20); + Assert.AreEqual(image, image2); + + Assert.IsFalse(image.Equals((IImage?)null)); + } + + [TestMethod] + public void EqualsImage() + { + Image image = TestDataHelper.CreateTestImage(10, 20); + + Image image2 = TestDataHelper.CreateTestImage(10, 20); + Assert.AreEqual(image, image2); + + Assert.IsFalse(image.Equals((Image?)null)); + } + + [TestMethod] + public void EqualsIImageWrongSize() + { + Image image = TestDataHelper.CreateTestImage(10, 20); + + IImage image2 = TestDataHelper.CreateTestImage(10, 10); + Assert.AreNotEqual(image, image2); + + IImage image3 = TestDataHelper.CreateTestImage(20, 20); + Assert.AreNotEqual(image, image3); + } + + [TestMethod] + public void EqualsGenericIImageWrongSize() + { + Image image = TestDataHelper.CreateTestImage(10, 20); + + IImage image2 = TestDataHelper.CreateTestImage(10, 10); + Assert.AreNotEqual(image, image2); + + IImage image3 = TestDataHelper.CreateTestImage(20, 20); + Assert.AreNotEqual(image, image3); + } + + [TestMethod] + public void EqualsImageWrongSize() + { + Image image = TestDataHelper.CreateTestImage(10, 20); + + Image image2 = TestDataHelper.CreateTestImage(10, 10); + Assert.AreNotEqual(image, image2); + + Image image3 = TestDataHelper.CreateTestImage(20, 20); + Assert.AreNotEqual(image, image3); + } + + [TestMethod] + public void EqualsIImageWrongPixel() + { + Image image = TestDataHelper.CreateTestImage(10, 20); + + ColorRGB[] array = image.ToArray(); + array[1] = new ColorRGB(255, 255, 255); + IImage image2 = Image.Create(array, 10, 20); + + Assert.AreNotEqual(image, image2); + } + + [TestMethod] + public void EqualsGenericIImageWrongPixel() + { + Image image = TestDataHelper.CreateTestImage(10, 20); + + ColorRGB[] array = image.ToArray(); + array[1] = new ColorRGB(255, 255, 255); + IImage image2 = Image.Create(array, 10, 20); + + Assert.AreNotEqual(image, image2); + } + + [TestMethod] + public void EqualsImageWrongPixel() + { + Image image = TestDataHelper.CreateTestImage(10, 20); + + ColorRGB[] array = image.ToArray(); + array[1] = new ColorRGB(255, 255, 255); + Image image2 = Image.Create(array, 10, 20); + + Assert.AreNotEqual(image, image2); + } + + [TestMethod] + public void EqualsIImageWrongFormat() + { + Image image = TestDataHelper.CreateTestImage(10, 20); + IImage image2 = TestDataHelper.CreateTestImage(10, 20); + + Assert.AreNotEqual(image, image2); + } + #endregion } \ No newline at end of file diff --git a/HPPH.Test/Image/RefImageTest.cs b/HPPH.Test/Image/RefImageTest.cs index 6134657..3ce3d1b 100644 --- a/HPPH.Test/Image/RefImageTest.cs +++ b/HPPH.Test/Image/RefImageTest.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using System.Runtime.CompilerServices; namespace HPPH.Test.Image; @@ -7,8 +8,7 @@ public class RefImageTest { #region Constants - private const int TEST_WIDTH = 1920; - private const int TEST_HEIGHT = 1080; + private readonly List<(int width, int height)> SIZES = [(1920, 1080), (1920, 1), (1, 1080), (200, 500), (1, 1)]; #endregion @@ -17,50 +17,61 @@ public class RefImageTest [TestMethod] public void ImageCreation() { - RefImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT).AsRefImage(); + foreach ((int width, int height) in SIZES) + { + RefImage image = TestDataHelper.CreateTestImage(width, height).AsRefImage(); - Assert.AreEqual(TEST_WIDTH, image.Width); - Assert.AreEqual(TEST_HEIGHT, image.Height); + Assert.AreEqual(width, image.Width); + Assert.AreEqual(height, image.Height); - for (int y = 0; y < image.Height; y++) - for (int x = 0; x < image.Width; x++) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), image[x, y]); + for (int y = 0; y < image.Height; y++) + for (int x = 0; x < image.Width; x++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), image[x, y]); + } } [TestMethod] public void ImageInnerFull() { - RefImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT).AsRefImage(); - image = image[0, 0, image.Width, image.Height]; + foreach ((int width, int height) in SIZES) + { + RefImage image = TestDataHelper.CreateTestImage(width, height).AsRefImage(); + image = image[0, 0, image.Width, image.Height]; - for (int y = 0; y < image.Height; y++) - for (int x = 0; x < image.Width; x++) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), image[x, y]); + for (int y = 0; y < image.Height; y++) + for (int x = 0; x < image.Width; x++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), image[x, y]); + } } [TestMethod] public void ImageEnumerator() { - RefImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT).AsRefImage(); - - int counter = 0; - foreach (ColorARGB color in image) + foreach ((int width, int height) in SIZES) { - int x = counter % image.Width; - int y = counter / image.Width; + RefImage image = TestDataHelper.CreateTestImage(width, height).AsRefImage(); - if (y == 1) Debugger.Break(); + int counter = 0; + foreach (ColorARGB color in image) + { + int x = counter % image.Width; + int y = counter / image.Width; - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), color); + if (y == 1) Debugger.Break(); - counter++; + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), color); + + counter++; + } } } [TestMethod] public void ImageInnerPartial() { - RefImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT).AsRefImage(); + (int width, int height) = SIZES[0]; + + RefImage image = TestDataHelper.CreateTestImage(width, height).AsRefImage(); image = image[163, 280, 720, 13]; Assert.AreEqual(720, image.Width); @@ -74,7 +85,9 @@ public class RefImageTest [TestMethod] public void ImageInnerInnerPartial() { - RefImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT).AsRefImage(); + (int width, int height) = SIZES[0]; + + RefImage image = TestDataHelper.CreateTestImage(width, height).AsRefImage(); image = image[163, 280, 720, 13]; image = image[15, 2, 47, 8]; @@ -89,92 +102,112 @@ public class RefImageTest [TestMethod] public void ImageRowIndexer() { - RefImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT).AsRefImage(); - - Assert.AreEqual(image.Height, image.Rows.Count); - - for (int y = 0; y < image.Height; y++) + foreach ((int width, int height) in SIZES) { - ImageRow row = image.Rows[y]; - Assert.AreEqual(image.Width, row.Length); - for (int x = 0; x < row.Length; x++) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), row[x]); + RefImage image = TestDataHelper.CreateTestImage(width, height).AsRefImage(); + + Assert.AreEqual(image.Height, image.Rows.Count); + + for (int y = 0; y < image.Height; y++) + { + ImageRow row = image.Rows[y]; + Assert.AreEqual(image.Width, row.Length); + for (int x = 0; x < row.Length; x++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), row[x]); + } } } [TestMethod] public void ImageRowEnumerator() { - RefImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT).AsRefImage(); - - int y = 0; - foreach (ImageRow row in image.Rows) + foreach ((int width, int height) in SIZES) { - for (int x = 0; x < row.Length; x++) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), row[x]); + RefImage image = TestDataHelper.CreateTestImage(width, height).AsRefImage(); - y++; + int y = 0; + foreach (ImageRow row in image.Rows) + { + for (int x = 0; x < row.Length; x++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), row[x]); + + y++; + } } } [TestMethod] public void ImageColumnIndexer() { - RefImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT).AsRefImage(); - - Assert.AreEqual(image.Width, image.Columns.Count); - - for (int x = 0; x < image.Width; x++) + foreach ((int width, int height) in SIZES) { - ImageColumn column = image.Columns[x]; - Assert.AreEqual(image.Height, column.Length); - for (int y = 0; y < column.Length; y++) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), column[y]); + RefImage image = TestDataHelper.CreateTestImage(width, height).AsRefImage(); + + Assert.AreEqual(image.Width, image.Columns.Count); + + for (int x = 0; x < image.Width; x++) + { + ImageColumn column = image.Columns[x]; + Assert.AreEqual(image.Height, column.Length); + for (int y = 0; y < column.Length; y++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), column[y]); + } } } [TestMethod] public void ImageColumnEnumerator() { - RefImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT).AsRefImage(); - - int x = 0; - foreach (ImageColumn column in image.Columns) + foreach ((int width, int height) in SIZES) { - for (int y = 0; y < column.Length; y++) - Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), column[y]); + RefImage image = TestDataHelper.CreateTestImage(width, height).AsRefImage(); - x++; + int x = 0; + foreach (ImageColumn column in image.Columns) + { + for (int y = 0; y < column.Length; y++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), column[y]); + + x++; + } } } [TestMethod] public void ToArray() { - RefImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT).AsRefImage(); - ColorARGB[] testData = image.ToArray(); + foreach ((int width, int height) in SIZES) + { + RefImage image = TestDataHelper.CreateTestImage(width, height).AsRefImage(); + 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]); + for (int y = 0; y < height; y++) + for (int x = 0; x < width; x++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), testData[(y * width) + x]); + } } [TestMethod] public void CopyTo() { - RefImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT).AsRefImage(); - ColorARGB[] testData = new ColorARGB[TEST_WIDTH * TEST_HEIGHT]; - image.CopyTo(testData); + foreach ((int width, int height) in SIZES) + { + RefImage image = TestDataHelper.CreateTestImage(width, height).AsRefImage(); + ColorARGB[] testData = new ColorARGB[width * 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]); + for (int y = 0; y < height; y++) + for (int x = 0; x < width; x++) + Assert.AreEqual(TestDataHelper.GetColorFromLocation(x, y), testData[(y * width) + x]); + } } [TestMethod] public void SubImage() { - RefImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT).AsRefImage(); + (int width, int height) = SIZES[0]; + + RefImage image = TestDataHelper.CreateTestImage(width, height).AsRefImage(); RefImage subImage = image[10, 20, 100, 200]; for (int y = 0; y < 200; y++) @@ -185,20 +218,252 @@ public class RefImageTest [TestMethod] public unsafe void Pin() { - RefImage image = TestDataHelper.CreateTestImage(TEST_WIDTH, TEST_HEIGHT).AsRefImage(); - ColorARGB[] reference = TestDataHelper.GetPixelData(TEST_WIDTH, TEST_HEIGHT); - - fixed (byte* ptr = image) + foreach ((int width, int height) in SIZES) { - for (int i = 0; i < reference.Length; i++) + RefImage image = TestDataHelper.CreateTestImage(width, height).AsRefImage(); + ColorARGB[] reference = TestDataHelper.GetPixelData(width, height); + + fixed (byte* ptr = image) { - 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]); + 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 PinEmpty() + { + RefImage image = TestDataHelper.CreateTestImage(0, 0).AsRefImage(); + Assert.IsTrue(Unsafe.IsNullRef(in image.GetPinnableReference())); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void CopyToColorNull() + { + TestDataHelper.CreateTestImage(10, 10).AsRefImage().CopyTo(null); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void CopyToColorWrongSize() + { + TestDataHelper.CreateTestImage(10, 10).AsRefImage().CopyTo(new ColorRGB[(10 * 10) - 1]); + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void IndexerWrongXBig() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + ColorRGB test = image[10, 19]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void IndexerWrongYBig() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + ColorRGB test = image[9, 20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void IndexerWrongXSmall() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + ColorRGB test = image[-1, 19]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void IndexerWrongYSmall() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + ColorRGB test = image[9, -1]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void SubImageWrongX() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + RefImage test = image[-1, 0, 10, 20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void SubImageWrongY() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + RefImage test = image[0, -1, 10, 20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void SubImageWrongWidth() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + RefImage test = image[0, 0, 0, 20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void SubImageWrongHeight() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + RefImage test = image[0, 0, 10, 0]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void SubImageInvalidSizeWidth() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + RefImage test = image[1, 0, 10, 20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void SubImageInvalidSizeHeight() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + RefImage test = image[0, 1, 10, 20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void ColumnsIndexerToBig() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + ImageColumn test = image.Columns[20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void ColumnsIndexerToSmall() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + ImageColumn test = image.Columns[-1]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void RowsIndexerToBig() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + ImageRow test = image.Rows[20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void RowsIndexerToSmall() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + ImageRow test = image.Rows[-1]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void ColumnIndexerToBig() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + IColor test = image.Columns[1][20]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void ColumnIndexerToSmall() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + IColor test = image.Columns[1][-1]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void RowIndexerToBig() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + IColor test = image.Rows[1][10]; + } + + [TestMethod] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void RowIndexerToSmall() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + IColor test = image.Rows[1][-1]; + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void ColumnCopyToByteNull() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + image.Columns[1].CopyTo((Span)null); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void ColumnCopyToColorNull() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + image.Rows[1].CopyTo((Span)null); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void ColumnCopyToByteToSmall() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + image.Columns[1].CopyTo(new byte[(20 * 3) - 1]); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void ColumnCopyToColorToSmall() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + image.Columns[1].CopyTo(new ColorRGB[19]); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void RowCopyToByteNull() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + image.Rows[1].CopyTo((Span)null); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void RowCopyToColorNull() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + image.Rows[1].CopyTo((Span)null); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void RowCopyToByteToSmall() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + image.Rows[1].CopyTo(new byte[(10 * 3) - 1]); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void RowCopyToColorToSmall() + { + RefImage image = TestDataHelper.CreateTestImage(10, 20).AsRefImage(); + image.Rows[1].CopyTo(new ColorRGB[9]); + } + #endregion } \ No newline at end of file diff --git a/HPPH.Test/PixelHelper/ConvertTests.cs b/HPPH.Test/PixelHelper/ConvertTests.cs index 948db7e..3e2c125 100644 --- a/HPPH.Test/PixelHelper/ConvertTests.cs +++ b/HPPH.Test/PixelHelper/ConvertTests.cs @@ -274,4 +274,34 @@ public class ConvertTests } } } + + [TestMethod] + public void Convert3ByteSameBppRGBToBGRReadOnlySpan() + { + foreach (string image in GetTestImages()) + { + for (int skip = 0; skip < 4; skip++) + { + ColorRGB[] data = ImageHelper.GetColorsFromImage(image).SkipLast(skip).ToArray(); + ReadOnlySpan referenceData = data; + + Span sourceData = new ColorRGB[referenceData.Length]; + referenceData.CopyTo(sourceData); + + Span result = ((ReadOnlySpan)sourceData).Convert(); + + Assert.AreEqual(referenceData.Length, result.Length); + for (int i = 0; i < referenceData.Length; i++) + { + ColorRGB reference = referenceData[i]; + ColorBGR test = result[i]; + + Assert.AreEqual(reference.R, test.R, $"R differs at index {i}. Image: {image}, skip: {skip}"); + Assert.AreEqual(reference.G, test.G, $"G differs at index {i}. Image: {image}, skip: {skip}"); + Assert.AreEqual(reference.B, test.B, $"B differs at index {i}. Image: {image}, skip: {skip}"); + Assert.AreEqual(reference.A, test.A, $"A differs at index {i}. Image: {image}, skip: {skip}"); + } + } + } + } } \ No newline at end of file diff --git a/HPPH.Test/Skia/SkiaTests.cs b/HPPH.Test/Skia/SkiaTests.cs new file mode 100644 index 0000000..41da659 --- /dev/null +++ b/HPPH.Test/Skia/SkiaTests.cs @@ -0,0 +1,52 @@ +using HPPH.SkiaSharp; +using SkiaSharp; + +namespace HPPH.Test.Skia; + +[TestClass] +public class SkiaTests +{ + private static IEnumerable GetTestImages() => Directory.EnumerateFiles(@"..\..\..\..\sample_data", "*.png", SearchOption.AllDirectories); + + [TestMethod] + public void ImageConversion24Bit() + { + Image image = TestDataHelper.CreateTestImage(1920, 1080); + using SKImage bitmap = image.ToSKImage(); + IImage image2 = bitmap.ToImage(); + + Assert.AreEqual(IColorFormat.BGRA, image2.ColorFormat); + + image2 = image2.ConvertTo(); + + Assert.AreEqual(image, image2); + } + + [TestMethod] + public void ImageConversion32Bit() + { + Image image = TestDataHelper.CreateTestImage(1920, 1080); + using SKImage bitmap = image.ToSKImage(); + IImage image2 = bitmap.ToImage(); + + Assert.AreEqual(IColorFormat.BGRA, image2.ColorFormat); + + image2 = image2.ConvertTo(); + + Assert.AreEqual(image, image2); + } + + [TestMethod] + public void LoadFileToPngLoadStream() + { + foreach (string image in GetTestImages()) + { + IImage img = SkiaSharp.ImageHelper.LoadImage(image); + byte[] png = img.ToPng(); + using MemoryStream ms = new(png); + IImage img2 = SkiaSharp.ImageHelper.LoadImage(ms); + + Assert.AreEqual(img, img2); + } + } +} \ No newline at end of file diff --git a/HPPH.Test/SystemDrawing/SystemDrawingTests.cs b/HPPH.Test/SystemDrawing/SystemDrawingTests.cs new file mode 100644 index 0000000..4b65a35 --- /dev/null +++ b/HPPH.Test/SystemDrawing/SystemDrawingTests.cs @@ -0,0 +1,52 @@ +using System.Drawing; +using HPPH.System.Drawing; + +namespace HPPH.Test.SystemDrawing; + +[TestClass] +public class SystemDrawingTests +{ + private static IEnumerable GetTestImages() => Directory.EnumerateFiles(@"..\..\..\..\sample_data", "*.png", SearchOption.AllDirectories); + + [TestMethod] + public void ImageConversion24Bit() + { + Image image = TestDataHelper.CreateTestImage(1920, 1080); + using Bitmap bitmap = image.ToBitmap(); + IImage image2 = bitmap.ToImage(); + + Assert.AreEqual(IColorFormat.BGR, image2.ColorFormat); + + image2 = image2.ConvertTo(); + + Assert.AreEqual(image, image2); + } + + [TestMethod] + public void ImageConversion32Bit() + { + Image image = TestDataHelper.CreateTestImage(1920, 1080); + using Bitmap bitmap = image.ToBitmap(); + IImage image2 = bitmap.ToImage(); + + Assert.AreEqual(IColorFormat.BGRA, image2.ColorFormat); + + image2 = image2.ConvertTo(); + + Assert.AreEqual(image, image2); + } + + [TestMethod] + public void LoadFileToPngLoadStream() + { + foreach (string image in GetTestImages()) + { + IImage img = System.Drawing.ImageHelper.LoadImage(image); + byte[] png = img.ToPng(); + using MemoryStream ms = new(png); + IImage img2 = System.Drawing.ImageHelper.LoadImage(ms); + + Assert.AreEqual(img, img2); + } + } +} \ No newline at end of file diff --git a/HPPH/Images/Image.cs b/HPPH/Images/Image.cs index a92d82d..e1deeeb 100644 --- a/HPPH/Images/Image.cs +++ b/HPPH/Images/Image.cs @@ -6,7 +6,7 @@ namespace HPPH; /// [SkipLocalsInit] -public sealed class Image : IImage +public sealed class Image : IImage, IEquatable> where T : struct, IColor { #region Properties & Fields @@ -224,5 +224,49 @@ public sealed class Image : IImage IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + //TODO DarthAffe 20.07.2024: All of those equals can be optimized + public bool Equals(IImage? other) + { + if (other == null) return false; + if (other.ColorFormat != ColorFormat) return false; + if (other.Width != Width) return false; + if (other.Height != Height) return false; + + for (int y = 0; y < Height; y++) + for (int x = 0; x < Width; x++) + if (!this[x, y].Equals(other[x, y])) + return false; + + return true; + } + + public bool Equals(IImage? other) + { + if (other == null) return false; + if (other.Width != Width) return false; + if (other.Height != Height) return false; + + for (int y = 0; y < Height; y++) + for (int x = 0; x < Width; x++) + if (!this[x, y].Equals(other[x, y])) + return false; + + return true; + } + + public bool Equals(Image? other) + { + if (other == null) return false; + if (other.Width != Width) return false; + if (other.Height != Height) return false; + + for (int y = 0; y < Height; y++) + for (int x = 0; x < Width; x++) + if (!this[x, y].Equals(other[x, y])) + return false; + + return true; + } + #endregion } \ No newline at end of file diff --git a/HPPH/Images/ImageColumn.cs b/HPPH/Images/ImageColumn.cs index 85792e9..4f06e22 100644 --- a/HPPH/Images/ImageColumn.cs +++ b/HPPH/Images/ImageColumn.cs @@ -56,15 +56,10 @@ public readonly ref struct ImageColumn if (destination == null) throw new ArgumentNullException(nameof(destination)); if (destination.Length < SizeInBytes) throw new ArgumentException("The destination is too small to fit this image.", nameof(destination)); - if (_step == 1) - _buffer.Slice(_start, SizeInBytes).CopyTo(destination); - else - { - 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] = Unsafe.As(ref Unsafe.Add(ref dataRef, i * _step)); - } + 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] = Unsafe.As(ref Unsafe.Add(ref dataRef, i * _step)); } public T[] ToArray() @@ -177,15 +172,10 @@ internal class IColorImageColumn : IImageColumn if (destination == null) throw new ArgumentNullException(nameof(destination)); if (destination.Length < SizeInBytes) throw new ArgumentException("The destination is too small to fit this image.", nameof(destination)); - if (_step == 1) - _buffer.AsSpan().Slice(_start, SizeInBytes).CopyTo(destination); - else - { - 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] = Unsafe.As(ref Unsafe.Add(ref dataRef, i * _step)); - } + 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] = Unsafe.As(ref Unsafe.Add(ref dataRef, i * _step)); } public IColor[] ToArray() diff --git a/HPPH/Images/ImageColumns.cs b/HPPH/Images/ImageColumns.cs index a9f3326..59a5eb2 100644 --- a/HPPH/Images/ImageColumns.cs +++ b/HPPH/Images/ImageColumns.cs @@ -28,7 +28,7 @@ public readonly ref struct ImageColumns [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - if ((column < 0) || (column > _width)) throw new IndexOutOfRangeException(); + if ((column < 0) || (column >= _width)) throw new IndexOutOfRangeException(); return new ImageColumn(_data, (_y * _stride) + ((column + _x) * _bpp), _height, _stride); } @@ -124,7 +124,7 @@ internal class IColorImageColumns : IImageColumns [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - if ((column < 0) || (column > _width)) throw new IndexOutOfRangeException(); + if ((column < 0) || (column >= _width)) throw new IndexOutOfRangeException(); return new IColorImageColumn(_data, (_y * _stride) + ((column + _x) * _bpp), _height, _stride); } diff --git a/HPPH/Images/ImageRow.cs b/HPPH/Images/ImageRow.cs index 9b553c4..184ad9a 100644 --- a/HPPH/Images/ImageRow.cs +++ b/HPPH/Images/ImageRow.cs @@ -152,6 +152,9 @@ internal class IColorImageRow : IImageRow public void CopyTo(Span destination) { + if (destination == null) throw new ArgumentNullException(nameof(destination)); + if (destination.Length < _length) throw new ArgumentException("The destination is too small to fit this image.", nameof(destination)); + for (int i = 0; i < _length; i++) destination[i] = this[i]; } diff --git a/HPPH/Images/ImageRows.cs b/HPPH/Images/ImageRows.cs index 22eb1af..3a20c74 100644 --- a/HPPH/Images/ImageRows.cs +++ b/HPPH/Images/ImageRows.cs @@ -27,7 +27,7 @@ public readonly ref struct ImageRows [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - if ((row < 0) || (row > _height)) throw new IndexOutOfRangeException(); + if ((row < 0) || (row >= _height)) throw new IndexOutOfRangeException(); return new ImageRow(_data, ((row + _y) * _stride) + _x, _width); } @@ -122,7 +122,7 @@ internal class IColorImageRows : IImageRows [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - if ((row < 0) || (row > _height)) throw new IndexOutOfRangeException(); + if ((row < 0) || (row >= _height)) throw new IndexOutOfRangeException(); return new IColorImageRow(_data, ((row + _y) * _stride) + _x, _width); } diff --git a/HPPH/Images/Interfaces/IImage.cs b/HPPH/Images/Interfaces/IImage.cs index ec312d4..d770079 100644 --- a/HPPH/Images/Interfaces/IImage.cs +++ b/HPPH/Images/Interfaces/IImage.cs @@ -3,7 +3,7 @@ /// /// Represents an image. /// -public interface IImage : IEnumerable +public interface IImage : IEnumerable, IEquatable { /// /// Gets the color format used in this image. @@ -61,7 +61,7 @@ public interface IImage : IEnumerable RefImage AsRefImage() where TColor : struct, IColor; IImage ConvertTo() where TColor : struct, IColor; - + /// /// Copies the contents of this into a destination instance. /// @@ -83,7 +83,7 @@ public interface IImage : IEnumerable /// /// Represents an image. /// -public interface IImage : IImage +public interface IImage : IImage, IEquatable> where T : struct, IColor { ///