public FaceDetection ConfigureDetection(NameValueCollection s) { var f = new FaceDetection(); //Parse min/max faces int[] count = NameValueCollectionExtensions.GetList <int>(s, "f.faces", null, 1, 2); if (count == null) { f.MinFaces = 1; f.MaxFaces = 8; } else if (count.Length > 0) { f.MinFaces = f.MaxFaces = count[0]; if (count.Length > 1) { f.MaxFaces = count[1]; } } //Parse min/default thresholds int[] threshold = NameValueCollectionExtensions.GetList <int>(s, "f.threshold", null, 1, 2); if (threshold != null && threshold.Length > 0) { f.MinConfidenceLevel = f.ConfidenceLevelThreshold = threshold[0]; if (threshold.Length > 1) { f.ConfidenceLevelThreshold = threshold[1]; } } //Parse min size percent f.MinSizePercent = NameValueCollectionExtensions.Get <float>(s, "f.minsize", f.MinSizePercent); //Parse expandsion rules double[] expand = NameValueCollectionExtensions.GetList <double>(s, "f.expand", null, 1, 2); //Exapnd bounding box by requested percentage if (expand != null) { f.ExpandX = expand[0]; f.ExpandY = expand.Length > 1 ? expand[1] : expand[0]; } return(f); }
protected override RequestedAction LayoutEffects(ImageState s) { float shadowWidth = s.settings.Get <float>("shadowWidth", 0); if (shadowWidth != 0) { var offset = NameValueCollectionExtensions.GetList <float>(s.settings, "shadowOffset", 0, 2); PointF shadowOffset = offset == null ? new PointF(0, 0) : new PointF(offset[0], offset[1]); //Clone last ring, then offset it - provides the inner bounds of the shadow later s.layout.AddInvisiblePolygon("shadowInner", PolygonMath.MovePoly(s.layout.LastRing.points, shadowOffset)); //Determine the outer bound of the shadow s.layout.AddRing("shadow", PolygonMath.InflatePoly(s.layout.LastRing.points, new float[] { Math.Max(0, shadowWidth - shadowOffset.Y), Math.Max(0, shadowWidth + shadowOffset.X), Math.Max(0, shadowWidth + shadowOffset.Y), Math.Max(0, shadowWidth - shadowOffset.X) })); } return(RequestedAction.None); }
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); } //Calculate bounding box for all coordinates specified. double[] focus = NameValueCollectionExtensions.GetList <double>(s.settings, "c.focus", null, 2, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72); if (focus == null) { return(RequestedAction.None); } RectangleF box = PolygonMath.GetBoundingBox(focus); var bounds = new RectangleF(new PointF(0, 0), s.originalSize); //Clip box to original image bounds box = PolygonMath.ClipRectangle(box, bounds); var targetSize = new SizeF(s.settings.Width, s.settings.Height); SizeF copySize; //Now, we can either crop as closely as possible or as loosely as possible. if (NameValueCollectionExtensions.Get <bool>(s.settings, "c.zoom", false) && box.Width > 0 && box.Height > 0) { //Crop close copySize = PolygonMath.ScaleOutside(box.Size, targetSize); } else { //Crop minimally copySize = PolygonMath.ScaleInside(targetSize, bounds.Size); //Ensure it's outside the box if (!PolygonMath.FitsInside(box.Size, copySize)) { copySize = PolygonMath.ScaleOutside(box.Size, copySize); } } //Clip to bounds. box = PolygonMath.ClipRectangle(PolygonMath.ExpandTo(box, copySize), bounds); s.copyRect = box; ///What is the vertical and horizontal aspect ratio different in result pixels? var padding = PolygonMath.ScaleInside(box.Size, targetSize); padding = new SizeF(targetSize.Width - padding.Width, targetSize.Height - padding.Height); //So, if we haven't met the aspect ratio yet, what mode will we pass on? var finalmode = NameValueCollectionExtensions.Get <FitMode>(s.settings, "c.finalmode", FitMode.Pad); //Crop off 1 or 2 pixels instead of padding without worrying too much if (finalmode == FitMode.Pad && padding.Width + padding.Height < 3) { finalmode = FitMode.Crop; } s.settings.Mode = finalmode; return(RequestedAction.None); }
protected override RequestedAction Render(ImageState s) { if (base.Render(s) == RequestedAction.Cancel) { return(RequestedAction.Cancel); } bool detecteyes = s.settings.Get <bool>("r.detecteyes", false); bool getlayout = s.settings.Get <bool>("r.getlayout", false); if (detecteyes || getlayout) { var d = new DetectionResponse <ObjRect>(); try { //Only detect eyes if it was requested. if (detecteyes) { using (var ed = new EyeDetection()) { d.features = ed.DetectFeatures(s.sourceBitmap); } } } catch (TypeInitializationException e) { throw e; } catch (Exception e) { d.message = e.Message; } d.PopulateFrom(s); throw d.GetResponseException(s.settings["callback"]); } if (s.sourceBitmap == null) { return(RequestedAction.None); } if (!string.IsNullOrEmpty(s.settings["r.eyes"])) { double[] eyes = NameValueCollectionExtensions.GetList <double>(s.settings, "r.eyes", 0); // lock source bitmap data BitmapData data = s.sourceBitmap.LockBits( new Rectangle(0, 0, s.sourceBitmap.Width, s.sourceBitmap.Height), ImageLockMode.ReadWrite, s.sourceBitmap.PixelFormat); try { UnmanagedImage ui = new UnmanagedImage(data); for (var i = 0; i < eyes.Length / 5; i++) { var x = eyes[i * 5]; var y = eyes[i * 5 + 1]; var w = eyes[i * 5 + 2]; var h = eyes[i * 5 + 3]; var a = eyes[i * 5 + 4]; var cx = x + w / 2; var cy = y + h / 2; var radius = Math.Sqrt(w * w + h * h) / 2; AdaptiveCircleFill.MarkEye(ui, new System.Drawing.Point((int)cx, (int)cy), (int)Math.Ceiling(radius), (float)(a > 6 ? radius / 4 : radius)); } } finally { // unlock image s.sourceBitmap.UnlockBits(data); } } return(RequestedAction.None); }
/// <summary> /// Supporting rounded corners. /// </summary> /// <param name="s"></param> /// <returns></returns> protected override RequestedAction PreRenderImage(ImageState s) { if (s.sourceBitmap == null) { return(RequestedAction.None); } double[] vals = NameValueCollectionExtensions.GetList <double>(s.settings, "s.roundcorners", 0, 1, 4); if (vals == null) { return(RequestedAction.None); } if (vals.Length == 1) { vals = new double[] { vals[0], vals[0], vals[0], vals[0] } } ; bool hasValue = false; foreach (double d in vals) { if (d > 0) { hasValue = true; } } if (!hasValue) { return(RequestedAction.None); } Bitmap cropped = null; try{ //Make sure cropping is applied, and use existing prerendered bitmap if present. s.ApplyCropping(); cropped = s.preRenderBitmap ?? s.sourceBitmap; s.preRenderBitmap = new Bitmap(cropped.Width, cropped.Height, PixelFormat.Format32bppArgb); int[] radius = new int[4]; //Radius percentages are 0-100, a percentage of the smaller of the width and height. for (int i = 0; i < vals.Length; i++) { radius[i] = (int)Math.Round(Math.Max(0, Math.Min(99.999, vals[i])) * ((double)Math.Min(s.preRenderBitmap.Width, s.preRenderBitmap.Height) / 100)); } s.preRenderBitmap.MakeTransparent(); using (Graphics g = Graphics.FromImage(s.preRenderBitmap)) { g.SmoothingMode = SmoothingMode.AntiAlias; g.CompositingMode = CompositingMode.SourceOver; g.CompositingQuality = CompositingQuality.HighQuality; g.PixelOffsetMode = PixelOffsetMode.HighQuality; using (TextureBrush tb = new TextureBrush(cropped)) using (GraphicsPath gp = new GraphicsPath(FillMode.Winding)) { Rectangle bounds = new Rectangle(0, 0, s.preRenderBitmap.Width, s.preRenderBitmap.Height); int[] angles = new int[] { 180, 270, 0, 90 }; int[] xs = new int[] { bounds.X, bounds.Right - radius[1], bounds.Right - radius[2], bounds.X }; int[] ys = new int[] { bounds.Y, bounds.Y, bounds.Bottom - radius[2], bounds.Bottom - radius[3] }; for (int i = 0; i < 4; i++) { if (radius[i] > 0) { gp.AddArc(xs[i], ys[i], radius[i], radius[i], angles[i], 90); } else { gp.AddLine(xs[i], ys[i], xs[i], ys[i]); } } g.FillPath(tb, gp); } } }finally{ if (cropped != null & cropped != s.sourceBitmap) { cropped.Dispose(); } } return(RequestedAction.None); }