Example #1
0
        /// <summary>
        /// Calculates the percentage of a given bitmap's region which is populated by certain colors.
        /// </summary>
        /// <param name="lb">The bitmap to analyze</param>
        /// <param name="boundingRect">The region of the bitmap to analyze</param>
        /// <param name="colors">The colors to scan for. Every other color is ignored.</param>
        /// <returns></returns>
        public static double GetBlobDensity(LockBitmap lb, Rectangle boundingRect, IEnumerable <Color> colors)
        {
            int totalMatches = 0;

            try
            {
                for (int x = (boundingRect.Left >= 0 ? boundingRect.Left : 0); x <= boundingRect.Right; x++)
                {
                    for (int y = boundingRect.Top; y <= boundingRect.Bottom && y < lb.Height; y++)
                    {
                        Color c = lb.GetPixel(x, y);
                        foreach (Color match in colors)
                        {
                            if (c == match)
                            {
                                totalMatches++;
                                break;
                            }
                        }
                    }
                }

                return((double)totalMatches / (boundingRect.Height * boundingRect.Width));
            }
            catch (Exception)
            {
                return(0.0f);
            }
        }
Example #2
0
 /// <summary>
 /// See above.
 /// </summary>
 /// <param name="b"></param>
 /// <param name="boundingRectangle"></param>
 /// <param name="threshold"></param>
 /// <returns></returns>
 public static List <Line> OCRBitmap(Bitmap b, Rectangle boundingRectangle, IEnumerable <Color> threshold)
 {
     // Perf -- lock crud
     using (LockBitmap lb = new LockBitmap(b))
     {
         return(OCRBitmap(lb, boundingRectangle, threshold));
     }
 }
Example #3
0
        public Line(LockBitmap b, Rectangle boundingRectangle)
        {
            BoundingRectangle = boundingRectangle;
            List <Char> characters = new List <Char>();
            int         rectLeft = -1, rectTop = -1, rectBottom = -1, rectRight = -1;
            bool        inRect = false;

            Color black = Color.FromArgb(255, 0, 0, 0);

            for (int x = boundingRectangle.Left; x <= boundingRectangle.Right; x++)
            {
                bool blackFound = false;
                for (int y = boundingRectangle.Top; y <= boundingRectangle.Bottom; y++)
                {
                    Color c = b.GetPixel(x, y);
                    if (c == black)
                    {
                        if (rectLeft == -1)
                        {
                            rectLeft = x;
                        }

                        if (y < rectTop || rectTop == -1)
                        {
                            rectTop = y;
                        }

                        if (y > rectBottom || rectBottom == -1)
                        {
                            rectBottom = y;
                        }
                        blackFound = true;
                        inRect     = true;
                    }
                }

                if (!blackFound && inRect)
                {
                    rectRight = x - 1;
                    characters.Add(new Char(new Rectangle(rectLeft, rectTop, rectRight - rectLeft, rectBottom - rectTop)));
                    rectLeft = rectTop = rectRight = rectBottom = -1;
                    inRect   = false;
                }
            }

            if (inRect)
            {
                rectRight = boundingRectangle.Right;
                characters.Add(new Char(new Rectangle(rectLeft, rectTop, rectRight - rectLeft, rectBottom - rectTop)));
            }

            Characters = characters;
        }
Example #4
0
        /// <summary>
        /// Performs OCR on this line, recursively calling each child Char's DoOCR function
        /// </summary>
        /// <param name="lb">The bitmap containing the line</param>
        /// <param name="screentotalArea">The total area of the playscreen, used for OCR purposes</param>
        /// <param name="specialcharsenabled">True if the line can contain "e" and "."</param>
        /// <param name="lthreshold">The left-threshold. Characters which are contained entirely to the left of this value are skipped</param>
        /// <param name="lskip">Left skip. Specifies a number of characters which will be skipped, when reading from left to right.</param>
        public void DoOcr(LockBitmap lb, int screentotalArea, bool specialcharsenabled = true, int lthreshold = -1, int lskip = -1)
        {
            StringBuilder sb       = new StringBuilder(Characters.Count());
            int           lskipped = 0;

            foreach (Char c in Characters)
            {
                if (lthreshold != -1 && c.GetBoundingRectangle().Right < lthreshold)
                {
                    continue;
                }

                if (lskip != -1 && lskipped < lskip)
                {
                    lskipped++;
                    continue;
                }

                c.DoOcr(lb, screentotalArea, specialcharsenabled);
                sb.Append(c.GuessedCharacter);
            }
            OcrString = sb.ToString();
        }
