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