From 07baed95c26d67d8ebd6199f3ddf81d2fb39fe4c Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 23 Feb 2018 01:30:30 +0100 Subject: [PATCH] replaced PixelAccessor with Buffer2D in several processors --- src/ImageSharp/Formats/Gif/GifDecoderCore.cs | 29 ++----------------- src/ImageSharp/Image/ImageFrame{TPixel}.cs | 20 +++++++++++-- src/ImageSharp/Memory/Buffer2D{T}.cs | 22 ++++++++++++-- .../Memory/MemoryManagerExtensions.cs | 6 ++++ .../Convolution/Convolution2DProcessor.cs | 4 +-- .../Convolution/Convolution2PassProcessor.cs | 13 ++++----- .../Convolution/ConvolutionProcessor.cs | 5 ++-- .../Effects/OilPaintingProcessor.cs | 6 ++-- .../Processors/Transforms/CropProcessor.cs | 4 +-- .../Processors/Transforms/FlipProcessor.cs | 7 +++-- .../Formats/Bmp/BmpEncoderTests.cs | 2 -- .../ImageSharp.Tests/Memory/Buffer2DTests.cs | 18 ++++++++++++ .../Convolution/GaussianBlurTest.cs | 9 ++---- .../Processors/Effects/OilPaintTest.cs | 10 +++---- .../Processors/Transforms/FlipTests.cs | 2 +- 15 files changed, 90 insertions(+), 67 deletions(-) diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs index 8fd7f04d2..48c8ceb8c 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs @@ -442,7 +442,7 @@ namespace SixLabors.ImageSharp.Formats.Gif imageFrame = currentFrame; - this.RestoreToBackground(imageFrame, image.Width, image.Height); + this.RestoreToBackground(imageFrame); } int i = 0; @@ -532,9 +532,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// The pixel format. /// The frame. - /// Width of the image. - /// Height of the image. - private void RestoreToBackground(ImageFrame frame, int imageWidth, int imageHeight) + private void RestoreToBackground(ImageFrame frame) where TPixel : struct, IPixel { if (this.restoreArea == null) @@ -545,29 +543,6 @@ namespace SixLabors.ImageSharp.Formats.Gif BufferArea pixelArea = frame.PixelBuffer.GetArea(this.restoreArea.Value); pixelArea.Clear(); - //if (this.restoreArea.Value.Width == imageWidth && - // this.restoreArea.Value.Height == imageHeight) - //{ - // using (PixelAccessor pixelAccessor = frame.Lock()) - // { - // pixelAccessor.Reset(); - // } - //} - //else - //{ - - // using (var emptyRow = new PixelArea(this.restoreArea.Value.Width, ComponentOrder.Xyzw)) - // { - // using (PixelAccessor pixelAccessor = frame.Lock()) - // { - // for (int y = this.restoreArea.Value.Top; y < this.restoreArea.Value.Top + this.restoreArea.Value.Height; y++) - // { - // pixelAccessor.CopyFrom(emptyRow, y, this.restoreArea.Value.Left); - // } - // } - // } - //} - this.restoreArea = null; } diff --git a/src/ImageSharp/Image/ImageFrame{TPixel}.cs b/src/ImageSharp/Image/ImageFrame{TPixel}.cs index 163c7a3b0..0dc730fe5 100644 --- a/src/ImageSharp/Image/ImageFrame{TPixel}.cs +++ b/src/ImageSharp/Image/ImageFrame{TPixel}.cs @@ -14,6 +14,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp { + using SixLabors.ImageSharp.Helpers; + /// /// Represents a single frame in a animation. /// @@ -151,12 +153,26 @@ namespace SixLabors.ImageSharp } /// - /// Copies the pixels to another of the same size. + /// Copies the pixels to a of the same size. /// /// The target pixel buffer accessor. internal void CopyTo(PixelAccessor target) { - SpanHelper.Copy(this.GetPixelSpan(), target.PixelBuffer.Span); + this.CopyTo(target.PixelBuffer); + } + + /// + /// Copies the pixels to a of the same size. + /// + /// The target pixel buffer accessor. + internal void CopyTo(Buffer2D target) + { + if (this.Size() != target.Size()) + { + throw new ArgumentException("ImageFrame.CopyTo(): target must be of the same size!", nameof(target)); + } + + SpanHelper.Copy(this.GetPixelSpan(), target.Span); } /// diff --git a/src/ImageSharp/Memory/Buffer2D{T}.cs b/src/ImageSharp/Memory/Buffer2D{T}.cs index 6b18aaa8f..d9e645845 100644 --- a/src/ImageSharp/Memory/Buffer2D{T}.cs +++ b/src/ImageSharp/Memory/Buffer2D{T}.cs @@ -29,14 +29,14 @@ namespace SixLabors.ImageSharp.Memory } /// - public int Width { get; } + public int Width { get; private set; } /// - public int Height { get; } + public int Height { get; private set; } public Span Span => this.Buffer.Span; - public IBuffer Buffer { get; } + public IBuffer Buffer { get; private set; } /// /// Gets a reference to the element at the specified position. @@ -60,5 +60,21 @@ namespace SixLabors.ImageSharp.Memory { this.Buffer?.Dispose(); } + + public static void SwapContents(Buffer2D a, Buffer2D b) + { + Size aSize = a.Size(); + Size bSize = b.Size(); + + IBuffer temp = a.Buffer; + a.Buffer = b.Buffer; + b.Buffer = temp; + + b.Width = aSize.Width; + b.Height = aSize.Height; + + a.Width = bSize.Width; + a.Height = bSize.Height; + } } } \ No newline at end of file diff --git a/src/ImageSharp/Memory/MemoryManagerExtensions.cs b/src/ImageSharp/Memory/MemoryManagerExtensions.cs index 3511d2039..810af13db 100644 --- a/src/ImageSharp/Memory/MemoryManagerExtensions.cs +++ b/src/ImageSharp/Memory/MemoryManagerExtensions.cs @@ -1,5 +1,7 @@ namespace SixLabors.ImageSharp.Memory { + using SixLabors.Primitives; + /// /// Extension methods for . /// @@ -44,6 +46,10 @@ return new Buffer2D(buffer, width, height); } + public static Buffer2D Allocate2D(this MemoryManager memoryManager, Size size) + where T : struct => + Allocate2D(memoryManager, size.Width, size.Height, false); + public static Buffer2D Allocate2D(this MemoryManager memoryManager, int width, int height) where T : struct => Allocate2D(memoryManager, width, height, false); diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs index 378978d63..2c13ead16 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs @@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.Processing.Processors int maxY = endY - 1; int maxX = endX - 1; - using (var targetPixels = new PixelAccessor(configuration.MemoryManager, source.Width, source.Height)) + using (Buffer2D targetPixels = configuration.MemoryManager.Allocate2D(source.Width, source.Height)) { source.CopyTo(targetPixels); @@ -122,7 +122,7 @@ namespace SixLabors.ImageSharp.Processing.Processors } }); - source.SwapPixelsBuffers(targetPixels); + Buffer2D.SwapContents(source.PixelBuffer, targetPixels); } } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs index 7730f1fa7..0d87aa1dc 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs @@ -43,15 +43,12 @@ namespace SixLabors.ImageSharp.Processing.Processors /// protected override void OnApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) { - int width = source.Width; - int height = source.Height; ParallelOptions parallelOptions = configuration.ParallelOptions; - using (var firstPassPixels = new PixelAccessor(configuration.MemoryManager, width, height)) - using (PixelAccessor sourcePixels = source.Lock()) + using (Buffer2D firstPassPixels = configuration.MemoryManager.Allocate2D(source.Size())) { - this.ApplyConvolution(firstPassPixels, sourcePixels, source.Bounds(), this.KernelX, parallelOptions); - this.ApplyConvolution(sourcePixels, firstPassPixels, sourceRectangle, this.KernelY, parallelOptions); + this.ApplyConvolution(firstPassPixels, source.PixelBuffer, source.Bounds(), this.KernelX, parallelOptions); + this.ApplyConvolution(source.PixelBuffer, firstPassPixels, sourceRectangle, this.KernelY, parallelOptions); } } @@ -67,8 +64,8 @@ namespace SixLabors.ImageSharp.Processing.Processors /// The kernel operator. /// The parellel options private void ApplyConvolution( - PixelAccessor targetPixels, - PixelAccessor sourcePixels, + Buffer2D targetPixels, + Buffer2D sourcePixels, Rectangle sourceRectangle, Fast2DArray kernel, ParallelOptions parallelOptions) diff --git a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs index b700343bf..2f369113d 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs @@ -5,6 +5,7 @@ using System; using System.Numerics; using System.Threading.Tasks; using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Helpers; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; @@ -45,7 +46,7 @@ namespace SixLabors.ImageSharp.Processing.Processors int maxY = endY - 1; int maxX = endX - 1; - using (var targetPixels = new PixelAccessor(configuration.MemoryManager, source.Width, source.Height)) + using (Buffer2D targetPixels = configuration.MemoryManager.Allocate2D(source.Size())) { source.CopyTo(targetPixels); @@ -94,7 +95,7 @@ namespace SixLabors.ImageSharp.Processing.Processors } }); - source.SwapPixelsBuffers(targetPixels); + Buffer2D.SwapContents(source.PixelBuffer, targetPixels); } } } diff --git a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs index af2c29759..950ffc60f 100644 --- a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs @@ -11,6 +11,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors { + using SixLabors.ImageSharp.Helpers; + /// /// An to apply an oil painting effect to an . /// @@ -65,7 +67,7 @@ namespace SixLabors.ImageSharp.Processing.Processors int radius = this.BrushSize >> 1; int levels = this.Levels; - using (var targetPixels = new PixelAccessor(configuration.MemoryManager, source.Width, source.Height)) + using (Buffer2D targetPixels = configuration.MemoryManager.Allocate2D(source.Size())) { source.CopyTo(targetPixels); @@ -133,7 +135,7 @@ namespace SixLabors.ImageSharp.Processing.Processors } }); - source.SwapPixelsBuffers(targetPixels); + Buffer2D.SwapContents(source.PixelBuffer, targetPixels); } } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs index 9448aac5e..37c76bdcf 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs @@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.Processing.Processors int minX = Math.Max(this.CropRectangle.X, sourceRectangle.X); int maxX = Math.Min(this.CropRectangle.Right, sourceRectangle.Right); - using (var targetPixels = new PixelAccessor(configuration.MemoryManager, this.CropRectangle.Width, this.CropRectangle.Height)) + using (Buffer2D targetPixels = configuration.MemoryManager.Allocate2D(this.CropRectangle.Size)) { Parallel.For( minY, @@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp.Processing.Processors SpanHelper.Copy(sourceRow, targetRow, maxX - minX); }); - source.SwapPixelsBuffers(targetPixels); + Buffer2D.SwapContents(source.PixelBuffer, targetPixels); } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs index f52bc97c1..eb1672591 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs @@ -10,6 +10,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors { + using SixLabors.ImageSharp.Helpers; + /// /// Provides methods that allow the flipping of an image around its center point. /// @@ -54,11 +56,10 @@ namespace SixLabors.ImageSharp.Processing.Processors /// The configuration. private void FlipX(ImageFrame source, Configuration configuration) { - int width = source.Width; int height = source.Height; int halfHeight = (int)Math.Ceiling(source.Height * .5F); - using (var targetPixels = new PixelAccessor(configuration.MemoryManager, width, height)) + using (Buffer2D targetPixels = configuration.MemoryManager.Allocate2D(source.Size())) { Parallel.For( 0, @@ -76,7 +77,7 @@ namespace SixLabors.ImageSharp.Processing.Processors altSourceRow.CopyTo(targetRow); }); - source.SwapPixelsBuffers(targetPixels); + Buffer2D.SwapContents(source.PixelBuffer, targetPixels); } } diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index a4ed0c0fd..3a5fbe838 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -48,9 +48,7 @@ namespace SixLabors.ImageSharp.Tests { TestBmpEncoderCore(provider, bitsPerPixel); } - - private static void TestBmpEncoderCore(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs b/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs index a765a77b1..565e06572 100644 --- a/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs +++ b/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs @@ -8,6 +8,7 @@ namespace SixLabors.ImageSharp.Tests.Memory using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Tests.Common; + using SixLabors.Primitives; using Xunit; @@ -127,5 +128,22 @@ namespace SixLabors.ImageSharp.Tests.Memory Assert.True(Unsafe.AreSame(ref expected, ref actual)); } } + + [Fact] + public void SwapContents() + { + using (Buffer2D a = this.MemoryManager.Allocate2D(10, 5)) + using (Buffer2D b = this.MemoryManager.Allocate2D(3, 7)) + { + IBuffer aa = a.Buffer; + IBuffer bb = b.Buffer; + + Buffer2D.SwapContents(a, b); + + Assert.Equal(bb, a.Buffer); + Assert.Equal(new Size(3, 7), a.Size()); + Assert.Equal(new Size(10, 5), b.Size()); + } + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs index 3508d544b..89e9a13b5 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs @@ -11,12 +11,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution { public class GaussianBlurTest : FileTestBase { - public static readonly TheoryData GaussianBlurValues - = new TheoryData - { - 3, - 5 - }; + public static readonly TheoryData GaussianBlurValues = new TheoryData { 3, 5 }; [Theory] [WithFileCollection(nameof(DefaultFiles), nameof(GaussianBlurValues), DefaultPixelType)] @@ -36,7 +31,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution where TPixel : struct, IPixel { using (Image source = provider.GetImage()) - using (var image = source.Clone()) + using (Image image = source.Clone()) { var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); diff --git a/tests/ImageSharp.Tests/Processing/Processors/Effects/OilPaintTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Effects/OilPaintTest.cs index 608fcf10c..a9127f61d 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Effects/OilPaintTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Effects/OilPaintTest.cs @@ -11,12 +11,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects { public class OilPaintTest : FileTestBase { - public static readonly TheoryData OilPaintValues - = new TheoryData - { - { 15, 10 }, - { 6, 5 } - }; + public static readonly TheoryData OilPaintValues = new TheoryData + { + { 15, 10 }, { 6, 5 } + }; [Theory] [WithFileCollection(nameof(DefaultFiles), nameof(OilPaintValues), DefaultPixelType)] diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/FlipTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/FlipTests.cs index d4de4c3d2..9ca399498 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/FlipTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/FlipTests.cs @@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms using (Image image = provider.GetImage()) { image.Mutate(x => x.Flip(flipType)); - image.DebugSave(provider, flipType, Extensions.Bmp); + image.DebugSave(provider, flipType); } } }