Browse Source

Update Crop method to accept rectangle

pull/35/head
James Jackson-South 10 years ago
parent
commit
9c8033010a
  1. 37
      src/ImageSharp/Filters/Processors/Transforms/CropProcessor.cs
  2. 30
      src/ImageSharp/Filters/Transforms/Crop.cs

37
src/ImageSharp/Filters/Processors/Transforms/CropProcessor.cs

@ -5,6 +5,7 @@
namespace ImageSharp.Processors namespace ImageSharp.Processors
{ {
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
/// <summary> /// <summary>
@ -19,18 +20,16 @@ namespace ImageSharp.Processors
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="CropProcessor{TColor,TPacked}"/> class. /// Initializes a new instance of the <see cref="CropProcessor{TColor,TPacked}"/> class.
/// </summary> /// </summary>
/// <param name="width">The target image width.</param> /// <param name="cropRectangle">The target cropped rectangle.</param>
/// <param name="height">The target image height.</param> public CropProcessor(Rectangle cropRectangle)
public CropProcessor(int width, int height)
{ {
this.Width = width; this.CropRectangle = cropRectangle;
this.Height = height;
} }
/// <summary> /// <summary>
/// Gets the width. /// Gets the width.
/// </summary> /// </summary>
public int Width { get; } public Rectangle CropRectangle { get; }
/// <summary> /// <summary>
/// Gets the height. /// Gets the height.
@ -40,22 +39,20 @@ namespace ImageSharp.Processors
/// <inheritdoc/> /// <inheritdoc/>
protected override void Apply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY) protected override void Apply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY)
{ {
int minX = 0; if (this.CropRectangle == sourceRectangle)
int maxX = this.Width; {
int minY = 0; return;
int maxY = this.Height; }
int sourceX = sourceRectangle.X;
int sourceY = sourceRectangle.Y;
Guard.MustBeGreaterThanOrEqualTo(minX, sourceX, nameof(minX)); int minY = Math.Max(this.CropRectangle.Y, startY);
Guard.MustBeGreaterThanOrEqualTo(minY, startY, nameof(startY)); int maxY = Math.Min(this.CropRectangle.Bottom, endY);
Guard.MustBeLessThanOrEqualTo(maxX, sourceRectangle.Right, nameof(maxX)); int minX = Math.Max(this.CropRectangle.X, sourceRectangle.X);
Guard.MustBeLessThanOrEqualTo(maxY, endY, nameof(maxY)); int maxX = Math.Min(this.CropRectangle.Right, sourceRectangle.Right);
TColor[] target = new TColor[this.Width * this.Height]; TColor[] target = new TColor[this.CropRectangle.Width * this.CropRectangle.Height];
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock()) using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(this.Width, this.Height)) using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(this.CropRectangle.Width, this.CropRectangle.Height))
{ {
Parallel.For( Parallel.For(
minY, minY,
@ -65,12 +62,12 @@ namespace ImageSharp.Processors
{ {
for (int x = minX; x < maxX; x++) for (int x = minX; x < maxX; x++)
{ {
targetPixels[x, y] = sourcePixels[x + sourceX, y + sourceY]; targetPixels[x - minX, y - minY] = sourcePixels[x, y];
} }
}); });
} }
source.SetPixels(this.Width, this.Height, target); source.SetPixels(this.CropRectangle.Width, this.CropRectangle.Height, target);
} }
} }
} }

30
src/ImageSharp/Filters/Transforms/Crop.cs

@ -25,41 +25,25 @@ namespace ImageSharp
where TColor : struct, IPackedPixel<TPacked> where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct where TPacked : struct
{ {
return Crop(source, width, height, source.Bounds); return Crop(source, new Rectangle(0, 0, width, height));
} }
/// <summary> /// <summary>
/// Crops an image to the given width and height with the given source rectangle. /// Crops an image to the given rectangle.
/// <remarks>
/// If the source rectangle is smaller than the target dimensions then the
/// area within the source is resized performing a zoomed crop.
/// </remarks>
/// </summary> /// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam> /// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam> /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
/// <param name="source">The image to crop.</param> /// <param name="source">The image to crop.</param>
/// <param name="width">The target image width.</param> /// <param name="cropRectangle">
/// <param name="height">The target image height.</param> /// The <see cref="Rectangle"/> structure that specifies the portion of the image object to retain.
/// <param name="sourceRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param> /// </param>
/// <returns>The <see cref="Image"/></returns> /// <returns>The <see cref="Image"/></returns>
public static Image<TColor, TPacked> Crop<TColor, TPacked>(this Image<TColor, TPacked> source, int width, int height, Rectangle sourceRectangle) public static Image<TColor, TPacked> Crop<TColor, TPacked>(this Image<TColor, TPacked> source, Rectangle cropRectangle)
where TColor : struct, IPackedPixel<TPacked> where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct where TPacked : struct
{ {
Guard.MustBeGreaterThan(width, 0, nameof(width)); CropProcessor<TColor, TPacked> processor = new CropProcessor<TColor, TPacked>(cropRectangle);
Guard.MustBeGreaterThan(height, 0, nameof(height)); return source.Process(source.Bounds, processor);
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<TColor, TPacked> processor = new CropProcessor<TColor, TPacked>(width, height);
return source.Process(sourceRectangle, processor);
} }
} }
} }
Loading…
Cancel
Save