From 4f7f51ae7a382fb55588ff99e6950ae3f0eaa8b8 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 8 Dec 2016 17:34:54 +1100 Subject: [PATCH] Move Crop --- .../Common/Extensions/ArrayExtensions.cs | 29 +++++++ .../Common/Extensions/ByteExtensions.cs | 4 +- .../Processors/Transforms/CropProcessor.cs | 76 +++++++++++++++++++ .../{Samplers => Filters}/Transforms/Crop.cs | 6 +- src/ImageSharp/Image/PixelAccessor.cs | 26 +++++++ .../Processors/Transforms/CropProcessor.cs | 49 ------------ .../{Samplers => Filters}/CropTest.cs | 0 7 files changed, 135 insertions(+), 55 deletions(-) create mode 100644 src/ImageSharp/Common/Extensions/ArrayExtensions.cs create mode 100644 src/ImageSharp/Filters/Processors/Transforms/CropProcessor.cs rename src/ImageSharp/{Samplers => Filters}/Transforms/Crop.cs (95%) delete mode 100644 src/ImageSharp/Samplers/Processors/Transforms/CropProcessor.cs rename tests/ImageSharp.Tests/Processors/{Samplers => Filters}/CropTest.cs (100%) diff --git a/src/ImageSharp/Common/Extensions/ArrayExtensions.cs b/src/ImageSharp/Common/Extensions/ArrayExtensions.cs new file mode 100644 index 000000000..57ca37217 --- /dev/null +++ b/src/ImageSharp/Common/Extensions/ArrayExtensions.cs @@ -0,0 +1,29 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp +{ + /// + /// Extension methods for arrays. + /// + public static class ArrayExtensions + { + /// + /// Locks the pixel buffer providing access to the pixels. + /// + /// The pixel format. + /// The packed format. uint, long, float. + /// The pixel buffer. + /// Gets the width of the image represented by the pixel buffer. + /// The height of the image represented by the pixel buffer. + /// The + public static PixelAccessor Lock(this TColor[] pixels, int width, int height) + where TColor : struct, IPackedPixel + where TPacked : struct + { + return new PixelAccessor(width, height, pixels); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Common/Extensions/ByteExtensions.cs b/src/ImageSharp/Common/Extensions/ByteExtensions.cs index 350777387..fc9c29e62 100644 --- a/src/ImageSharp/Common/Extensions/ByteExtensions.cs +++ b/src/ImageSharp/Common/Extensions/ByteExtensions.cs @@ -5,8 +5,6 @@ namespace ImageSharp { - using System; - /// /// Extension methods for the struct. /// @@ -44,4 +42,4 @@ namespace ImageSharp } } } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Filters/Processors/Transforms/CropProcessor.cs b/src/ImageSharp/Filters/Processors/Transforms/CropProcessor.cs new file mode 100644 index 000000000..789538b2c --- /dev/null +++ b/src/ImageSharp/Filters/Processors/Transforms/CropProcessor.cs @@ -0,0 +1,76 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Processors +{ + using System.Threading.Tasks; + + /// + /// Provides methods to allow the cropping of an image. + /// + /// The pixel format. + /// The packed format. uint, long, float. + public class CropProcessor : ImageFilteringProcessor + where TColor : struct, IPackedPixel + where TPacked : struct + { + /// + /// Initializes a new instance of the class. + /// + /// The target image width. + /// The target image height. + public CropProcessor(int width, int height) + { + this.Width = width; + this.Height = height; + } + + /// + /// Gets the width. + /// + public int Width { get; } + + /// + /// Gets the height. + /// + public int Height { get; } + + /// + protected override void Apply(ImageBase source, Rectangle sourceRectangle, int startY, int endY) + { + int minX = 0; + int maxX = this.Width; + int minY = 0; + int maxY = this.Height; + int sourceX = sourceRectangle.X; + int sourceY = sourceRectangle.Y; + + Guard.MustBeGreaterThanOrEqualTo(minX, sourceX, nameof(minX)); + Guard.MustBeGreaterThanOrEqualTo(minY, startY, nameof(startY)); + Guard.MustBeLessThanOrEqualTo(maxX, sourceRectangle.Right, nameof(maxX)); + Guard.MustBeLessThanOrEqualTo(maxY, endY, nameof(maxY)); + + TColor[] target = new TColor[this.Width * this.Height]; + + using (PixelAccessor sourcePixels = source.Lock()) + using (PixelAccessor targetPixels = target.Lock(this.Width, this.Height)) + { + Parallel.For( + minY, + maxY, + this.ParallelOptions, + y => + { + for (int x = minX; x < maxX; x++) + { + targetPixels[x, y] = sourcePixels[x + sourceX, y + sourceY]; + } + }); + } + + source.SetPixels(this.Width, this.Height, target); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Samplers/Transforms/Crop.cs b/src/ImageSharp/Filters/Transforms/Crop.cs similarity index 95% rename from src/ImageSharp/Samplers/Transforms/Crop.cs rename to src/ImageSharp/Filters/Transforms/Crop.cs index a266db3b2..95091358c 100644 --- a/src/ImageSharp/Samplers/Transforms/Crop.cs +++ b/src/ImageSharp/Filters/Transforms/Crop.cs @@ -58,8 +58,8 @@ namespace ImageSharp source = source.Resize(sourceRectangle.Width, sourceRectangle.Height); } - CropProcessor processor = new CropProcessor(); - return source.Process(width, height, sourceRectangle, new Rectangle(0, 0, width, height), processor); + CropProcessor processor = new CropProcessor(width, height); + return source.Process(sourceRectangle, processor); } } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Image/PixelAccessor.cs b/src/ImageSharp/Image/PixelAccessor.cs index f11082df7..8f693584b 100644 --- a/src/ImageSharp/Image/PixelAccessor.cs +++ b/src/ImageSharp/Image/PixelAccessor.cs @@ -64,6 +64,32 @@ namespace ImageSharp this.RowStride = this.Width * this.PixelSize; } + /// + /// Initializes a new instance of the class. + /// + /// Gets the width of the image represented by the pixel buffer. + /// The height of the image represented by the pixel buffer. + /// The pixel buffer. + public PixelAccessor(int width, int height, TColor[] pixels) + { + Guard.NotNull(pixels, nameof(pixels)); + Guard.MustBeGreaterThan(width, 0, nameof(width)); + Guard.MustBeGreaterThan(height, 0, nameof(height)); + + if (pixels.Length != width * height) + { + throw new ArgumentException("Pixel array must have the length of Width * Height."); + } + + this.Width = width; + this.Height = height; + this.pixelsHandle = GCHandle.Alloc(pixels, GCHandleType.Pinned); + this.dataPointer = this.pixelsHandle.AddrOfPinnedObject(); + this.pixelsBase = (byte*)this.dataPointer.ToPointer(); + this.PixelSize = Unsafe.SizeOf(); + this.RowStride = this.Width * this.PixelSize; + } + /// /// Finalizes an instance of the class. /// diff --git a/src/ImageSharp/Samplers/Processors/Transforms/CropProcessor.cs b/src/ImageSharp/Samplers/Processors/Transforms/CropProcessor.cs deleted file mode 100644 index 3a479fa2d..000000000 --- a/src/ImageSharp/Samplers/Processors/Transforms/CropProcessor.cs +++ /dev/null @@ -1,49 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Processors -{ - using System.Threading.Tasks; - - /// - /// Provides methods to allow the cropping of an image. - /// - /// The pixel format. - /// The packed format. uint, long, float. - public class CropProcessor : ImageSamplingProcessor - where TColor : struct, IPackedPixel - where TPacked : struct - { - /// - public override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) - { - int startX = targetRectangle.X; - int endX = targetRectangle.Right; - int sourceX = sourceRectangle.X; - int sourceY = sourceRectangle.Y; - - Guard.MustBeGreaterThanOrEqualTo(startX, sourceX, nameof(targetRectangle)); - Guard.MustBeGreaterThanOrEqualTo(startY, sourceY, nameof(targetRectangle)); - Guard.MustBeLessThanOrEqualTo(endX, sourceRectangle.Right, nameof(targetRectangle)); - Guard.MustBeLessThanOrEqualTo(endY, sourceRectangle.Bottom, nameof(targetRectangle)); - - using (PixelAccessor sourcePixels = source.Lock()) - using (PixelAccessor targetPixels = target.Lock()) - { - Parallel.For( - startY, - endY, - this.ParallelOptions, - y => - { - for (int x = startX; x < endX; x++) - { - targetPixels[x, y] = sourcePixels[x + sourceX, y + sourceY]; - } - }); - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Samplers/CropTest.cs b/tests/ImageSharp.Tests/Processors/Filters/CropTest.cs similarity index 100% rename from tests/ImageSharp.Tests/Processors/Samplers/CropTest.cs rename to tests/ImageSharp.Tests/Processors/Filters/CropTest.cs