Example #5
0
        /// <summary>
        /// Performs OCR on a bitmap, reading the Chars and Lines present.
        /// </summary>
        /// <param name="lb">The bitmap to OCR</param>
        /// <param name="boundingRectangle">Defines the region of the bitmap to OCR. Defining a larger region than necessary will have perf consequences.</param>
        /// <param name="threshold">An enumeration of colors which are considered text colors. Every pixel which is not one of these colors will be ignored.</param>
        /// <returns>A list of lines. Note that character OCR is not performed on the returned lines -- those lines' DoOCR function needs to be called separately (for perf reasons)</returns>
        public static List <Line> OCRBitmap(LockBitmap lb, Rectangle boundingRectangle, IEnumerable <Color> threshold)
        {
            List <Line> lines = new List <Line>();

            int  rectLeft = -1, rectRight = -1, rectTop = -1, rectBot = -1;
            bool inLine = false;

            for (int y = boundingRectangle.Top; y < boundingRectangle.Bottom; y++)
            {
                bool foundBlack = false;

                for (int x = boundingRectangle.Left; x < boundingRectangle.Right; x++)
                {
                    Color pixel = lb.GetPixel(x, y);
                    if (pixel == Color.FromArgb(255, 0, 0, 0))
                    {
                        lb.SetPixel(x, y, Color.White);
                    }

                    foreach (Color c in threshold)
                    {
                        if (c == pixel)
                        {
                            lb.SetPixel(x, y, Color.Black);

                            if (rectTop == -1)
                            {
                                rectTop = y;
                            }

                            if (x < rectLeft || rectLeft == -1)
                            {
                                rectLeft = x;
                            }

                            if (x > rectRight || rectRight == -1)
                            {
                                rectRight = x;
                            }

                            foundBlack = true;
                            inLine     = true;
                            break;
                        }
                    }
                }

                if (inLine && !foundBlack)
                {
                    rectBot = y - 1;

                    // Minimum area requirements
                    if ((rectBot - rectTop) > 5)
                    {
                        lines.Add(new Line(lb, new Rectangle(rectLeft, rectTop, rectRight - rectLeft, rectBot - rectTop)));
                    }
                    rectLeft = rectTop = rectRight = rectBot = -1;
                    inLine   = false;
                }
            }

            return(lines);
        }
        /// <summary>
        /// Tries to get the current amount of money from the screen. Is slow.
        /// </summary>
        /// <returns></returns>
        public static double GetMoney()
        {
            Size s = MoneyArea.Size;
            double money = -1;

            using (Bitmap bitmap = GetImage(MoneyArea))
            {
                IEnumerable<Line> lines = OCREngine.OCRBitmap(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height), new Color[] {
                    Color.FromArgb(255, 254, 254, 254),
                    Color.FromArgb(255, 254, 254, 253)
                });

                using (LockBitmap lb = new LockBitmap(bitmap))
                {
                    if (lines.Count() != 0)
                    {
                        Rectangle playableArea = GameEngine.GetPlayableArea();
                        lines.First().DoOcr(lb, playableArea.Height * playableArea.Width);
                        try
                        {
                            money = Convert.ToDouble(lines.First().OcrString);
                        }
                        catch (Exception)
                        {
                            // ignore
                        }
                    }
                }

                return money;
            }
        }
        ///// <summary>
        ///// Tries to get the current amount of money from the screen. Is slow.
        ///// </summary>
        ///// <returns></returns>
        //public static string GetDamagePerSecond()
        //{
        //    Size s = DamagePerSecondArea.Size;
        //    string dps = "";
        //    using (Bitmap bitmap = GetDamagePerSecondBMP())
        //    {
        //        IEnumerable<Line> lines = OCREngine.OCRBitmap(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height),
        //            new Color[]
        //            {
        //                Color.FromArgb(255, 254, 254, 254),
        //                Color.FromArgb(255, 254, 254, 253)
        //            });
        //        if (lines.Count() != 0)
        //        {
        //            using (LockBitmap lb = new LockBitmap(bitmap))
        //            {
        //                Rectangle playableArea = GameEngine.GetPlayableArea();
        //                lines.First().DoOcr(lb, playableArea.Height * playableArea.Width);
        //                try
        //                {
        //                    //dps = Convert.ToDouble(lines.First().OcrString);
        //                    dps = lines.First().OcrString;
        //                }
        //                catch (Exception)
        //                {
        //                    // ignore
        //                }
        //            }
        //        }
        //        return dps;
        //    }
        //}
        //public static Bitmap GetDamagePerSecondBMP()
        //{
        //    Bitmap bitmap = GetImage(DamagePerSecondArea);
        //    Bitmap resizedBitmap = new Bitmap(bitmap, new Size((int) (bitmap.Width * 2), (int) (bitmap.Height * 2)));
        //   // return resizedBitmap;
        //    Bitmap newBitmap = new Bitmap(resizedBitmap.Width, resizedBitmap.Height);
        //    var newColor = Color.FromArgb(255, 254, 254, 254);
        //    var white = Color.DeepPink;
        //    for (int i = 0; i < resizedBitmap.Width; i++)
        //    {
        //        for (int j = 0; j < resizedBitmap.Height; j++)
        //        {
        //            var actulaColor = resizedBitmap.GetPixel(i, j);
        //            if (actulaColor.R > 220)
        //                newBitmap.SetPixel(i, j, newColor);
        //            else
        //                newBitmap.SetPixel(i, j, white);
        //        }
        //    }
        //    return newBitmap;
        //}
        /// <summary>
        /// Tries to parse all heroes on screen. Is null if there is crap on the screen preventing the heros from being parsed. Is very slow.
        /// </summary>
        /// <returns></returns>
        public static ParsedHeroes GetHeroes()
        {
            Size s = HeroesArea.Size;

            using (Bitmap bitmap = GetImage(HeroesArea))
            {
                List<Line> lines = OCREngine.OCRBitmap(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height), new Color[] {
                        Color.FromArgb(255, 254, 254, 254),
                        Color.FromArgb(255, 254, 254, 253),
                        Color.FromArgb(255, 102, 51, 204), // purple for gilded heroes
                    });

                using (LockBitmap lb = new LockBitmap(bitmap))
                {
                    ParsedHeroes ph = GameEngine.ParseHeroes(lines, lb);
                    if (ph == null)
                    {
                        return null;
                    }

                    foreach (HeroStats hs in ph.HeroStats)
                    {
                        hs.CalculateUpgrades(lb);
                    }

                    return ph;
                }
            }
        }
        /// <summary>
        /// Tries to get the current amount of money from the screen. Is slow.
        /// </summary>
        /// <returns></returns>
        public static double GetMoney()
        {
            Size s = MoneyArea.Size;
            double money = -1;
            Console.WriteLine(s.Width);
            Console.WriteLine(s.Height);
            using (Bitmap bitmap = new Bitmap(s.Width, s.Height))
            {
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    g.CopyFromScreen(new Point(MoneyArea.Left, MoneyArea.Top), Point.Empty, s);
                }

                IEnumerable<Line> lines = OCREngine.OCRBitmap(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height), new Color[] {
                    Color.FromArgb(255, 254, 254, 254),
                    Color.FromArgb(255, 254, 254, 253)
                });

                using (LockBitmap lb = new LockBitmap(bitmap))
                {
                    if (lines.Count() != 0)
                    {
                        Rectangle playableArea = GameEngine.GetPlayableArea();
                        lines.First().DoOcr(lb, playableArea.Height * playableArea.Width);
                        try
                        {
                            money = Convert.ToDouble(lines.First().OcrString);
                        }
                        catch (Exception)
                        {
                            // ignore
                        }
                    }
                }

                return money;
            }
        }
        /// <summary>
        /// Populates the HeroStat's UpgradeBitfield.
        /// </summary>
        /// <param name="lb"></param>
        public void CalculateUpgrades(LockBitmap lb)
        {
            UpgradeBitfield = 0;
            for (int i = 0; i < 7; i++)
            {
                Rectangle r = GetUpgradeRect(i);
                if (r.Bottom > lb.Height)
                {
                    UpgradeBitfield = Int16.MinValue;
                    return;
                }

                double d = OCREngine.GetBlobDensity(lb, r, new Color[] { Color.FromArgb(39, 166, 10), // Normal
                                                                         Color.FromArgb(7, 33, 1), // Bugged out
                                                                       });

                if (d > 0.003)
                {
                    UpgradeBitfield |= (Int16)(1 << i);
                }
            }
        }
        /// <summary>
        /// Performs OCR on this char
        /// </summary>
        /// <param name="b">The bitmap containing this char</param>
        /// <param name="screentotalArea">The total area of the entire playscreen, used for OCR purposes</param>
        /// <param name="specialcharsenabled">True if "e" and "." can appear in the string </param>
        public void DoOcr(LockBitmap b, int screentotalArea, bool specialcharsenabled = true)
        {
            int totalArea = 0, lArea = 0, tArea = 0;
            int leftArea = 0, rightArea = 0;
            int groupsDownMiddleVertical = 0;
            int midwidth = 0;
            for (int i = BoundingRect.Left; i <= BoundingRect.Right; i++)
            {
                for (int j = BoundingRect.Top; j <= BoundingRect.Bottom; j++)
                {
                    if (b.GetPixel(i, j) == Color.FromArgb(255, 0, 0, 0))
                    {
                        totalArea++;
                        if (j < (BoundingRect.Bottom - BoundingRect.Top) / 2 + BoundingRect.Top)
                        {
                            tArea++;
                        }
                        else
                        {
                            if (j == (BoundingRect.Bottom - BoundingRect.Top) / 2 + BoundingRect.Top)
                            {
                                midwidth++;
                            }
                            lArea++;
                        }

                        if (i < (BoundingRect.Right - BoundingRect.Left) / 2 + BoundingRect.Left)
                        {
                            leftArea++;
                        }
                        else
                        {
                            rightArea++;
                        }

                    }

                }
            }

            bool isBlack = false;
            bool storedWhiteSubgroup = false;
            for (int j = BoundingRect.Top; j <= BoundingRect.Bottom; j++)
            {
                if (b.GetPixel((BoundingRect.Right - BoundingRect.Left) / 2 + BoundingRect.Left, j) == Color.FromArgb(255, 0, 0, 0))
                {
                    isBlack = true;
                    if (storedWhiteSubgroup)
                    {
                        groupsDownMiddleVertical++;
                        storedWhiteSubgroup = false;
                    }
                }
                else
                {
                    if (isBlack)
                    {
                        storedWhiteSubgroup = true;
                        isBlack = false;
                    }
                }
            }

            char guessedchar = '~';
            switch (groupsDownMiddleVertical)
            {
                case 0:
                    if (totalArea > 0.000157 * screentotalArea || specialcharsenabled == false)
                    {
                        guessedchar = '1';
                    }
                    else
                    {
                        guessedchar = '.';
                    }
                    break;
                case 2:
                    if (totalArea < 0.0003571 * screentotalArea && specialcharsenabled) //(double)rightArea / leftArea < 1.1) //1.1256)
                    {
                        guessedchar = 'e';
                    } else if ((double)rightArea / leftArea > 1.6160) //1.6   1.6177
                    {
                        guessedchar = '3';
                    }
                    else if ((double)midwidth / BoundingRect.Width > 0.75) //1.2597)
                    {
                        guessedchar = '5';
                    }
                    else
                    {
                        guessedchar = '8';
                    }
                    break;
                case 1:
                    if ((double)lArea / tArea > 1.6691) //1.6406 1.7420 1.6933
                    {
                        guessedchar = '6';
                    }
                    else if ((double)lArea / tArea > 1.3405) //1.2514
                    {
                        guessedchar = '4';
                    }
                    else if ((double)lArea / tArea <= 1) //0.9769
                    {
                        if ((double)midwidth / BoundingRect.Width < 0.7045)
                        {
                            guessedchar = '7';
                        }
                        else
                        {
                            guessedchar = '9';
                        }
                    }
                    else
                    {
                        if ((double)rightArea / leftArea > 1.20) // 1.1540)
                        {
                            guessedchar = '2';
                        }
                        else
                        {
                            guessedchar = '0';
                        }
                    }
                    break;

                default:
                    break;
            }

            TotalArea = totalArea;
            MaxVerticalGroups = groupsDownMiddleVertical;
            UpperArea = tArea;
            LowerArea = lArea;
            LeftArea = leftArea;
            RightArea = rightArea;
            GuessedCharacter = guessedchar;
        }
 /// <summary>
 /// See above.
 /// </summary>
 /// <param name="b"></param>
 /// <param name="boundingRectangle"></param>
 /// <param name="threshold"></param>
 /// <returns></returns>
 public static List<Line> OCRBitmap(Bitmap b, Rectangle boundingRectangle, IEnumerable<Color> threshold)
 {
     // Perf -- lock crud
     using (LockBitmap lb = new LockBitmap(b))
     {
         return OCRBitmap(lb, boundingRectangle, threshold);
     }
 }
        /// <summary>
        /// Performs OCR on a bitmap, reading the Chars and Lines present.
        /// </summary>
        /// <param name="lb">The bitmap to OCR</param>
        /// <param name="boundingRectangle">Defines the region of the bitmap to OCR. Defining a larger region than necessary will have perf consequences.</param>
        /// <param name="threshold">An enumeration of colors which are considered text colors. Every pixel which is not one of these colors will be ignored.</param>
        /// <returns>A list of lines. Note that character OCR is not performed on the returned lines -- those lines' DoOCR function needs to be called separately (for perf reasons)</returns>
        public static List<Line> OCRBitmap(LockBitmap lb, Rectangle boundingRectangle, IEnumerable<Color> threshold)
        {
            List<Line> lines = new List<Line>();

            int rectLeft = -1, rectRight = -1, rectTop = -1, rectBot = -1;
            bool inLine = false;

            for (int y = boundingRectangle.Top; y < boundingRectangle.Bottom; y++)
            {
                bool foundBlack = false;

                for (int x = boundingRectangle.Left; x < boundingRectangle.Right; x++)
                {
                    Color pixel = lb.GetPixel(x, y);
                    if (pixel == Color.FromArgb(255, 0, 0, 0))
                    {
                        lb.SetPixel(x, y, Color.White);
                    }

                    foreach (Color c in threshold)
                    {
                        if (c == pixel)
                        {
                            lb.SetPixel(x, y, Color.Black);

                            if (rectTop == -1)
                            {
                                rectTop = y;
                            }

                            if (x < rectLeft || rectLeft == -1)
                            {
                                rectLeft = x;
                            }

                            if (x > rectRight || rectRight == -1)
                            {
                                rectRight = x;
                            }

                            foundBlack = true;
                            inLine = true;
                            break;
                        }
                    }
                }

                if (inLine && !foundBlack)
                {
                    rectBot = y - 1;

                    // Minimum area requirements
                    if ((rectBot - rectTop) > 5)
                    {
                        lines.Add(new Line(lb, new Rectangle(rectLeft, rectTop, rectRight - rectLeft, rectBot - rectTop)));
                    }
                    rectLeft = rectTop = rectRight = rectBot = -1;
                    inLine = false;
                }
            }

            return lines;
        }
        /// <summary>
        /// Calculates the percentage of a given bitmap's region which is populated by certain colors.
        /// </summary>
        /// <param name="lb">The bitmap to analyze</param>
        /// <param name="boundingRect">The region of the bitmap to analyze</param>
        /// <param name="colors">The colors to scan for. Every other color is ignored.</param>
        /// <returns></returns>
        public static double GetBlobDensity(LockBitmap lb, Rectangle boundingRect, IEnumerable<Color> colors)
        {
            int totalMatches = 0;

            try
            {
                for (int x = (boundingRect.Left >= 0 ? boundingRect.Left : 0); x <= boundingRect.Right; x++)
                {
                    for (int y = boundingRect.Top; y <= boundingRect.Bottom && y < lb.Height; y++)
                    {
                        Color c = lb.GetPixel(x, y);
                        foreach (Color match in colors)
                        {
                            if (c == match)
                            {
                                totalMatches++;
                                break;
                            }
                        }
                    }
                }

                return (double)totalMatches / (boundingRect.Height * boundingRect.Width);
            }
            catch (Exception)
            {
                return 0.0f;
            }
        }
        /// <summary>
        /// Performs OCR on this line, recursively calling each child Char's DoOCR function
        /// </summary>
        /// <param name="lb">The bitmap containing the line</param>
        /// <param name="screentotalArea">The total area of the playscreen, used for OCR purposes</param>
        /// <param name="specialcharsenabled">True if the line can contain "e" and "."</param>
        /// <param name="lthreshold">The left-threshold. Characters which are contained entirely to the left of this value are skipped</param>
        /// <param name="lskip">Left skip. Specifies a number of characters which will be skipped, when reading from left to right.</param>
        public void DoOcr(LockBitmap lb, int screentotalArea, bool specialcharsenabled = true, int lthreshold = -1, int lskip = -1)
        {
            StringBuilder sb = new StringBuilder(Characters.Count());
            int lskipped = 0;
            foreach (Char c in Characters)
            {
                if (lthreshold != -1 && c.GetBoundingRectangle().Right < lthreshold)
                {
                    continue;
                }

                if (lskip != -1 && lskipped < lskip)
                {
                    lskipped++;
                    continue;
                }

                c.DoOcr(lb, screentotalArea, specialcharsenabled);
                sb.Append(c.GuessedCharacter);
            }
            OcrString = sb.ToString();
        }
        public Line(LockBitmap b, Rectangle boundingRectangle)
        {
            BoundingRectangle = boundingRectangle;
            List<Char> characters = new List<Char>();
            int rectLeft = -1, rectTop = -1, rectBottom = -1, rectRight = -1;
            bool inRect = false;

            Color black = Color.FromArgb(255, 0, 0, 0);
            for (int x = boundingRectangle.Left; x <= boundingRectangle.Right; x++)
            {
                bool blackFound = false;
                for (int y = boundingRectangle.Top; y <= boundingRectangle.Bottom; y++)
                {
                    Color c = b.GetPixel(x, y);
                    if (c == black)
                    {
                        if (rectLeft == -1)
                        {
                            rectLeft = x;
                        }

                        if (y < rectTop || rectTop == -1)
                        {
                            rectTop = y;
                        }

                        if (y > rectBottom || rectBottom == -1)
                        {
                            rectBottom = y;
                        }
                        blackFound = true;
                        inRect = true;
                    }
                }

                if (!blackFound && inRect)
                {
                    rectRight = x - 1;
                    characters.Add(new Char(new Rectangle(rectLeft, rectTop, rectRight - rectLeft, rectBottom - rectTop)));
                    rectLeft = rectTop = rectRight = rectBottom = -1;
                    inRect = false;
                }
            }

            if (inRect)
            {
                rectRight = boundingRectangle.Right;
                characters.Add(new Char(new Rectangle(rectLeft, rectTop, rectRight - rectLeft, rectBottom - rectTop)));
            }

            Characters = characters;
        }
        /// <summary>
        /// Helper method for GetHeroes
        /// </summary>
        /// <param name="lines"></param>
        /// <param name="lb"></param>
        /// <returns></returns>
        private static ParsedHeroes ParseHeroes(List<Line> lines, LockBitmap lb)
        {
            ParsedHeroes parsedHeroes = new ParsedHeroes();

            if (lines.Count() == 0)
            {
                return null;
            } else if (lines.Count() <= 3)
            {
                // it's cid it's cid it's cid
                // Note: Cid is special because of 2 reasons: when she appears it's the only time in the game
                // there can be less than 3 heroes on screen. Second, she doesn't have a number to represent DPS,
                // so we need to special case some stuff to make OCR work.
                parsedHeroes.HeroStats = new List<HeroStats>();
                parsedHeroes.FirstHeroIndex = 0;
                parsedHeroes.LastHeroIndex = 0;
                HeroStats cid = new HeroStats();
                cid.Hero = GameEngine.HeroList[0];
                cid.Level = 0;
                cid.bottomright.X = lines[0].GetBoundingRectangle().Right;
                cid.bottomright.Y = lines[0].GetBoundingRectangle().Bottom;
                parsedHeroes.HeroStats.Add(cid);

                return parsedHeroes;
            }

            List<Line> widths = new List<Line>();
            List<Line> levels = new List<Line>();
            int i = -1;
            bool rectSkipped = false;
            if (lines[1].GetBoundingRectangle().Top - lines[0].GetBoundingRectangle().Top > HeroSeperatorHeight)
            {
                i = 1;
                rectSkipped = true;
            } else {
                i = 0;
            }

            for (; i < lines.Count(); i+=2)
            {
                widths.Add(lines[i]);
                if (i + 1 < lines.Count())
                {
                    levels.Add(lines[i + 1]);
                }
            }

            // If less than 6 lines -- it's Cid
            if (lines.Count() < 6)
            {
                parsedHeroes.FirstHeroIndex = 0;
                parsedHeroes.LastHeroIndex = lines.Count() / 2;
            }
            else
            {
                int smallestIndex = -1;
                int smallestScore = int.MaxValue;

                for (int j = 0; j + widths.Count() <= HeroList.Count(); j++)
                {
                    int thisScore = 0;
                    for (int k = 0; k < widths.Count(); k++)
                    {
                        thisScore += Math.Abs((int)(HeroList[j + k].Namewidth * PlayableArea.Width - widths[k].GetBoundingRectangle().Width));
                    }
                    if (thisScore < smallestScore)
                    {
                        smallestScore = thisScore;
                        smallestIndex = j;
                    }
                }

                parsedHeroes.FirstHeroIndex = smallestIndex;
                parsedHeroes.LastHeroIndex = smallestIndex + widths.Count() - 1;
            }

            List<HeroStats> heroStats = new List<HeroStats>();
            if (parsedHeroes.FirstHeroIndex == 1 && rectSkipped)
            {
                // oh god, is it cid? why is it always cid
                if (lines[0].GetBoundingRectangle().Left < lb.Width / 2)
                {
                    HeroStats stats = new HeroStats();
                    stats.Hero = HeroList[0];
                    stats.Level = 0;
                    stats.bottomright = new Point(lines[0].GetBoundingRectangle().Right, lines[0].GetBoundingRectangle().Bottom);
                    heroStats.Add(stats);
                    parsedHeroes.FirstHeroIndex = 0;
                }
            }

            for (int j = 0; j < widths.Count(); j++)
            {
                HeroStats stats = new HeroStats();
                stats.Hero = HeroList[parsedHeroes.FirstHeroIndex + j];
                stats.bottomright = new Point(widths[j].GetBoundingRectangle().Right, widths[j].GetBoundingRectangle().Bottom);

                if (j < levels.Count())
                {
                    levels[j].DoOcr(lb, PlayableArea.Width * PlayableArea.Height, false, lb.Width / 2, 3 /* lvl */);
                    if (!int.TryParse(levels[j].OcrString, out stats.Level))
                    {
                        stats.Level = 0;
                    }
                }
                else
                {
                    stats.Level = -1;
                }

                heroStats.Add(stats);
            }
            parsedHeroes.HeroStats = heroStats;
            return parsedHeroes;
        }
