private List<byte> ThresholdSupression(int x, int y,int thresholdLow, int thresholdHigh, ImageReader image)
        {
            var returnList = new List<byte>();

            var oneR = image.GetPixel(x - 1, y - 1, 0);
            var twoR = image.GetPixel(x, y - 1, 0);
            var threeR = image.GetPixel(x + 1, y - 1, 0);
            var fourR = image.GetPixel(x - 1, y, 0);
            var fiveR = image.GetPixel(x, y, 0);
            var sixR = image.GetPixel(x + 1, y, 0);
            var sevenR = image.GetPixel(x - 1, y + 1, 0);
            var eightR = image.GetPixel(x, y + 1, 0);
            var nineR = image.GetPixel(x + 1, y + 1, 0);

            var smallWindow = new List<byte> { oneR, twoR, threeR, fourR, sixR, sevenR, eightR, nineR };
            var pixelToTest = fiveR;

            int size = 5;
            var locationP = (size - 1) / 2;

            List<byte> LargeWindow = new List<byte>();
            for (int j = -locationP; j < locationP + 1; j++)
            {
                for (int i = -locationP; i < locationP + 1; i++)
                {
                    LargeWindow.Add(image.GetPixel(x + i, y + j, 0));
                }
            }

            /*
             * • If pixel (x, y) has gradient magnitude less than tlow discard the edge (write out black).
            • If pixel (x, y) has gradient magnitude greater than thigh keep the edge (write out white).

             *
             * */
            if (pixelToTest < thresholdLow)
            {
                returnList.Add(0);
                returnList.Add(0);
                returnList.Add(0);
            }
            else if (pixelToTest >= thresholdHigh)
            {
                returnList.Add(255);
                returnList.Add(255);
                returnList.Add(255);
            }
            else if (pixelToTest < thresholdHigh && pixelToTest >= thresholdLow)
            {
                returnList = this.WindowThresholdSuppresion(thresholdLow, thresholdHigh, smallWindow, LargeWindow);
            }
            else
            {
                throw new InvalidDataException("Shouldn't be here!");
            }

            return returnList;
        }
        private List<byte> Average(int x, int y, int squareSize, ImageReader image)
        {
            var returnList = new List<byte>();

            var oneR = image.GetPixel(x - 1, y - 1, 0);
            var twoR = image.GetPixel(x, y - 1, 0);
            var threeR = image.GetPixel(x + 1, y - 1, 0);
            var fourR = image.GetPixel(x - 1, y, 0);
            var fiveR = image.GetPixel(x, y, 0);
            var sixR = image.GetPixel(x + 1, y, 0);
            var sevenR = image.GetPixel(x - 1, y + 1, 0);
            var eightR = image.GetPixel(x, y + 1, 0);
            var nineR = image.GetPixel(x + 1, y + 1, 0);

            var oneG = image.GetPixel(x - 1, y - 1, 1);
            var twoG = image.GetPixel(x, y - 1, 1);
            var threeG = image.GetPixel(x + 1, y - 1, 1);
            var fourG = image.GetPixel(x - 1, y, 1);
            var fiveG = image.GetPixel(x, y, 1);
            var sixG = image.GetPixel(x + 1, y, 1);
            var sevenG = image.GetPixel(x - 1, y + 1, 1);
            var eightG = image.GetPixel(x, y + 1, 1);
            var nineG = image.GetPixel(x + 1, y + 1, 1);

            var oneB = image.GetPixel(x - 1, y - 1, 2);
            var twoB = image.GetPixel(x, y - 1, 2);
            var threeB = image.GetPixel(x + 1, y - 1, 2);
            var fourB = image.GetPixel(x - 1, y, 2);
            var fiveB = image.GetPixel(x, y, 2);
            var sixB = image.GetPixel(x + 1, y, 2);
            var sevenB = image.GetPixel(x - 1, y + 1, 2);
            var eightB = image.GetPixel(x, y + 1, 2);
            var nineB = image.GetPixel(x + 1, y + 1, 2);

            var r = (oneR + twoR + threeR + fourR + fiveR + sixR + sevenR + eightR + nineR) / 9;
            var g = (oneG + twoG + threeG + fourG + fiveG + sixG + sevenG + eightG + nineG) / 9;
            var b = (oneB + twoB + threeB + fourB + fiveB + sixB + sevenB + eightB + nineB) / 9;
            returnList.Add((byte)r);
            returnList.Add((byte)g);
            returnList.Add((byte)b);

            return returnList;
        }
        private List<byte> SobelDetection(int x, int y, ImageReader image)
        {
            var returnList = new List<byte>();

            var oneR = image.GetPixel(x - 1, y - 1, 0);
            var twoR = image.GetPixel(x, y - 1, 0);
            var threeR = image.GetPixel(x + 1, y - 1, 0);
            var fourR = image.GetPixel(x - 1, y, 0);
            var fiveR = image.GetPixel(x, y, 0);
            var sixR = image.GetPixel(x + 1, y, 0);
            var sevenR = image.GetPixel(x - 1, y + 1, 0);
            var eightR = image.GetPixel(x, y + 1, 0);
            var nineR = image.GetPixel(x + 1, y + 1, 0);

            var oneG = image.GetPixel(x - 1, y - 1, 1);
            var twoG = image.GetPixel(x, y - 1, 1);
            var threeG = image.GetPixel(x + 1, y - 1, 1);
            var fourG = image.GetPixel(x - 1, y, 1);
            var fiveG = image.GetPixel(x, y, 1);
            var sixG = image.GetPixel(x + 1, y, 1);
            var sevenG = image.GetPixel(x - 1, y + 1, 1);
            var eightG = image.GetPixel(x, y + 1, 1);
            var nineG = image.GetPixel(x + 1, y + 1, 1);

            var oneB = image.GetPixel(x - 1, y - 1, 2);
            var twoB = image.GetPixel(x, y - 1, 2);
            var threeB = image.GetPixel(x + 1, y - 1, 2);
            var fourB = image.GetPixel(x - 1, y, 2);
            var fiveB = image.GetPixel(x, y, 2);
            var sixB = image.GetPixel(x + 1, y, 2);
            var sevenB = image.GetPixel(x - 1, y + 1, 2);
            var eightB = image.GetPixel(x, y + 1, 2);
            var nineB = image.GetPixel(x + 1, y + 1, 2);

            // GX
            // -1 0 1
            // -2 0 2
            // -1 0 1

            //GY
            // 1 2 1
            // 0 0 0
            // -1 -2 -1
            //abs(gx)+abs(gy)
            //clamp to 255 or 0 just in case?
            var GX = new List<int> { -1, 0, 1, -2, 0, 2, -1, 0, 1 };
            var GY = new List<int> { 1, 2, 1, 0, 0, 0, -1, -2, -1 };
            var RArray = new List<byte> { oneR, twoR, threeR, fourR, fiveR, sixR, sevenR, eightR, nineR };
            var GArray = new List<byte> { oneG, twoG, threeG, fourG, fiveG, sixG, sevenG, eightG, nineG };
            var BArray = new List<byte> { oneB, twoB, threeB, fourB, fiveB, sixB, sevenB, eightB, nineB };

            int GXR = 0;
            int GXG = 0;
            int GXB = 0;
            int GYR = 0;
            int GYG = 0;
            int GYB = 0;

            for (int i = 0; i < 9; i++)
            {
                GXR += GX[i] * RArray[i];
                GXG += GX[i] * GArray[i];
                GXB += GX[i] * BArray[i];

                GYR += GY[i] * RArray[i];
                GYG += GY[i] * GArray[i];
                GYB += GY[i] * BArray[i];
            }

            //TODO: this estimation is wrong i think!
            //var newR = Math.Abs(GXR) + Math.Abs(GYR);
            //var newG = Math.Abs(GXG) + Math.Abs(GYG);
            //var newB = Math.Abs(GXB) + Math.Abs(GYB);

            //try these
            var newR = Math.Sqrt(GXR * GXR + GYR * GYR);
            var newG = Math.Sqrt(GXG * GXG + GYG * GYG);
            var newB = Math.Sqrt(GXB * GXB + GYB * GYB);
            double orientation, toAngle = 180.0 / System.Math.PI;
            // --- get orientation
            if (GXR == 0)
            {
                // can not divide by zero
                orientation = (GYR == 0) ? 0 : 90;
            }
            else
            {
                double div = (double)GYR / GXR;

                // handle angles of the 2nd and 4th quads
                if (div < 0)
                {
                    orientation = 180 - System.Math.Atan(-div) * toAngle;
                }
                // handle angles of the 1st and 3rd quads
                else
                {
                    orientation = System.Math.Atan(div) * toAngle;
                }

                // get closest angle from 0, 45, 90, 135 set
                if (orientation < 22.5)
                    orientation = 0;
                else if (orientation < 67.5)
                    orientation = 45;
                else if (orientation < 112.5)
                    orientation = 90;
                else if (orientation < 157.5)
                    orientation = 135;
                else orientation = 0;
            }

            // save orientation
            var convertedThetas = new List<byte>();
            convertedThetas.Add((byte)orientation);
            convertedThetas.Add((byte)orientation);
            convertedThetas.Add((byte)orientation);

            if (newR > 255) newR = 255;
            if (newG > 255) newG = 255;
            if (newB > 255) newB = 255;
            var r = newR;
            var g = newG;
            var b = newB;
            returnList.Add((byte)r);
            returnList.Add((byte)g);
            returnList.Add((byte)b);

            returnList.AddRange(convertedThetas);

            return returnList;
        }
 private List<byte> Krisch(int x, int y, ImageReader image)
 {
     var returnList = new List<byte>();
     var cr = image.GetPixel(x + 1, y, 0);
     var cl = image.GetPixel(x - 1, y, 0);
     var cu = image.GetPixel(x, y - 1, 0);
     var cd = image.GetPixel(x, y + 1, 0);
     var cld = image.GetPixel(x - 1, y + 1, 0);
     var clu = image.GetPixel(x - 1, y - 1, 0);
     var crd = image.GetPixel(x + 1, y + 1, 0);
     var cru = image.GetPixel(x + 1, y - 1, 0);
     int power = getMaxD(cr, cl, cu, cd, cld, clu, cru, crd);
     if (power > 100)
     {
     //ret.SetPixel(i, j, Color.Yellow);
     returnList.Add(0);
     returnList.Add(0);
     returnList.Add(255);
     }
     else
     {
     //ret.SetPixel(i, j, Color.Black);
     returnList.Add(255);
     returnList.Add(255);
     returnList.Add(255);
     }
     return returnList;
 }
        //m = -cotθ  --- Math.PI/2 - Math.Atan(x)
        //c = p*cosecθ
        //cosecant (csc), secant (sec), and cotangent (cot).
        //Cosecant Cosec(X) = 1 / Sin(X)
        //Cotangent Cotan(X) = 1 / Tan(X)
        // var m = -1*(1/Math.tan(x));
        // var c = p*(1/Math.Sin(x));
        private void HoughTransformCommandExecute()
        {
            var image = new ImageReader(LeftPictureLocation);
            int rhoMax =(int) Math.Round(Math.Sqrt((image.Width*image.Width)+(image.Height*image.Height)));
              double[,] A = new double[180,rhoMax*2];
              List<Tuple<double, double, double>> listOfThings = new List<Tuple<double, double, double>>();
            // var gaussImageToSend = new byte[image.Width,image.Height];
            List<string> outputList = new List<string>();
            for (var h = 0; h < image.Height; h++)
            {
                for (var w = 0; w < image.Width; w++)
                {
                    var pixel = image.GetPixel(w, h, 0);
                    if (pixel == 255)
                    {
                        for (int i = -90; i <= 90; i++)
                        {
                            double angle = Math.PI * i / 180.0;
                            var rho = (w * Math.Cos(angle)) + (h * Math.Sin(angle));
                            var rhoRounded = Math.Round(rho, 4);
                            int angleAccessor = (int)angle + 90;
                            int rhoAccessor = ((int)Math.Round(rho))+rhoMax;
                            A[angleAccessor, rhoAccessor]++;
                            bool found = false;
                            Tuple<double, double, double> itemToRemove = null;
                            foreach (var item in listOfThings)
                            {
                                if (item.Item1 == i && item.Item2 == rhoRounded)
                                {
                                    found = true;
                                    itemToRemove = item;
                                    break;
                                }
                            }
                            if (found == false)
                            {
                                listOfThings.Add(new Tuple<double, double, double>(i, rhoRounded, 1));
                            }
                            else
                            {
                                listOfThings.Remove(itemToRemove);
                                listOfThings.Add(new Tuple<double, double, double>(itemToRemove.Item1, itemToRemove.Item2, itemToRemove.Item3 + 1));

                            }
                           outputList.Add(rho.ToString() + "," + i.ToString());
                        }
                    }
                }
            }
            System.IO.File.WriteAllLines("test.txt", outputList.ToArray());
            int counter = 0;
            //y = m*x + c
            var newLinesImage = new ImageReader();
            newLinesImage.Width = image.Width;
            newLinesImage.Height = image.Height;
            newLinesImage.Pixels = new List<byte>(image.Pixels);
            newLinesImage.depth = image.depth;
            newLinesImage.Count = image.Count;

            foreach (var item in listOfThings)
            {
                //if (item.Item3 >2)
               // {
                    counter++;
                    var angle = item.Item1;
                    double x = Math.PI * angle / 180.0;
                    var p = item.Item2;
                    var m = -1*(1/Math.Tan(x));
                    var c = p*(1/Math.Sin(x));
                    for (int ix = 0; ix < newLinesImage.Width; ix++)
                    {
                        var iy =(int)( (m * ix) + c);
                        if (iy > 0 && iy < newLinesImage.Height)
                        {
                            newLinesImage.SetPixel(ix, iy, 0, 255);
                        }
                    }
                //}
            }
            int stop = -1;
            newLinesImage.SaveAsBitmap("MyLinesOutputFromHT.bmp");
        }
        private List<byte> FindMedians(int x, int y, int squareSize, ImageReader image)
        {
            var returnList = new List<byte>();

            var oneR = image.GetPixel(x - 1, y - 1, 0);
            var twoR = image.GetPixel(x, y - 1, 0);
            var threeR = image.GetPixel(x + 1, y - 1, 0);
            var fourR = image.GetPixel(x - 1, y, 0);
            var fiveR = image.GetPixel(x, y, 0);
            var sixR = image.GetPixel(x + 1, y, 0);
            var sevenR = image.GetPixel(x - 1, y + 1, 0);
            var eightR = image.GetPixel(x, y + 1, 0);
            var nineR = image.GetPixel(x + 1, y + 1, 0);

            var oneG = image.GetPixel(x - 1, y - 1, 1);
            var twoG = image.GetPixel(x, y - 1, 1);
            var threeG = image.GetPixel(x + 1, y - 1, 1);
            var fourG = image.GetPixel(x - 1, y, 1);
            var fiveG = image.GetPixel(x, y, 1);
            var sixG = image.GetPixel(x + 1, y, 1);
            var sevenG = image.GetPixel(x - 1, y + 1, 1);
            var eightG = image.GetPixel(x, y + 1, 1);
            var nineG = image.GetPixel(x + 1, y + 1, 1);

            var oneB = image.GetPixel(x - 1, y - 1, 2);
            var twoB = image.GetPixel(x, y - 1, 2);
            var threeB = image.GetPixel(x + 1, y - 1, 2);
            var fourB = image.GetPixel(x - 1, y, 2);
            var fiveB = image.GetPixel(x, y, 2);
            var sixB = image.GetPixel(x + 1, y, 2);
            var sevenB = image.GetPixel(x - 1, y + 1, 2);
            var eightB = image.GetPixel(x, y + 1, 2);
            var nineB = image.GetPixel(x + 1, y + 1, 2);

            var r = GetMedian(new List<byte> { oneR, twoR, threeR, fourR, fiveR, sixR, sevenR, eightR, nineR });
            var g = GetMedian(new List<byte> { oneG, twoG, threeG, fourG, fiveG, sixG, sevenG, eightG, nineG });
            var b = GetMedian(new List<byte> { oneB, twoB, threeB, fourB, fiveB, sixB, sevenB, eightB, nineB });
            returnList.Add(r);
            returnList.Add(g);
            returnList.Add(b);

            return returnList;
        }
        private List<byte> FindGaussian(int x, int y, int size, double sigma, ImageReader image)
        {
            var locationP = (size - 1) / 2;
            GaussianBlur gb = new GaussianBlur(sigma, size);

            var countercounter = 0.0;
            foreach (var item in gb.Kernel)
            {
                countercounter += (double)item / (double)gb.Divisor;
            }
            List<byte> windowR = new List<byte>();
            for (int j = -locationP; j < locationP + 1; j++)
            {
                for (int i = -locationP; i < locationP + 1; i++)
                {
                    windowR.Add(image.GetPixel(x + i, y + j, 0));
                }
            }

            var byteWindowR = new byte[size, size];
            int counter = 0;
            for (int i = 0; i < size; i++)
            {
                for (int j = 0; j < size; j++)
                {
                    byteWindowR[i, j] = windowR[counter];
                    counter++;
                }
            }

            List<byte> windowG = new List<byte>();
            for (int j = -locationP; j < locationP + 1; j++)
            {
                for (int i = -locationP; i < locationP + 1; i++)
                {
                    windowG.Add(image.GetPixel(x + i, y + j, 1));
                }
            }

            var byteWindowG = new byte[size, size];
            counter = 0;
            for (int i = 0; i < size; i++)
            {
                for (int j = 0; j < size; j++)
                {
                    byteWindowG[i, j] = windowG[counter];
                    counter++;
                }
            }

            List<byte> windowB = new List<byte>();
            for (int j = -locationP; j < locationP + 1; j++)
            {
                for (int i = -locationP; i < locationP + 1; i++)
                {
                    windowB.Add(image.GetPixel(x + i, y + j, 2));
                }
            }

            var byteWindowB = new byte[size, size];
            counter = 0;
            for (int i = 0; i < size; i++)
            {
                for (int j = 0; j < size; j++)
                {
                    byteWindowB[i, j] = windowB[counter];
                    counter++;
                }
            }

            var returnList = new List<byte>();

            var runningR = 0.0;
            for (int i = 0; i < size; i++)
            {
                for (int j = 0; j < size; j++)
                {
                    runningR += byteWindowR[i, j] * gb.Kernel[i, j];
                }
            }

            var runningG = 0.0;
            for (int i = 0; i < size; i++)
            {
                for (int j = 0; j < size; j++)
                {
                    runningG += byteWindowG[i, j] * gb.Kernel[i, j];
                }
            }

            var runningB = 0.0;
            for (int i = 0; i < size; i++)
            {
                for (int j = 0; j < size; j++)
                {
                    runningB += byteWindowB[i, j] * gb.Kernel[i, j];
                }
            }

            var origR = image.GetPixel(x, y, 0);
            var origG = image.GetPixel(x, y, 1);
            var origB = image.GetPixel(x, y, 2);
            var r = (byte)Math.Round(runningR / gb.Divisor,MidpointRounding.AwayFromZero);
            var g = (byte)Math.Round(runningG / gb.Divisor, MidpointRounding.AwayFromZero);
            var b = (byte)Math.Round(runningB / gb.Divisor, MidpointRounding.AwayFromZero);
            returnList.Add(r);
            returnList.Add(g);
            returnList.Add(b);

            return returnList;
        }