Example #1
0
        public string NocrFastCheck(Bitmap bitmap)
        {
            var nbmpInput = new NikseBitmap(bitmap);
            nbmpInput.ReplaceNonWhiteWithTransparent();

            var matches = new List<CompareMatch>();
            List<ImageSplitterItem> list = NikseBitmapImageSplitter.SplitBitmapToLetters(nbmpInput, (int)numericUpDownNumberOfPixelsIsSpaceNOCR.Value, checkBoxRightToLeft.Checked, Configuration.Settings.VobSubOcr.TopToBottom);

            foreach (ImageSplitterItem item in list)
            {
                if (item.NikseBitmap != null)
                {
                    item.NikseBitmap.ReplaceTransparentWith(Color.Black);
                }
            }
            int index = 0;

            while (index < list.Count)
            {
                ImageSplitterItem item = list[index];
                if (item.NikseBitmap == null)
                {
                    matches.Add(new CompareMatch(item.SpecialCharacter, false, 0, null));
                }
                else
                {
                    CompareMatch match = null;

                    var nbmp = item.NikseBitmap;
                    int topMargin = item.Y - item.ParentY;
                    foreach (NOcrChar oc in _nOcrDb.OcrCharacters)
                    {
                        if (Math.Abs(oc.Width - nbmp.Width) < 3 && Math.Abs(oc.Height - nbmp.Height) < 4 && Math.Abs(oc.MarginTop - topMargin) < 4)
                        { // only very accurate matches

                            bool ok = true;
                            var index2 = 0;
                            while (index2 < oc.LinesForeground.Count && ok)
                            {
                                NOcrPoint op = oc.LinesForeground[index2];
                                foreach (Point point in op.ScaledGetPoints(oc, nbmp.Width, nbmp.Height))
                                {
                                    if (point.X >= 0 && point.Y >= 0 && point.X < nbmp.Width && point.Y < nbmp.Height)
                                    {
                                        Color c = nbmp.GetPixel(point.X, point.Y);
                                        if (c.A > 150 && c.R + c.G + c.B > NocrMinColor)
                                        {
                                        }
                                        else
                                        {
                                            Point p = new Point(point.X - 1, point.Y);
                                            if (p.X < 0)
                                                p.X = 1;
                                            c = nbmp.GetPixel(p.X, p.Y);
                                            if (nbmp.Width > 20 && c.A > 150 && c.R + c.G + c.B > NocrMinColor)
                                            {
                                            }
                                            else
                                            {
                                                ok = false;
                                                break;
                                            }
                                        }
                                    }
                                }
                                index2++;
                            }
                            index2 = 0;
                            while (index2 < oc.LinesBackground.Count && ok)
                            {
                                NOcrPoint op = oc.LinesBackground[index2];
                                foreach (Point point in op.ScaledGetPoints(oc, nbmp.Width, nbmp.Height))
                                {
                                    if (point.X >= 0 && point.Y >= 0 && point.X < nbmp.Width && point.Y < nbmp.Height)
                                    {
                                        Color c = nbmp.GetPixel(point.X, point.Y);
                                        if (c.A > 150 && c.R + c.G + c.B > NocrMinColor)
                                        {
                                            Point p = new Point(point.X, point.Y);
                                            if (oc.Width > 19 && point.X > 0)
                                                p.X = p.X - 1;
                                            c = nbmp.GetPixel(p.X, p.Y);
                                            if (c.A > 150 && c.R + c.G + c.B > NocrMinColor)
                                            {
                                                ok = false;
                                                break;
                                            }
                                        }
                                    }
                                }
                                index2++;
                            }
                            if (ok)
                                match = new CompareMatch(oc.Text, oc.Italic, 0, null);
                        }
                    }

                    if (match == null)
                    {
                        matches.Add(new CompareMatch("*", false, 0, null));
                    }
                    else // found image match
                    {
                        matches.Add(new CompareMatch(match.Text, match.Italic, 0, null));
                        if (match.ExpandCount > 0)
                            index += match.ExpandCount - 1;
                    }
                }
                index++;
            }
            return GetStringWithItalicTags(matches);
        }
