public Bitmap applyBernzenThersholding(Bitmap image, Point imageSize, Point filterSize, bool convert = true)
        {
            Bitmap rezult = new Bitmap(image);
            Bitmap tempImage;

            if (convert)
            {
                tempImage = convertImageToGrayscale(image);
            }
            else
            {
                tempImage = new Bitmap(image);
            }

            ApertureService service = new ApertureService();

            List <Aperture> apertures = service.getApertureMatrixGenerator(imageSize, filterSize);

            for (int x = 0; x < apertures.Count; x++)
            {
                int    minValue = 255, maxValue = 0;
                double average;

                List <List <Point> > matrix = apertures[x].matrix;
                foreach (var matrixLine in matrix)
                {
                    foreach (var Point in matrixLine)
                    {
                        int pixelPosX = Point.X;
                        int pixelPosY = Point.Y;

                        //т.к. картинка черно белая, то значения РГБ одинаковы, можно брыть любое из трех.
                        if (tempImage.GetPixel(pixelPosX, pixelPosY).R > maxValue)
                        {
                            maxValue = tempImage.GetPixel(pixelPosX, pixelPosY).R;
                        }
                        if (tempImage.GetPixel(pixelPosX, pixelPosY).R < minValue)
                        {
                            minValue = tempImage.GetPixel(pixelPosX, pixelPosY).R;
                        }
                    }
                }
                average = ((double)minValue + maxValue) / 2;

                foreach (var matrixLine in matrix)
                {
                    foreach (var Point in matrixLine)
                    {
                        int pixelPosX = Point.X;
                        int pixelPosY = Point.Y;


                        if (tempImage.GetPixel(pixelPosX, pixelPosY).R < average)
                        {
                            rezult.SetPixel(pixelPosX, pixelPosY, Color.FromArgb(0, 0, 0));
                        }
                        else
                        {
                            rezult.SetPixel(pixelPosX, pixelPosY, Color.FromArgb(255, 255, 255));
                        }
                    }
                }
            }

            service = null;
            for (int i = 0; i < apertures.Count; i++)
            {
                apertures[i].Dispose();
            }
            apertures.Clear();

            return(rezult);
        }
        public static Bitmap applyGaussianBlurFilter(string colorMode, Bitmap image, Point imageSize, Point filterSize, int colorChannelIndex = 0)
        {
            Bitmap rezult = new Bitmap(image);

            ApertureService service = new ApertureService();

            List <Aperture> apertures = service.getApertureMatrixGenerator(imageSize, filterSize);

            double sigma = 0.5;

            for (int x = 0; x < apertures.Count; x++)
            {
                double rSum = 0, gSum = 0, bSum = 0, kSum = 0;

                List <List <Point> > matrix = apertures[x].matrix;
                int line = 0;
                foreach (var matrixLine in matrix)
                {
                    foreach (var Point in matrixLine)
                    {
                        int pixelPosX = Point.X;
                        int pixelPosY = Point.Y;

                        Color  color = image.GetPixel(pixelPosX, pixelPosY);
                        double kVal  = calculateGaussian(line, sigma);

                        rSum += color.R * kVal;
                        gSum += color.G * kVal;
                        bSum += color.B * kVal;

                        kSum += kVal;
                    }
                    line++;
                }

                if (kSum <= 0)
                {
                    kSum = 1;
                }

                rSum = rSum / kSum;
                if (rSum < 0)
                {
                    rSum = 0;
                }
                else if (rSum > 255)
                {
                    rSum = 255;
                }

                gSum = gSum / kSum;
                if (gSum < 0)
                {
                    gSum = 0;
                }
                else if (gSum > 255)
                {
                    gSum = 255;
                }

                bSum = bSum / kSum;
                if (bSum < 0)
                {
                    bSum = 0;
                }
                else if (bSum > 255)
                {
                    bSum = 255;
                }



                int aperturePosX = matrix.Count / 2;


                if (matrix.Count != 0 && matrix[aperturePosX].Count / 2 != 0)
                {
                    int aperturePosY = matrix[aperturePosX].Count / 2;

                    Color oldColor = image.GetPixel(matrix[aperturePosX][aperturePosY].X, matrix[aperturePosX][aperturePosY].Y);

                    if (colorChannelIndex == 0)
                    {
                        rezult.SetPixel(matrix[aperturePosX][aperturePosY].X, matrix[aperturePosX][aperturePosY].Y, Color.FromArgb((int)rSum, (int)gSum, (int)bSum));
                    }
                    else if (colorChannelIndex == 1)
                    {
                        rezult.SetPixel(matrix[aperturePosX][aperturePosY].X, matrix[aperturePosX][aperturePosY].Y, Color.FromArgb((int)rSum, oldColor.G, oldColor.B));
                    }
                    else if (colorChannelIndex == 2)
                    {
                        rezult.SetPixel(matrix[aperturePosX][aperturePosY].X, matrix[aperturePosX][aperturePosY].Y, Color.FromArgb(oldColor.R, (int)gSum, oldColor.B));
                    }
                    else if (colorChannelIndex == 3)
                    {
                        rezult.SetPixel(matrix[aperturePosX][aperturePosY].X, matrix[aperturePosX][aperturePosY].Y, Color.FromArgb(oldColor.R, oldColor.G, (int)bSum));
                    }
                }
            }

            service = null;
            for (int i = 0; i < apertures.Count; i++)
            {
                apertures[i].Dispose();
            }
            apertures.Clear();

            return(rezult);
        }
        public Bitmap applyMedianFilter(string colorMode, Bitmap image, Point imageSize, Point filterSize,
                                        int colorChannelIndex = 0)
        {
            Bitmap rezult = new Bitmap(image);

            ApertureService service = new ApertureService();

            List <Aperture> apertures = service.getApertureMatrixGenerator(imageSize, filterSize);

            List <int> redList   = new List <int>();
            List <int> greenList = new List <int>();
            List <int> blueList  = new List <int>();

            for (int x = 0; x < apertures.Count; x++)
            {
                redList.Clear();
                blueList.Clear();
                greenList.Clear();

                List <List <Point> > matrix = apertures[x].matrix;
                foreach (var matrixLine in matrix)
                {
                    foreach (var Point in matrixLine)
                    {
                        int pixelPosX = Point.X;
                        int pixelPosY = Point.Y;

                        Color color = image.GetPixel(pixelPosX, pixelPosY);
                        redList.Add(color.R);
                        greenList.Add(color.G);
                        blueList.Add(color.B);
                    }
                }

                redList.Sort();
                greenList.Sort();
                blueList.Sort();

                int apertureCenter = redList.Count / 2;
                int rValue         = redList[apertureCenter];
                int gValue         = greenList[apertureCenter];
                int bValue         = blueList[apertureCenter];

                int aperturePosX = matrix.Count / 2;
                int aperturePosY = matrix[aperturePosX].Count / 2;

                Color oldColor = image.GetPixel(matrix[aperturePosX][aperturePosY].X,
                                                matrix[aperturePosX][aperturePosY].Y);

                if (colorChannelIndex == 0)
                {
                    rezult.SetPixel(matrix[aperturePosX][aperturePosY].X, matrix[aperturePosX][aperturePosY].Y,
                                    Color.FromArgb(rValue, gValue, bValue));
                }
                else if (colorChannelIndex == 1)
                {
                    rezult.SetPixel(matrix[aperturePosX][aperturePosY].X, matrix[aperturePosX][aperturePosY].Y,
                                    Color.FromArgb(rValue, oldColor.G, oldColor.B));
                }
                else if (colorChannelIndex == 2)
                {
                    rezult.SetPixel(matrix[aperturePosX][aperturePosY].X, matrix[aperturePosX][aperturePosY].Y,
                                    Color.FromArgb(oldColor.R, gValue, oldColor.B));
                }
                else if (colorChannelIndex == 3)
                {
                    rezult.SetPixel(matrix[aperturePosX][aperturePosY].X, matrix[aperturePosX][aperturePosY].Y,
                                    Color.FromArgb(oldColor.R, oldColor.G, bValue));
                }
            }

            service = null;
            for (int i = 0; i < apertures.Count; i++)
            {
                apertures[i].Dispose();
            }
            apertures.Clear();

            return(rezult);
        }
        public int adaptiveFilterProcess(Bitmap image, string colorMode, int x, int y, Point filterSize, Point imageSize,
                                         Point maxFilterSize)
        {
            ApertureService service = new ApertureService();
            int             pixelPosX = 0, pixelPosY = 0;
            int             rMax = 0, gMax = 0, bMax = 0;
            int             rMin = 256, gMin = 256, bMin = 256;
            int             rMedian, gMedian, bMedian;
            Color           thisPixelColor = image.GetPixel(x, y);

            List <int> redList   = new List <int>();
            List <int> greenList = new List <int>();
            List <int> blueList  = new List <int>();


            for (int i = 0; i < filterSize.X; i++)
            {
                for (int j = 0; j < filterSize.Y; j++)
                {
                    service.getAperturePosition(x, y, imageSize, i, j, new Point(filterSize.X, filterSize.Y),
                                                out pixelPosX, out pixelPosY);

                    if (pixelPosX == -1 || pixelPosY == -1)
                    {
                        continue;
                    }
                    else
                    {
                        Color color = image.GetPixel(pixelPosX, pixelPosY);

                        if (rMax < color.R)
                        {
                            rMax = color.R;
                        }
                        if (rMin > color.R)
                        {
                            rMin = color.R;
                        }

                        if (gMax < color.G)
                        {
                            gMax = color.G;
                        }
                        if (gMin > color.G)
                        {
                            gMin = color.G;
                        }

                        if (bMax < color.B)
                        {
                            bMax = color.B;
                        }
                        if (bMin > color.B)
                        {
                            bMin = color.B;
                        }

                        redList.Add(color.R);
                        greenList.Add(color.G);
                        blueList.Add(color.B);
                    }
                }
            }

            //сортировка списков
            redList.Sort();
            greenList.Sort();
            blueList.Sort();

            //находим медиану яркости для апертуры
            int apertureCenter = redList.Count / 2;

            rMedian = redList[apertureCenter];
            gMedian = greenList[apertureCenter];
            bMedian = blueList[apertureCenter];

            int checkMedian, checkMin, checkMax, checkColor;

            if (colorMode == "R")
            {
                checkMedian = rMedian;
                checkMin    = rMin;
                checkMax    = rMax;
                checkColor  = thisPixelColor.R;
            }
            else if (colorMode == "G")
            {
                checkMedian = gMedian;
                checkMin    = gMin;
                checkMax    = gMax;
                checkColor  = thisPixelColor.G;
            }
            else if (colorMode == "B")
            {
                checkMedian = bMedian;
                checkMin    = bMin;
                checkMax    = bMax;
                checkColor  = thisPixelColor.B;
            }
            else
            {
                return(0);
            }

            //branch a
            if (checkMedian - checkMin > 0 && checkMedian - checkMax < 0) //goto branch b
            {
                //branch b
                if (checkColor - checkMin > 0 && checkColor - checkMax < 0)
                {
                    return(checkColor);
                }
                else
                {
                    return(checkMedian);
                }
            }
            else
            {
                filterSize.X++;
                filterSize.Y++;

                if (filterSize.X > maxFilterSize.X || filterSize.Y > maxFilterSize.Y)
                {
                    return(checkColor);
                }
                else
                {
                    return(adaptiveFilterProcess(image, colorMode, x, y, filterSize, imageSize, maxFilterSize));
                }
            }
        }
        public Bitmap applyRecursiveFilter(string colorMode, Bitmap image, Point imageSize, Point filterSize,
                                           int colorChannelIndex = 0)
        {
            Bitmap rezult = new Bitmap(image);

            ApertureService service = new ApertureService();

            List <Aperture> apertures = service.getApertureMatrixGenerator(imageSize, filterSize);

            List <int> redList   = new List <int>();
            List <int> greenList = new List <int>();
            List <int> blueList  = new List <int>();

            double[] rSumsArray = new double[apertures.Count];
            double[] gSumsArray = new double[apertures.Count];
            double[] bSumsArray = new double[apertures.Count];

            for (int x = 0; x < apertures.Count; x++)
            {
                redList.Clear();
                blueList.Clear();
                greenList.Clear();
                int rSum = 0, gSum = 0, bSum = 0, kSum = 0;
                List <List <Point> > matrix = apertures[x].matrix;
                bool isSideAperture         = false;
                foreach (var matrixLine in matrix)
                {
                    foreach (var Point in matrixLine)
                    {
                        int pixelPosX = Point.X;
                        int pixelPosY = Point.Y;

                        //проверяем, выйдем ли мы за границы изображения слева, при расчетах,
                        // ведь идем от -r до +r потом.
                        if (pixelPosX <= filterSize.X || pixelPosY <= filterSize.Y)
                        {
                            isSideAperture = true;
                        }

                        Color color = image.GetPixel(pixelPosX, pixelPosY);
                        redList.Add(color.R);
                        greenList.Add(color.G);
                        blueList.Add(color.B);
                        kSum += 1;
                    }
                }
                //если при расчетах выйдем за рамки, считаем просто стреднее арифметическое.
                if (isSideAperture)
                {
                    for (int i = 0; i < redList.Count; i++)
                    {
                        rSum += redList[i];
                        gSum += greenList[i];
                        bSum += blueList[i];
                    }

                    rSumsArray[x] = rSum;
                    gSumsArray[x] = gSum;
                    bSumsArray[x] = bSum;
                }
                else
                {
                    int rSum1 = 0, gSum1 = 0, bSum1 = 0, kSum1 = 0;
                    int rSum2 = 0, gSum2 = 0, bSum2 = 0, kSum2 = 0;

                    //крайне правый элемент предыдущего окна
                    for (int i = 0; i < matrix.Count; i++)
                    {
                        Color color = image.GetPixel(matrix[i][0].X - 1, matrix[i][0].Y);
                        rSum1 += color.R;
                        gSum1 += color.G;
                        bSum1 += color.B;
                        kSum1 += 1;
                    }

                    for (int i = 0; i < matrix.Count; i++)
                    {
                        Color color = image.GetPixel(matrix[i][filterSize.X - 1].X, matrix[i][filterSize.X - 1].Y);
                        rSum2 += color.R;
                        gSum2 += color.G;
                        bSum2 += color.B;
                        kSum2 += 1;
                    }

                    //вычислять рекурсию только если предыдущая апертура на той же линии
                    if (apertures[x].y == apertures[x - 1].y)
                    {
                        double rSumReal = rSumsArray[x - 1] - rSum1 + rSum2;
                        double gSumReal = gSumsArray[x - 1] - rSum1 + rSum2;
                        double bSumReal = gSumsArray[x - 1] - rSum1 + rSum2;

                        rSumsArray[x] = rSumReal;
                        gSumsArray[x] = gSumReal;
                        bSumsArray[x] = bSumReal;
                    }
                    else
                    {
                        for (int i = 0; i < redList.Count; i++)
                        {
                            rSum += redList[i];
                            gSum += greenList[i];
                            bSum += blueList[i];
                        }

                        rSumsArray[x] = rSum;
                        gSumsArray[x] = gSum;
                        bSumsArray[x] = bSum;
                    }
                }

                // int pixelCount = filterSize.X * filterSize.Y;

                rSum = (int)rSumsArray[x] / kSum;
                if (rSum < 0)
                {
                    rSum = 0;
                }
                else if (rSum > 255)
                {
                    rSum = 255;
                }

                gSum = (int)gSumsArray[x] / kSum;
                if (gSum < 0)
                {
                    gSum = 0;
                }
                else if (gSum > 255)
                {
                    gSum = 255;
                }

                bSum = (int)bSumsArray[x] / kSum;
                if (bSum < 0)
                {
                    bSum = 0;
                }
                else if (bSum > 255)
                {
                    bSum = 255;
                }

                int aperturePosX = matrix.Count / 2;
                if (matrix.Count != 0 && matrix[aperturePosX].Count / 2 != 0)
                {
                    int aperturePosY = matrix[aperturePosX].Count / 2;

                    Color oldColor = image.GetPixel(matrix[aperturePosX][aperturePosY].X,
                                                    matrix[aperturePosX][aperturePosY].Y);

                    if (colorChannelIndex == 0)
                    {
                        rezult.SetPixel(matrix[aperturePosX][aperturePosY].X, matrix[aperturePosX][aperturePosY].Y,
                                        Color.FromArgb((int)rSum, (int)gSum, (int)bSum));
                    }
                    else if (colorChannelIndex == 1)
                    {
                        rezult.SetPixel(matrix[aperturePosX][aperturePosY].X, matrix[aperturePosX][aperturePosY].Y,
                                        Color.FromArgb((int)rSum, oldColor.G, oldColor.B));
                    }
                    else if (colorChannelIndex == 2)
                    {
                        rezult.SetPixel(matrix[aperturePosX][aperturePosY].X, matrix[aperturePosX][aperturePosY].Y,
                                        Color.FromArgb(oldColor.R, (int)gSum, oldColor.B));
                    }
                    else if (colorChannelIndex == 3)
                    {
                        rezult.SetPixel(matrix[aperturePosX][aperturePosY].X, matrix[aperturePosX][aperturePosY].Y,
                                        Color.FromArgb(oldColor.R, oldColor.G, (int)bSum));
                    }
                }
            }

            service = null;
            for (int i = 0; i < apertures.Count; i++)
            {
                apertures[i].Dispose();
            }
            apertures.Clear();

            return(rezult);
        }