private void ApplyFilter() { if (previewBitmap == null || cmbSmoothingFilter.SelectedIndex == -1) { return; } if (previewBitmap != null) { SmoothingFilterType filterType = ((SmoothingFilterType)cmbSmoothingFilter.SelectedItem); resultBitmap = previewBitmap.CartoonEffectFilter(this, filterType); } }
public static Bitmap CartoonEffectFilter( Bitmap sourceBitmap, byte threshold = 0, SmoothingFilterType smoothFilter = SmoothingFilterType.None) { sourceBitmap = SmoothingFilter(sourceBitmap, smoothFilter); BitmapData sourceData = sourceBitmap.LockBits(new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); byte[] pixelBuffer = new byte[sourceData.Stride * sourceData.Height]; byte[] resultBuffer = new byte[sourceData.Stride * sourceData.Height]; Marshal.Copy(sourceData.Scan0, pixelBuffer, 0, pixelBuffer.Length); sourceBitmap.UnlockBits(sourceData); int byteOffset = 0; int blueGradient, greenGradient, redGradient = 0; double blue = 0, green = 0, red = 0; bool exceedsThreshold = false; for (int offsetY = 1; offsetY < sourceBitmap.Height - 1; offsetY++) { for (int offsetX = 1; offsetX < sourceBitmap.Width - 1; offsetX++) { byteOffset = offsetY * sourceData.Stride + offsetX * 4; blueGradient = Math.Abs(pixelBuffer[byteOffset - 4] - pixelBuffer[byteOffset + 4]); blueGradient += Math.Abs(pixelBuffer[byteOffset - sourceData.Stride] - pixelBuffer[byteOffset + sourceData.Stride]); byteOffset++; greenGradient = Math.Abs(pixelBuffer[byteOffset - 4] - pixelBuffer[byteOffset + 4]); greenGradient += Math.Abs(pixelBuffer[byteOffset - sourceData.Stride] - pixelBuffer[byteOffset + sourceData.Stride]); byteOffset++; redGradient = Math.Abs(pixelBuffer[byteOffset - 4] - pixelBuffer[byteOffset + 4]); redGradient += Math.Abs(pixelBuffer[byteOffset - sourceData.Stride] - pixelBuffer[byteOffset + sourceData.Stride]); if (blueGradient + greenGradient + redGradient > threshold) { exceedsThreshold = true; } else { byteOffset -= 2; blueGradient = Math.Abs(pixelBuffer[byteOffset - 4] - pixelBuffer[byteOffset + 4]); byteOffset++; greenGradient = Math.Abs(pixelBuffer[byteOffset - 4] - pixelBuffer[byteOffset + 4]); byteOffset++; redGradient = Math.Abs(pixelBuffer[byteOffset - 4] - pixelBuffer[byteOffset + 4]); if (blueGradient + greenGradient + redGradient > threshold) { exceedsThreshold = true; } else { byteOffset -= 2; blueGradient = Math.Abs(pixelBuffer[byteOffset - sourceData.Stride] - pixelBuffer[byteOffset + sourceData.Stride]); byteOffset++; greenGradient = Math.Abs(pixelBuffer[byteOffset - sourceData.Stride] - pixelBuffer[byteOffset + sourceData.Stride]); byteOffset++; redGradient = Math.Abs(pixelBuffer[byteOffset - sourceData.Stride] - pixelBuffer[byteOffset + sourceData.Stride]); if (blueGradient + greenGradient + redGradient > threshold) { exceedsThreshold = true; } else { byteOffset -= 2; blueGradient = Math.Abs(pixelBuffer[byteOffset - 4 - sourceData.Stride] - pixelBuffer[byteOffset + 4 + sourceData.Stride]); blueGradient += Math.Abs(pixelBuffer[byteOffset - sourceData.Stride + 4] - pixelBuffer[byteOffset + sourceData.Stride - 4]); byteOffset++; greenGradient = Math.Abs(pixelBuffer[byteOffset - 4 - sourceData.Stride] - pixelBuffer[byteOffset + 4 + sourceData.Stride]); greenGradient += Math.Abs(pixelBuffer[byteOffset - sourceData.Stride + 4] - pixelBuffer[byteOffset + sourceData.Stride - 4]); byteOffset++; redGradient = Math.Abs(pixelBuffer[byteOffset - 4 - sourceData.Stride] - pixelBuffer[byteOffset + 4 + sourceData.Stride]); redGradient += Math.Abs(pixelBuffer[byteOffset - sourceData.Stride + 4] - pixelBuffer[byteOffset + sourceData.Stride - 4]); if (blueGradient + greenGradient + redGradient > threshold) { exceedsThreshold = true; } else { exceedsThreshold = false; } } } } byteOffset -= 2; if (exceedsThreshold) { blue = 0; green = 0; red = 0; } else { blue = pixelBuffer[byteOffset]; green = pixelBuffer[byteOffset + 1]; red = pixelBuffer[byteOffset + 2]; } blue = (blue > 255 ? 255 : (blue < 0 ? 0 : blue)); green = (green > 255 ? 255 : (green < 0 ? 0 : green)); red = (red > 255 ? 255 : (red < 0 ? 0 : red)); resultBuffer[byteOffset] = (byte)blue; resultBuffer[byteOffset + 1] = (byte)green; resultBuffer[byteOffset + 2] = (byte)red; resultBuffer[byteOffset + 3] = 255; } } Bitmap resultBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height); BitmapData resultData = resultBitmap.LockBits(new Rectangle(0, 0, resultBitmap.Width, resultBitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); Marshal.Copy(resultBuffer, 0, resultData.Scan0, resultBuffer.Length); resultBitmap.UnlockBits(resultData); return(resultBitmap); }
public static Bitmap SmoothingFilter(Bitmap sourceBitmap, SmoothingFilterType smoothFilter = SmoothingFilterType.None) { Bitmap inputBitmap = null; switch (smoothFilter) { case SmoothingFilterType.None: { inputBitmap = sourceBitmap; } break; case SmoothingFilterType.Gaussian3x3: { inputBitmap = ConvolutionFilter(sourceBitmap, Matrix.Gaussian3x3, 1.0 / 16.0, 0); } break; case SmoothingFilterType.Gaussian5x5: { inputBitmap = ConvolutionFilter(sourceBitmap, Matrix.Gaussian5x5, 1.0 / 159.0, 0); } break; case SmoothingFilterType.Gaussian7x7: { inputBitmap = ConvolutionFilter(sourceBitmap, Matrix.Gaussian7x7, 1.0 / 136.0, 0); } break; case SmoothingFilterType.Median3x3: { inputBitmap = MedianFilter(sourceBitmap, 3); } break; case SmoothingFilterType.Median5x5: { inputBitmap = MedianFilter(sourceBitmap, 5); } break; case SmoothingFilterType.Median7x7: { inputBitmap = MedianFilter(sourceBitmap, 7); } break; case SmoothingFilterType.Median9x9: { inputBitmap = MedianFilter(sourceBitmap, 9); } break; case SmoothingFilterType.Mean3x3: { inputBitmap = ConvolutionFilter(sourceBitmap, Matrix.Mean3x3, 1.0 / 9.0, 0); } break; case SmoothingFilterType.Mean5x5: { inputBitmap = ConvolutionFilter(sourceBitmap, Matrix.Mean5x5, 1.0 / 25.0, 0); } break; case SmoothingFilterType.LowPass3x3: { inputBitmap = ConvolutionFilter(sourceBitmap, Matrix.LowPass3x3, 1.0 / 16.0, 0); } break; case SmoothingFilterType.LowPass5x5: { inputBitmap = ConvolutionFilter(sourceBitmap, Matrix.LowPass5x5, 1.0 / 60.0, 0); } break; case SmoothingFilterType.Sharpen3x3: { inputBitmap = ConvolutionFilter(sourceBitmap, Matrix.Sharpen3x3, 1.0 / 8.0, 0); } break; } return(inputBitmap); }
public static Bitmap CartoonEffectFilter(this Bitmap sourceBitmap, MainForm form, SmoothingFilterType smoothFilter = SmoothingFilterType.Nenhum) { sourceBitmap = sourceBitmap.SmoothingFilter(form, smoothFilter); return(sourceBitmap); }
public static Bitmap SmoothingFilter(this Bitmap sourceBitmap, MainForm form, SmoothingFilterType smoothFilter = SmoothingFilterType.Nenhum) { Bitmap inputBitmap = null; //Progress bar form.algorithmProgress = 0; switch (smoothFilter) { case SmoothingFilterType.Nenhum: { inputBitmap = sourceBitmap; } break; case SmoothingFilterType.Gaussiano3x3: { inputBitmap = sourceBitmap.ConvolutionFilter( Matrix.Gaussian3x3, 1.0 / 16.0, 0); } break; case SmoothingFilterType.Gaussiano5x5: { inputBitmap = sourceBitmap.ConvolutionFilter( Matrix.Gaussian5x5, 1.0 / 159.0, 0); } break; case SmoothingFilterType.Gaussiano7x7: { inputBitmap = sourceBitmap.ConvolutionFilter( Matrix.Gaussian7x7, 1.0 / 136.0, 0); } break; case SmoothingFilterType.Mediano3x3: { inputBitmap = sourceBitmap.MedianFilter(3); } break; case SmoothingFilterType.Mediano5x5: { inputBitmap = sourceBitmap.MedianFilter(5); } break; case SmoothingFilterType.Mediano7x7: { inputBitmap = sourceBitmap.MedianFilter(7); } break; case SmoothingFilterType.Mediano9x9: { inputBitmap = sourceBitmap.MedianFilter(9); } break; case SmoothingFilterType.Mean3x3: { inputBitmap = sourceBitmap.ConvolutionFilter( Matrix.Mean3x3, 1.0 / 9.0, 0); } break; case SmoothingFilterType.Mean5x5: { inputBitmap = sourceBitmap.ConvolutionFilter( Matrix.Mean5x5, 1.0 / 25.0, 0); } break; case SmoothingFilterType.LowPass3x3: { inputBitmap = sourceBitmap.ConvolutionFilter( Matrix.LowPass3x3, 1.0 / 16.0, 0); } break; case SmoothingFilterType.LowPass5x5: { inputBitmap = sourceBitmap.ConvolutionFilter( Matrix.LowPass5x5, 1.0 / 60.0, 0); } break; case SmoothingFilterType.Sharpen3x3: { inputBitmap = sourceBitmap.ConvolutionFilter( Matrix.Sharpen3x3, 1.0 / 8.0, 0); } break; } //Progress bar form.algorithmProgress = 20; // START additional filters ADDED BY GABRIEL inputBitmap = AForge.Imaging.Image.Clone(inputBitmap, PixelFormat.Format24bppRgb); //Accepted format Bilateral filterB = new Bilateral(); Grayscale filterG = new Grayscale(0.2125, 0.7154, 0.0721); //arbitrary values CannyEdgeDetector filterE = new CannyEdgeDetector(); ColorImageQuantizer filterC = new ColorImageQuantizer(new MedianCutQuantizer()); Dilatation filterD = new Dilatation(); //Bilateral filter as present in the article filterB.KernelSize = form.kernelValue; filterB.SpatialFactor = form.spatialFactor; filterB.ColorFactor = form.colorFactor; filterB.ColorPower = form.colorPower; filterB.ApplyInPlace(inputBitmap); form.algorithmProgress = 40; /* GENERATING BORDERS */ //Generate a grayscale version for edge detection Bitmap edges = filterG.Apply(inputBitmap); filterE.HighThreshold = form.highThreshold; filterE.LowThreshold = form.lowThreshold; filterE.ApplyInPlace(edges); // a new image, edges, is created here defining the edges of inputBitmap //Dilatation filter edges = filterD.Apply(edges); generateBorder(edges); //Making bg transparent edges.MakeTransparent(Color.White); form.algorithmProgress = 70; // Color reduction as present in the article inputBitmap = filterC.ReduceColors(inputBitmap, form.colorReductionFactor); // reduces to 24 variation inputBitmap = AForge.Imaging.Image.Clone(inputBitmap, PixelFormat.Format32bppArgb); //Accepted format // images merge Bitmap bitmapResult = new Bitmap(inputBitmap.Width, inputBitmap.Height, inputBitmap.PixelFormat); Graphics g = Graphics.FromImage(bitmapResult); g.DrawImage(inputBitmap, 0, 0, inputBitmap.Width, inputBitmap.Height); g.DrawImage(edges, 0, 0, inputBitmap.Width, inputBitmap.Height); // END additional filters ADDED BY GABRIEL form.algorithmProgress = 100; return(bitmapResult); // it was returning input Bitmap before }
/// <summary> /// Smoothing Filter /// </summary> /// <param name="sourceBitmap">Set source Bitmap</param> /// <param name="smoothFilter">Set smoothing filter</param> /// <returns></returns> public static System.Drawing.Bitmap SmoothingFilter(this System.Drawing.Bitmap sourceBitmap, SmoothingFilterType smoothFilter = SmoothingFilterType.None) { System.Drawing.Bitmap inputBitmap = null; switch (smoothFilter) { case SmoothingFilterType.None: { inputBitmap = sourceBitmap; } break; case SmoothingFilterType.Gaussian3x3: { inputBitmap = sourceBitmap.CartoonConvolutionFilter( Matrix.Gaussian3x3, 1.0 / 16.0, 0); } break; case SmoothingFilterType.Gaussian5x5: { inputBitmap = sourceBitmap.CartoonConvolutionFilter( Matrix.Gaussian5x5, 1.0 / 159.0, 0); } break; case SmoothingFilterType.Gaussian7x7: { inputBitmap = sourceBitmap.CartoonConvolutionFilter( Matrix.Gaussian7x7, 1.0 / 136.0, 0); } break; case SmoothingFilterType.Median3x3: { inputBitmap = sourceBitmap.CartoonMedianFilter(3); } break; case SmoothingFilterType.Median5x5: { inputBitmap = sourceBitmap.CartoonMedianFilter(5); } break; case SmoothingFilterType.Median7x7: { inputBitmap = sourceBitmap.CartoonMedianFilter(7); } break; case SmoothingFilterType.Median9x9: { inputBitmap = sourceBitmap.CartoonMedianFilter(9); } break; case SmoothingFilterType.Mean3x3: { inputBitmap = sourceBitmap.CartoonConvolutionFilter( Matrix.Mean3x3, 1.0 / 9.0, 0); } break; case SmoothingFilterType.Mean5x5: { inputBitmap = sourceBitmap.CartoonConvolutionFilter( Matrix.Mean5x5, 1.0 / 25.0, 0); } break; case SmoothingFilterType.LowPass3x3: { inputBitmap = sourceBitmap.CartoonConvolutionFilter( Matrix.LowPass3x3, 1.0 / 16.0, 0); } break; case SmoothingFilterType.LowPass5x5: { inputBitmap = sourceBitmap.CartoonConvolutionFilter( Matrix.LowPass5x5, 1.0 / 60.0, 0); } break; case SmoothingFilterType.Sharpen3x3: { inputBitmap = sourceBitmap.CartoonConvolutionFilter( Matrix.Sharpen3x3, 1.0 / 8.0, 0); } break; } return(inputBitmap); }