Example #2
0
        private CompareMatch GetCompareMatchNew(ImageSplitterItem targetItem, out CompareMatch secondBestGuess, List<ImageSplitterItem> list, int listIndex)
        {
            double maxDiff = _numericUpDownMaxErrorPct;
            secondBestGuess = null;
            int index = 0;
            int smallestDifference = 10000;
            int smallestIndex = -1;
            var target = targetItem.NikseBitmap;
            if (_binaryOcrDb == null)
            {
                return null;
            }

            var bob = new BinaryOcrBitmap(target) { X = targetItem.X, Y = targetItem.Top };

            for (int k = 0; k < _binaryOcrDb.CompareImagesExpanded.Count; k++)
            {
                var b = _binaryOcrDb.CompareImagesExpanded[k];
                if ((bob.Hash == b.Hash && bob.Width == b.Width && bob.Height == b.Height && bob.NumberOfColoredPixels == b.NumberOfColoredPixels) || GetPixelDifPercentage(b, bob, target) <= maxDiff)
                {
                    bool ok = false;
                    for (int i = 0; i < b.ExpandedList.Count; i++)
                    {
                        if (listIndex + i + 1 < list.Count && list[listIndex + i + 1].NikseBitmap != null)
                        {
                            var bobNext = new BinaryOcrBitmap(list[listIndex + i + 1].NikseBitmap);
                            if (b.ExpandedList[i].Hash == bobNext.Hash)
                            {
                                ok = true;
                            }
                            else if (GetPixelDifPercentage(b.ExpandedList[i], bobNext, list[listIndex + i + 1].NikseBitmap) <= maxDiff)
                            {
                                ok = true;
                            }
                            else
                            {
                                ok = false;
                                break;
                            }
                        }
                    }
                    if (ok)
                    {
                        return new CompareMatch(b.Text, b.Italic, b.ExpandCount, b.Key);
                    }
                }
            }

            FindBestMatchNew(ref index, ref smallestDifference, ref smallestIndex, target, _binaryOcrDb, bob, maxDiff);
            if (maxDiff > 0)
            {
                if (target.Width > 16 && target.Height > 16 && (smallestIndex == -1 || smallestDifference * 100.0 / (target.Width * target.Height) > maxDiff))
                {
                    var t2 = target.CopyRectangle(new Rectangle(0, 1, target.Width, target.Height - 1));
                    FindBestMatchNew(ref index, ref smallestDifference, ref smallestIndex, t2, _binaryOcrDb, bob, maxDiff);
                }
                if (target.Width > 16 && target.Height > 16 && (smallestIndex == -1 || smallestDifference * 100.0 / (target.Width * target.Height) > maxDiff))
                {
                    var t2 = target.CopyRectangle(new Rectangle(1, 0, target.Width - 1, target.Height));
                    FindBestMatchNew(ref index, ref smallestDifference, ref smallestIndex, t2, _binaryOcrDb, bob, maxDiff);
                }
                if (target.Width > 16 && target.Height > 16 && (smallestIndex == -1 || smallestDifference * 100.0 / (target.Width * target.Height) > maxDiff))
                {
                    var t2 = target.CopyRectangle(new Rectangle(0, 0, target.Width - 1, target.Height));
                    FindBestMatchNew(ref index, ref smallestDifference, ref smallestIndex, t2, _binaryOcrDb, bob, maxDiff);
                }
            }

            if (smallestIndex >= 0)
            {
                double differencePercentage = smallestDifference * 100.0 / (target.Width * target.Height);
                if (differencePercentage <= maxDiff)
                {
                    var hit = _binaryOcrDb.CompareImages[smallestIndex];

                    string text = hit.Text;
                    if (smallestDifference > 0)
                    {
                        int h = hit.Height;
                        if (text == "V" || text == "W" || text == "U" || text == "S" || text == "Z" || text == "O" || text == "X" || text == "Ø" || text == "C")
                        {
                            if (_binOcrLastLowercaseHeight > 3 && h - _binOcrLastLowercaseHeight < 2)
                                text = text.ToLower();
                        }
                        else if (text == "v" || text == "w" || text == "u" || text == "s" || text == "z" || text == "o" || text == "x" || text == "ø" || text == "c")
                        {
                            if (_binOcrLastUppercaseHeight > 3 && _binOcrLastUppercaseHeight - h < 2)
                                text = text.ToUpper();
                        }
                    }
                    else
                    {
                        SetBinOcrLowercaseUppercase(hit.Height, text);
                    }
                    if (differencePercentage > 0)
                    {
                        bool dummy;
                        if ((hit.Text == "l" || hit.Text == "!") && bob.IsLowercaseI(out dummy))
                        {
                            hit = null;
                        }
                        else if ((hit.Text == "i" || hit.Text == "!") && bob.IsLowercaseL())
                        {
                            hit = null;
                        }
                        else if ((hit.Text == "o" || hit.Text == "O") && bob.IsC())
                        {
                            return new CompareMatch(hit.Text == "o" ? "c" : "C", false, 0, null);
                        }
                        else if ((hit.Text == "c" || hit.Text == "C") && !bob.IsC() && bob.IsO())
                        {
                            return new CompareMatch(hit.Text == "c" ? "o" : "O", false, 0, null);
                        }
                    }

                    if (hit != null)
                    {
                        if (_binOcrLastLowercaseHeight < 0 && differencePercentage < 9 && (text == "e" || text == "d" || text == "a"))
                            _binOcrLastLowercaseHeight = bob.Height;
                        return new CompareMatch(text, hit.Italic, hit.ExpandCount, hit.Key);
                    }
                }

                var guess = _binaryOcrDb.CompareImages[smallestIndex];
                secondBestGuess = new CompareMatch(guess.Text, guess.Italic, guess.ExpandCount, guess.Key);
            }

            if (bob.IsPeriod())
            {
                return new CompareMatch(".", false, 0, null);
            }
            if (bob.IsComma())
            {
                return new CompareMatch(",", false, 0, null);
            }
            if (maxDiff > 0 && bob.IsApostrophe())
            {
                return new CompareMatch("'", false, 0, null);
            }
            if (bob.IsLowercaseJ()) // "j" detection must be before "i"
            {
                return new CompareMatch("j", false, 0, null);
            }
            bool italicLowercaseI;
            if (bob.IsLowercaseI(out italicLowercaseI))
            {
                return new CompareMatch("i", italicLowercaseI, 0, null);
            }
            if (bob.IsColon())
            {
                return new CompareMatch(":", false, 0, null);
            }
            if (bob.IsExclamationMark())
            {
                return new CompareMatch("!", false, 0, null);
            }
            if (bob.IsDash())
            {
                return new CompareMatch("-", false, 0, null);
            }

            return null;
        }
