/// <summary> /// Creates a comic rendered copy of the input image. /// </summary> public override Bitmap Render(Bitmap sourceImage) { GrayscaleToRGB convertColor = new GrayscaleToRGB(); if (sourceImage.PixelFormat == PixelFormat.Format8bppIndexed) { sourceImage = convertColor.Apply(sourceImage); } BilateralBlur blur = new BilateralBlur(3, 0.1); Bitmap comic = blur.Apply(sourceImage); // Edges Bitmap grayscale = Grayscale.CommonAlgorithms.Y.Apply(comic); SobelEdgeDetector sobelEdge = new SobelEdgeDetector(); sobelEdge.ScaleIntensity = true; Bitmap edgeLayer = sobelEdge.Apply(grayscale); edgeLayer = convertColor.Apply(edgeLayer); Invert invertEdge = new Invert(); invertEdge.ApplyInPlace(edgeLayer); HSLLinear edgeLinear = new HSLLinear(); edgeLinear.InLuminance.Min = 0; edgeLinear.InLuminance.Max = 0.8; edgeLinear.ApplyInPlace(edgeLayer); // highlights Bitmap highlightLayer = invertEdge.Apply(edgeLayer); Dilatation highlightDilitation = new Dilatation(); highlightDilitation.ApplyInPlace(highlightLayer); BrightnessCorrection highlightBright = new BrightnessCorrection(-0.35); highlightBright.ApplyInPlace(highlightLayer); ColorDodge highlightBlend = new ColorDodge(highlightLayer); highlightBlend.ApplyInPlace(comic); // Merge edges with working layer Multiply multEdge = new Multiply(edgeLayer); multEdge.ApplyInPlace(comic); return(comic); }
public mFilterHSLLinear(wDomain SaturationIn, wDomain SaturationOut, wDomain LuminanceIn, wDomain LuminanceOut) { SatIn = SaturationIn; SatOut = SaturationOut; LumIn = LuminanceIn; LumOut = LuminanceOut; BitmapType = mFilter.BitmapTypes.None; Effect = new HSLLinear(); Effect.InSaturation = new Accord.Range((float)SatIn.T0, (float)SatIn.T1); Effect.OutSaturation = new Accord.Range((float)SatOut.T0, (float)SatOut.T1); Effect.InLuminance = new Accord.Range((float)LumIn.T0, (float)LumIn.T1); Effect.OutLuminance = new Accord.Range((float)LumOut.T0, (float)LumOut.T1); filter = Effect; }
/// <summary> /// /// </summary> /// <param name="f"></param> /// <param name="contrast">-1..1 float to adjust contrast. </param> /// <param name="brightness">-1..1 float to adjust luminance (brightness). 0 does nothing</param> /// <param name="saturation">-1..1 float to adjust saturation. 0 does nothing </param> /// <param name="truncate">If false, adjusting brightness and luminance will adjust contrast also. True causes white/black washout instead.</param> protected void AdjustContrastBrightnessSaturation(HSLLinear f, float contrast, float brightness, float saturation, bool truncate) { brightness = Math.Max(-1.0f, Math.Min(1.0f, brightness)); saturation = Math.Max(-1.0f, Math.Min(1.0f, saturation)); contrast = Math.Max(-1.0f, Math.Min(1.0f, contrast)); // create luminance filter if (brightness > 0) { f.InLuminance = new Range(0.0f, 1.0f - (truncate ? brightness : 0)); //TODO - isn't it better not to truncate, but compress? f.OutLuminance = new Range(brightness, 1.0f); } else { f.InLuminance = new Range((truncate ? -brightness : 0), 1.0f); f.OutLuminance = new Range(0.0f, 1.0f + brightness); } // create saturation filter if (saturation > 0) { f.InSaturation = new Range(0.0f, 1.0f - (truncate ? saturation : 0)); //Ditto? f.OutSaturation = new Range(saturation, 1.0f); } else { f.InSaturation = new Range((truncate ? -saturation : 0), 1.0f); f.OutSaturation = new Range(0.0f, 1.0f + saturation); } if (contrast > 0) { float adjustment = contrast * (f.InLuminance.Max - f.InLuminance.Min) / 2; f.InLuminance = new Range(f.InLuminance.Min + adjustment, f.InLuminance.Max - adjustment); } else if (contrast < 0) { float adjustment = -contrast * (f.OutLuminance.Max - f.OutLuminance.Min) / 2; f.OutLuminance = new Range(f.OutLuminance.Min + adjustment, f.OutLuminance.Max - adjustment); } }
/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param> protected override void SolveInstance(IGH_DataAccess DA) { Bitmap img = null; DA.GetData(0, ref img); Interval L = new Interval(0, 1); DA.GetData("Luminance", ref L); Interval S = new Interval(0, 1); DA.GetData("Saturation", ref S); Interval Y = new Interval(0, 255); DA.GetData("Luma", ref Y); Interval Cb = new Interval(-1, 1); DA.GetData("Chroma_Blue", ref Cb); Interval Cr = new Interval(-1, 1); DA.GetData("Chroma_Red", ref Cr); Interval R = new Interval(0, 255); DA.GetData("Red", ref R); Interval G = new Interval(0, 255); DA.GetData("Green", ref G); Interval B = new Interval(0, 255); DA.GetData("Blue", ref B); Bitmap filteredImage = img; Interval bInterval = new Interval(0, 1); Interval Interval255 = new Interval(0, 255); Interval IntervalMinusOne = new Interval(-1, 1); ////////////////////////////////////////////////////////////////////////// HSLLinear myHSLfilter = new HSLLinear(); if (bInterval.IncludesInterval(L)) { myHSLfilter.InLuminance = new AForge.Range(Convert.ToSingle(L.Min), Convert.ToSingle(L.Max)); } if (bInterval.IncludesInterval(S)) { myHSLfilter.InSaturation = new AForge.Range(Convert.ToSingle(S.Min), Convert.ToSingle(S.Max)); } filteredImage = myHSLfilter.Apply(img); ////////////////////////////////////////////////////////////////////////// YCbCrLinear myYCbCrfilter = new YCbCrLinear(); if (Interval255.IncludesInterval(Y)) { myYCbCrfilter.InCb = new AForge.Range(Convert.ToSingle(Y.Min), Convert.ToSingle(Y.Max)); } if (IntervalMinusOne.IncludesInterval(Cb)) { myYCbCrfilter.InCb = new AForge.Range(Convert.ToSingle(Cb.Min), Convert.ToSingle(Cb.Max)); } if (IntervalMinusOne.IncludesInterval(Cr)) { myYCbCrfilter.InCr = new AForge.Range(Convert.ToSingle(Cr.Min), Convert.ToSingle(Cr.Max)); } filteredImage = myYCbCrfilter.Apply(filteredImage); ////////////////////////////////////////////////////////////////////////// LevelsLinear myRGBfilter = new LevelsLinear(); if (Interval255.IncludesInterval(R)) { myRGBfilter.InRed = new AForge.IntRange((int)(R.Min), (int)(R.Max)); } if (Interval255.IncludesInterval(G)) { myRGBfilter.InGreen = new AForge.IntRange((int)(G.Min), (int)(G.Max)); } if (Interval255.IncludesInterval(B)) { myRGBfilter.InBlue = new AForge.IntRange((int)(B.Min), (int)(B.Max)); } filteredImage = myRGBfilter.Apply(filteredImage); DA.SetData(0, filteredImage); }
protected void ApplyFiltersTo(ref Bitmap b, ImageState s) { var imageRectF = s.layout.GetRingAsRectF("image"); var areaOfEffect = imageRectF == null ? new Rectangle(0, 0, b.Width, b.Height) : PolygonMath.ToRectangleShrinkRound(imageRectF.Value); //TODO: if the image is unrotated, use a rectangle to limit the effect to the desired area string str = null; int i = 0; //If radiusunits is specified, use that code path. double units = s.settings.Get <double>("a.radiusunits", 1000); //TODO: move blur/sharpen aliases to a compatibility shim, deprecate them i = GetRadius(s, "blur", "a.blur", units); if (i > 0) { new GaussianBlur(1.4, i).ApplyInPlace(b, areaOfEffect); } i = GetRadius(s, "sharpen", "a.sharpen", units); if (i > 0) { new GaussianSharpen(1.4, Math.Min(11, i)).ApplyInPlace(b, areaOfEffect); } i = GetRadius(s, "a.oilpainting", null, units); if (i > 0) { new OilPainting(i).ApplyInPlace(b, areaOfEffect); } if ("true".Equals(s.settings["a.removenoise"], StringComparison.OrdinalIgnoreCase)) { new ConservativeSmoothing(3).ApplyInPlace(b, areaOfEffect); } else { i = GetRadius(s, "a.removenoise", null, units); if (i > 0) { new ConservativeSmoothing(i).ApplyInPlace(b, areaOfEffect); } } //Sobel only supports 8bpp grayscale images. //true/false if ("true".Equals(s.settings["a.sobel"], StringComparison.OrdinalIgnoreCase)) { Bitmap old = b; try{ b = Grayscale.CommonAlgorithms.Y.Apply(b); }finally{ if (old != s.sourceBitmap) { old.Dispose(); } } new SobelEdgeDetector().ApplyInPlace(b, areaOfEffect); str = s.settings["a.threshold"]; //radius if (!string.IsNullOrEmpty(str) && int.TryParse(str, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out i) && i > 0) { new Threshold(i).ApplyInPlace(b, areaOfEffect); } } //Canny Edge Detector only supports 8bpp grayscale images. //true/false if ("true".Equals(s.settings["a.canny"], StringComparison.OrdinalIgnoreCase)) { Bitmap old = b; try { b = Grayscale.CommonAlgorithms.Y.Apply(b); } finally { if (old != s.sourceBitmap) { old.Dispose(); } } new CannyEdgeDetector().ApplyInPlace(b, areaOfEffect); } //true/false - duplicate with SimpleFilters? if ("true".Equals(s.settings["a.sepia"], StringComparison.OrdinalIgnoreCase)) { new Sepia().ApplyInPlace(b, areaOfEffect); } //true/false if ("true".Equals(s.settings["a.equalize"], StringComparison.OrdinalIgnoreCase)) { new HistogramEqualization().ApplyInPlace(b, areaOfEffect); } //White balance adjustment var whiteAlg = s.settings.Get <HistogramThresholdAlgorithm>("a.balancewhite"); var whiteVal = s.settings.Get <double>("a.balancethreshold"); if (whiteAlg != null || whiteVal != null) { var bal = new AutoWhiteBalance(whiteAlg ?? HistogramThresholdAlgorithm.Area); if (whiteVal != null) { bal.LowThreshold = bal.HighThreshold = whiteVal.Value / 100; } bal.ApplyInPlace(b, areaOfEffect); } str = s.settings["a.posterize"]; //number of colors to merge if (!string.IsNullOrEmpty(str) && int.TryParse(str, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out i) && i > 0) { SimplePosterization sp = new SimplePosterization(); if (i < 1) { i = 1; } if (i > 255) { i = 255; } sp.PosterizationInterval = (byte)i; sp.ApplyInPlace(b, areaOfEffect); } //Pixelate doesn't support 32-bit images, only 24-bit //str = s.settings["a.pixelate"]; //number of colors to merge //if (!string.IsNullOrEmpty(str) && int.TryParse(str, out i)){ // if (i < 2) i = 2; // if (i > 32) i = 32; // new Pixelate(i).ApplyInPlace(s.destBitmap); //} float contrast = s.settings.Get <float>("a.contrast", 0); float brightness = s.settings.Get <float>("a.brightness", 0); float saturation = s.settings.Get <float>("a.saturation", 0); if (contrast != 0 || brightness != 0 || saturation != 0) { HSLLinear adjust = new HSLLinear(); AdjustContrastBrightnessSaturation(adjust, contrast, brightness, saturation, "true".Equals(s.settings["a.truncate"])); adjust.ApplyInPlace(b, areaOfEffect); } //TODO - add grayscale? //For adding fax-like thresholding, use BradleyLocalThresholding //For trimming solid-color whitespace, use Shrink }