diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index 04176e033..4faccc58f 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -265,7 +265,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp using (var buffer = Buffer2D.CreateClean(width, height)) { - this.UncompressRle8(width, buffer); + this.UncompressRle8(width, buffer.Span); for (int y = 0; y < height; y++) { @@ -385,7 +385,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp padding = 4 - padding; } - using (var row = Buffer.CreateClean(arrayWidth + padding)) + using (var row = MemoryManager.Current.Allocate(arrayWidth + padding, true)) { var color = default(TPixel); var rgba = new Rgba32(0, 0, 0, 255); @@ -435,7 +435,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp var color = default(TPixel); var rgba = new Rgba32(0, 0, 0, 255); - using (var buffer = new Buffer(stride)) + using (var buffer = MemoryManager.Current.Allocate(stride)) { for (int y = 0; y < height; y++) { diff --git a/src/ImageSharp/Image/PixelAccessor{TPixel}.cs b/src/ImageSharp/Image/PixelAccessor{TPixel}.cs index 8dcb1f760..70d67954c 100644 --- a/src/ImageSharp/Image/PixelAccessor{TPixel}.cs +++ b/src/ImageSharp/Image/PixelAccessor{TPixel}.cs @@ -86,7 +86,7 @@ namespace SixLabors.ImageSharp /// /// Gets the pixel buffer array. /// - public TPixel[] PixelArray => this.PixelBuffer.Array; + public TPixel[] PixelArray => this.PixelBuffer.Buffer.Array; /// /// Gets the size of a single pixel in the number of bytes. @@ -105,7 +105,7 @@ namespace SixLabors.ImageSharp public int Height { get; private set; } /// - Span IBuffer2D.Span => this.PixelBuffer; + Span IBuffer2D.Span => this.PixelBuffer.Span; private static PixelOperations Operations => PixelOperations.Instance; @@ -158,7 +158,7 @@ namespace SixLabors.ImageSharp /// public void Reset() { - this.PixelBuffer.Clear(); + this.PixelBuffer.Buffer.Clear(); } /// diff --git a/src/ImageSharp/Memory/Buffer2D{T}.cs b/src/ImageSharp/Memory/Buffer2D{T}.cs index 99b10cae7..6dd4c93a5 100644 --- a/src/ImageSharp/Memory/Buffer2D{T}.cs +++ b/src/ImageSharp/Memory/Buffer2D{T}.cs @@ -6,14 +6,15 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Memory { + using System; + /// /// Represents a buffer of value type objects /// interpreted as a 2D region of x elements. /// /// The value type. - internal class Buffer2D : Buffer, IBuffer2D - where T : struct - { + internal class Buffer2D : IBuffer2D, IDisposable + where T : struct { public Buffer2D(Size size) : this(size.Width, size.Height) { @@ -25,7 +26,7 @@ namespace SixLabors.ImageSharp.Memory /// The number of elements in a row /// The number of rows public Buffer2D(int width, int height) - : base(width * height) + : this(MemoryManager.Current.Allocate(width * height), width, height) { this.Width = width; this.Height = height; @@ -37,9 +38,20 @@ namespace SixLabors.ImageSharp.Memory /// The array to pin /// The number of elements in a row /// The number of rows - public Buffer2D(T[] array, int width, int height) - : base(array, width * height) - { + public Buffer2D(T[] array, int width, int height) { + this.Buffer = new Buffer(array, width * height); + this.Width = width; + this.Height = height; + } + + /// + /// Initializes a new instance of the class. + /// + /// The buffer to wrap + /// The number of elements in a row + /// The number of rows + public Buffer2D(Buffer wrappedBuffer, int width, int height) { + this.Buffer = wrappedBuffer; this.Width = width; this.Height = height; } @@ -50,6 +62,10 @@ namespace SixLabors.ImageSharp.Memory /// public int Height { get; } + public Span Span => this.Buffer.Span; + + public Buffer Buffer { get; } + /// /// Gets a reference to the element at the specified position. /// @@ -64,7 +80,7 @@ namespace SixLabors.ImageSharp.Memory DebugGuard.MustBeLessThan(x, this.Width, nameof(x)); DebugGuard.MustBeLessThan(y, this.Height, nameof(y)); - return ref this.Array[(this.Width * y) + x]; + return ref this.Buffer.Array[(this.Width * y) + x]; } } @@ -76,9 +92,7 @@ namespace SixLabors.ImageSharp.Memory /// The instance public static Buffer2D CreateClean(int width, int height) { - var buffer = new Buffer2D(width, height); - buffer.Clear(); - return buffer; + return new Buffer2D(MemoryManager.Current.Allocate(width*height, true), width, height); } /// @@ -87,5 +101,9 @@ namespace SixLabors.ImageSharp.Memory /// The size of the buffer /// The instance public static Buffer2D CreateClean(Size size) => CreateClean(size.Width, size.Height); + + public void Dispose() { + this.Buffer?.Dispose(); + } } } \ No newline at end of file diff --git a/src/ImageSharp/Memory/Buffer{T}.cs b/src/ImageSharp/Memory/Buffer{T}.cs index f5c9ed00a..186a2212c 100644 --- a/src/ImageSharp/Memory/Buffer{T}.cs +++ b/src/ImageSharp/Memory/Buffer{T}.cs @@ -71,6 +71,12 @@ namespace SixLabors.ImageSharp.Memory this.isPoolingOwner = false; } + internal Buffer(T[] array, int length, MemoryManager memoryManager) + : this(array, length) + { + this.memoryManager = memoryManager; + } + /// /// Finalizes an instance of the class. /// diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs index 22a7c90b7..9d76bf60f 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs @@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.Processing.Processors { this.flatStartIndex = (index * buffer.Width) + left; this.Left = left; - this.buffer = buffer; + this.buffer = buffer.Buffer; this.Length = length; } @@ -69,7 +69,7 @@ namespace SixLabors.ImageSharp.Processing.Processors /// /// The [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Span GetWindowSpan() => this.buffer.Slice(this.flatStartIndex, this.Length); + public Span GetWindowSpan() => this.buffer.Span.Slice(this.flatStartIndex, this.Length); /// /// Computes the sum of vectors in 'rowSpan' weighted by weight values, pointed by this instance. diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs index 17b42c504..bb0845776 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs @@ -123,7 +123,7 @@ namespace SixLabors.ImageSharp.Processing.Processors // TODO: Using a transposed variant of 'firstPassPixels' could eliminate the need for the WeightsWindow.ComputeWeightedColumnSum() method, and improve speed! using (var firstPassPixels = new Buffer2D(width, source.Height)) { - firstPassPixels.Clear(); + firstPassPixels.Buffer.Clear(); Parallel.For( 0, diff --git a/tests/ImageSharp.Benchmarks/General/PixelIndexing.cs b/tests/ImageSharp.Benchmarks/General/PixelIndexing.cs index 0e21caffb..b0560b163 100644 --- a/tests/ImageSharp.Benchmarks/General/PixelIndexing.cs +++ b/tests/ImageSharp.Benchmarks/General/PixelIndexing.cs @@ -33,9 +33,9 @@ public Data(Buffer2D buffer) { - this.pointer = (Vector4*)buffer.Pin(); - this.pinnable = Unsafe.As>(buffer.Array); - this.array = buffer.Array; + this.pointer = (Vector4*)buffer.Buffer.Pin(); + this.pinnable = Unsafe.As>(buffer.Buffer.Array); + this.array = buffer.Buffer.Array; this.width = buffer.Width; } @@ -150,8 +150,8 @@ { this.width = 2048; this.buffer = new Buffer2D(2048, 2048); - this.pointer = (Vector4*)this.buffer.Pin(); - this.array = this.buffer.Array; + this.pointer = (Vector4*)this.buffer.Buffer.Pin(); + this.array = this.buffer.Buffer.Array; this.pinnable = Unsafe.As>(this.array); this.startIndex = 2048 / 2 - (this.Count / 2); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs index 6e68c43f2..46d832883 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs @@ -106,7 +106,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg this.Output.WriteLine($"Component{i}: {diff}"); averageDifference += diff.average; totalDifference += diff.total; - tolerance += libJpegComponent.SpectralBlocks.Length; + tolerance += libJpegComponent.SpectralBlocks.Buffer.Length; } averageDifference /= componentCount; diff --git a/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs b/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs index d662a1b3e..7ab0ed949 100644 --- a/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs +++ b/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs @@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.Tests.Memory { Assert.Equal(width, buffer.Width); Assert.Equal(height, buffer.Height); - Assert.Equal(width * height, buffer.Length); + Assert.Equal(width * height, buffer.Buffer.Length); } } @@ -49,7 +49,7 @@ namespace SixLabors.ImageSharp.Tests.Memory { Assert.Equal(width, buffer.Width); Assert.Equal(height, buffer.Height); - Assert.Equal(width * height, buffer.Length); + Assert.Equal(width * height, buffer.Buffer.Length); } } @@ -61,10 +61,10 @@ namespace SixLabors.ImageSharp.Tests.Memory { using (Buffer2D buffer = Buffer2D.CreateClean(42, 42)) { - for (int j = 0; j < buffer.Length; j++) + for (int j = 0; j < buffer.Buffer.Length; j++) { - Assert.Equal(0, buffer.Array[j]); - buffer.Array[j] = 666; + Assert.Equal(0, buffer.Buffer.Array[j]); + buffer.Buffer.Array[j] = 666; } } } @@ -82,7 +82,7 @@ namespace SixLabors.ImageSharp.Tests.Memory // Assert.Equal(width * y, span.Start); Assert.Equal(width, span.Length); - Assert.SpanPointsTo(span, buffer, width * y); + Assert.SpanPointsTo(span, buffer.Buffer, width * y); } } @@ -98,7 +98,7 @@ namespace SixLabors.ImageSharp.Tests.Memory // Assert.Equal(width * y + x, span.Start); Assert.Equal(width - x, span.Length); - Assert.SpanPointsTo(span, buffer, width * y + x); + Assert.SpanPointsTo(span, buffer.Buffer, width * y + x); } } @@ -110,7 +110,7 @@ namespace SixLabors.ImageSharp.Tests.Memory { using (Buffer2D buffer = new Buffer2D(width, height)) { - TestStructs.Foo[] array = buffer.Array; + TestStructs.Foo[] array = buffer.Buffer.Array; ref TestStructs.Foo actual = ref buffer[x, y]; diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index 2b3cb1bcc..fbada505a 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -233,9 +233,9 @@ namespace SixLabors.ImageSharp.Tests Span pixels = image.Frames.RootFrame.GetPixelSpan(); - for (int i = 0; i < buffer.Length; i++) + for (int i = 0; i < buffer.Buffer.Length; i++) { - float value = buffer[i] * scale; + float value = buffer.Buffer[i] * scale; var v = new Vector4(value, value, value, 1f); pixels[i].PackFromVector4(v); }