diff --git a/src/ImageProcessorCore/Samplers/Crop.cs b/src/ImageProcessorCore/Samplers/Crop.cs
new file mode 100644
index 000000000..6ff3f49c0
--- /dev/null
+++ b/src/ImageProcessorCore/Samplers/Crop.cs
@@ -0,0 +1,76 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+// -------------------------------------------------------------------------------------------------------------------
+
+namespace ImageProcessorCore
+{
+ using Processors;
+
+ ///
+ /// Extension methods for the type.
+ ///
+ public static partial class ImageExtensions
+ {
+ ///
+ /// Crops an image to the given width and height.
+ ///
+ /// The pixel format.
+ /// The packed format. long, float.
+ /// The image to resize.
+ /// The target image width.
+ /// The target image height.
+ /// A delegate which is called as progress is made processing the image.
+ /// The
+ public static Image Crop(this Image source, int width, int height, ProgressEventHandler progressHandler = null)
+ where T : IPackedVector
+ where TP : struct
+ {
+ return Crop(source, width, height, source.Bounds, progressHandler);
+ }
+
+ ///
+ /// Crops an image to the given width and height with the given source rectangle.
+ ///
+ /// If the source rectangle is smaller than the target dimensions then the
+ /// area within the source is resized performing a zoomed crop.
+ ///
+ ///
+ /// The pixel format.
+ /// The packed format. long, float.
+ /// The image to crop.
+ /// The target image width.
+ /// The target image height.
+ ///
+ /// The structure that specifies the portion of the image object to draw.
+ ///
+ /// A delegate which is called as progress is made processing the image.
+ /// The
+ public static Image Crop(this Image source, int width, int height, Rectangle sourceRectangle, ProgressEventHandler progressHandler = null)
+ where T : IPackedVector
+ where TP : struct
+ {
+ Guard.MustBeGreaterThan(width, 0, nameof(width));
+ Guard.MustBeGreaterThan(height, 0, nameof(height));
+
+ if (sourceRectangle.Width < width || sourceRectangle.Height < height)
+ {
+ // If the source rectangle is smaller than the target perform a
+ // cropped zoom.
+ source = source.Resize(sourceRectangle.Width, sourceRectangle.Height);
+ }
+
+ CropProcessor processor = new CropProcessor();
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(width, height, sourceRectangle, new Rectangle(0, 0, width, height), processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
+ }
+ }
+}
diff --git a/src/ImageProcessorCore/Samplers/Processors/CropProcessor.cs b/src/ImageProcessorCore/Samplers/Processors/CropProcessor.cs
new file mode 100644
index 000000000..2029c33bd
--- /dev/null
+++ b/src/ImageProcessorCore/Samplers/Processors/CropProcessor.cs
@@ -0,0 +1,41 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageProcessorCore.Processors
+{
+ using System.Threading.Tasks;
+
+ ///
+ /// Provides methods to allow the cropping of an image.
+ ///
+ public class CropProcessor : ImageSampler
+ {
+ ///
+ protected 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;
+
+ using (IPixelAccessor sourcePixels = source.Lock())
+ using (IPixelAccessor targetPixels = target.Lock())
+ {
+ Parallel.For(
+ startY,
+ endY,
+ y =>
+ {
+ for (int x = startX; x < endX; x++)
+ {
+ targetPixels[x, y] = sourcePixels[x + sourceX, y + sourceY];
+ }
+
+ this.OnRowProcessed();
+ });
+ }
+ }
+ }
+}
diff --git a/src/ImageProcessorCore/Samplers/Resize.cs b/src/ImageProcessorCore/Samplers/Resize.cs
index 8e5405870..aa2089d07 100644
--- a/src/ImageProcessorCore/Samplers/Resize.cs
+++ b/src/ImageProcessorCore/Samplers/Resize.cs
@@ -8,20 +8,21 @@ namespace ImageProcessorCore
using Processors;
///
- /// Extension methods for the type.
+ /// Extension methods for the type.
///
public static partial class ImageExtensions
{
///
/// Resizes an image in accordance with the given .
///
- /// The type of pixels contained within the image.
+ /// The pixel format.
+ /// The packed format. long, float.
/// The image to resize.
/// The resize options.
/// A delegate which is called as progress is made processing the image.
- /// The
+ /// The
/// Passing zero for one of height or width within the resize options will automatically preserve the aspect ratio of the original image
- public static Image Resize(this Image source, ResizeOptions options, ProgressEventHandler progressHandler = null)
+ public static Image Resize(this Image source, ResizeOptions options, ProgressEventHandler progressHandler = null)
where T : IPackedVector
where TP : struct
{
@@ -44,14 +45,15 @@ namespace ImageProcessorCore
///
/// Resizes an image to the given width and height.
///
- /// The type of pixels contained within the image.
+ /// The pixel format.
+ /// The packed format. long, float.
/// The image to resize.
/// The target image width.
/// The target image height.
/// A delegate which is called as progress is made processing the image.
- /// The
+ /// The
/// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image
- public static Image Resize(this Image source, int width, int height, ProgressEventHandler progressHandler = null)
+ public static Image Resize(this Image source, int width, int height, ProgressEventHandler progressHandler = null)
where T : IPackedVector
where TP : struct
{
@@ -61,15 +63,16 @@ namespace ImageProcessorCore
///
/// Resizes an image to the given width and height.
///
- /// The type of pixels contained within the image.
+ /// The pixel format.
+ /// The packed format. long, float.
/// The image to resize.
/// The target image width.
/// The target image height.
/// Whether to compress and expand the image color-space to gamma correct the image during processing.
/// A delegate which is called as progress is made processing the image.
- /// The
+ /// The
/// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image
- public static Image Resize(this Image source, int width, int height, bool compand, ProgressEventHandler progressHandler = null)
+ public static Image Resize(this Image source, int width, int height, bool compand, ProgressEventHandler progressHandler = null)
where T : IPackedVector
where TP : struct
{
@@ -79,16 +82,17 @@ namespace ImageProcessorCore
///
/// Resizes an image to the given width and height with the given sampler.
///
- /// The type of pixels contained within the image.
+ /// The pixel format.
+ /// The packed format. long, float.
/// The image to resize.
/// The target image width.
/// The target image height.
/// The to perform the resampling.
/// Whether to compress and expand the image color-space to gamma correct the image during processing.
/// A delegate which is called as progress is made processing the image.
- /// The
+ /// The
/// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image
- public static Image Resize(this Image source, int width, int height, IResampler sampler, bool compand, ProgressEventHandler progressHandler = null)
+ public static Image Resize(this Image source, int width, int height, IResampler sampler, bool compand, ProgressEventHandler progressHandler = null)
where T : IPackedVector
where TP : struct
{
@@ -99,7 +103,8 @@ namespace ImageProcessorCore
/// Resizes an image to the given width and height with the given sampler and
/// source rectangle.
///
- /// The type of pixels contained within the image.
+ /// The pixel format.
+ /// The packed format. long, float.
/// The image to resize.
/// The target image width.
/// The target image height.
@@ -112,9 +117,9 @@ namespace ImageProcessorCore
///
/// Whether to compress and expand the image color-space to gamma correct the image during processing.
/// A delegate which is called as progress is made processing the image.
- /// The
+ /// The
/// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image
- public static Image Resize(this Image source, int width, int height, IResampler sampler, Rectangle sourceRectangle, Rectangle targetRectangle, bool compand = false, ProgressEventHandler progressHandler = null)
+ public static Image Resize(this Image source, int width, int height, IResampler sampler, Rectangle sourceRectangle, Rectangle targetRectangle, bool compand = false, ProgressEventHandler progressHandler = null)
where T : IPackedVector
where TP : struct
{
diff --git a/tests/ImageProcessorCore.Benchmarks/Samplers/Crop.cs b/tests/ImageProcessorCore.Benchmarks/Samplers/Crop.cs
index 5eae5cdef..4eaeea6ec 100644
--- a/tests/ImageProcessorCore.Benchmarks/Samplers/Crop.cs
+++ b/tests/ImageProcessorCore.Benchmarks/Samplers/Crop.cs
@@ -1,40 +1,40 @@
-//namespace ImageProcessorCore.Benchmarks
-//{
-// using System.Drawing;
-// using System.Drawing.Drawing2D;
+namespace ImageProcessorCore.Benchmarks
+{
+ using System.Drawing;
+ using System.Drawing.Drawing2D;
-// using BenchmarkDotNet.Attributes;
-// using CoreImage = ImageProcessorCore.Image;
-// using CoreSize = ImageProcessorCore.Size;
+ using BenchmarkDotNet.Attributes;
+ using CoreSize = ImageProcessorCore.Size;
+ using CoreImage = ImageProcessorCore.Image;
-// public class Crop
-// {
-// [Benchmark(Baseline = true, Description = "System.Drawing Crop")]
-// public Size CropSystemDrawing()
-// {
-// using (Bitmap source = new Bitmap(400, 400))
-// {
-// using (Bitmap destination = new Bitmap(100, 100))
-// {
-// using (Graphics graphics = Graphics.FromImage(destination))
-// {
-// graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
-// graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
-// graphics.CompositingQuality = CompositingQuality.HighQuality;
-// graphics.DrawImage(source, new Rectangle(0, 0, 100, 100), 0, 0, 100, 100, GraphicsUnit.Pixel);
-// }
+ public class Crop
+ {
+ [Benchmark(Baseline = true, Description = "System.Drawing Crop")]
+ public Size CropSystemDrawing()
+ {
+ using (Bitmap source = new Bitmap(400, 400))
+ {
+ using (Bitmap destination = new Bitmap(100, 100))
+ {
+ using (Graphics graphics = Graphics.FromImage(destination))
+ {
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.DrawImage(source, new Rectangle(0, 0, 100, 100), 0, 0, 100, 100, GraphicsUnit.Pixel);
+ }
-// return destination.Size;
-// }
-// }
-// }
+ return destination.Size;
+ }
+ }
+ }
-// [Benchmark(Description = "ImageProcessorCore Crop")]
-// public CoreSize CropResizeCore()
-// {
-// CoreImage image = new CoreImage(400, 400);
-// image.Crop(100, 100);
-// return new CoreSize(image.Width, image.Height);
-// }
-// }
-//}
+ [Benchmark(Description = "ImageProcessorCore Crop")]
+ public CoreSize CropResizeCore()
+ {
+ CoreImage image = new CoreImage(400, 400);
+ image.Crop(100, 100);
+ return new CoreSize(image.Width, image.Height);
+ }
+ }
+}