Browse Source

Move Crop

af/merge-core
James Jackson-South 9 years ago
parent
commit
4f7f51ae7a
  1. 29
      src/ImageSharp/Common/Extensions/ArrayExtensions.cs
  2. 4
      src/ImageSharp/Common/Extensions/ByteExtensions.cs
  3. 76
      src/ImageSharp/Filters/Processors/Transforms/CropProcessor.cs
  4. 6
      src/ImageSharp/Filters/Transforms/Crop.cs
  5. 26
      src/ImageSharp/Image/PixelAccessor.cs
  6. 49
      src/ImageSharp/Samplers/Processors/Transforms/CropProcessor.cs
  7. 0
      tests/ImageSharp.Tests/Processors/Filters/CropTest.cs

29
src/ImageSharp/Common/Extensions/ArrayExtensions.cs

@ -0,0 +1,29 @@
// <copyright file="ArrayExtensions.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
/// <summary>
/// Extension methods for arrays.
/// </summary>
public static class ArrayExtensions
{
/// <summary>
/// Locks the pixel buffer providing access to the pixels.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
/// <param name="pixels">The pixel buffer.</param>
/// <param name="width">Gets the width of the image represented by the pixel buffer.</param>
/// <param name="height">The height of the image represented by the pixel buffer.</param>
/// <returns>The <see cref="PixelAccessor{TColor,TPacked}"/></returns>
public static PixelAccessor<TColor, TPacked> Lock<TColor, TPacked>(this TColor[] pixels, int width, int height)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return new PixelAccessor<TColor, TPacked>(width, height, pixels);
}
}
}

4
src/ImageSharp/Common/Extensions/ByteExtensions.cs

@ -5,8 +5,6 @@
namespace ImageSharp
{
using System;
/// <summary>
/// Extension methods for the <see cref="byte"/> struct.
/// </summary>
@ -44,4 +42,4 @@ namespace ImageSharp
}
}
}
}
}

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

@ -0,0 +1,76 @@
// <copyright file="CropProcessor.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Processors
{
using System.Threading.Tasks;
/// <summary>
/// Provides methods to allow the cropping of an image.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public class CropProcessor<TColor, TPacked> : ImageFilteringProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="CropProcessor{TColor,TPacked}"/> class.
/// </summary>
/// <param name="width">The target image width.</param>
/// <param name="height">The target image height.</param>
public CropProcessor(int width, int height)
{
this.Width = width;
this.Height = height;
}
/// <summary>
/// Gets the width.
/// </summary>
public int Width { get; }
/// <summary>
/// Gets the height.
/// </summary>
public int Height { get; }
/// <inheritdoc/>
protected override void Apply(ImageBase<TColor, TPacked> 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<TColor, TPacked> sourcePixels = source.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(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);
}
}
}

6
src/ImageSharp/Samplers/Transforms/Crop.cs → src/ImageSharp/Filters/Transforms/Crop.cs

@ -58,8 +58,8 @@ namespace ImageSharp
source = source.Resize(sourceRectangle.Width, sourceRectangle.Height);
}
CropProcessor<TColor, TPacked> processor = new CropProcessor<TColor, TPacked>();
return source.Process(width, height, sourceRectangle, new Rectangle(0, 0, width, height), processor);
CropProcessor<TColor, TPacked> processor = new CropProcessor<TColor, TPacked>(width, height);
return source.Process(sourceRectangle, processor);
}
}
}
}

26
src/ImageSharp/Image/PixelAccessor.cs

@ -64,6 +64,32 @@ namespace ImageSharp
this.RowStride = this.Width * this.PixelSize;
}
/// <summary>
/// Initializes a new instance of the <see cref="PixelAccessor{TColor,TPacked}"/> class.
/// </summary>
/// <param name="width">Gets the width of the image represented by the pixel buffer.</param>
/// <param name="height">The height of the image represented by the pixel buffer.</param>
/// <param name="pixels">The pixel buffer.</param>
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<TPacked>();
this.RowStride = this.Width * this.PixelSize;
}
/// <summary>
/// Finalizes an instance of the <see cref="PixelAccessor{TColor,TPacked}"/> class.
/// </summary>

49
src/ImageSharp/Samplers/Processors/Transforms/CropProcessor.cs

@ -1,49 +0,0 @@
// <copyright file="CropProcessor.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Processors
{
using System.Threading.Tasks;
/// <summary>
/// Provides methods to allow the cropping of an image.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public class CropProcessor<TColor, TPacked> : ImageSamplingProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
/// <inheritdoc/>
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> 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<TColor, TPacked> sourcePixels = source.Lock())
using (PixelAccessor<TColor, TPacked> 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];
}
});
}
}
}
}

0
tests/ImageSharp.Tests/Processors/Samplers/CropTest.cs → tests/ImageSharp.Tests/Processors/Filters/CropTest.cs

Loading…
Cancel
Save