/// <summary>
 /// Subtract b2 from b1 and normalize the image
 /// </summary>
 /// <param name="b1">Image</param>
 /// <param name="b2">Image</param>
 /// <returns>Normalized Image</returns>
 public static Bitmap Subtract(Bitmap b1, Bitmap b2)
 {
     if (b1.Width != b2.Width || b1.Height != b2.Height)
             throw new Exception("Images not the same size cannot subtract");
         ImagerBitmap i = new ImagerBitmap(b1.Clone() as Bitmap);
         ImagerBitmap i2 = new ImagerBitmap(b2.Clone() as Bitmap);
         int[,] red = new int[i.Bitmap.Width, i.Bitmap.Height];
         int[,] blue = new int[i.Bitmap.Width, i.Bitmap.Height];
         int[,] green = new int[i.Bitmap.Width, i.Bitmap.Height];
         int redMax = 0;
         int redMin = 0;
         int redRange = 0;
         int blueMax = 0;
         int blueMin = 0;
         int blueRange = 0;
         int greenMax = 0;
         int greenMin = 0;
         int greenRange = 0;
         //fill the arrays with the subtracted values
         //Keep track of the min and max values for later
         for (int column = 0; column < i.Bitmap.Width; column++)
         {
             for (int row = 0; row < i.Bitmap.Height; row++)
             {
                 Color c1 = i.GetPixel(column, row);
                 Color c2 = i2.GetPixel(column, row);
                 red[column, row] = c2.R - c1.R;
                 blue[column, row] = c2.B - c1.B;
                 green[column, row] = c2.G - c1.G;
                 if (red[column, row] > redMax) redMax = red[column, row];
                 if (red[column, row] < redMin) redMin = red[column, row];
                 if (blue[column, row] > blueMax) blueMax = blue[column, row];
                 if (blue[column, row] < blueMin) blueMin = blue[column, row];
                 if (green[column, row] > greenMax) greenMax = green[column, row];
                 if (green[column, row] < greenMin) greenMin = green[column, row];
             }
         }
         //find the range of the min an max
         redRange = Math.Abs(redMax - redMin);
         blueRange = Math.Abs(blueMax - blueMin);
         greenRange = Math.Abs(greenRange - greenMin);
         //Normalize the values in the arrays and load the result image
         for (int column = 0; column < i.Bitmap.Width; column++)
         {
             for (int row = 0; row < i.Bitmap.Height; row++)
             {
                 if (redRange != 0)
                     red[column, row] = 255 - (((redMax - red[column, row]) * 255) / redRange);
                 if (blueRange != 0)
                     blue[column, row] = 255 - (((blueMax - blue[column, row]) * 255) / blueRange);
                 if (greenRange != 0)
                     green[column, row] = 255 - (((greenMax - green[column, row]) * 255) / greenRange);
                 if (red[column, row] < 0)
                     red[column, row] = 0;
                 if (blue[column, row] < 0)
                     blue[column, row] = 0;
                 if (green[column, row] < 0)
                     green[column, row] = 0;
                 i2.SetPixel(column, row, Color.FromArgb(red[column, row], green[column, row],
                     blue[column, row]));
             }
         }
         i.UnlockBitmap();
         i2.UnlockBitmap();
         return i2.Bitmap.Clone() as Bitmap;
 }
 /// <summary>
 /// Get the red pixels from the bitmap
 /// </summary>
 /// <param name="b">Image to Process</param>
 /// <returns>Filtered Image</returns>
 public static Bitmap GetRedBitmap(Bitmap b)
 {
     ImagerBitmap i = new ImagerBitmap(b.Clone() as Bitmap);
         for (int column = 0; column < i.Bitmap.Width; column++)
         {
             for (int row = 0; row < i.Bitmap.Height; row++)
             {
                 i.SetPixel(column, row, Color.FromArgb(i.GetPixel(column, row).R, 0, 0));
             }
         }
         i.UnlockBitmap();
         return i.Bitmap.Clone() as Bitmap;
 }
 /// <summary>
 /// Make the image black and white
 /// </summary>
 /// <param name="b">Image to Process</param>
 /// <returns>Filtered Image</returns>
 public static Bitmap GetBlackAndWhiteBitmap(Bitmap b)
 {
     ImagerBitmap i = new ImagerBitmap(b.Clone() as Bitmap);
         double[] histogram = new double[256];
         for (int column = 0; column < i.Bitmap.Width; column++)
         {
             for (int row = 0; row < i.Bitmap.Height; row++)
             {
                 histogram[i.GetGreyPixel(column, row)]++;
             }
         }
         //find the position of the max value on the left
         int leftK = 0;
         for (int k = 0; k < 128; k++)
         {
             if (histogram[k] > histogram[leftK]) leftK = k;
         }
         //find the position of the max value on the right
         int rightK = 0;
         for (int k = 128; k < 256; k++)
         {
             if (histogram[k] > histogram[rightK]) rightK = k;
         }
         //find the min value between the 2 local maxes
         int localMin = rightK;
         for (int k = leftK; k < rightK; k++)
         {
             if (histogram[k] < histogram[localMin]) localMin = k;
         }
         for (int column = 0; column < i.Bitmap.Width; column++)
         {
             for (int row = 0; row < i.Bitmap.Height; row++)
             {
                 int val = (i.GetPixel(column, row).R + i.GetPixel(column, row).G
                     + i.GetPixel(column, row).B) / 3;
                 if (val > localMin)
                     val = 255;
                 else
                     val = 0;
                 i.SetPixel(column, row, Color.FromArgb(val, val, val));
             }
         }
         i.UnlockBitmap();
         return i.Bitmap.Clone() as Bitmap;
 }
 public static Bitmap GetBlackAndWhiteBitmap2(Bitmap b)
 {
     ImagerBitmap i = new ImagerBitmap(b.Clone() as Bitmap);
         double[] histogram = new double[256];
         for (int column = 0; column < i.Bitmap.Width; column++)
         {
             for (int row = 0; row < i.Bitmap.Height; row++)
             {
                 histogram[i.GetGreyPixel(column, row)]++;
             }
         }
         double k = b.Width * b.Height;
         double half = k / 2;
         int middle = 0;
         while (k > half)
         {
             k = k - histogram[middle];
             middle++;
         }
         for (int column = 0; column < i.Bitmap.Width; column++)
         {
             for (int row = 0; row < i.Bitmap.Height; row++)
             {
                 int val = (i.GetPixel(column, row).R + i.GetPixel(column, row).G
                     + i.GetPixel(column, row).B) / 3;
                 if (val > middle)
                     val = 255;
                 else
                     val = 0;
                 i.SetPixel(column, row, Color.FromArgb(val, val, val));
             }
         }
         i.UnlockBitmap();
         return i.Bitmap.Clone() as Bitmap;
 }
 public static void GenerateExcelFile(Bitmap b)
 {
     ImagerBitmap i = new ImagerBitmap(b.Clone() as Bitmap);
         string fileName = "output.txt";
         int f = 0;
         using (StreamWriter sw = new StreamWriter(fileName, false))
         {
             sw.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}", "Index", "Row", "Column", "Red",
                 "Green", "Blue", "Gray");
             for (int column = 0; column < i.Bitmap.Width; column++)
             {
                 for (int row = 0; row < i.Bitmap.Height; row++)
                 {
                     f++;
                     Color c = i.GetPixel(column, row);
                     int g = i.GetGreyPixel(column, row);
                     sw.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}", f,
                         row, column, c.R, c.G, c.B, g);
                 }
             }
         }
         i.UnlockBitmap();
         System.Diagnostics.Process.Start(fileName);
 }