Example #3
0
        private CompareMatch GetCompareMatch(ImageSplitterItem targetItem, NikseBitmap parentBitmap, out CompareMatch secondBestGuess, List<ImageSplitterItem> list, int listIndex)
        {
            secondBestGuess = null;
            int index = 0;
            int smallestDifference = 10000;
            int smallestIndex = -1;
            NikseBitmap target = targetItem.NikseBitmap;
            if (_compareBitmaps == null)
            {
                return null;
            }

            foreach (CompareItem compareItem in _compareBitmaps)
            {
                // check for expand match!
                if (compareItem.ExpandCount > 0 && compareItem.Bitmap.Width > target.Width &&
                    parentBitmap.Width >= compareItem.Bitmap.Width + targetItem.X) // &&   parentBitmap.Height >= compareItem.Bitmap.Height + targetItem.Y) //NIXE-debug-test- what not correct?
                {
                    int minY = targetItem.Y;
                    for (int j = 1; j < compareItem.ExpandCount; j++)
                    {
                        if (list != null && list.Count > listIndex + j && list[listIndex + j].Y < minY)
                            minY = list[listIndex + j].Y;
                    }
                    if (parentBitmap.Height >= compareItem.Bitmap.Height + minY)
                    {
                        var cutBitmap = parentBitmap.CopyRectangle(new Rectangle(targetItem.X, minY, compareItem.Bitmap.Width, compareItem.Bitmap.Height));
                        int dif = NikseBitmapImageSplitter.IsBitmapsAlike(compareItem.Bitmap, cutBitmap);
                        if (dif < smallestDifference && (Math.Abs(target.Height - compareItem.Bitmap.Height) <= 5 || compareItem.Text != "\""))
                        {
                            smallestDifference = dif;
                            smallestIndex = index;
                            if (dif == 0)
                                break; // foreach ending
                        }
                    }
                }
                index++;
            }

            // Search images with minor location changes
            FindBestMatch(ref index, ref smallestDifference, ref smallestIndex, target, _compareBitmaps);

            if (smallestDifference * 100.0 / (target.Width * target.Height) > _vobSubOcrSettings.AllowDifferenceInPercent && target.Width < 70)
            {
                if (smallestDifference > 2 && target.Width > 25)
                {
                    var cutBitmap = target.CopyRectangle(new Rectangle(4, 0, target.Width - 4, target.Height));
                    FindBestMatch(ref index, ref smallestDifference, ref smallestIndex, cutBitmap, _compareBitmaps);
                }

                if (smallestDifference > 2 && target.Width > 12)
                {
                    var cutBitmap = target.CopyRectangle(new Rectangle(1, 0, target.Width - 2, target.Height));
                    FindBestMatch(ref index, ref smallestDifference, ref smallestIndex, cutBitmap, _compareBitmaps);
                }

                if (smallestDifference > 2 && target.Width > 12)
                {
                    var cutBitmap = target.CopyRectangle(new Rectangle(0, 0, target.Width - 2, target.Height));
                    FindBestMatch(ref index, ref smallestDifference, ref smallestIndex, cutBitmap, _compareBitmaps);
                }

                if (smallestDifference > 2 && target.Width > 12)
                {
                    var cutBitmap = target.CopyRectangle(new Rectangle(1, 0, target.Width - 2, target.Height));
                    int topCrop = 0;
                    var cutBitmap2 = NikseBitmapImageSplitter.CropTopAndBottom(cutBitmap, out topCrop, 2);
                    if (cutBitmap2.Height != target.Height)
                        FindBestMatch(ref index, ref smallestDifference, ref smallestIndex, cutBitmap2, _compareBitmaps);
                }

                if (smallestDifference > 2 && target.Width > 15)
                {
                    var cutBitmap = target.CopyRectangle(new Rectangle(1, 0, target.Width - 2, target.Height));
                    int topCrop = 0;
                    var cutBitmap2 = NikseBitmapImageSplitter.CropTopAndBottom(cutBitmap, out topCrop);
                    if (cutBitmap2.Height != target.Height)
                        FindBestMatch(ref index, ref smallestDifference, ref smallestIndex, cutBitmap2, _compareBitmaps);
                }

                if (smallestDifference > 2 && target.Width > 15)
                {
                    var cutBitmap = target.CopyRectangle(new Rectangle(1, 0, target.Width - 2, target.Height));
                    int topCrop;
                    var cutBitmap2 = NikseBitmapImageSplitter.CropTopAndBottom(cutBitmap, out topCrop);
                    if (cutBitmap2.Height != target.Height)
                        FindBestMatch(ref index, ref smallestDifference, ref smallestIndex, cutBitmap2, _compareBitmaps);
                }
            }

            if (smallestIndex >= 0)
            {
                double differencePercentage = smallestDifference * 100.0 / (target.Width * target.Height);
                double maxDiff = (double)numericUpDownMaxErrorPct.Value;
                if (differencePercentage <= maxDiff)
                {
                    var hit = _compareBitmaps[smallestIndex];
                    return new CompareMatch(hit.Text, hit.Italic, hit.ExpandCount, hit.Name);
                }

                var guess = _compareBitmaps[smallestIndex];
                secondBestGuess = new CompareMatch(guess.Text, guess.Italic, guess.ExpandCount, guess.Name);
            }

            return null;
        }
