private static void Convolute(BMPImage image, double[] kernel)
        {
            byte[][][] copy = new byte[image.Height][][];
            for (int i = 0; i < image.Height; i++)
            {
                copy[i] = new byte[image.Width][];
                for (int j = 0; j < image.Width; j++)
                {
                    copy[i][j] = new byte[image.Channels];
                }
            }

            for (int i = 1; i < image.Height - 1; i++)
            {
                for (int j = 1; j < image.Width - 1; j++)
                {
                    for (int c = 0; c < image.Channels; c++)
                    {
                        double pixelByte = 0;
                        for (int k = -1; k < 2; k++)
                        {
                            for (int l = -1; l < 2; l++)
                            {
                                pixelByte += kernel[(k + 1) * 3 + l + 1] * image.Bytes[i + k][j + l][c];
                            }
                        }
                        if (pixelByte == 0)
                        {
                            copy[i][j][c] = 0;
                        }
                        else if (Math.Abs(pixelByte) < 255)
                        {
                            copy[i][j][c] = (byte)Math.Abs(pixelByte);
                        }
                        else
                        {
                            copy[i][j][c] = 255;
                        }
                    }
                }
            }

            for (int i = 0; i < image.Height; i++)
            {
                for (int j = 0; j < image.Width; j++)
                {
                    for (int c = 0; c < image.Channels; c++)
                    {
                        image.Bytes[i][j][c] = copy[i][j][c];
                    }
                }
            }
        }
 public static void ApplyGrayscale(BMPImage image)
 {
     for (int i = 1; i < image.Height - 1; i++)
     {
         for (int j = 1; j < image.Width - 1; j++)
         {
             for (int c = 0; c < image.Channels; c++)
             {
                 if (c == 3)
                 {
                     image.Bytes[i][j][c] = 255;
                 }
                 else
                 {
                     image.Bytes[i][j][c] = (byte)Math.Max(image.Bytes[i][j][2], Math.Max(image.Bytes[i][j][1], image.Bytes[i][j][0]));
                 }
             }
         }
     }
 }
 public static void ApplyMedian(BMPImage image)
 {
     for (int i = 1; i < image.Height - 1; i++)
     {
         for (int j = 1; j < image.Width - 1; j++)
         {
             for (int c = 0; c < image.Channels; c++)
             {
                 int[] surroundings = new int[9];
                 for (int k = -1; k < 2; k++)
                 {
                     for (int l = -1; l < 2; l++)
                     {
                         surroundings[(k + 1) * 3 + l + 1] = image.Bytes[i + k][j + l][c];
                     }
                 }
                 Array.Sort(surroundings);
                 image.Bytes[i][j][c] = (byte)surroundings[4];
             }
         }
     }
 }
        static void Main(string[] args)
        {
            Console.WriteLine("This program applies to input 24 or 32 bit BMP image one of median, gauss, sobelX, sobelY, grayscale filters.");

            if (args.Length != 3)
            {
                Console.WriteLine("Input error. Please, enter data in following order: program name, input file, filter name, output file.");
                return;
            }

            if (String.Compare(args[1], "median") != 0 && String.Compare(args[1], "gauss") != 0 && String.Compare(args[1], "sobelX") != 0 && String.Compare(args[1], "sobelY") != 0 && String.Compare(args[1], "grayscale") != 0)
            {
                Console.WriteLine("There is only median, gauss, sobelX, sobelY and grayscale filters.");
                return;
            }

            FileStream input;

            try
            {
                input = new FileStream(args[0], FileMode.Open, FileAccess.Read);
            }
            catch (FileNotFoundException)
            {
                Console.WriteLine("File not found.");
                return;
            }

            BMPImage image = new BMPImage(input);

            FileStream output;

            try
            {
                output = new FileStream(args[2], FileMode.OpenOrCreate, FileAccess.Write);
            }
            catch (Exception)
            {
                Console.WriteLine("Failed to create or to find output file.");
                input.Close();
                return;
            }

            if (args[1].Equals("median"))
            {
                Filters.ApplyMedian(image);
            }
            else if (args[1].Equals("gauss"))
            {
                Filters.ApplyGauss(image);
            }
            else if (args[1].Equals("sobelX"))
            {
                Filters.ApplySobelX(image);
            }
            else if (args[1].Equals("sobelY"))
            {
                Filters.ApplySobelY(image);
            }
            else if (args[1].Equals("grayscale"))
            {
                Filters.ApplyGrayscale(image);
            }

            image.WriteToFile(output);

            input.Close();
            output.Close();
        }
 public static void ApplySobelY(BMPImage image)
 {
     double[] kernel = new double[] { 1, 2, 1, 0, 0, 0, -1, -2, -1 };
     Convolute(image, kernel);
 }
 public static void ApplyGauss(BMPImage image)
 {
     double[] kernel = new double[] { 0.0626, 0.1250, 0.0626, 0.1250, 0.2497, 0.1250, 0.0626, 0.1250, 0.0626 };
     Convolute(image, kernel);
 }