Example #17
0
        /// <summary>
        /// Performs OCR on this char
        /// </summary>
        /// <param name="b">The bitmap containing this char</param>
        /// <param name="screentotalArea">The total area of the entire playscreen, used for OCR purposes</param>
        /// <param name="specialcharsenabled">True if "e" and "." can appear in the string </param>
        public void DoOcr(LockBitmap b, int screentotalArea, bool specialcharsenabled = true)
        {
            int totalArea = 0, lArea = 0, tArea = 0;
            int leftArea = 0, rightArea = 0;
            int groupsDownMiddleVertical = 0;
            int midwidth = 0;

            for (int i = BoundingRect.Left; i <= BoundingRect.Right; i++)
            {
                for (int j = BoundingRect.Top; j <= BoundingRect.Bottom; j++)
                {
                    if (b.GetPixel(i, j) == Color.FromArgb(255, 0, 0, 0))
                    {
                        totalArea++;
                        if (j < (BoundingRect.Bottom - BoundingRect.Top) / 2 + BoundingRect.Top)
                        {
                            tArea++;
                        }
                        else
                        {
                            if (j == (BoundingRect.Bottom - BoundingRect.Top) / 2 + BoundingRect.Top)
                            {
                                midwidth++;
                            }
                            lArea++;
                        }

                        if (i < (BoundingRect.Right - BoundingRect.Left) / 2 + BoundingRect.Left)
                        {
                            leftArea++;
                        }
                        else
                        {
                            rightArea++;
                        }
                    }
                }
            }

            bool isBlack             = false;
            bool storedWhiteSubgroup = false;

            for (int j = BoundingRect.Top; j <= BoundingRect.Bottom; j++)
            {
                if (b.GetPixel((BoundingRect.Right - BoundingRect.Left) / 2 + BoundingRect.Left, j) == Color.FromArgb(255, 0, 0, 0))
                {
                    isBlack = true;
                    if (storedWhiteSubgroup)
                    {
                        groupsDownMiddleVertical++;
                        storedWhiteSubgroup = false;
                    }
                }
                else
                {
                    if (isBlack)
                    {
                        storedWhiteSubgroup = true;
                        isBlack             = false;
                    }
                }
            }

            char guessedchar = '~';

            switch (groupsDownMiddleVertical)
            {
            case 0:
                if (totalArea > 0.000157 * screentotalArea || specialcharsenabled == false)
                {
                    guessedchar = '1';
                }
                else
                {
                    guessedchar = '.';
                }
                break;

            case 2:
                if (totalArea < 0.0003571 * screentotalArea && specialcharsenabled)     //(double)rightArea / leftArea < 1.1) //1.1256)
                {
                    guessedchar = 'e';
                }
                else if ((double)rightArea / leftArea > 1.6160)       //1.6   1.6177
                {
                    guessedchar = '3';
                }
                else if ((double)midwidth / BoundingRect.Width > 0.75)     //1.2597)
                {
                    guessedchar = '5';
                }
                else
                {
                    guessedchar = '8';
                }
                break;

            case 1:
                if ((double)lArea / tArea > 1.6691)     //1.6406 1.7420 1.6933
                {
                    guessedchar = '6';
                }
                else if ((double)lArea / tArea > 1.3405)     //1.2514
                {
                    guessedchar = '4';
                }
                else if ((double)lArea / tArea <= 1)     //0.9769
                {
                    if ((double)midwidth / BoundingRect.Width < 0.7045)
                    {
                        guessedchar = '7';
                    }
                    else
                    {
                        guessedchar = '9';
                    }
                }
                else
                {
                    if ((double)rightArea / leftArea > 1.20)     // 1.1540)
                    {
                        guessedchar = '2';
                    }
                    else
                    {
                        guessedchar = '0';
                    }
                }
                break;

            default:
                break;
            }

            TotalArea         = totalArea;
            MaxVerticalGroups = groupsDownMiddleVertical;
            UpperArea         = tArea;
            LowerArea         = lArea;
            LeftArea          = leftArea;
            RightArea         = rightArea;
            GuessedCharacter  = guessedchar;
        }
        /// <summary>
        /// Tries to parse all heroes on screen. Is null if there is crap on the screen preventing the heros from being parsed. Is very slow.
        /// </summary>
        /// <returns></returns>
        public static ParsedHeroes GetHeroes()
        {
            Size s = HeroesArea.Size;

            using (Bitmap bitmap = new Bitmap(s.Width, s.Height))
            {
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    g.CopyFromScreen(new Point(HeroesArea.Left, HeroesArea.Top), Point.Empty, s);
                }

                using (LockBitmap lb = new LockBitmap(bitmap))
                {
                    List<Line> lines = OCREngine.OCRBitmap(lb, new Rectangle(0, 0, bitmap.Width, bitmap.Height), new Color[] {
                        Color.FromArgb(255, 254, 254, 254),
                        Color.FromArgb(255, 254, 254, 253),
                        Color.FromArgb(255, 102, 51, 204), // purple for gilded heroes
                    });

                    ParsedHeroes ph = GameEngine.ParseHeroes(lines, lb);
                    if (ph == null)
                    {
                        return null;
                    }

                    foreach (HeroStats hs in ph.HeroStats)
                    {
                        hs.CalculateUpgrades(lb);
                    }

                    return ph;
                }
            }
        }