diff --git a/src/ImageSharp/Memory/ArrayPoolMemoryAllocator.Buffer{T}.cs b/src/ImageSharp/Memory/ArrayPoolMemoryAllocator.Buffer{T}.cs
index 2b7497cbf..d0f68c9c6 100644
--- a/src/ImageSharp/Memory/ArrayPoolMemoryAllocator.Buffer{T}.cs
+++ b/src/ImageSharp/Memory/ArrayPoolMemoryAllocator.Buffer{T}.cs
@@ -16,7 +16,7 @@ namespace SixLabors.Memory
/// The buffer implementation of .
/// In this implementation is owned.
///
- private class Buffer : ManagedBufferBase, IBuffer
+ private class Buffer : ManagedBufferBase
where T : struct
{
///
diff --git a/src/ImageSharp/Memory/BasicArrayBuffer.cs b/src/ImageSharp/Memory/BasicArrayBuffer.cs
index 500a99069..5e3893d08 100644
--- a/src/ImageSharp/Memory/BasicArrayBuffer.cs
+++ b/src/ImageSharp/Memory/BasicArrayBuffer.cs
@@ -9,7 +9,7 @@ namespace SixLabors.Memory
///
/// Wraps an array as an instance. In this implementation is owned.
///
- internal class BasicArrayBuffer : ManagedBufferBase, IBuffer
+ internal class BasicArrayBuffer : ManagedBufferBase
where T : struct
{
public BasicArrayBuffer(T[] array, int length)
diff --git a/src/ImageSharp/Memory/Buffer2D{T}.cs b/src/ImageSharp/Memory/Buffer2D{T}.cs
index bbfe2d1d3..b62156ffb 100644
--- a/src/ImageSharp/Memory/Buffer2D{T}.cs
+++ b/src/ImageSharp/Memory/Buffer2D{T}.cs
@@ -39,6 +39,10 @@ namespace SixLabors.Memory
///
public IBuffer Buffer { get; private set; }
+ public Memory Memory => this.Buffer.Memory;
+
+ public Span Span => this.Buffer.GetSpan();
+
///
/// Gets a reference to the element at the specified position.
///
@@ -65,13 +69,34 @@ namespace SixLabors.Memory
this.Buffer?.Dispose();
}
+ ///
+ /// Swaps the contents of 'destination' with 'source' if the buffers are owned (1),
+ /// copies the contents of 'source' to 'destination' otherwise (2). Buffers should be of same size in case 2!
+ ///
+ public static void SwapOrCopyContent(Buffer2D destination, Buffer2D source)
+ {
+ if (source.Buffer.IsMemoryOwner && destination.Buffer.IsMemoryOwner)
+ {
+ SwapContents(destination, source);
+ }
+ else
+ {
+ if (destination.Size() != source.Size())
+ {
+ throw new InvalidOperationException("SwapOrCopyContents(): buffers should both owned or the same size!");
+ }
+
+ source.Span.CopyTo(destination.Span);
+ }
+ }
+
///
/// Swap the contents (, , ) of the two buffers.
/// Useful to transfer the contents of a temporary to a persistent
///
/// The first buffer
/// The second buffer
- public static void SwapContents(Buffer2D a, Buffer2D b)
+ private static void SwapContents(Buffer2D a, Buffer2D b)
{
Size aSize = a.Size();
Size bSize = b.Size();
diff --git a/src/ImageSharp/Memory/ConsumedBuffer.cs b/src/ImageSharp/Memory/ConsumedBuffer.cs
index b793b29c2..73468a381 100644
--- a/src/ImageSharp/Memory/ConsumedBuffer.cs
+++ b/src/ImageSharp/Memory/ConsumedBuffer.cs
@@ -20,6 +20,8 @@ namespace SixLabors.Memory
public Memory Memory { get; }
+ public bool IsMemoryOwner => false;
+
public Span GetSpan()
{
return this.Memory.Span;
diff --git a/src/ImageSharp/Memory/IBuffer{T}.cs b/src/ImageSharp/Memory/IBuffer{T}.cs
index 4e0e0c702..847f2741d 100644
--- a/src/ImageSharp/Memory/IBuffer{T}.cs
+++ b/src/ImageSharp/Memory/IBuffer{T}.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers;
namespace SixLabors.Memory
{
@@ -10,6 +11,8 @@ namespace SixLabors.Memory
/// Depending on it's implementation, an can (1) OWN or (2) CONSUME the instance it wraps.
/// For a deeper understanding of the owner/consumer model, read the following docs:
/// https://gist.github.com/GrabYourPitchforks/4c3e1935fd4d9fa2831dbfcab35dffc6
+ /// TODO: We need more SOC here! For owned buffers we should use .
+ /// For the consumption case we should not use buffers at all. We need to refactor Buffer2D{T} for this.
///
/// The value type
internal interface IBuffer : IDisposable
@@ -20,6 +23,11 @@ namespace SixLabors.Memory
///
Memory Memory { get; }
+ ///
+ /// Gets a value indicating whether this instance is owning the .
+ ///
+ bool IsMemoryOwner { get; }
+
///
/// Gets the span to the memory "promised" by this buffer when it's OWNED (1).
/// Gets `this.Memory.Span` when the buffer CONSUMED (2).
diff --git a/src/ImageSharp/Memory/ManagedBufferBase.cs b/src/ImageSharp/Memory/ManagedBufferBase.cs
index c1cc51274..606d1c962 100644
--- a/src/ImageSharp/Memory/ManagedBufferBase.cs
+++ b/src/ImageSharp/Memory/ManagedBufferBase.cs
@@ -9,10 +9,13 @@ namespace SixLabors.Memory
///
/// Provides a base class for implementations by implementing pinning logic for adaption.
///
- internal abstract class ManagedBufferBase : System.Buffers.MemoryManager
+ internal abstract class ManagedBufferBase : System.Buffers.MemoryManager, IBuffer
+ where T : struct
{
private GCHandle pinHandle;
+ public bool IsMemoryOwner => true;
+
///
/// Gets the object that should be pinned.
///
diff --git a/src/ImageSharp/Processing/Convolution/Processors/Convolution2DProcessor.cs b/src/ImageSharp/Processing/Convolution/Processors/Convolution2DProcessor.cs
index 5636f167c..48503e999 100644
--- a/src/ImageSharp/Processing/Convolution/Processors/Convolution2DProcessor.cs
+++ b/src/ImageSharp/Processing/Convolution/Processors/Convolution2DProcessor.cs
@@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.Processing.Convolution.Processors
}
});
- Buffer2D.SwapContents(source.PixelBuffer, targetPixels);
+ Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels);
}
}
}
diff --git a/src/ImageSharp/Processing/Convolution/Processors/ConvolutionProcessor.cs b/src/ImageSharp/Processing/Convolution/Processors/ConvolutionProcessor.cs
index 918b67caf..221cf19ec 100644
--- a/src/ImageSharp/Processing/Convolution/Processors/ConvolutionProcessor.cs
+++ b/src/ImageSharp/Processing/Convolution/Processors/ConvolutionProcessor.cs
@@ -96,7 +96,7 @@ namespace SixLabors.ImageSharp.Processing.Convolution.Processors
}
});
- Buffer2D.SwapContents(source.PixelBuffer, targetPixels);
+ Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels);
}
}
}
diff --git a/src/ImageSharp/Processing/Effects/Processors/OilPaintingProcessor.cs b/src/ImageSharp/Processing/Effects/Processors/OilPaintingProcessor.cs
index 15dd000b4..cdaa6113f 100644
--- a/src/ImageSharp/Processing/Effects/Processors/OilPaintingProcessor.cs
+++ b/src/ImageSharp/Processing/Effects/Processors/OilPaintingProcessor.cs
@@ -134,7 +134,7 @@ namespace SixLabors.ImageSharp.Processing.Effects.Processors
}
});
- Buffer2D.SwapContents(source.PixelBuffer, targetPixels);
+ Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels);
}
}
}
diff --git a/src/ImageSharp/Processing/Transforms/Processors/FlipProcessor.cs b/src/ImageSharp/Processing/Transforms/Processors/FlipProcessor.cs
index e2ec556fc..5d4961f57 100644
--- a/src/ImageSharp/Processing/Transforms/Processors/FlipProcessor.cs
+++ b/src/ImageSharp/Processing/Transforms/Processors/FlipProcessor.cs
@@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.Processing.Transforms.Processors
altSourceRow.CopyTo(targetRow);
});
- Buffer2D.SwapContents(source.PixelBuffer, targetPixels);
+ Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels);
}
}
@@ -109,7 +109,7 @@ namespace SixLabors.ImageSharp.Processing.Transforms.Processors
}
});
- Buffer2D.SwapContents(source.PixelBuffer, targetPixels);
+ Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels);
}
}
}
diff --git a/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs b/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs
index 1b473ab5f..366266652 100644
--- a/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs
+++ b/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs
@@ -6,11 +6,14 @@ using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
using Xunit;
+// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Tests.Advanced
{
using System.Buffers;
+ using SixLabors.Memory;
+
public class AdvancedImageExtensionsTests
{
public class GetPixelMemory
@@ -40,34 +43,6 @@ namespace SixLabors.ImageSharp.Tests.Advanced
}
}
- class TestMemoryManager : MemoryManager
- {
- public TestMemoryManager(TPixel[] pixelArray)
- {
- this.PixelArray = pixelArray;
- }
-
- public TPixel[] PixelArray { get; }
-
- protected override void Dispose(bool disposing)
- {
- }
-
- public override Span GetSpan()
- {
- return this.PixelArray;
- }
-
- public override MemoryHandle Pin(int elementIndex = 0)
- {
- throw new NotImplementedException();
- }
-
- public override void Unpin()
- {
- throw new NotImplementedException();
- }
- }
[Theory]
[WithSolidFilledImages(1, 1, "Red", PixelTypes.Rgba32 | PixelTypes.Bgr24)]
@@ -97,6 +72,7 @@ namespace SixLabors.ImageSharp.Tests.Advanced
image0.ComparePixelBufferTo(externalMemory.Span);
}
}
+
}
[Theory]
diff --git a/tests/ImageSharp.Tests/Image/ImageLoadTests.cs b/tests/ImageSharp.Tests/Image/ImageLoadTests.cs
deleted file mode 100644
index 35d6b5722..000000000
--- a/tests/ImageSharp.Tests/Image/ImageLoadTests.cs
+++ /dev/null
@@ -1,337 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.IO;
-using SixLabors.ImageSharp.Formats;
-using SixLabors.ImageSharp.IO;
-using Moq;
-using Xunit;
-using SixLabors.ImageSharp.Advanced;
-using SixLabors.ImageSharp.PixelFormats;
-
-namespace SixLabors.ImageSharp.Tests
-{
- ///
- /// Tests the class.
- ///
- public partial class ImageLoadTests : IDisposable
- {
- private readonly Mock fileSystem;
- private Image returnImage;
- private Mock localDecoder;
- private readonly string FilePath;
- private readonly IImageFormatDetector localMimeTypeDetector;
- private readonly Mock localImageFormatMock;
-
- public Configuration LocalConfiguration { get; private set; }
- public byte[] Marker { get; private set; }
- public MemoryStream DataStream { get; private set; }
- public byte[] DecodedData { get; private set; }
-
- public ImageLoadTests()
- {
- this.returnImage = new Image(1, 1);
-
- this.localImageFormatMock = new Mock();
-
- this.localDecoder = new Mock();
- this.localMimeTypeDetector = new MockImageFormatDetector(this.localImageFormatMock.Object);
- this.localDecoder.Setup(x => x.Decode(It.IsAny(), It.IsAny()))
-
- .Callback((c, s) =>
- {
- using (var ms = new MemoryStream())
- {
- s.CopyTo(ms);
- this.DecodedData = ms.ToArray();
- }
- })
- .Returns(this.returnImage);
-
- this.fileSystem = new Mock();
-
- this.LocalConfiguration = new Configuration
- {
- FileSystem = this.fileSystem.Object
- };
- this.LocalConfiguration.ImageFormatsManager.AddImageFormatDetector(this.localMimeTypeDetector);
- this.LocalConfiguration.ImageFormatsManager.SetDecoder(this.localImageFormatMock.Object, this.localDecoder.Object);
-
- TestFormat.RegisterGlobalTestFormat();
- this.Marker = Guid.NewGuid().ToByteArray();
- this.DataStream = TestFormat.GlobalTestFormat.CreateStream(this.Marker);
-
- this.FilePath = Guid.NewGuid().ToString();
- this.fileSystem.Setup(x => x.OpenRead(this.FilePath)).Returns(this.DataStream);
-
- TestFileSystem.RegisterGlobalTestFormat();
- TestFileSystem.Global.AddFile(this.FilePath, this.DataStream);
- }
-
- [Fact]
- public void LoadFromStream()
- {
- Image img = Image.Load(this.DataStream);
-
- Assert.NotNull(img);
-
- TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, Configuration.Default);
- }
-
- [Fact]
- public void LoadFromNoneSeekableStream()
- {
- NoneSeekableStream stream = new NoneSeekableStream(this.DataStream);
- Image img = Image.Load(stream);
-
- Assert.NotNull(img);
-
- TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, Configuration.Default);
- }
-
- [Fact]
- public void LoadFromStreamWithType()
- {
- Image img = Image.Load(this.DataStream);
-
- Assert.NotNull(img);
- Assert.Equal(TestFormat.GlobalTestFormat.Sample(), img);
-
- TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, Configuration.Default);
- }
-
-
- [Fact]
- public void LoadFromStreamWithConfig()
- {
- Stream stream = new MemoryStream();
- Image img = Image.Load(this.LocalConfiguration, stream);
-
- Assert.NotNull(img);
-
- this.localDecoder.Verify(x => x.Decode(this.LocalConfiguration, stream));
- }
-
- [Fact]
- public void LoadFromStreamWithTypeAndConfig()
- {
- Stream stream = new MemoryStream();
- Image img = Image.Load(this.LocalConfiguration, stream);
-
- Assert.NotNull(img);
- Assert.Equal(this.returnImage, img);
-
- this.localDecoder.Verify(x => x.Decode(this.LocalConfiguration, stream));
- }
-
-
- [Fact]
- public void LoadFromStreamWithDecoder()
- {
- Stream stream = new MemoryStream();
- Image img = Image.Load(stream, this.localDecoder.Object);
-
- Assert.NotNull(img);
- this.localDecoder.Verify(x => x.Decode(Configuration.Default, stream));
- }
-
- [Fact]
- public void LoadFromStreamWithTypeAndDecoder()
- {
- Stream stream = new MemoryStream();
- Image img = Image.Load(stream, this.localDecoder.Object);
-
- Assert.NotNull(img);
- Assert.Equal(this.returnImage, img);
- this.localDecoder.Verify(x => x.Decode(Configuration.Default, stream));
- }
-
- [Fact]
- public void LoadFromBytes()
- {
- Image img = Image.Load(this.DataStream.ToArray());
-
- Assert.NotNull(img);
-
- TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, Configuration.Default);
- }
-
- [Fact]
- public void LoadFromBytesWithType()
- {
- Image img = Image.Load(this.DataStream.ToArray());
-
- Assert.NotNull(img);
- Assert.Equal(TestFormat.GlobalTestFormat.Sample(), img);
-
- TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, Configuration.Default);
-
- }
-
- [Fact]
- public void LoadFromBytesWithConfig()
- {
- Image img = Image.Load(this.LocalConfiguration, this.DataStream.ToArray());
-
- Assert.NotNull(img);
-
- this.localDecoder.Verify(x => x.Decode(this.LocalConfiguration, It.IsAny()));
-
- Assert.Equal(this.DataStream.ToArray(), this.DecodedData);
- }
-
- [Fact]
- public void LoadFromBytesWithTypeAndConfig()
- {
- Image img = Image.Load(this.LocalConfiguration, this.DataStream.ToArray());
-
- Assert.NotNull(img);
- Assert.Equal(this.returnImage, img);
-
- this.localDecoder.Verify(x => x.Decode(this.LocalConfiguration, It.IsAny()));
-
- Assert.Equal(this.DataStream.ToArray(), this.DecodedData);
- }
-
- [Fact]
- public void LoadFromBytesWithDecoder()
- {
- Image img = Image.Load(this.DataStream.ToArray(), this.localDecoder.Object);
-
- Assert.NotNull(img);
- this.localDecoder.Verify(x => x.Decode(Configuration.Default, It.IsAny()));
- Assert.Equal(this.DataStream.ToArray(), this.DecodedData);
- }
-
- [Fact]
- public void LoadFromBytesWithTypeAndDecoder()
- {
- Image img = Image.Load(this.DataStream.ToArray(), this.localDecoder.Object);
-
- Assert.NotNull(img);
- Assert.Equal(this.returnImage, img);
- this.localDecoder.Verify(x => x.Decode(Configuration.Default, It.IsAny()));
- Assert.Equal(this.DataStream.ToArray(), this.DecodedData);
- }
-
- [Fact]
- public void LoadFromFile()
- {
- Image img = Image.Load(this.DataStream);
-
- Assert.NotNull(img);
-
- TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, Configuration.Default);
- }
-
- [Fact]
- public void LoadFromFileWithType()
- {
- Image img = Image.Load(this.DataStream);
-
- Assert.NotNull(img);
- Assert.Equal(TestFormat.GlobalTestFormat.Sample(), img);
-
- TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, Configuration.Default);
- }
-
- [Fact]
- public void LoadFromFileWithConfig()
- {
- Image img = Image.Load(this.LocalConfiguration, this.FilePath);
-
- Assert.NotNull(img);
-
- this.localDecoder.Verify(x => x.Decode(this.LocalConfiguration, this.DataStream));
- }
-
- [Fact]
- public void LoadFromFileWithTypeAndConfig()
- {
- Image img = Image.Load(this.LocalConfiguration, this.FilePath);
-
- Assert.NotNull(img);
- Assert.Equal(this.returnImage, img);
-
- this.localDecoder.Verify(x => x.Decode(this.LocalConfiguration, this.DataStream));
- }
-
- [Fact]
- public void LoadFromFileWithDecoder()
- {
- Image img = Image.Load(this.FilePath, this.localDecoder.Object);
-
- Assert.NotNull(img);
- this.localDecoder.Verify(x => x.Decode(Configuration.Default, this.DataStream));
- }
-
- [Fact]
- public void LoadFromFileWithTypeAndDecoder()
- {
- Image img = Image.Load(this.FilePath, this.localDecoder.Object);
-
- Assert.NotNull(img);
- Assert.Equal(this.returnImage, img);
- this.localDecoder.Verify(x => x.Decode(Configuration.Default, this.DataStream));
- }
-
- [Fact]
- public void LoadFromPixelData_Pixels()
- {
- var img = Image.LoadPixelData(new Rgba32[] {
- Rgba32.Black, Rgba32.White,
- Rgba32.White, Rgba32.Black,
- }, 2, 2);
-
- Assert.NotNull(img);
- using (var px = img.Lock())
- {
- Assert.Equal(Rgba32.Black, px[0, 0]);
- Assert.Equal(Rgba32.White, px[0, 1]);
-
- Assert.Equal(Rgba32.White, px[1, 0]);
- Assert.Equal(Rgba32.Black, px[1, 1]);
- }
- }
-
- [Fact]
- public void LoadFromPixelData_Bytes()
- {
- var img = Image.LoadPixelData(new byte[] {
- 0,0,0,255, // 0,0
- 255,255,255,255, // 0,1
- 255,255,255,255, // 1,0
- 0,0,0,255, // 1,1
- }, 2, 2);
-
- Assert.NotNull(img);
- using (var px = img.Lock())
- {
- Assert.Equal(Rgba32.Black, px[0, 0]);
- Assert.Equal(Rgba32.White, px[0, 1]);
-
- Assert.Equal(Rgba32.White, px[1, 0]);
- Assert.Equal(Rgba32.Black, px[1, 1]);
- }
- }
-
-
- [Fact]
- public void LoadsImageWithoutThrowingCrcException()
- {
- var image1Provider = TestImageProvider.File(TestImages.Png.VersioningImage1);
-
- using (Image img = image1Provider.GetImage())
- {
- Assert.Equal(166036, img.Frames.RootFrame.GetPixelSpan().Length);
- }
- }
-
- public void Dispose()
- {
- // clean up the global object;
- this.returnImage?.Dispose();
- }
- }
-}
diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Load_BasicCases.cs b/tests/ImageSharp.Tests/Image/ImageTests.Load_BasicCases.cs
new file mode 100644
index 000000000..e442b5654
--- /dev/null
+++ b/tests/ImageSharp.Tests/Image/ImageTests.Load_BasicCases.cs
@@ -0,0 +1,63 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using SixLabors.ImageSharp.PixelFormats;
+using Xunit;
+// ReSharper disable InconsistentNaming
+
+namespace SixLabors.ImageSharp.Tests
+{
+ public partial class ImageTests
+ {
+ public class Load_BasicCases
+ {
+ [Fact]
+ public void ByteArray()
+ {
+ Assert.Throws(() =>
+ {
+ Image.Load((byte[])null);
+ });
+
+ var file = TestFile.Create(TestImages.Bmp.Car);
+ using (var image = Image.Load(file.Bytes))
+ {
+ Assert.Equal(600, image.Width);
+ Assert.Equal(450, image.Height);
+ }
+ }
+
+ [Fact]
+ public void FileSystemPath()
+ {
+ var file = TestFile.Create(TestImages.Bmp.Car);
+ using (var image = Image.Load(file.FullPath))
+ {
+ Assert.Equal(600, image.Width);
+ Assert.Equal(450, image.Height);
+ }
+ }
+
+ [Fact]
+ public void FileSystemPath_FileNotFound()
+ {
+ System.IO.FileNotFoundException ex = Assert.Throws(
+ () =>
+ {
+ Image.Load(Guid.NewGuid().ToString());
+ });
+ }
+
+ [Fact]
+ public void FileSystemPath_NullPath()
+ {
+ ArgumentNullException ex = Assert.Throws(
+ () =>
+ {
+ Image.Load((string)null);
+ });
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Load_ComplexCases.cs b/tests/ImageSharp.Tests/Image/ImageTests.Load_ComplexCases.cs
new file mode 100644
index 000000000..957e5c40a
--- /dev/null
+++ b/tests/ImageSharp.Tests/Image/ImageTests.Load_ComplexCases.cs
@@ -0,0 +1,338 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using System.IO;
+
+using Moq;
+
+using SixLabors.ImageSharp.Advanced;
+using SixLabors.ImageSharp.Formats;
+using SixLabors.ImageSharp.IO;
+using SixLabors.ImageSharp.PixelFormats;
+
+using Xunit;
+// ReSharper disable InconsistentNaming
+
+namespace SixLabors.ImageSharp.Tests
+{
+ public partial class ImageTests
+ {
+ ///
+ /// Tests the class.
+ ///
+ public class Load_ComplexCases : IDisposable
+ {
+ private readonly Mock fileSystem;
+ private readonly Image returnImage;
+ private readonly Mock localDecoder;
+ private readonly string FilePath;
+ private readonly IImageFormatDetector localMimeTypeDetector;
+ private readonly Mock localImageFormatMock;
+
+ public Configuration LocalConfiguration { get; private set; }
+ public byte[] Marker { get; private set; }
+ public MemoryStream DataStream { get; private set; }
+ public byte[] DecodedData { get; private set; }
+
+ public Load_ComplexCases()
+ {
+ this.returnImage = new Image(1, 1);
+
+ this.localImageFormatMock = new Mock();
+
+ this.localDecoder = new Mock();
+ this.localMimeTypeDetector = new MockImageFormatDetector(this.localImageFormatMock.Object);
+ this.localDecoder.Setup(x => x.Decode(It.IsAny(), It.IsAny()))
+
+ .Callback((c, s) =>
+ {
+ using (var ms = new MemoryStream())
+ {
+ s.CopyTo(ms);
+ this.DecodedData = ms.ToArray();
+ }
+ })
+ .Returns(this.returnImage);
+
+ this.fileSystem = new Mock();
+
+ this.LocalConfiguration = new Configuration
+ {
+ FileSystem = this.fileSystem.Object
+ };
+ this.LocalConfiguration.ImageFormatsManager.AddImageFormatDetector(this.localMimeTypeDetector);
+ this.LocalConfiguration.ImageFormatsManager.SetDecoder(this.localImageFormatMock.Object, this.localDecoder.Object);
+
+ TestFormat.RegisterGlobalTestFormat();
+ this.Marker = Guid.NewGuid().ToByteArray();
+ this.DataStream = TestFormat.GlobalTestFormat.CreateStream(this.Marker);
+
+ this.FilePath = Guid.NewGuid().ToString();
+ this.fileSystem.Setup(x => x.OpenRead(this.FilePath)).Returns(this.DataStream);
+
+ TestFileSystem.RegisterGlobalTestFormat();
+ TestFileSystem.Global.AddFile(this.FilePath, this.DataStream);
+ }
+
+ [Fact]
+ public void LoadFromStream()
+ {
+ var img = Image.Load(this.DataStream);
+
+ Assert.NotNull(img);
+
+ TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, Configuration.Default);
+ }
+
+ [Fact]
+ public void LoadFromNoneSeekableStream()
+ {
+ var stream = new NoneSeekableStream(this.DataStream);
+ var img = Image.Load(stream);
+
+ Assert.NotNull(img);
+
+ TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, Configuration.Default);
+ }
+
+ [Fact]
+ public void LoadFromStreamWithType()
+ {
+ var img = Image.Load(this.DataStream);
+
+ Assert.NotNull(img);
+ Assert.Equal(TestFormat.GlobalTestFormat.Sample(), img);
+
+ TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, Configuration.Default);
+ }
+
+
+ [Fact]
+ public void LoadFromStreamWithConfig()
+ {
+ Stream stream = new MemoryStream();
+ var img = Image.Load(this.LocalConfiguration, stream);
+
+ Assert.NotNull(img);
+
+ this.localDecoder.Verify(x => x.Decode(this.LocalConfiguration, stream));
+ }
+
+ [Fact]
+ public void LoadFromStreamWithTypeAndConfig()
+ {
+ Stream stream = new MemoryStream();
+ var img = Image.Load(this.LocalConfiguration, stream);
+
+ Assert.NotNull(img);
+ Assert.Equal(this.returnImage, img);
+
+ this.localDecoder.Verify(x => x.Decode(this.LocalConfiguration, stream));
+ }
+
+
+ [Fact]
+ public void LoadFromStreamWithDecoder()
+ {
+ Stream stream = new MemoryStream();
+ var img = Image.Load(stream, this.localDecoder.Object);
+
+ Assert.NotNull(img);
+ this.localDecoder.Verify(x => x.Decode(Configuration.Default, stream));
+ }
+
+ [Fact]
+ public void LoadFromStreamWithTypeAndDecoder()
+ {
+ Stream stream = new MemoryStream();
+ var img = Image.Load(stream, this.localDecoder.Object);
+
+ Assert.NotNull(img);
+ Assert.Equal(this.returnImage, img);
+ this.localDecoder.Verify(x => x.Decode(Configuration.Default, stream));
+ }
+
+ [Fact]
+ public void LoadFromBytes()
+ {
+ var img = Image.Load(this.DataStream.ToArray());
+
+ Assert.NotNull(img);
+
+ TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, Configuration.Default);
+ }
+
+ [Fact]
+ public void LoadFromBytesWithType()
+ {
+ var img = Image.Load(this.DataStream.ToArray());
+
+ Assert.NotNull(img);
+ Assert.Equal(TestFormat.GlobalTestFormat.Sample(), img);
+
+ TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, Configuration.Default);
+
+ }
+
+ [Fact]
+ public void LoadFromBytesWithConfig()
+ {
+ var img = Image.Load(this.LocalConfiguration, this.DataStream.ToArray());
+
+ Assert.NotNull(img);
+
+ this.localDecoder.Verify(x => x.Decode(this.LocalConfiguration, It.IsAny()));
+
+ Assert.Equal(this.DataStream.ToArray(), this.DecodedData);
+ }
+
+ [Fact]
+ public void LoadFromBytesWithTypeAndConfig()
+ {
+ var img = Image.Load(this.LocalConfiguration, this.DataStream.ToArray());
+
+ Assert.NotNull(img);
+ Assert.Equal(this.returnImage, img);
+
+ this.localDecoder.Verify(x => x.Decode(this.LocalConfiguration, It.IsAny()));
+
+ Assert.Equal(this.DataStream.ToArray(), this.DecodedData);
+ }
+
+ [Fact]
+ public void LoadFromBytesWithDecoder()
+ {
+ var img = Image.Load(this.DataStream.ToArray(), this.localDecoder.Object);
+
+ Assert.NotNull(img);
+ this.localDecoder.Verify(x => x.Decode(Configuration.Default, It.IsAny()));
+ Assert.Equal(this.DataStream.ToArray(), this.DecodedData);
+ }
+
+ [Fact]
+ public void LoadFromBytesWithTypeAndDecoder()
+ {
+ var img = Image.Load(this.DataStream.ToArray(), this.localDecoder.Object);
+
+ Assert.NotNull(img);
+ Assert.Equal(this.returnImage, img);
+ this.localDecoder.Verify(x => x.Decode(Configuration.Default, It.IsAny()));
+ Assert.Equal(this.DataStream.ToArray(), this.DecodedData);
+ }
+
+ [Fact]
+ public void LoadFromFile()
+ {
+ var img = Image.Load(this.DataStream);
+
+ Assert.NotNull(img);
+
+ TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, Configuration.Default);
+ }
+
+ [Fact]
+ public void LoadFromFileWithType()
+ {
+ var img = Image.Load(this.DataStream);
+
+ Assert.NotNull(img);
+ Assert.Equal(TestFormat.GlobalTestFormat.Sample(), img);
+
+ TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, Configuration.Default);
+ }
+
+ [Fact]
+ public void LoadFromFileWithConfig()
+ {
+ var img = Image.Load(this.LocalConfiguration, this.FilePath);
+
+ Assert.NotNull(img);
+
+ this.localDecoder.Verify(x => x.Decode(this.LocalConfiguration, this.DataStream));
+ }
+
+ [Fact]
+ public void LoadFromFileWithTypeAndConfig()
+ {
+ var img = Image.Load(this.LocalConfiguration, this.FilePath);
+
+ Assert.NotNull(img);
+ Assert.Equal(this.returnImage, img);
+
+ this.localDecoder.Verify(x => x.Decode(this.LocalConfiguration, this.DataStream));
+ }
+
+ [Fact]
+ public void LoadFromFileWithDecoder()
+ {
+ var img = Image.Load(this.FilePath, this.localDecoder.Object);
+
+ Assert.NotNull(img);
+ this.localDecoder.Verify(x => x.Decode(Configuration.Default, this.DataStream));
+ }
+
+ [Fact]
+ public void LoadFromFileWithTypeAndDecoder()
+ {
+ var img = Image.Load(this.FilePath, this.localDecoder.Object);
+
+ Assert.NotNull(img);
+ Assert.Equal(this.returnImage, img);
+ this.localDecoder.Verify(x => x.Decode(Configuration.Default, this.DataStream));
+ }
+
+ [Fact]
+ public void LoadFromPixelData_Pixels()
+ {
+ var img = Image.LoadPixelData(new Rgba32[] {
+ Rgba32.Black, Rgba32.White,
+ Rgba32.White, Rgba32.Black,
+ }, 2, 2);
+
+ Assert.NotNull(img);
+ Assert.Equal(Rgba32.Black, img[0, 0]);
+ Assert.Equal(Rgba32.White, img[0, 1]);
+
+ Assert.Equal(Rgba32.White, img[1, 0]);
+ Assert.Equal(Rgba32.Black, img[1, 1]);
+ }
+
+ [Fact]
+ public void LoadFromPixelData_Bytes()
+ {
+ var img = Image.LoadPixelData(new byte[] {
+ 0,0,0,255, // 0,0
+ 255,255,255,255, // 0,1
+ 255,255,255,255, // 1,0
+ 0,0,0,255, // 1,1
+ }, 2, 2);
+
+ Assert.NotNull(img);
+ Assert.Equal(Rgba32.Black, img[0, 0]);
+ Assert.Equal(Rgba32.White, img[0, 1]);
+
+ Assert.Equal(Rgba32.White, img[1, 0]);
+ Assert.Equal(Rgba32.Black, img[1, 1]);
+ }
+
+
+ [Fact]
+ public void LoadsImageWithoutThrowingCrcException()
+ {
+ var image1Provider = TestImageProvider.File(TestImages.Png.VersioningImage1);
+
+ using (Image img = image1Provider.GetImage())
+ {
+ Assert.Equal(166036, img.Frames.RootFrame.GetPixelSpan().Length);
+ }
+ }
+
+ public void Dispose()
+ {
+ // clean up the global object;
+ this.returnImage?.Dispose();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Save.cs b/tests/ImageSharp.Tests/Image/ImageTests.Save.cs
new file mode 100644
index 000000000..45399919a
--- /dev/null
+++ b/tests/ImageSharp.Tests/Image/ImageTests.Save.cs
@@ -0,0 +1,70 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+// ReSharper disable InconsistentNaming
+
+using System;
+using SixLabors.ImageSharp.Formats.Png;
+using SixLabors.ImageSharp.PixelFormats;
+using Xunit;
+
+namespace SixLabors.ImageSharp.Tests
+{
+ using SixLabors.ImageSharp.Formats;
+
+ public partial class ImageTests
+ {
+ public class Save
+ {
+ [Fact]
+ public void DetecedEncoding()
+ {
+ string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageTests));
+ string file = System.IO.Path.Combine(dir, "DetecedEncoding.png");
+
+ using (var image = new Image(10, 10))
+ {
+ image.Save(file);
+ }
+
+ using (var img = Image.Load(file, out IImageFormat mime))
+ {
+ Assert.Equal("image/png", mime.DefaultMimeType);
+ }
+ }
+
+ [Fact]
+ public void WhenExtensionIsUnknown_Throws()
+ {
+ string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageTests));
+ string file = System.IO.Path.Combine(dir, "UnknownExtensionsEncoding_Throws.tmp");
+
+ NotSupportedException ex = Assert.Throws(
+ () =>
+ {
+ using (var image = new Image(10, 10))
+ {
+ image.Save(file);
+ }
+ });
+ }
+
+ [Fact]
+ public void SetEncoding()
+ {
+ string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageTests));
+ string file = System.IO.Path.Combine(dir, "SetEncoding.dat");
+
+ using (var image = new Image(10, 10))
+ {
+ image.Save(file, new PngEncoder());
+ }
+
+ using (var img = Image.Load(file, out var mime))
+ {
+ Assert.Equal("image/png", mime.DefaultMimeType);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs b/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs
new file mode 100644
index 000000000..066be4a73
--- /dev/null
+++ b/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs
@@ -0,0 +1,24 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using SixLabors.Memory;
+using Xunit;
+
+// ReSharper disable InconsistentNaming
+namespace SixLabors.ImageSharp.Tests
+{
+ public partial class ImageTests
+ {
+ public class WrapMemory
+ {
+ [Fact]
+ public void ConsumedBuffer_IsMemoryOwner_ReturnsFalse()
+ {
+ var memory = new Memory(new int[55]);
+ var buffer = new ConsumedBuffer(memory);
+ Assert.False(buffer.IsMemoryOwner);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Image/ImageTests.cs b/tests/ImageSharp.Tests/Image/ImageTests.cs
index 8234df24e..ed142ed97 100644
--- a/tests/ImageSharp.Tests/Image/ImageTests.cs
+++ b/tests/ImageSharp.Tests/Image/ImageTests.cs
@@ -1,19 +1,17 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System;
using SixLabors.ImageSharp.Advanced;
-using SixLabors.ImageSharp.Formats;
-using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;
using Xunit;
+// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Tests
{
///
/// Tests the class.
///
- public class ImageTests
+ public partial class ImageTests
{
public class Constructor
{
@@ -64,101 +62,5 @@ namespace SixLabors.ImageSharp.Tests
}
}
}
-
- [Fact]
- public void Load_ByteArray()
- {
- Assert.Throws(() =>
- {
- Image.Load((byte[])null);
- });
-
- TestFile file = TestFile.Create(TestImages.Bmp.Car);
- using (Image image = Image.Load(file.Bytes))
- {
- Assert.Equal(600, image.Width);
- Assert.Equal(450, image.Height);
- }
- }
-
- [Fact]
- public void Load_FileSystemPath()
- {
- TestFile file = TestFile.Create(TestImages.Bmp.Car);
- using (Image image = Image.Load(file.FullPath))
- {
- Assert.Equal(600, image.Width);
- Assert.Equal(450, image.Height);
- }
- }
-
- [Fact]
- public void Load_FileSystemPath_FileNotFound()
- {
- System.IO.FileNotFoundException ex = Assert.Throws(
- () =>
- {
- Image.Load(Guid.NewGuid().ToString());
- });
- }
-
- [Fact]
- public void Load_FileSystemPath_NullPath()
- {
- ArgumentNullException ex = Assert.Throws(
- () =>
- {
- Image.Load((string)null);
- });
- }
-
- [Fact]
- public void Save_DetecedEncoding()
- {
- string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageTests));
- string file = System.IO.Path.Combine(dir, "Save_DetecedEncoding.png");
-
- using (Image image = new Image(10, 10))
- {
- image.Save(file);
- }
-
- using (Image img = Image.Load(file, out var mime))
- {
- Assert.Equal("image/png", mime.DefaultMimeType);
- }
- }
-
- [Fact]
- public void Save_WhenExtensionIsUnknown_Throws()
- {
- string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageTests));
- string file = System.IO.Path.Combine(dir, "Save_UnknownExtensionsEncoding_Throws.tmp");
-
- NotSupportedException ex = Assert.Throws(
- () =>
- {
- using (Image image = new Image(10, 10))
- {
- image.Save(file);
- }
- });
- }
-
- [Fact]
- public void Save_SetEncoding()
- {
- string dir = TestEnvironment.CreateOutputDirectory(nameof(ImageTests));
- string file = System.IO.Path.Combine(dir, "Save_SetEncoding.dat");
-
- using (Image image = new Image(10, 10))
- {
- image.Save(file, new PngEncoder());
- }
- using (Image img = Image.Load(file, out var mime))
- {
- Assert.Equal("image/png", mime.DefaultMimeType);
- }
- }
}
}
diff --git a/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs b/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs
index f22e558f3..301a76f56 100644
--- a/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs
+++ b/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs
@@ -1,11 +1,14 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
+// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Tests.Memory
{
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+
+ using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.ImageSharp.Tests.Common;
using SixLabors.Primitives;
@@ -128,22 +131,92 @@ namespace SixLabors.ImageSharp.Tests.Memory
Assert.True(Unsafe.AreSame(ref expected, ref actual));
}
}
-
- [Fact]
- public void SwapContents()
+
+ public class SwapOrCopyContent
{
- using (Buffer2D a = this.MemoryAllocator.Allocate2D(10, 5))
- using (Buffer2D b = this.MemoryAllocator.Allocate2D(3, 7))
+ private MemoryAllocator MemoryAllocator { get; } = new MockMemoryAllocator();
+
+ [Fact]
+ public void WhenBothBuffersAreMemoryOwners_ShouldSwap()
+ {
+ using (Buffer2D a = this.MemoryAllocator.Allocate2D(10, 5))
+ using (Buffer2D b = this.MemoryAllocator.Allocate2D(3, 7))
+ {
+ IBuffer aa = a.Buffer;
+ IBuffer bb = b.Buffer;
+
+ Buffer2D.SwapOrCopyContent(a, b);
+
+ Assert.Equal(bb, a.Buffer);
+ Assert.Equal(aa, b.Buffer);
+
+ Assert.Equal(new Size(3, 7), a.Size());
+ Assert.Equal(new Size(10, 5), b.Size());
+ }
+ }
+
+ [Fact]
+ public void WhenDestIsNotMemoryOwner_SameSize_ShouldCopy()
+ {
+ var data = new Rgba32[3 * 7];
+ var color = new Rgba32(1, 2, 3, 4);
+
+ var mmg = new TestMemoryManager(data);
+ var aBuff = new ConsumedBuffer(mmg.Memory);
+
+ using (Buffer2D a = new Buffer2D(aBuff, 3, 7))
+ {
+ IBuffer aa = a.Buffer;
+
+ // Precondition:
+ Assert.Equal(aBuff, aa);
+
+ using (Buffer2D b = this.MemoryAllocator.Allocate2D(3, 7))
+ {
+ IBuffer bb = b.Buffer;
+ bb.GetSpan()[10] = color;
+
+ // Act:
+ Buffer2D.SwapOrCopyContent(a, b);
+
+ // Assert:
+ Assert.Equal(aBuff, a.Buffer);
+ Assert.Equal(bb, b.Buffer);
+ }
+
+ // Assert:
+ Assert.Equal(color, a.Buffer.GetSpan()[10]);
+ }
+ }
+
+ [Fact]
+ public void WhenDestIsNotMemoryOwner_DifferentSize_Throws()
{
- IBuffer aa = a.Buffer;
- IBuffer bb = b.Buffer;
+ var data = new Rgba32[3 * 7];
+ var color = new Rgba32(1, 2, 3, 4);
+ data[10] = color;
- Buffer2D.SwapContents(a, b);
+ var mmg = new TestMemoryManager(data);
+ var aBuff = new ConsumedBuffer(mmg.Memory);
- Assert.Equal(bb, a.Buffer);
- Assert.Equal(new Size(3, 7), a.Size());
- Assert.Equal(new Size(10, 5), b.Size());
+ using (Buffer2D a = new Buffer2D(aBuff, 3, 7))
+ {
+ IBuffer aa = a.Buffer;
+ using (Buffer2D b = this.MemoryAllocator.Allocate2D(3, 8))
+ {
+ IBuffer bb = b.Buffer;
+
+ Assert.ThrowsAny(
+ () =>
+ {
+ Buffer2D.SwapOrCopyContent(a, b);
+ });
+ }
+
+ Assert.Equal(color, a.Buffer.GetSpan()[10]);
+ }
}
+
}
}
}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Memory/BufferTestSuite.cs b/tests/ImageSharp.Tests/Memory/BufferTestSuite.cs
index b7e5cfb32..6530850ec 100644
--- a/tests/ImageSharp.Tests/Memory/BufferTestSuite.cs
+++ b/tests/ImageSharp.Tests/Memory/BufferTestSuite.cs
@@ -64,6 +64,15 @@ namespace SixLabors.ImageSharp.Tests.Memory
public static readonly TheoryData LenthValues = new TheoryData { 0, 1, 7, 1023, 1024 };
+ [Fact]
+ public void IsMemoryOwner()
+ {
+ using (IBuffer buffer = this.MemoryAllocator.Allocate(42))
+ {
+ Assert.True(buffer.IsMemoryOwner);
+ }
+ }
+
[Theory]
[MemberData(nameof(LenthValues))]
public void HasCorrectLength_byte(int desiredLength)
diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs
index e83d7009b..87a057549 100644
--- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs
+++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs
@@ -7,9 +7,12 @@ using SixLabors.ImageSharp.Processing.Convolution;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
using SixLabors.Primitives;
using Xunit;
+// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution
{
+ using SixLabors.ImageSharp.Advanced;
+
public class DetectEdgesTest : FileTestBase
{
private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.001f);
@@ -30,6 +33,21 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution
EdgeDetectionOperators.Sobel
};
+ [Theory]
+ [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)]
+ public void DetectEdges_WorksOnWrappedMemoryImage(TestImageProvider provider)
+ where TPixel : struct, IPixel
+ {
+ provider.RunValidatingProcessorTestOnWrappedMemoryImage(
+ ctx =>
+ {
+ Size size = ctx.GetCurrentSize();
+ var bounds = new Rectangle(10, 10, size.Width / 2, size.Height / 2);
+ ctx.DetectEdges(bounds);
+ },
+ testName: nameof(this.DetectEdges_InBox));
+ }
+
[Theory]
[WithTestPatternImages(nameof(DetectEdgesFilters), 100, 100, DefaultPixelType)]
[WithFileCollection(nameof(CommonTestImages), nameof(DetectEdgesFilters), DefaultPixelType)]
diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/FlipTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/FlipTests.cs
index 3f028259c..dd475675b 100644
--- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/FlipTests.cs
+++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/FlipTests.cs
@@ -5,6 +5,7 @@ using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using Xunit;
+// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
{
@@ -23,15 +24,21 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
};
[Theory]
- [WithFileCollection(nameof(FlipFiles), nameof(FlipValues), DefaultPixelType)]
- public void ImageShouldFlip(TestImageProvider provider, FlipMode flipType)
+ [WithTestPatternImages(nameof(FlipValues), 53, 37, DefaultPixelType)]
+ [WithTestPatternImages(nameof(FlipValues), 17, 32, DefaultPixelType)]
+ public void Flip(TestImageProvider provider, FlipMode flipMode)
where TPixel : struct, IPixel
{
- using (Image image = provider.GetImage())
- {
- image.Mutate(x => x.Flip(flipType));
- image.DebugSave(provider, flipType);
- }
+ provider.RunValidatingProcessorTest(ctx => ctx.Flip(flipMode), testOutputDetails: flipMode);
+ }
+
+ [Theory]
+ [WithTestPatternImages(nameof(FlipValues), 53, 37, DefaultPixelType)]
+ [WithTestPatternImages(nameof(FlipValues), 17, 32, DefaultPixelType)]
+ public void Flip_WorksOnWrappedMemoryImage(TestImageProvider provider, FlipMode flipMode)
+ where TPixel : struct, IPixel
+ {
+ provider.RunValidatingProcessorTestOnWrappedMemoryImage(ctx => ctx.Flip(flipMode), testOutputDetails: flipMode);
}
}
}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/TestUtilities/TestMemoryManager.cs b/tests/ImageSharp.Tests/TestUtilities/TestMemoryManager.cs
new file mode 100644
index 000000000..e7ecb2dda
--- /dev/null
+++ b/tests/ImageSharp.Tests/TestUtilities/TestMemoryManager.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Buffers;
+
+namespace SixLabors.ImageSharp.Tests
+{
+ using SixLabors.ImageSharp.Advanced;
+ using SixLabors.ImageSharp.PixelFormats;
+
+ class TestMemoryManager : MemoryManager
+ where T : struct, IPixel
+ {
+ public TestMemoryManager(T[] pixelArray)
+ {
+ this.PixelArray = pixelArray;
+ }
+
+ public T[] PixelArray { get; }
+
+ protected override void Dispose(bool disposing)
+ {
+ }
+
+ public override Span GetSpan()
+ {
+ return this.PixelArray;
+ }
+
+ public override MemoryHandle Pin(int elementIndex = 0)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void Unpin()
+ {
+ throw new NotImplementedException();
+ }
+
+ public static TestMemoryManager CreateAsCopyOfPixelData(Span pixelData)
+ {
+ var pixelArray = new T[pixelData.Length];
+ pixelData.CopyTo(pixelArray);
+ return new TestMemoryManager(pixelArray);
+ }
+
+ public static TestMemoryManager CreateAsCopyOfPixelData(Image