Example #4
0
        private static void ImageCompareThreadDoWork(object sender, DoWorkEventArgs e)
        {
            var p = (ImageCompareThreadParameter)e.Argument;
            e.Result = p;
            Bitmap bitmap = p.Picture;
            var matches = new List<CompareMatch>();
            List<ImageSplitterItem> lines = NikseBitmapImageSplitter.SplitVertical(bitmap);
            List<ImageSplitterItem> list = NikseBitmapImageSplitter.SplitBitmapToLetters(lines, p.NumberOfPixelsIsSpace, p.RightToLeft, Configuration.Settings.VobSubOcr.TopToBottom);

            int outerIndex = 0;
            while (outerIndex < list.Count)
            {
                ImageSplitterItem item = list[outerIndex];
                if (item.NikseBitmap == null)
                {
                    matches.Add(new CompareMatch(item.SpecialCharacter, false, 0, null));
                }
                else
                {
                    var target = item.NikseBitmap;
                    int numberOfForegroundColors = CalculateNumberOfForegroundColors(target);

                    int smallestDifference = 10000;
                    int smallestIndex = -1;

                    int index;
                    if (smallestDifference > 0)
                    {
                        index = 0;
                        foreach (CompareItem compareItem in p.CompareBitmaps)
                        {
                            if (compareItem.Bitmap.Width == target.Width && compareItem.Bitmap.Height == target.Height)
                            {
                                if (compareItem.NumberOfForegroundColors < 1)
                                    compareItem.NumberOfForegroundColors = CalculateNumberOfForegroundColors(compareItem.Bitmap);

                                if (Math.Abs(compareItem.NumberOfForegroundColors - numberOfForegroundColors) < 30)
                                {
                                    int dif = NikseBitmapImageSplitter.IsBitmapsAlike(compareItem.Bitmap, target);
                                    if (dif < smallestDifference)
                                    {
                                        smallestDifference = dif;
                                        smallestIndex = index;
                                        if (dif < 0.2)
                                            break; // foreach ending
                                    }
                                }
                            }
                            index++;
                        }
                    }

                    if (smallestDifference > 1 && target.Width < 55 && target.Width > 5)
                    {
                        index = 0;
                        foreach (CompareItem compareItem in p.CompareBitmaps)
                        {
                            if (compareItem.Bitmap.Width == target.Width && compareItem.Bitmap.Height == target.Height + 1)
                            {
                                if (compareItem.NumberOfForegroundColors == -1)
                                    compareItem.NumberOfForegroundColors = CalculateNumberOfForegroundColors(compareItem.Bitmap);

                                if (Math.Abs(compareItem.NumberOfForegroundColors - numberOfForegroundColors) < 50)
                                {
                                    int dif = NikseBitmapImageSplitter.IsBitmapsAlike(target, compareItem.Bitmap);
                                    if (dif < smallestDifference)
                                    {
                                        smallestDifference = dif;
                                        smallestIndex = index;
                                        if (dif < 0.5)
                                            break; // foreach ending
                                    }
                                }
                            }
                            index++;
                        }
                    }

                    if (smallestDifference > 1 && target.Width < 55 && target.Width > 5)
                    {
                        index = 0;
                        foreach (CompareItem compareItem in p.CompareBitmaps)
                        {
                            if (compareItem.Bitmap.Width == target.Width - 1 && compareItem.Bitmap.Height == target.Height ||
                                compareItem.Bitmap.Width == target.Width - 1 && compareItem.Bitmap.Height == target.Height - 1 ||
                                compareItem.Bitmap.Width == target.Width && compareItem.Bitmap.Height == target.Height - 1)
                            {
                                if (compareItem.NumberOfForegroundColors < 1)
                                    compareItem.NumberOfForegroundColors = CalculateNumberOfForegroundColors(compareItem.Bitmap);

                                if (Math.Abs(compareItem.NumberOfForegroundColors - numberOfForegroundColors) < 55)
                                {
                                    int dif = NikseBitmapImageSplitter.IsBitmapsAlike(compareItem.Bitmap, target);
                                    if (dif < smallestDifference)
                                    {
                                        smallestDifference = dif;
                                        smallestIndex = index;
                                        if (dif < 0.5)
                                            break; // foreach ending
                                    }
                                }
                            }
                            index++;
                        }
                    }

                    double differencePercentage = smallestDifference * 100.0 / (item.NikseBitmap.Width * item.NikseBitmap.Height);
                    double maxDiff = p.MaxErrorPercent;
                    if (differencePercentage <= maxDiff && smallestIndex >= 0)
                    {
                        var hit = p.CompareBitmaps[smallestIndex];
                        var match = new CompareMatch(hit.Text, hit.Italic, hit.ExpandCount, hit.Name);
                        matches.Add(new CompareMatch(match.Text, match.Italic, 0, null));
                        if (match.ExpandCount > 0)
                            outerIndex += match.ExpandCount - 1;
                    }
                    else
                    {
                        p.Result = string.Empty;
                        return;
                    }
                }
                outerIndex++;
            }
            bitmap.Dispose();
            p.Result = GetStringWithItalicTags(matches);
        }
