mirror of https://github.com/SixLabors/ImageSharp
3 changed files with 60 additions and 108 deletions
@ -0,0 +1,58 @@ |
|||
// <copyright file="EntropyCropProcessor.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Processors |
|||
{ |
|||
/// <summary>
|
|||
/// Provides methods to allow the cropping of an image to preserve areas of highest
|
|||
/// entropy.
|
|||
/// </summary>
|
|||
/// <typeparam name="TColor">The pixel format.</typeparam>
|
|||
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
|
|||
public class EntropyCropProcessor<TColor, TPacked> : ImageFilteringProcessor<TColor, TPacked> |
|||
where TColor : struct, IPackedPixel<TPacked> |
|||
where TPacked : struct |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="EntropyCropProcessor{TColor, TPacked}"/> class.
|
|||
/// </summary>
|
|||
/// <param name="threshold">The threshold to split the image. Must be between 0 and 1.</param>
|
|||
/// <exception cref="System.ArgumentException">
|
|||
/// <paramref name="threshold"/> is less than 0 or is greater than 1.
|
|||
/// </exception>
|
|||
public EntropyCropProcessor(float threshold) |
|||
{ |
|||
Guard.MustBeBetweenOrEqualTo(threshold, 0, 1, nameof(threshold)); |
|||
this.Value = threshold; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the threshold value.
|
|||
/// </summary>
|
|||
public float Value { get; } |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void Apply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY) |
|||
{ |
|||
ImageBase<TColor, TPacked> temp = new Image<TColor, TPacked>(source.Width, source.Height); |
|||
|
|||
// Detect the edges.
|
|||
new SobelProcessor<TColor, TPacked>().Apply(temp, source, sourceRectangle); |
|||
|
|||
// Apply threshold binarization filter.
|
|||
new BinaryThresholdProcessor<TColor, TPacked>(this.Value).Apply(temp, sourceRectangle); |
|||
|
|||
// Search for the first white pixels
|
|||
Rectangle rectangle = ImageMaths.GetFilteredBoundingRectangle(temp, 0); |
|||
|
|||
if (rectangle == sourceRectangle) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
new CropProcessor<TColor, TPacked>(rectangle).Apply(source, sourceRectangle); |
|||
} |
|||
} |
|||
} |
|||
@ -1,107 +0,0 @@ |
|||
// <copyright file="EntropyCropProcessor.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; |
|||
using System.Threading.Tasks; |
|||
|
|||
/// <summary>
|
|||
/// Provides methods to allow the cropping of an image to preserve areas of highest
|
|||
/// entropy.
|
|||
/// </summary>
|
|||
/// <typeparam name="TColor">The pixel format.</typeparam>
|
|||
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
|
|||
public class EntropyCropProcessor<TColor, TPacked> : ImageSamplingProcessor<TColor, TPacked> |
|||
where TColor : struct, IPackedPixel<TPacked> |
|||
where TPacked : struct |
|||
{ |
|||
/// <summary>
|
|||
/// The rectangle for cropping
|
|||
/// </summary>
|
|||
private Rectangle cropRectangle; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="EntropyCropProcessor{TColor, TPacked}"/> class.
|
|||
/// </summary>
|
|||
/// <param name="threshold">The threshold to split the image. Must be between 0 and 1.</param>
|
|||
/// <exception cref="System.ArgumentException">
|
|||
/// <paramref name="threshold"/> is less than 0 or is greater than 1.
|
|||
/// </exception>
|
|||
public EntropyCropProcessor(float threshold) |
|||
{ |
|||
Guard.MustBeBetweenOrEqualTo(threshold, 0, 1, nameof(threshold)); |
|||
this.Value = threshold; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the threshold value.
|
|||
/// </summary>
|
|||
public float Value { get; } |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) |
|||
{ |
|||
// Jump out, we'll deal with that later.
|
|||
if (source.Bounds == target.Bounds) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
int targetY = this.cropRectangle.Y; |
|||
int targetBottom = this.cropRectangle.Bottom; |
|||
int startX = this.cropRectangle.X; |
|||
int endX = this.cropRectangle.Right; |
|||
|
|||
int minY = Math.Max(targetY, startY); |
|||
int maxY = Math.Min(targetBottom, endY); |
|||
|
|||
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock()) |
|||
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock()) |
|||
{ |
|||
Parallel.For( |
|||
minY, |
|||
maxY, |
|||
this.ParallelOptions, |
|||
y => |
|||
{ |
|||
for (int x = startX; x < endX; x++) |
|||
{ |
|||
targetPixels[x - startX, y - targetY] = sourcePixels[x, y]; |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void OnApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle) |
|||
{ |
|||
ImageBase<TColor, TPacked> temp = new Image<TColor, TPacked>(source.Width, source.Height); |
|||
|
|||
// Detect the edges.
|
|||
new SobelProcessor<TColor, TPacked>().Apply(temp, source, sourceRectangle); |
|||
|
|||
// Apply threshold binarization filter.
|
|||
new BinaryThresholdProcessor<TColor, TPacked>(.5f).Apply(temp, sourceRectangle); |
|||
|
|||
// Search for the first white pixels
|
|||
Rectangle rectangle = ImageMaths.GetFilteredBoundingRectangle(temp, 0); |
|||
|
|||
// Reset the target pixel to the correct size.
|
|||
target.SetPixels(rectangle.Width, rectangle.Height, new TColor[rectangle.Width * rectangle.Height]); |
|||
this.cropRectangle = rectangle; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void AfterApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle) |
|||
{ |
|||
// Copy the pixels over.
|
|||
if (source.Bounds == target.Bounds) |
|||
{ |
|||
target.ClonePixels(target.Width, target.Height, source.Pixels); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue