/// <summary>
        /// Mean Filter
        /// </summary>
        /// <param name="sourceBitmap">Set source Bitmap</param>
        /// <param name="meanSize">Set mean size</param>
        /// <returns></returns>
        public static System.Drawing.Bitmap MeanFilter(this System.Drawing.Bitmap sourceBitmap,
                                                       int meanSize)
        {
            byte[] pixelBuffer  = sourceBitmap.GetByteArray();
            byte[] resultBuffer = new byte[pixelBuffer.Length];

            double blue = 0.0, green = 0.0, red = 0.0;
            double factor = 1.0 / (meanSize * meanSize);

            int imageStride = sourceBitmap.Width * 4;
            int filterOffset = meanSize / 2;
            int calcOffset = 0, filterY = 0, filterX = 0;

            for (int k = 0; k + 4 < pixelBuffer.Length; k += 4)
            {
                blue    = 0; green = 0; red = 0;
                filterY = -filterOffset;
                filterX = -filterOffset;

                while (filterY <= filterOffset)
                {
                    calcOffset = k + (filterX * 4) +
                                 (filterY * imageStride);

                    calcOffset = (calcOffset < 0 ? 0 :
                                  (calcOffset >= pixelBuffer.Length - 2 ?
                                   pixelBuffer.Length - 3 : calcOffset));

                    blue  += pixelBuffer[calcOffset];
                    green += pixelBuffer[calcOffset + 1];
                    red   += pixelBuffer[calcOffset + 2];

                    filterX++;

                    if (filterX > filterOffset)
                    {
                        filterX = -filterOffset;
                        filterY++;
                    }
                }

                resultBuffer[k]     = ClipByte(factor * blue);
                resultBuffer[k + 1] = ClipByte(factor * green);
                resultBuffer[k + 2] = ClipByte(factor * red);
                resultBuffer[k + 3] = 255;
            }

            return(resultBuffer.GetImage(sourceBitmap.Width, sourceBitmap.Height));
        }
        /// <summary>
        /// Boolean Edge Detection Filter
        /// </summary>
        /// <param name="sourceBitmap">Set source Bitmap</param>
        /// <param name="edgeFactor">Set edge factor</param>
        /// <returns></returns>
        public static System.Drawing.Bitmap BooleanEdgeDetectionFilter(
            this System.Drawing.Bitmap sourceBitmap, float edgeFactor)
        {
            byte[] pixelBuffer  = sourceBitmap.GetByteArray();
            byte[] resultBuffer = new byte[pixelBuffer.Length];
            Buffer.BlockCopy(pixelBuffer, 0, resultBuffer,
                             0, pixelBuffer.Length);

            List <string> edgeMasks = GetBooleanEdgeMasks();

            int    imageStride = sourceBitmap.Width * 4;
            int    matrixMean = 0, pixelTotal = 0;
            int    filterY = 0, filterX = 0, calcOffset = 0;
            string matrixPatern = String.Empty;

            for (int k = 0; k + 4 < pixelBuffer.Length; k += 4)
            {
                matrixPatern = String.Empty;
                matrixMean   = 0; pixelTotal = 0;
                filterY      = -1; filterX = -1;

                while (filterY < 2)
                {
                    calcOffset = k + (filterX * 4) +
                                 (filterY * imageStride);

                    calcOffset = (calcOffset < 0 ? 0 :
                                  (calcOffset >= pixelBuffer.Length - 2 ?
                                   pixelBuffer.Length - 3 : calcOffset));

                    matrixMean += pixelBuffer[calcOffset];
                    matrixMean += pixelBuffer[calcOffset + 1];
                    matrixMean += pixelBuffer[calcOffset + 2];

                    filterX += 1;

                    if (filterX > 1)
                    {
                        filterX = -1; filterY += 1;
                    }
                }

                matrixMean = matrixMean / 9;
                filterY    = -1; filterX = -1;

                while (filterY < 2)
                {
                    calcOffset = k + (filterX * 4) +
                                 (filterY * imageStride);

                    calcOffset = (calcOffset < 0 ? 0 :
                                  (calcOffset >= pixelBuffer.Length - 2 ?
                                   pixelBuffer.Length - 3 : calcOffset));

                    pixelTotal  = pixelBuffer[calcOffset];
                    pixelTotal += pixelBuffer[calcOffset + 1];
                    pixelTotal += pixelBuffer[calcOffset + 2];

                    matrixPatern += (pixelTotal > matrixMean
                                                 ? "1" : "0");
                    filterX += 1;

                    if (filterX > 1)
                    {
                        filterX = -1; filterY += 1;
                    }
                }

                if (edgeMasks.Contains(matrixPatern))
                {
                    resultBuffer[k] =
                        ClipByte(resultBuffer[k] * edgeFactor);

                    resultBuffer[k + 1] =
                        ClipByte(resultBuffer[k + 1] * edgeFactor);

                    resultBuffer[k + 2] =
                        ClipByte(resultBuffer[k + 2] * edgeFactor);
                }
            }

            return(resultBuffer.GetImage(sourceBitmap.Width, sourceBitmap.Height));
        }