Example #5
0
        private CompareMatch GetCompareMatchNew(ImageSplitterItem targetItem, NikseBitmap parentBitmap, out CompareMatch secondBestGuess, List<ImageSplitterItem> list, int listIndex)
        {
            double maxDiff = (double)numericUpDownMaxErrorPct.Value;
            secondBestGuess = null;
            int index = 0;
            int smallestDifference = 10000;
            int smallestIndex = -1;
            NikseBitmap target = targetItem.NikseBitmap;
            if (_binaryOcrDb == null)
            {
                secondBestGuess = null;
                return null;
            }

            var bob = new BinaryOcrBitmap(target);

            for (int k = 0; k < _binaryOcrDb.CompareImagesExpanded.Count; k++)
            {
                var b = _binaryOcrDb.CompareImagesExpanded[k];
                if (bob.Hash == b.Hash && bob.Width == b.Width && bob.Height == b.Height && bob.NumberOfColoredPixels == b.NumberOfColoredPixels)
                {
                    bool ok = false;
                    for (int i = 0; i < b.ExpandedList.Count; i++)
                    {
                        if (listIndex + i + 1 < list.Count && list[listIndex + i + 1].NikseBitmap != null && b.ExpandedList[i].Hash == new BinaryOcrBitmap(list[listIndex + i + 1].NikseBitmap).Hash)
                        {
                            ok = true;
                        }
                        else
                        {
                            ok = false;
                            break;
                        }
                    }
                    if (ok)
                    {
                        secondBestGuess = null;
                        return new CompareMatch(b.Text, b.Italic, b.ExpandCount, b.Key);
                    }
                }
            }

            FindBestMatchNew(ref index, ref smallestDifference, ref smallestIndex, target, _binaryOcrDb, bob, maxDiff);

            if (smallestIndex >= 0)
            {
                double differencePercentage = smallestDifference * 100.0 / (target.Width * target.Height);
                if (differencePercentage <= maxDiff)
                {
                    var hit = _binaryOcrDb.CompareImages[smallestIndex];

                    string text = hit.Text;
                    if (smallestDifference > 0)
                    {
                        int h = hit.Height;
                        if (text == "V" || text == "W" || text == "U" || text == "S" || text == "Z" || text == "O" || text == "X" || text == "Ø" || text == "C")
                        {
                            if (_binOcrLastLowercaseHeight > 3 && h - _binOcrLastLowercaseHeight < 2)
                                text = text.ToLower();
                        }
                        else if (text == "v" || text == "w" || text == "u" || text == "s" || text == "z" || text == "o" || text == "x" || text == "ø" || text == "c")
                        {
                            if (_binOcrLastUppercaseHeight > 3 && _binOcrLastUppercaseHeight - h < 2)
                                text = text.ToUpper();
                        }
                    }
                    else
                    {
                        SetBinOcrLowercaseUppercase(hit.Height, text);
                    }

                    return new CompareMatch(text, hit.Italic, hit.ExpandCount, hit.Key);
                }

                var guess = _binaryOcrDb.CompareImages[smallestIndex];
                secondBestGuess = new CompareMatch(guess.Text, guess.Italic, guess.ExpandCount, guess.Key);
            }

            return null;
        }
Example #6
0
        private CompareMatch GetCompareMatchNew(ImageSplitterItem targetItem, NikseBitmap parentBitmap, out CompareMatch secondBestGuess, List<ImageSplitterItem> list, int listIndex)
        {
            double maxDiff = (double)numericUpDownMaxErrorPct.Value;
            secondBestGuess = null;
            int index = 0;
            int smallestDifference = 10000;
            int smallestIndex = -1;
            NikseBitmap target = targetItem.NikseBitmap;
            if (_binaryOcrDb == null)
            {
                secondBestGuess = null;
                return null;
            }

            foreach (BinaryOcrBitmap compareItem in _binaryOcrDb.CompareImages)
            {
                // check for expand match!
                if (compareItem.ExpandCount > 0 && compareItem.Width > target.Width &&
                    parentBitmap.Width >= compareItem.Width + targetItem.X) // &&   parentBitmap.Height >= compareItem.Bitmap.Height + targetItem.Y) //NIXE-debug-test- what not correct?
                {
                    int minY = targetItem.Y;
                    for (int j = 1; j < compareItem.ExpandCount; j++)
                    {
                        if (list != null && list.Count > listIndex + j && list[listIndex + j].Y < minY)
                            minY = list[listIndex + j].Y;
                    }
                    if (parentBitmap.Height >= compareItem.Height + minY)
                    {
                        var cutBitmap = parentBitmap.CopyRectangle(new Rectangle(targetItem.X, minY, compareItem.Width, compareItem.Height));
                        int dif = NikseBitmapImageSplitter.IsBitmapsAlike(compareItem, cutBitmap);
                        if (dif < smallestDifference)
                        {
                            bool allow = true;
                            if (Math.Abs(target.Height - compareItem.Height) > 5 && compareItem.Text == "\"")
                                allow = false;
                            if (allow)
                            {
                                smallestDifference = dif;
                                smallestIndex = index;
                                if (dif == 0)
                                    break; // foreach ending
                            }
                        }
                    }
                }
                index++;
            }

            // Search images with minor location changes
            FindBestMatchNew(ref index, ref smallestDifference, ref smallestIndex, target, _binaryOcrDb);
            if (maxDiff > 0)
            {
                if (smallestDifference * 100.0 / (target.Width * target.Height) > _vobSubOcrSettings.AllowDifferenceInPercent && target.Width < 70)
                {
                    if (smallestDifference > 2 && target.Width > 25)
                    {
                        var cutBitmap = target.CopyRectangle(new Rectangle(4, 0, target.Width - 4, target.Height));
                        FindBestMatchNew(ref index, ref smallestDifference, ref smallestIndex, cutBitmap, _binaryOcrDb);
                        double differencePercentage = smallestDifference * 100.0 / (target.Width * target.Height);
                    }

                    if (smallestDifference > 2 && target.Width > 12)
                    {
                        var cutBitmap = target.CopyRectangle(new Rectangle(1, 0, target.Width - 2, target.Height));
                        FindBestMatchNew(ref index, ref smallestDifference, ref smallestIndex, cutBitmap, _binaryOcrDb);
                    }

                    if (smallestDifference > 2 && target.Width > 12)
                    {
                        var cutBitmap = target.CopyRectangle(new Rectangle(0, 0, target.Width - 2, target.Height));
                        FindBestMatchNew(ref index, ref smallestDifference, ref smallestIndex, cutBitmap, _binaryOcrDb);
                    }

                    if (smallestDifference > 2 && target.Width > 12)
                    {
                        var cutBitmap = target.CopyRectangle(new Rectangle(1, 0, target.Width - 2, target.Height));
                        int topCrop = 0;
                        var cutBitmap2 = NikseBitmapImageSplitter.CropTopAndBottom(cutBitmap, out topCrop, 2);
                        if (cutBitmap2.Height != target.Height)
                            FindBestMatchNew(ref index, ref smallestDifference, ref smallestIndex, cutBitmap2, _binaryOcrDb);
                    }

                    if (smallestDifference > 2 && target.Width > 15)
                    {
                        var cutBitmap = target.CopyRectangle(new Rectangle(1, 0, target.Width - 2, target.Height));
                        int topCrop = 0;
                        var cutBitmap2 = NikseBitmapImageSplitter.CropTopAndBottom(cutBitmap, out topCrop);
                        if (cutBitmap2.Height != target.Height)
                            FindBestMatchNew(ref index, ref smallestDifference, ref smallestIndex, cutBitmap2, _binaryOcrDb);
                    }

                    if (smallestDifference > 2 && target.Width > 15)
                    {
                        var cutBitmap = target.CopyRectangle(new Rectangle(1, 0, target.Width - 2, target.Height));
                        int topCrop = 0;
                        var cutBitmap2 = NikseBitmapImageSplitter.CropTopAndBottom(cutBitmap, out topCrop);
                        if (cutBitmap2.Height != target.Height)
                            FindBestMatchNew(ref index, ref smallestDifference, ref smallestIndex, cutBitmap2, _binaryOcrDb);
                    }
                }
            }

            if (smallestIndex >= 0)
            {
                double differencePercentage = smallestDifference * 100.0 / (target.Width * target.Height);
                if (differencePercentage <= maxDiff)
                {
                    var hit = _binaryOcrDb.CompareImages[smallestIndex];

                    string text = hit.Text;
                    int h = hit.Height;
                    if (text == "V" || text == "W" || text == "U" || text == "S" || text == "Z" || text == "O" || text == "X" || text == "Ø" || text == "C")
                    {
                        if (_binOcrLastLowercaseHeight > 3 && h - _nocrLastLowercaseHeight < 2)
                            text = text.ToLower();
                    }
                    else if (text == "v" || text == "w" || text == "u" || text == "s" || text == "z" || text == "o" || text == "x" || text == "ø" || text == "c")
                    {
                        if (_binOcrLastUppercaseHeight > 3 && _binOcrLastUppercaseHeight - h < 2)
                            text = text.ToUpper();
                    }
                    hit.Text = text;

                    if (smallestDifference < 0.1)
                        SetBinOcrLowercaseUppercase(hit.Height, hit.Text);

                    return new CompareMatch(hit.Text, hit.Italic, hit.ExpandCount, hit.Text + "_" + hit.Hash.ToString());
                }

                var guess = _binaryOcrDb.CompareImages[smallestIndex];
                secondBestGuess = new CompareMatch(guess.Text, guess.Italic, guess.ExpandCount, guess.Text + "_" + guess.Hash.ToString());
            }

            return null;
        }