Browse Source

Add Crop

Former-commit-id: 63386b63ab93e14d3c50383739c042a656efab9f
Former-commit-id: 0a1b7a7367d9ea360cc4cf0a821c788bd468b607
Former-commit-id: 8430af726048214b3820969d1dfe31b9df72a695
pull/1/head
James Jackson-South 10 years ago
parent
commit
78b871ff2a
  1. 76
      src/ImageProcessorCore/Samplers/Crop.cs
  2. 41
      src/ImageProcessorCore/Samplers/Processors/CropProcessor.cs
  3. 37
      src/ImageProcessorCore/Samplers/Resize.cs
  4. 72
      tests/ImageProcessorCore.Benchmarks/Samplers/Crop.cs

76
src/ImageProcessorCore/Samplers/Crop.cs

@ -0,0 +1,76 @@
// <copyright file="Crop.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>-------------------------------------------------------------------------------------------------------------------
namespace ImageProcessorCore
{
using Processors;
/// <summary>
/// Extension methods for the <see cref="Image"/> type.
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Crops an image to the given width and height.
/// </summary>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="source">The image to resize.</param>
/// <param name="width">The target image width.</param>
/// <param name="height">The target image height.</param>
/// <param name="progressHandler">A delegate which is called as progress is made processing the image.</param>
/// <returns>The <see cref="Image{T,TP}"/></returns>
public static Image<T, TP> Crop<T, TP>(this Image<T, TP> source, int width, int height, ProgressEventHandler progressHandler = null)
where T : IPackedVector<TP>
where TP : struct
{
return Crop(source, width, height, source.Bounds, progressHandler);
}
/// <summary>
/// Crops an image to the given width and height with the given source 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>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="source">The image to crop.</param>
/// <param name="width">The target image width.</param>
/// <param name="height">The target image height.</param>
/// <param name="sourceRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param>
/// <param name="progressHandler">A delegate which is called as progress is made processing the image.</param>
/// <returns>The <see cref="Image"/></returns>
public static Image<T, TP> Crop<T, TP>(this Image<T, TP> source, int width, int height, Rectangle sourceRectangle, ProgressEventHandler progressHandler = null)
where T : IPackedVector<TP>
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;
}
}
}
}

41
src/ImageProcessorCore/Samplers/Processors/CropProcessor.cs

@ -0,0 +1,41 @@
// <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 ImageProcessorCore.Processors
{
using System.Threading.Tasks;
/// <summary>
/// Provides methods to allow the cropping of an image.
/// </summary>
public class CropProcessor : ImageSampler
{
/// <inheritdoc/>
protected override void Apply<T, TP>(ImageBase<T, TP> target, ImageBase<T, TP> 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<T, TP> sourcePixels = source.Lock())
using (IPixelAccessor<T, TP> 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();
});
}
}
}
}

37
src/ImageProcessorCore/Samplers/Resize.cs

