/// <summary>
        /// Dilate and erode morphological filters.
        /// </summary>
        /// <param name="sourceBitmap">Source image</param>
        /// <param name="matrixSize">Size of the matrix</param>
        /// <param name="morphType">Morphology type</param>
        /// <param name="applyBlue">Apply a color blue</param>
        /// <param name="applyGreen">Apply a color green</param>
        /// <param name="applyRed">Apply a color red</param>
        /// <param name="edgeType">Sets the edge type</param>
        /// <returns></returns>
        public static Bitmap DilateAndErodeFilter(this Bitmap sourceBitmap,
                                                int matrixSize,
                                                MorphologyType morphType,
                                                bool applyBlue = true,
                                                bool applyGreen = true,
                                                bool applyRed = true,
                                                MorphologyEdgeType edgeType =
                                                MorphologyEdgeType.None)
        {
            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 filterOffset = (matrixSize - 1) / 2;
            int calcOffset = 0;

            int byteOffset = 0;

            int blue = 0;
            int green = 0;
            int red = 0;

            byte morphResetValue = 0;

            if (morphType == MorphologyType.Erosion)
            {
                morphResetValue = 255;
            }

            for (int offsetY = filterOffset; offsetY <
                sourceBitmap.Height - filterOffset; offsetY++)
            {
                for (int offsetX = filterOffset; offsetX <
                    sourceBitmap.Width - filterOffset; offsetX++)
                {
                    byteOffset = offsetY *
                                 sourceData.Stride +
                                 offsetX * 4;

                    blue = morphResetValue;
                    green = morphResetValue;
                    red = morphResetValue;

                    if (morphType == MorphologyType.Dilation)
                    {
                        for (int filterY = -filterOffset;
                            filterY <= filterOffset; filterY++)
                        {
                            for (int filterX = -filterOffset;
                                filterX <= filterOffset; filterX++)
                            {
                                calcOffset = byteOffset +
                                             (filterX * 4) +
                                (filterY * sourceData.Stride);

                                if (pixelBuffer[calcOffset] > blue)
                                {
                                    blue = pixelBuffer[calcOffset];
                                }

                                if (pixelBuffer[calcOffset + 1] > green)
                                {
                                    green = pixelBuffer[calcOffset + 1];
                                }

                                if (pixelBuffer[calcOffset + 2] > red)
                                {
                                    red = pixelBuffer[calcOffset + 2];
                                }
                            }
                        }
                    }
                    else if (morphType == MorphologyType.Erosion)
                    {
                        for (int filterY = -filterOffset;
                            filterY <= filterOffset; filterY++)
                        {
                            for (int filterX = -filterOffset;
                                filterX <= filterOffset; filterX++)
                            {
                                calcOffset = byteOffset +
                                             (filterX * 4) +
                                (filterY * sourceData.Stride);

                                if (pixelBuffer[calcOffset] < blue)
                                {
                                    blue = pixelBuffer[calcOffset];
                                }

                                if (pixelBuffer[calcOffset + 1] < green)
                                {
                                    green = pixelBuffer[calcOffset + 1];
                                }

                                if (pixelBuffer[calcOffset + 2] < red)
                                {
                                    red = pixelBuffer[calcOffset + 2];
                                }
                            }
                        }
                    }

                    if (applyBlue == false)
                    {
                        blue = pixelBuffer[byteOffset];
                    }

                    if (applyGreen == false)
                    {
                        green = pixelBuffer[byteOffset + 1];
                    }

                    if (applyRed == false)
                    {
                        red = pixelBuffer[byteOffset + 2];
                    }

                    if (edgeType == MorphologyEdgeType.EdgeDetection)
                    {
                        if (morphType == MorphologyType.Dilation)
                        {
                            blue = blue - pixelBuffer[byteOffset];
                            green = green - pixelBuffer[byteOffset + 1];
                            red = red - pixelBuffer[byteOffset + 2];
                        }
                        else if (morphType == MorphologyType.Erosion)
                        {
                            blue = pixelBuffer[byteOffset] - blue;
                            green = pixelBuffer[byteOffset + 1] - green;
                            red = pixelBuffer[byteOffset + 2] - red;
                        }
                    }

                    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;
        }
        /// <summary>
        /// Dilate And Erode Filter
        /// </summary>
        /// <param name="sourceBitmap">Set source Bitmap</param>
        /// <param name="matrixSize">Set matrix size</param>
        /// <param name="morphType">Set Morphology Type</param>
        /// <param name="applyBlue">Apply Blue</param>
        /// <param name="applyGreen">Apply Green</param>
        /// <param name="applyRed">Apply Red</param>
        /// <param name="edgeType">Morphology Edge Type</param>
        /// <returns></returns>
        public static System.Drawing.Bitmap DilateAndErodeFilter(this System.Drawing.Bitmap sourceBitmap,
                                                                 int matrixSize,
                                                                 MorphologyType morphType,
                                                                 bool applyBlue              = true,
                                                                 bool applyGreen             = true,
                                                                 bool applyRed               = true,
                                                                 MorphologyEdgeType edgeType =
                                                                 MorphologyEdgeType.None)
        {
            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 filterOffset = (matrixSize - 1) / 2;
            int calcOffset   = 0;

            int byteOffset = 0;

            int blue  = 0;
            int green = 0;
            int red   = 0;

            byte morphResetValue = 0;

            if (morphType == MorphologyType.Erosion)
            {
                morphResetValue = 255;
            }

            for (int offsetY = filterOffset; offsetY <
                 sourceBitmap.Height - filterOffset; offsetY++)
            {
                for (int offsetX = filterOffset; offsetX <
                     sourceBitmap.Width - filterOffset; offsetX++)
                {
                    byteOffset = offsetY *
                                 sourceData.Stride +
                                 offsetX * 4;

                    blue  = morphResetValue;
                    green = morphResetValue;
                    red   = morphResetValue;

                    if (morphType == MorphologyType.Dilation)
                    {
                        for (int filterY = -filterOffset;
                             filterY <= filterOffset; filterY++)
                        {
                            for (int filterX = -filterOffset;
                                 filterX <= filterOffset; filterX++)
                            {
                                calcOffset = byteOffset +
                                             (filterX * 4) +
                                             (filterY * sourceData.Stride);

                                if (pixelBuffer[calcOffset] > blue)
                                {
                                    blue = pixelBuffer[calcOffset];
                                }

                                if (pixelBuffer[calcOffset + 1] > green)
                                {
                                    green = pixelBuffer[calcOffset + 1];
                                }

                                if (pixelBuffer[calcOffset + 2] > red)
                                {
                                    red = pixelBuffer[calcOffset + 2];
                                }
                            }
                        }
                    }
                    else if (morphType == MorphologyType.Erosion)
                    {
                        for (int filterY = -filterOffset;
                             filterY <= filterOffset; filterY++)
                        {
                            for (int filterX = -filterOffset;
                                 filterX <= filterOffset; filterX++)
                            {
                                calcOffset = byteOffset +
                                             (filterX * 4) +
                                             (filterY * sourceData.Stride);

                                if (pixelBuffer[calcOffset] < blue)
                                {
                                    blue = pixelBuffer[calcOffset];
                                }

                                if (pixelBuffer[calcOffset + 1] < green)
                                {
                                    green = pixelBuffer[calcOffset + 1];
                                }

                                if (pixelBuffer[calcOffset + 2] < red)
                                {
                                    red = pixelBuffer[calcOffset + 2];
                                }
                            }
                        }
                    }

                    if (applyBlue == false)
                    {
                        blue = pixelBuffer[byteOffset];
                    }

                    if (applyGreen == false)
                    {
                        green = pixelBuffer[byteOffset + 1];
                    }

                    if (applyRed == false)
                    {
                        red = pixelBuffer[byteOffset + 2];
                    }

                    if (edgeType == MorphologyEdgeType.EdgeDetection ||
                        edgeType == MorphologyEdgeType.SharpenEdgeDetection)
                    {
                        if (morphType == MorphologyType.Dilation)
                        {
                            blue  = blue - pixelBuffer[byteOffset];
                            green = green - pixelBuffer[byteOffset + 1];
                            red   = red - pixelBuffer[byteOffset + 2];
                        }
                        else if (morphType == MorphologyType.Erosion)
                        {
                            blue  = pixelBuffer[byteOffset] - blue;
                            green = pixelBuffer[byteOffset + 1] - green;
                            red   = pixelBuffer[byteOffset + 2] - red;
                        }

                        if (edgeType == MorphologyEdgeType.SharpenEdgeDetection)
                        {
                            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;
                }
            }

            System.Drawing.Bitmap resultBitmap = new System.Drawing.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);
        }
        /// <summary>
        /// Erosion filter
        /// </summary>
        /// <param name="image">The image.</param>
        /// <param name="matrixSize">Size of the matrix.</param>
        /// <param name="applyBlue">if set to <c>true</c> [apply blue].</param>
        /// <param name="applyGreen">if set to <c>true</c> [apply green].</param>
        /// <param name="applyRed">if set to <c>true</c> [apply red].</param>
        /// <param name="edgeType">Type of the edge.</param>
        /// <returns>Image.</returns>
        public static Image Erosion(this Image image, int matrixSize, bool applyBlue = true, bool applyGreen = true, bool applyRed = true, MorphologyEdgeType edgeType = MorphologyEdgeType.None)
        {
            ImageFilter imageFilter = new ImageFilter();

            return imageFilter.DilateAndErodeFilter(new Bitmap(image), matrixSize, MorphologyType.Erosion, applyBlue, applyGreen, applyRed, edgeType);
        }