// // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // namespace ImageProcessor.Samplers { using System; using System.Threading.Tasks; using ImageProcessor.Filters; /// /// Provides methods to allow the cropping of an image to preserve areas of highest /// entropy. /// public class EntropyCrop : ParallelImageProcessor { /// /// Initializes a new instance of the class. /// /// The threshold to split the image. Must be between 0 and 1. /// /// is less than 0 or is greater than 1. /// public EntropyCrop(float threshold) { Guard.MustBeBetweenOrEqualTo(threshold, 0, 1, nameof(threshold)); this.Value = threshold; } /// /// Gets the threshold value. /// public float Value { get; } /// protected override void OnApply(ImageBase source, ImageBase target, Rectangle targetRectangle, Rectangle sourceRectangle) { ImageBase temp = new Image(source.Width, source.Height); // TODO: Should we detect edges on a grayscale image? new Sobel() { Greyscale = true }.Apply(temp, source, sourceRectangle); // Apply threshold binarization filter. new Threshold(.5f).Apply(temp, temp, sourceRectangle); // Search for the first white pixels Rectangle rectangle = ImageMaths.GetFilteredBoundingRectangle(temp, 0); target.SetPixels(rectangle.Width, rectangle.Height, new float[rectangle.Width * rectangle.Height * 4]); } /// protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) { int targetY = targetRectangle.Y; int targetBottom = targetRectangle.Height; int startX = targetRectangle.X; int endX = targetRectangle.Width; Parallel.For( startY, endY, y => { if (y >= targetY && y < targetBottom) { for (int x = startX; x < endX; x++) { target[x, y] = source[x, y]; } } }); } } }