@ -8,20 +8,21 @@ namespace ImageProcessorCore
using Processors;
/// <summary>
/// Extension methods for the <see cref="Image{IPackedVector}"/> type.
/// Extension methods for the <see cref="Image{T,TP}"/> type.
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Resizes an image in accordance with the given <see cref="ResizeOptions"/>.
/// </summary>
/// <typeparam name="T">The type of pixels contained within the image.</typeparam>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="source">The image to resize.</param>
/// <param name="options">The resize options.</param>
/// <param name="progressHandler">A delegate which is called as progress is made processing the image.</param>
/// <returns>The <see cref="Image{T}"/></returns>
/// <returns>The <see cref="Image{T,TP}"/></returns>
/// <remarks>Passing zero for one of height or width within the resize options will automatically preserve the aspect ratio of the original image</remarks>
public static Image<T,TP> Resize<T,TP>(this Image<T,TP> source, ResizeOptions options, ProgressEventHandler progressHandler = null)
public static Image<T, TP> Resize<T, TP>(this Image<T, TP> source, ResizeOptions options, ProgressEventHandler progressHandler = null)
where T : IPackedVector<TP>
where TP : struct
{
@ -44,14 +45,15 @@ namespace ImageProcessorCore
/// <summary>
/// Resizes an image to the given width and height.
/// </summary>
/// <typeparam name="T">The type of pixels contained within the image.</typeparam>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="source">The image to resize.</param>
/// <param name="width">The target image width.</param>
/// <param name="height">The target image height.</param>
/// <param name="progressHandler">A delegate which is called as progress is made processing the image.</param>
/// <returns>The <see cref="Image{T}"/></returns>
/// <returns>The <see cref="Image{T,TP}"/></returns>
/// <remarks>Passing zero for one of height or width will automatically preserve the aspect ratio of the original image</remarks>
public static Image<T,TP> Resize<T,TP>(this Image<T,TP> source, int width, int height, ProgressEventHandler progressHandler = null)
public static Image<T, TP> Resize<T, TP>(this Image<T, TP> source, int width, int height, ProgressEventHandler progressHandler = null)
where T : IPackedVector<TP>
where TP : struct
{
@ -61,15 +63,16 @@ namespace ImageProcessorCore
/// <summary>
/// Resizes an image to the given width and height.
/// </summary>
/// <typeparam name="T">The type of pixels contained within the image.</typeparam>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="source">The image to resize.</param>
/// <param name="width">The target image width.</param>
/// <param name="height">The target image height.</param>
/// <param name="compand">Whether to compress and expand the image color-space to gamma correct the image during processing.</param>
/// <param name="progressHandler">A delegate which is called as progress is made processing the image.</param>
/// <returns>The <see cref="Image{T}"/></returns>
/// <returns>The <see cref="Image{T,TP}"/></returns>
/// <remarks>Passing zero for one of height or width will automatically preserve the aspect ratio of the original image</remarks>
public static Image<T,TP> Resize<T,TP>(this Image<T,TP> source, int width, int height, bool compand, ProgressEventHandler progressHandler = null)
public static Image<T, TP> Resize<T, TP>(this Image<T, TP> source, int width, int height, bool compand, ProgressEventHandler progressHandler = null)
where T : IPackedVector<TP>
where TP : struct
{
@ -79,16 +82,17 @@ namespace ImageProcessorCore
/// <summary>
/// Resizes an image to the given width and height with the given sampler.
/// </summary>
/// <typeparam name="T">The type of pixels contained within the image.</typeparam>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="source">The image to resize.</param>
/// <param name="width">The target image width.</param>
/// <param name="height">The target image height.</param>
/// <param name="sampler">The <see cref="IResampler"/> to perform the resampling.</param>
/// <param name="compand">Whether to compress and expand the image color-space to gamma correct the image during processing.</param>
/// <param name="progressHandler">A delegate which is called as progress is made processing the image.</param>
/// <returns>The <see cref="Image{T}"/></returns>
/// <returns>The <see cref="Image{T,TP}"/></returns>
/// <remarks>Passing zero for one of height or width will automatically preserve the aspect ratio of the original image</remarks>
public static Image<T,TP> Resize<T,TP>(this Image<T,TP> source, int width, int height, IResampler sampler, bool compand, ProgressEventHandler progressHandler = null)
public static Image<T, TP> Resize<T, TP>(this Image<T, TP> source, int width, int height, IResampler sampler, bool compand, ProgressEventHandler progressHandler = null)
where T : IPackedVector<TP>
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.
/// </summary>
/// <typeparam name="T">The type of pixels contained within the image.</typeparam>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="source">The image to resize.</param>
/// <param name="width">The target image width.</param>
/// <param name="height">The target image height.</param>
@ -112,9 +117,9 @@ namespace ImageProcessorCore
/// </param>
/// <param name="compand">Whether to compress and expand the image color-space to gamma correct the image during processing.</param>
/// <param name="progressHandler">A delegate which is called as progress is made processing the image.</param>
/// <returns>The <see cref="Image{T}"/></returns>
/// <returns>The <see cref="Image{T,TP}"/></returns>
/// <remarks>Passing zero for one of height or width will automatically preserve the aspect ratio of the original image</remarks>
public static Image<T,TP> Resize<T,TP>(this Image<T,TP> source, int width, int height, IResampler sampler, Rectangle sourceRectangle, Rectangle targetRectangle, bool compand = false, ProgressEventHandler progressHandler = null)
public static Image<T, TP> Resize<T, TP>(this Image<T, TP> source, int width, int height, IResampler sampler, Rectangle sourceRectangle, Rectangle targetRectangle, bool compand = false, ProgressEventHandler progressHandler = null)
where T : IPackedVector<TP>
where TP : struct
{

72
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);
}
}
}

Loading…
Cancel
Save