/// <summary>
 /// Calculate the distance of two different points.
 /// </summary>
 /// <param name="p1"></param>
 /// <param name="p2"></param>
 /// <returns></returns>
 public static double calPointDistance(iPoint p1, iPoint p2)
 {
     return Math.Sqrt(
         Math.Pow(p1.Width_Position - p2.Width_Position, 2)
         +
         Math.Pow(p1.Height_Position - p2.Height_Position, 2)
         );
 }
        /// <summary>
        /// Do image recognition operation.
        /// </summary>
        public static void ImageRecognition()
        {
            int i = 0;
            List<CharacterTemplate> lsTemplate = FileOperation.read_Template_From_Image_To_Struct();

            for (i = 0; i <= 1024; i++)
            {
                iPoint left_top = new iPoint();
                iPoint right_bottom = new iPoint();

                Bitmap bitmap24 = ImageOperation.saveTo24BMP(string.Format(@"..\..\DATA\i({0}).png", i));
#if DEBUG
                bitmap24.Save(string.Format(@"..\..\DATA\{0}.bmp", i));
#endif

                ImageOperation.changeBackground(bitmap24);

#if DEBUG
                bitmap24.Save(string.Format(@"..\..\DATA\{0}_changebackground.bmp", i));
#endif

                ImageOperation.sameNearbyPixel(bitmap24);

#if DEBUG
                bitmap24.Save(string.Format(@"..\..\DATA\{0}_sameNearbyPixel.bmp", i));
#endif

                ImageOperation.sameNeighbourNearbyPixel(bitmap24);
#if DEBUG
                bitmap24.Save(string.Format(@"..\..\DATA\{0}_sameVerticalNearbyPixel.bmp", i));
#endif

#if DEBUG_COMPONENT
                List<ConnectedComponent> ccImage = ImageOperation.findAllConnectedComponents(bitmap24);
                ImageOperation.mergeAllConnectedComponents(ccImage, bitmap24);
#endif
                ImageOperation.findDiagonalPoints(bitmap24, left_top, right_bottom);

#if DEBUG_DIAGONAL
                FileOperation.write_Image_Diagonal_Points_To_Text(i, left_top, right_bottom);
#endif

                string retValue = ImageOperation.ImageRecogonitionMainBranch(left_top, right_bottom, lsTemplate, bitmap24);

#if DEBUG_TEST_RESULT
                FileOperation.write_Test_Result_To_Text(retValue);
#endif

#if DEBUG
                FileOperation.write_Connected_Components_To_Bmp(i, ccImage, bitmap24);
                FileOperation.write_Bmp_To_RGB_Number(bitmap24, ConfigParameters.Str_Image_Text_Path + string.Format("rgb_text{0}.txt", i));
#endif
                Console.WriteLine(string.Format("Image {0} has been processed.", i));
            }
        }
        /// <summary>
        /// The main branch for image recogonition.
        /// </summary>
        /// <param name="left_top"></param>
        /// <param name="right_bottom"></param>
        /// <param name="lsTemplate"></param>
        /// <param name="sourceImage"></param>
        /// <returns></returns>
        public static string ImageRecogonitionMainBranch(iPoint left_top, iPoint right_bottom, List<CharacterTemplate> lsTemplate, Bitmap sourceImage)
        {
            int i = 0, j = 0, m = 0, n = 0;
            int iw = 0, ih = 0, tmp = 0;

            int startVertical = left_top.Width_Position;
            int endVertical = right_bottom.Width_Position;
            int startHorizontal = left_top.Height_Position;
            int endHorizontal = right_bottom.Height_Position;

            int sizeVertical = endVertical - startVertical + 1;
            int sizeHorizontal = endHorizontal - startHorizontal + 1;

            string retValue = "";
            bool match = false;
            char cName = ' ';
            int maxMatch = int.MinValue;

            for (i = startVertical; i <= endVertical; )
            {
                match = false;
                maxMatch = int.MinValue;
                for (j = 0; j < lsTemplate.Count; j++)
                {
                    if (endVertical - i + 1 >= lsTemplate[j].Width && sizeHorizontal >= lsTemplate[j].Height)
                    {
                        StringBuilder sbSubRegion = new StringBuilder();
                        for (m = i; m <= endVertical - lsTemplate[j].Width + 1; m++)
                        {
                            for (n = startHorizontal; n <= endHorizontal - lsTemplate[j].Height + 1; n++)
                            {
                                for (iw = 0; iw < lsTemplate[j].Width; iw++)
                                {
                                    for (ih = 0; ih < lsTemplate[j].Height; ih++)
                                    {
                                        Color color = sourceImage.GetPixel(m + iw, n + ih);
                                        if (color.R != 255 || color.G != 255 || color.B != 255)
                                        {
                                            sbSubRegion.Append("1");
                                        }
                                        else
                                        {
                                            sbSubRegion.Append("0");
                                        }
                                    }
                                }
                                //ulong[] sourceSubImageUlongArray = BitOperation.TransferOneZeroStringToUlongArray(sbSubRegion.ToString());
                                if (BitOperation.is_BlockA_Contains_BlockB(lsTemplate[j].CountOne, lsTemplate[j].ZOString, sbSubRegion.ToString(), ref tmp))
                                {
                                    match = true;
                                    //tmp = calMathBlackPositions(sbSubRegion.ToString(), lsTemplate[j].ZOString);
                                    if (tmp > maxMatch)
                                    {
                                        maxMatch = tmp;
                                        cName = lsTemplate[j].Character;
                                    }
                                }
                            }
                        }
                    }
                }
                if (match) { i = m; retValue += cName; }
                else { i++; }
            }
            return retValue;
        }
        /// <summary>
        /// Find the left-top and right-bottom points from Black-White image.
        /// </summary>
        /// <param name="sourceImage"></param>
        /// <param name="left_top"></param>
        /// <param name="right_bottom"></param>
        public static void findDiagonalPoints(Bitmap sourceImage, iPoint left_top, iPoint right_bottom)
        {
            int i = 0;
            int j = 0;
            int minWidth = int.MaxValue;
            int minHeight = int.MaxValue;
            int maxWidth = int.MinValue;
            int maxHeight = int.MinValue;

            for (i = 0; i < sourceImage.Width; i++)
            {
                for (j = 0; j < sourceImage.Height; j++)
                {
                    Color c = sourceImage.GetPixel(i, j);
                    if (c.R != 255 || c.G != 255 || c.B != 255)
                    {
                        if (i < minWidth) { minWidth = i; }
                        if (i > maxWidth) { maxWidth = i; }
                        if (j < minHeight) { minHeight = j; }
                        if (j > maxHeight) { maxHeight = j; }
                    }
                }
            }
            left_top.Height_Position = minHeight;
            left_top.Width_Position = minWidth;
            right_bottom.Height_Position = maxHeight;
            right_bottom.Width_Position = maxWidth;
        }
        /// <summary>
        /// Write the image's diagonal points into a text file.
        /// </summary>
        /// <param name="left_top"></param>
        /// <param name="right_bottom"></param>
        public static void write_Image_Diagonal_Points_To_Text(int index, iPoint left_top, iPoint right_bottom)
        {
            try
            {
                StreamWriter sw = new StreamWriter(new FileStream(ConfigParameters.Str_Image_Diagonal_Text_Path, FileMode.Append));
                sw.WriteLine(string.Format("Image {0}\t[Left-top: \twidth={1}, \theight={2}; \tright_bottom: \twidth={3}, \theight={4}]",
                    index.ToString(),
                    left_top.Width_Position,
                    left_top.Height_Position,
                    right_bottom.Width_Position,
                    right_bottom.Height_Position));

                sw.Flush();
                sw.Close();

            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
 public iPoint(iPoint _ipoint)
 {
     iniParameter(_ipoint.Width_Position, _ipoint.Height_Position);
 }
 /// <summary>
 /// Initialize the parameters of this object.
 /// </summary>
 /// <param name="_w"></param>
 /// <param name="_h"></param>
 private void iniParameter(iPoint _lt, iPoint _rb, List<iPoint> _pointSet)
 {
     LEFT_TOP = new iPoint(_lt.Width_Position, _lt.Height_Position);
     RIGHT_BOTTOM = new iPoint(_rb.Width_Position, _rb.Height_Position);
     POINT_SET = new List<iPoint>();
     foreach (iPoint point in _pointSet)
     {
         POINT_SET.Add(new iPoint(point.Width_Position, point.Height_Position));
     }
 }
 public ConnectedComponent(iPoint _lt, iPoint _rb, List<iPoint> _pointSet)
 {
     iniParameter(_lt, _rb, _pointSet);
 }