protected override RequestedAction LayoutImage(ImageState s) { //Only activated if both width and height are specified, and mode=crop. if (s.settings.Mode != FitMode.Crop || s.settings.Width < 0 || s.settings.Height < 0) { return(RequestedAction.None); } var finalMode = s.settings.Get("c.finalmode", FitMode.Pad); var regions = SalientArea.FromQuery(s.settings); if (regions.Length == 0) { return(RequestedAction.None); } var a = new Aligner { Regions = regions, ImageSize = s.originalSize, TargetSize = new Size(s.settings.Width, s.settings.Height), NeverCropSalientArea = finalMode != FitMode.Crop, Zoom = regions[0].Area.Width > 0 && regions[0].Area.Height > 0 && s.settings.Get("c.zoom", false) }; s.copyRect = a.GetCrop(); s.ValidateCropping(); //So, if we haven't met the aspect ratio yet, what mode will we pass on? s.settings.Mode = finalMode; return(RequestedAction.None); }
internal RectangleF GetCrop() { if (Zoom) { return(GetZoomCrop()); } var salientBounds = SalientBoundingBox(); var idealCropSize = PolygonMath.ScaleInside(TargetSize, ImageSize); var fits = PolygonMath.FitsInside(salientBounds.Size, idealCropSize); // If there's no need to crop out a salient region, then center on the salient bounding box and align within the image bounds. if (fits) { return(PolygonMath.AlignWithin(new RectangleF(PointF.Empty, idealCropSize), new RectangleF(PointF.Empty, ImageSize), PolygonMath.Midpoint(salientBounds))); } if (NeverCropSalientArea) { var compromiseCrop = new SizeF(Math.Max(salientBounds.Width, idealCropSize.Width), Math.Max(salientBounds.Height, idealCropSize.Height)); // Don't worry about 3 pixels or less, that's just annoying. if (compromiseCrop.Width - idealCropSize.Width <= 3 && compromiseCrop.Height - idealCropSize.Height <= 3) { compromiseCrop = idealCropSize; } return(PolygonMath.AlignWithin(new RectangleF(PointF.Empty, compromiseCrop), new RectangleF(PointF.Empty, ImageSize), PolygonMath.Midpoint(salientBounds))); } // Find the least bad crop (brute force) var vertical = salientBounds.Height > idealCropSize.Height; var choiceCount = vertical ? salientBounds.Height - idealCropSize.Height : salientBounds.Width - idealCropSize.Width; var searchArea = new RectangleF(vertical ? 0 : salientBounds.X, vertical ? salientBounds.Y : 0, vertical ? idealCropSize.Width : salientBounds.Width, vertical ? salientBounds.Height : idealCropSize.Height); var initialWindow = PolygonMath.AlignWith(new RectangleF(PointF.Empty, idealCropSize), searchArea, ContentAlignment.TopLeft); double bestVolume = 0; var bestCrop = initialWindow; for (var i = 0; i < choiceCount; i++) { var window = initialWindow; window.Offset(vertical ? 0 : i, vertical ? i : 0); var volume = SalientArea.IntersectVolume(window, Regions); if (volume > bestVolume) { bestVolume = volume; bestCrop = window; } } return(bestCrop); }