/// <summary>
 /// Initializes a new instance of the <see cref="ImageSplitterItem"/> class.
 /// </summary>
 /// <param name="x">
 /// The x.
 /// </param>
 /// <param name="y">
 /// The y.
 /// </param>
 /// <param name="bitmap">
 /// The bitmap.
 /// </param>
 public ImageSplitterItem(int x, int y, NikseBitmap bitmap)
 {
     this.X = x;
     this.Y = y;
     this.NikseBitmap = bitmap;
     this.SpecialCharacter = null;
 }
Пример #2
0
        private byte[] GetSubImageBuffer(RunLengthTwoParts twoPartBuffer, NikseBitmap nbmp, Paragraph p, ContentAlignment alignment)
        {
            var ms = new MemoryStream();

            // sup picture datasize
            WriteEndianWord(twoPartBuffer.Length + 34, ms);

            // first display control sequence table address
            int startDisplayControlSequenceTableAddress = twoPartBuffer.Length + 4;
            WriteEndianWord(startDisplayControlSequenceTableAddress, ms);

            // Write image
            const int imageTopFieldDataAddress = 4;
            ms.Write(twoPartBuffer.Buffer1, 0, twoPartBuffer.Buffer1.Length);
            int imageBottomFieldDataAddress = 4 + twoPartBuffer.Buffer1.Length;
            ms.Write(twoPartBuffer.Buffer2, 0, twoPartBuffer.Buffer2.Length);

            // Write zero delay
            ms.WriteByte(0);
            ms.WriteByte(0);

            // next display control sequence table address (use current is last)
            WriteEndianWord(startDisplayControlSequenceTableAddress + 24, ms); // start of display control sequence table address

            // Control command start
            if (p.Forced)
                ms.WriteByte(0); // ForcedStartDisplay==0
            else
                ms.WriteByte(1); // StartDisplay==1

            // Control command 3 = SetColor
            WriteColors(ms); // 3 bytes

            // Control command 4 = SetContrast
            WriteContrast(ms); // 3 bytes

            // Control command 5 = SetDisplayArea
            WriteDisplayArea(ms, nbmp, alignment); // 7 bytes

            // Control command 6 = SetPixelDataAddress
            WritePixelDataAddress(ms, imageTopFieldDataAddress, imageBottomFieldDataAddress); // 5 bytes

            // Control command exit
            ms.WriteByte(255); // 1 byte

            // Control Sequence Table
            // Write delay - subtitle duration
            WriteEndianWord(Convert.ToInt32(p.Duration.TotalMilliseconds * 90.0 - 1023) >> 10, ms);

            // next display control sequence table address (use current is last)
            WriteEndianWord(startDisplayControlSequenceTableAddress + 24, ms); // start of display control sequence table address

            // Control command 2 = StopDisplay
            ms.WriteByte(2);

            // extra byte - for compatability with gpac/MP4BOX
            ms.WriteByte(255); // 1 byte

            return ms.ToArray();
        }
Пример #3
0
 public ImageSplitterItem(int x, int y, NikseBitmap bitmap)
 {
     X = x;
     Y = y;
     NikseBitmap = bitmap;
     SpecialCharacter = null;
 }
Пример #4
0
 public BinaryOcrBitmap(NikseBitmap nbmp, bool italic, int expandCount, string text)
 {
     InitializeViaNikseBmp(nbmp);
     Italic = italic;
     ExpandCount = expandCount;
     Text = text;
 }
 public BinaryOcrBitmap(NikseBitmap nbmp, bool italic, int expandCount, string text, int x, int y)
 {
     this.InitializeViaNikseBmp(nbmp);
     this.Italic = italic;
     this.ExpandCount = expandCount;
     this.Text = text;
     this.X = x;
     this.Y = y;
 }
        public static NikseBitmap CropTopAndBottom(NikseBitmap bmp, out int topCropping, int maxDifferentPixelsOnLine)
        {
            int startTop = 0;
            int maxTop = bmp.Height - 2;
            if (maxTop > bmp.Height)
                maxTop = bmp.Height;

            for (int y = 0; y < maxTop; y++)
            {
                int difference = 0;
                bool allTransparent = true;
                for (int x = 1; x < bmp.Width - 1; x++)
                {
                    int a = bmp.GetAlpha(x, y);
                    if (a != 0)
                    {
                        difference++;
                        if (difference >= maxDifferentPixelsOnLine)
                        {
                            allTransparent = false;
                            break;
                        }
                    }
                }
                if (!allTransparent)
                    break;
                startTop++;
            }
            if (startTop > 9)
                startTop -= 5; // if top space > 9, then allways leave blank 5 pixels on top (so . is not confused with ').
            topCropping = startTop;

            for (int y = bmp.Height - 1; y > 3; y--)
            {
                int difference = 0;
                bool allTransparent = true;
                for (int x = 1; x < bmp.Width - 1; x++)
                {
                    int a = bmp.GetAlpha(x, y);
                    if (a != 0)
                    {
                        difference++;
                        if (difference >= maxDifferentPixelsOnLine)
                        {
                            allTransparent = false;
                            break;
                        }
                    }
                }
                if (allTransparent == false)
                    return bmp.CopyRectangle(new Rectangle(0, startTop, bmp.Width - 1, y - startTop + 1));
            }
            return bmp;
        }
        internal void Initialize(Bitmap vobSubImage, ImageSplitterItem character, Point position, bool italicChecked, bool showShrink)
        {
            listBoxLinesForeground.Items.Clear();
            listBoxlinesBackground.Items.Clear();
            NikseBitmap nbmp = new NikseBitmap(vobSubImage);
            nbmp.ReplaceTransparentWith(Color.Black);
            vobSubImage = nbmp.GetBitmap();

            radioButtonHot.Checked = true;
            ShrinkSelection = false;
            ExpandSelection = false;

            textBoxCharacters.Text = string.Empty;
            _nocrChar = new NOcrChar();
            _nocrChar.MarginTop = character.Y - character.ParentY;
            _imageWidth = character.NikseBitmap.Width;
            _imageHeight = character.NikseBitmap.Height;
            _drawLineOn = false;
            _warningNoNotForegroundLinesShown = false;

            buttonShrinkSelection.Visible = showShrink;

            if (position.X != -1 && position.Y != -1)
            {
                StartPosition = FormStartPosition.Manual;
                Left = position.X;
                Top = position.Y;
            }

            pictureBoxSubtitleImage.Image = vobSubImage;
            pictureBoxCharacter.Image = character.NikseBitmap.GetBitmap();

            Bitmap org = (Bitmap)vobSubImage.Clone();
            Bitmap bm = new Bitmap(org.Width, org.Height);
            Graphics g = Graphics.FromImage(bm);
            g.DrawImage(org, 0, 0, org.Width, org.Height);
            g.DrawRectangle(Pens.Red, character.X, character.Y, character.NikseBitmap.Width, character.NikseBitmap.Height - 1);
            g.Dispose();
            pictureBoxSubtitleImage.Image = bm;

            pictureBoxCharacter.Top = labelCharacters.Top + 16;
            SizePictureBox();
            checkBoxItalic.Checked = italicChecked;

            _history = new List<NOcrChar>();
            _historyIndex = -1;

            _nocrChar.Width = _imageWidth;
            _nocrChar.Height = _imageHeight;
            GenerateLineSegments(150, false, _nocrChar, new NikseBitmap(pictureBoxCharacter.Image as Bitmap));
            ShowOcrPoints();
            pictureBoxCharacter.Invalidate();
        }
        internal void Initialize(Bitmap bitmap, int pixelsIsSpace, bool rightToLeft, NOcrDb nOcrDb, VobSubOcr vobSubOcr)
        {
            _bitmap = bitmap;
            var nbmp = new NikseBitmap(bitmap);
            nbmp.ReplaceNonWhiteWithTransparent();
            bitmap = nbmp.GetBitmap();
            _bitmap2 = bitmap;
            _nocrChars = nOcrDb.OcrCharacters;
            _matchList = new List<VobSubOcr.CompareMatch>();
            _vobSubOcr = vobSubOcr;

            const int minLineHeight = 6;
            _imageList = NikseBitmapImageSplitter.SplitBitmapToLettersNew(nbmp, pixelsIsSpace, rightToLeft, Configuration.Settings.VobSubOcr.TopToBottom, minLineHeight);
            // _imageList = NikseBitmapImageSplitter.SplitBitmapToLetters(nbmp, pixelsIsSpace, rightToLeft, Configuration.Settings.VobSubOcr.TopToBottom);

            int index = 0;
            while (index < _imageList.Count)
            {
                ImageSplitterItem item = _imageList[index];
                if (item.NikseBitmap == null)
                {
                    listBoxInspectItems.Items.Add(item.SpecialCharacter);
                    _matchList.Add(null);
                }
                else
                {
                    nbmp = item.NikseBitmap;
                    nbmp.ReplaceNonWhiteWithTransparent();
                    item.Y += nbmp.CropTopTransparent(0);
                    nbmp.CropTransparentSidesAndBottom(0, true);
                    nbmp.ReplaceTransparentWith(Color.Black);

                    //get nocr matches
                    var match = vobSubOcr.GetNOcrCompareMatchNew(item, nbmp, nOcrDb, false, false);
                    if (match == null)
                    {
                        listBoxInspectItems.Items.Add("?");
                        _matchList.Add(null);
                    }
                    else
                    {
                        listBoxInspectItems.Items.Add(match.Text);
                        _matchList.Add(match);
                    }
                }
                index++;
            }
        }
        public static NikseBitmap CropTopAndBottom(NikseBitmap bmp, out int topCropping)
        {
            int startTop = 0;
            int maxTop = bmp.Height - 2;
            if (maxTop > bmp.Height)
                maxTop = bmp.Height;
            for (int y = 0; y < maxTop; y++)
            {
                bool allTransparent = true;
                for (int x = 0; x < bmp.Width; x++)
                {
                    int a = bmp.GetAlpha(x, y);
                    if (a != 0)
                    {
                        allTransparent = false;
                        break;
                    }
                }
                if (!allTransparent)
                    break;
                startTop++;
            }
            //if (startTop > 9)
            //startTop -= 5; // if top space > 9, then allways leave blank 5 pixels on top (so . is not confused with ').
            topCropping = startTop;

            int h = bmp.Height;
            bool bottomCroppingDone = false;
            for (int y = bmp.Height - 1; y > 3; y--)
            {
                for (int x = 0; x < bmp.Width; x++)
                {
                    int a = bmp.GetAlpha(x, y);
                    if (a != 0)
                    {
                        bottomCroppingDone = true;
                        break;
                    }
                }
                h = y;
                if (bottomCroppingDone)
                    break;
            }
            if (h - startTop + 1 <= 0)
                return new NikseBitmap(0, 0);
            return bmp.CopyRectangle(new Rectangle(0, startTop, bmp.Width, h - startTop + 1));
        }
Пример #10
0
        private string SaveCompareItem(NikseBitmap newTarget, string text, bool isItalic, int expandCount)
        {
            string path = Configuration.VobSubCompareFolder + comboBoxCharacterDatabase.SelectedItem + Path.DirectorySeparatorChar;
            string databaseName = path + "Images.db";
            FileStream f;
            long pos;
            if (!File.Exists(databaseName))
            {
                if (!Directory.Exists(Configuration.OcrFolder))
                {
                    Directory.CreateDirectory(Configuration.OcrFolder);
                }

                using (f = new FileStream(databaseName, FileMode.Create))
                {
                    pos = f.Position;
                    new ManagedBitmap(newTarget).AppendToStream(f);
                }
            }
            else
            {
                using (f = new FileStream(databaseName, FileMode.Append))
                {
                    pos = f.Position;
                    new ManagedBitmap(newTarget).AppendToStream(f);
                }
            }
            string name = pos.ToString(CultureInfo.InvariantCulture);

            if (_compareDoc == null)
            {
                _compareDoc = new XmlDocument();
                _compareDoc.LoadXml("<OcrBitmaps></OcrBitmaps>");
            }
            if (_compareBitmaps == null)
                _compareBitmaps = new List<CompareItem>();
            _compareBitmaps.Add(new CompareItem(new ManagedBitmap(newTarget), name, isItalic, expandCount, text));

            XmlElement element = _compareDoc.CreateElement("Item");
            XmlAttribute attribute = _compareDoc.CreateAttribute("Text");
            attribute.InnerText = text;
            element.Attributes.Append(attribute);
            if (expandCount > 0)
            {
                XmlAttribute expandSelection = _compareDoc.CreateAttribute("Expand");
                expandSelection.InnerText = expandCount.ToString(CultureInfo.InvariantCulture);
                element.Attributes.Append(expandSelection);
            }
            if (isItalic)
            {
                XmlAttribute italic = _compareDoc.CreateAttribute("Italic");
                italic.InnerText = "true";
                element.Attributes.Append(italic);
            }
            element.InnerText = pos.ToString(CultureInfo.InvariantCulture);
            _compareDoc.DocumentElement.AppendChild(element);
            _compareDoc.Save(path + "Images.xml");
            return name;
        }
Пример #11
0
        private string OcrViaNOCR(Bitmap bitmap, int listViewIndex)
        {
            if (_ocrFixEngine == null)
                comboBoxDictionaries_SelectedIndexChanged(null, null);

            string line = string.Empty;
            if (_nocrThreadResults != null)
                line = _nocrThreadResults[listViewIndex];
            if (string.IsNullOrEmpty(line))
            {
                var nbmpInput = new NikseBitmap(bitmap);

                var matches = new List<CompareMatch>();

                int minLineHeight = _binOcrLastLowercaseHeight - 3;
                if (minLineHeight < 5)
                    minLineHeight = _nocrLastLowercaseHeight - 3;
                if (minLineHeight < 5)
                    minLineHeight = 5;
                List<ImageSplitterItem> list = NikseBitmapImageSplitter.SplitBitmapToLettersNew(nbmpInput, (int)numericUpDownNumberOfPixelsIsSpaceNOCR.Value, checkBoxRightToLeft.Checked, Configuration.Settings.VobSubOcr.TopToBottom, minLineHeight);

                foreach (ImageSplitterItem item in list)
                {
                    if (item.NikseBitmap != null)
                    {
                        item.NikseBitmap.ReplaceTransparentWith(Color.Black);
                    }
                }
                int index = 0;
                bool expandSelection = false;
                bool shrinkSelection = false;
                var expandSelectionList = new List<ImageSplitterItem>();
                while (index < list.Count)
                {
                    ImageSplitterItem item = list[index];
                    if (expandSelection || shrinkSelection)
                    {
                        expandSelection = false;
                        if (shrinkSelection && index > 0)
                        {
                            shrinkSelection = false;
                        }
                        else if (index + 1 < list.Count && list[index + 1].NikseBitmap != null) // only allow expand to EndOfLine or space
                        {
                            index++;
                            expandSelectionList.Add(list[index]);
                        }
                        item = GetExpandedSelection(nbmpInput, expandSelectionList, checkBoxRightToLeft.Checked);
                        if (item.NikseBitmap != null)
                        {
                            item.NikseBitmap.ReplaceTransparentWith(Color.Black);
                        }

                        _vobSubOcrNOcrCharacter.Initialize(bitmap, item, _manualOcrDialogPosition, _italicCheckedLast, expandSelectionList.Count > 1);
                        DialogResult result = _vobSubOcrNOcrCharacter.ShowDialog(this);
                        _manualOcrDialogPosition = _vobSubOcrNOcrCharacter.FormPosition;
                        if (result == DialogResult.OK && _vobSubOcrNOcrCharacter.ShrinkSelection)
                        {
                            shrinkSelection = true;
                            index--;
                            if (expandSelectionList.Count > 0)
                                expandSelectionList.RemoveAt(expandSelectionList.Count - 1);
                        }
                        else if (result == DialogResult.OK && _vobSubOcrNOcrCharacter.ExpandSelection)
                        {
                            expandSelection = true;
                        }
                        else if (result == DialogResult.OK)
                        {
                            var c = _vobSubOcrNOcrCharacter.NOcrChar;
                            if (expandSelectionList.Count > 1)
                                c.ExpandCount = expandSelectionList.Count;
                            _nOcrDb.Add(c);
                            SaveNOcrWithCurrentLanguage();
                            string text = _vobSubOcrNOcrCharacter.NOcrChar.Text;
                            //string name = SaveCompareItem(item.NikseBitmap, text, _vobSubOcrNOcrCharacter.IsItalic, expandSelectionList.Count);
                            //var addition = new ImageCompareAddition(name, text, item.NikseBitmap, _vobSubOcrNOcrCharacter.IsItalic, listViewIndex);
                            //_lastAdditions.Add(addition);
                            matches.Add(new CompareMatch(text, _vobSubOcrNOcrCharacter.IsItalic, expandSelectionList.Count, null));
                            expandSelectionList = new List<ImageSplitterItem>();
                        }
                        else if (result == DialogResult.Abort)
                        {
                            _abort = true;
                        }
                        else
                        {
                            matches.Add(new CompareMatch("*", false, 0, null));
                        }
                        _italicCheckedLast = _vobSubOcrNOcrCharacter.IsItalic;
                    }
                    else if (item.NikseBitmap == null)
                    {
                        matches.Add(new CompareMatch(item.SpecialCharacter, false, 0, null));
                    }
                    else
                    {
                        CompareMatch match = GetNOcrCompareMatchNew(item, nbmpInput, _nOcrDb, checkBoxNOcrItalic.Checked, !checkBoxNOcrCorrect.Checked);
                        if (match == null)
                        {
                            _vobSubOcrNOcrCharacter.Initialize(bitmap, item, _manualOcrDialogPosition, _italicCheckedLast, false);
                            DialogResult result = _vobSubOcrNOcrCharacter.ShowDialog(this);
                            _manualOcrDialogPosition = _vobSubOcrNOcrCharacter.FormPosition;
                            if (result == DialogResult.OK && _vobSubOcrNOcrCharacter.ExpandSelection)
                            {
                                expandSelectionList.Add(item);
                                expandSelection = true;
                            }
                            else if (result == DialogResult.OK)
                            {
                                _nOcrDb.Add(_vobSubOcrNOcrCharacter.NOcrChar);
                                SaveNOcrWithCurrentLanguage();
                                string text = _vobSubOcrNOcrCharacter.NOcrChar.Text;
                                //string name = SaveCompareItem(item.NikseBitmap, text, _vobSubOcrNOcrCharacter.IsItalic, 0);
                                //var addition = new ImageCompareAddition(name, text, item.NikseBitmap, _vobSubOcrNOcrCharacter.IsItalic, listViewIndex);
                                //_lastAdditions.Add(addition);
                                matches.Add(new CompareMatch(text, _vobSubOcrNOcrCharacter.IsItalic, 0, null));
                            }
                            else if (result == DialogResult.Abort)
                            {
                                _abort = true;
                            }
                            else
                            {
                                matches.Add(new CompareMatch("*", false, 0, null));
                            }
                            _italicCheckedLast = _vobSubOcrNOcrCharacter.IsItalic;
                        }
                        else // found image match
                        {
                            matches.Add(new CompareMatch(match.Text, match.Italic, 0, null));
                            if (match.ExpandCount > 0)
                                index += match.ExpandCount - 1;
                        }
                    }
                    if (_abort)
                        return string.Empty;
                    if (!expandSelection && !shrinkSelection)
                        index++;
                    if (shrinkSelection && expandSelectionList.Count < 2)
                    {
                        shrinkSelection = false;
                        expandSelectionList = new List<ImageSplitterItem>();
                    }
                }
                line = GetStringWithItalicTags(matches);
            }

            line = FixNocrHardcodedStuff(line);

            //OCR fix engine
            string textWithOutFixes = line;
            if (_ocrFixEngine.IsDictionaryLoaded)
            {
                if (checkBoxAutoFixCommonErrors.Checked)
                    line = _ocrFixEngine.FixOcrErrors(line, listViewIndex, _lastLine, true, GetAutoGuessLevel());
                int correctWords;
                int wordsNotFound = _ocrFixEngine.CountUnknownWordsViaDictionary(line, out correctWords);

                if (wordsNotFound > 0 || correctWords == 0 || textWithOutFixes != null && string.IsNullOrWhiteSpace(textWithOutFixes.Replace("~", string.Empty)))
                {
                    _ocrFixEngine.AutoGuessesUsed.Clear();
                    _ocrFixEngine.UnknownWordsFound.Clear();
                    line = _ocrFixEngine.FixUnknownWordsViaGuessOrPrompt(out wordsNotFound, line, listViewIndex, bitmap, checkBoxAutoFixCommonErrors.Checked, checkBoxPromptForUnknownWords.Checked, true, GetAutoGuessLevel());
                }

                if (_ocrFixEngine.Abort)
                {
                    ButtonStopClick(null, null);
                    _ocrFixEngine.Abort = false;
                    return string.Empty;
                }

                // Log used word guesses (via word replace list)
                foreach (string guess in _ocrFixEngine.AutoGuessesUsed)
                    listBoxLogSuggestions.Items.Add(guess);
                _ocrFixEngine.AutoGuessesUsed.Clear();

                // Log unkown words guess (found via spelling dictionaries)
                LogUnknownWords();

                ColorLineByNumberOfUnknownWords(listViewIndex, wordsNotFound, line);
            }

            if (textWithOutFixes.Trim() != line.Trim())
            {
                _tesseractOcrAutoFixes++;
                labelFixesMade.Text = string.Format(" - {0}", _tesseractOcrAutoFixes);
                LogOcrFix(listViewIndex, textWithOutFixes, line);
            }

            return line;
        }
Пример #12
0
        public Bitmap GetSubtitleBitmap(int index)
        {
            Bitmap returnBmp = null;
            Color background;
            Color pattern;
            Color emphasis1;
            Color emphasis2;

            if (_mp4List != null)
            {
                if (index >= 0 && index < _mp4List.Count)
                {
                    if (checkBoxCustomFourColors.Checked)
                    {
                        GetCustomColors(out background, out pattern, out emphasis1, out emphasis2);

                        returnBmp = _mp4List[index].Picture.GetBitmap(null, background, pattern, emphasis1, emphasis2, true);
                        if (checkBoxAutoTransparentBackground.Checked)
                            returnBmp.MakeTransparent();
                    }
                    else
                    {
                        returnBmp = _mp4List[index].Picture.GetBitmap(null, Color.Transparent, Color.Black, Color.White, Color.Black, false);
                        if (checkBoxAutoTransparentBackground.Checked)
                            returnBmp.MakeTransparent();
                    }
                }
            }
            else if (_spList != null)
            {
                if (index >= 0 && index < _spList.Count)
                {
                    if (checkBoxCustomFourColors.Checked)
                    {
                        GetCustomColors(out background, out pattern, out emphasis1, out emphasis2);

                        returnBmp = _spList[index].Picture.GetBitmap(null, background, pattern, emphasis1, emphasis2, true);
                        if (checkBoxAutoTransparentBackground.Checked)
                            returnBmp.MakeTransparent();
                    }
                    else
                    {
                        returnBmp = _spList[index].Picture.GetBitmap(null, Color.Transparent, Color.Black, Color.White, Color.Black, false);
                        if (checkBoxAutoTransparentBackground.Checked)
                            returnBmp.MakeTransparent();
                    }
                }
            }
            else if (_bdnXmlSubtitle != null)
            {
                if (index >= 0 && index < _bdnXmlSubtitle.Paragraphs.Count)
                {
                    var fileNames = _bdnXmlSubtitle.Paragraphs[index].Text.SplitToLines();
                    var bitmaps = new List<Bitmap>();
                    int maxWidth = 0;
                    int totalHeight = 0;

                    foreach (string fn in fileNames)
                    {
                        string fullFileName = Path.Combine(Path.GetDirectoryName(_bdnFileName), fn);
                        if (!File.Exists(fullFileName))
                        {
                            // fix AVISubDetector lines
                            int idxOfIEquals = fn.IndexOf("i=", StringComparison.OrdinalIgnoreCase);
                            if (idxOfIEquals >= 0)
                            {
                                int idxOfSpace = fn.IndexOf(' ', idxOfIEquals);
                                if (idxOfSpace > 0)
                                {
                                    fullFileName = Path.Combine(Path.GetDirectoryName(_bdnFileName), fn.Remove(0, idxOfSpace).Trim());
                                }
                            }
                        }
                        if (File.Exists(fullFileName))
                        {
                            try
                            {
                                var temp = new Bitmap(fullFileName);
                                if (temp.Width > maxWidth)
                                    maxWidth = temp.Width;
                                totalHeight += temp.Height;
                                bitmaps.Add(temp);
                            }
                            catch
                            {
                                return null;
                            }
                        }
                    }

                    Bitmap b = null;
                    if (bitmaps.Count > 1)
                    {
                        var merged = new Bitmap(maxWidth, totalHeight + 7 * bitmaps.Count);
                        int y = 0;
                        for (int k = 0; k < bitmaps.Count; k++)
                        {
                            Bitmap part = bitmaps[k];
                            if (checkBoxAutoTransparentBackground.Checked)
                                part.MakeTransparent();
                            using (var g = Graphics.FromImage(merged))
                                g.DrawImage(part, 0, y);
                            y += part.Height + 7;
                            part.Dispose();
                        }
                        b = merged;
                    }
                    else if (bitmaps.Count == 1)
                    {
                        b = bitmaps[0];
                    }

                    if (b != null)
                    {
                        if (_isSon && checkBoxCustomFourColors.Checked)
                        {
                            GetCustomColors(out background, out pattern, out emphasis1, out emphasis2);

                            FastBitmap fbmp = new FastBitmap(b);
                            fbmp.LockImage();
                            for (int x = 0; x < fbmp.Width; x++)
                            {
                                for (int y = 0; y < fbmp.Height; y++)
                                {
                                    Color c = fbmp.GetPixel(x, y);
                                    if (c.R == Color.Red.R && c.G == Color.Red.G && c.B == Color.Red.B) // normally anti-alias
                                        fbmp.SetPixel(x, y, emphasis2);
                                    else if (c.R == Color.Blue.R && c.G == Color.Blue.G && c.B == Color.Blue.B) // normally text?
                                        fbmp.SetPixel(x, y, pattern);
                                    else if (c.R == Color.White.R && c.G == Color.White.G && c.B == Color.White.B) // normally background
                                        fbmp.SetPixel(x, y, background);
                                    else if (c.R == Color.Black.R && c.G == Color.Black.G && c.B == Color.Black.B) // outline/border
                                        fbmp.SetPixel(x, y, emphasis1);
                                    else
                                        fbmp.SetPixel(x, y, c);
                                }
                            }
                            fbmp.UnlockImage();
                        }
                        if (checkBoxAutoTransparentBackground.Checked)
                            b.MakeTransparent();
                        returnBmp = b;
                    }
                }
            }
            else if (_xSubList != null)
            {
                if (index >= 0 && index < _xSubList.Count)
                {
                    if (checkBoxCustomFourColors.Checked)
                    {
                        GetCustomColors(out background, out pattern, out emphasis1, out emphasis2);
                        returnBmp = _xSubList[index].GetImage(background, pattern, emphasis1, emphasis2);
                    }
                    else
                    {
                        returnBmp = _xSubList[index].GetImage();
                    }
                }
            }
            else if (_dvbSubtitles != null)
            {
                if (index >= 0 && index < _dvbSubtitles.Count)
                {
                    var dvbBmp = _dvbSubtitles[index].GetActiveImage();
                    var nDvbBmp = new NikseBitmap(dvbBmp);
                    nDvbBmp.CropTopTransparent(2);
                    nDvbBmp.CropTransparentSidesAndBottom(2, true);
                    if (checkBoxTransportStreamGetColorAndSplit.Checked)
                        _dvbSubColor = nDvbBmp.GetBrightestColorWhiteIsTransparent();
                    if (checkBoxAutoTransparentBackground.Checked)
                        nDvbBmp.MakeBackgroundTransparent((int)numericUpDownAutoTransparentAlphaMax.Value);
                    if (checkBoxTransportStreamGrayscale.Checked)
                        nDvbBmp.GrayScale();
                    dvbBmp.Dispose();
                    returnBmp = nDvbBmp.GetBitmap();
                }
            }
            else if (_dvbPesSubtitles != null)
            {
                if (index >= 0 && index < _dvbPesSubtitles.Count)
                {
                    var dvbBmp = _dvbPesSubtitles[index].GetImageFull();
                    var nDvbBmp = new NikseBitmap(dvbBmp);
                    nDvbBmp.CropTopTransparent(2);
                    nDvbBmp.CropTransparentSidesAndBottom(2, true);
                    if (checkBoxTransportStreamGetColorAndSplit.Checked)
                        _dvbSubColor = nDvbBmp.GetBrightestColorWhiteIsTransparent();
                    if (checkBoxAutoTransparentBackground.Checked)
                        nDvbBmp.MakeBackgroundTransparent((int)numericUpDownAutoTransparentAlphaMax.Value);
                    if (checkBoxTransportStreamGrayscale.Checked)
                        nDvbBmp.GrayScale();
                    dvbBmp.Dispose();
                    returnBmp = nDvbBmp.GetBitmap();
                }
            }
            else if (_bluRaySubtitlesOriginal != null)
            {
                if (index >= 0 && index < _bluRaySubtitles.Count)
                {
                    returnBmp = _bluRaySubtitles[index].GetBitmap();
                }
            }
            else if (index >= 0 && index < _vobSubMergedPackist.Count)
            {
                if (checkBoxCustomFourColors.Checked)
                {
                    GetCustomColors(out background, out pattern, out emphasis1, out emphasis2);

                    returnBmp = _vobSubMergedPackist[index].SubPicture.GetBitmap(null, background, pattern, emphasis1, emphasis2, true);
                    if (checkBoxAutoTransparentBackground.Checked)
                        returnBmp.MakeTransparent();
                }
                else
                {
                    returnBmp = _vobSubMergedPackist[index].SubPicture.GetBitmap(_palette, Color.Transparent, Color.Black, Color.White, Color.Black, false);
                    if (checkBoxAutoTransparentBackground.Checked)
                        returnBmp.MakeTransparent();
                }
            }

            if (returnBmp == null)
                return null;

            if ((_binaryOcrDb == null && _nOcrDb == null) || _fromMenuItem)
                return returnBmp;

            var n = new NikseBitmap(returnBmp);
            n.MakeTwoColor(280);
            returnBmp.Dispose();
            return n.GetBitmap();
        }
Пример #13
0
        private double GetPixelDifPercentage(BinaryOcrBitmap expanded, BinaryOcrBitmap bobNext, NikseBitmap nbmpNext)
        {
            var difColoredPercentage = (Math.Abs(expanded.NumberOfColoredPixels - bobNext.NumberOfColoredPixels)) * 100.0 / (bobNext.Width * bobNext.Height);
            if (difColoredPercentage > 1 && expanded.Width < 3 || bobNext.Width < 3)
                return 100;

            int dif = int.MaxValue;
            if (expanded.Height == bobNext.Height && expanded.Width == bobNext.Width)
            {
                dif = NikseBitmapImageSplitter.IsBitmapsAlike(nbmpNext, expanded);
            }
            else if (expanded.Height == bobNext.Height && expanded.Width == bobNext.Width + 1)
            {
                dif = NikseBitmapImageSplitter.IsBitmapsAlike(nbmpNext, expanded);
            }
            else if (expanded.Height == bobNext.Height && expanded.Width == bobNext.Width - 1)
            {
                dif = NikseBitmapImageSplitter.IsBitmapsAlike(expanded, nbmpNext);
            }
            else if (expanded.Width == bobNext.Width && expanded.Height == bobNext.Height + 1)
            {
                dif = NikseBitmapImageSplitter.IsBitmapsAlike(nbmpNext, expanded);
            }
            else if (expanded.Width == bobNext.Width && expanded.Height == bobNext.Height - 1)
            {
                dif = NikseBitmapImageSplitter.IsBitmapsAlike(expanded, nbmpNext);
            }
            var percentage = dif * 100.0 / (bobNext.Width * bobNext.Height);
            return percentage;
        }
Пример #14
0
        private static void NOcrThreadDoWork(object sender, DoWorkEventArgs e)
        {
            var p = (NOcrThreadParameter)e.Argument;
            e.Result = p;
            var nbmpInput = new NikseBitmap(p.Picture);
            nbmpInput.ReplaceNonWhiteWithTransparent();

            var matches = new List<CompareMatch>();
            int minLineHeight = p.NOcrLastLowercaseHeight;
            if (minLineHeight < 10)
                minLineHeight = 22;
            int maxLineHeight = p.NOcrLastUppercaseHeight;
            if (maxLineHeight < 10)
                minLineHeight = 80;

            List<ImageSplitterItem> list = NikseBitmapImageSplitter.SplitBitmapToLettersNew(nbmpInput, p.NumberOfPixelsIsSpace, p.RightToLeft, Configuration.Settings.VobSubOcr.TopToBottom, minLineHeight);
            foreach (ImageSplitterItem item in list)
            {
                if (item.NikseBitmap != null)
                {
                    var nbmp = item.NikseBitmap;
                    //                    nbmp.ReplaceNonWhiteWithTransparent();
                    item.Y += nbmp.CropTopTransparent(0);
                    nbmp.CropTransparentSidesAndBottom(0, true);
                    nbmp.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 = GetNOcrCompareMatch(item, nbmpInput, p);
                    if (match == null)
                    {
                        p.Result = string.Empty;
                        return;
                    }
                    else // found image match
                    {
                        matches.Add(new CompareMatch(match.Text, match.Italic, 0, null));
                        if (match.ExpandCount > 0)
                            index += match.ExpandCount - 1;
                    }
                }
                index++;
            }
            p.Result = GetStringWithItalicTags(matches);
        }
Пример #15
0
        private static void FindBestMatchNew(ref int index, ref int smallestDifference, ref int smallestIndex, NikseBitmap target, BinaryOcrDb binOcrDb, BinaryOcrBitmap bob, double maxDiff)
        {
            var bobExactMatch = binOcrDb.FindExactMatch(bob);
            if (bobExactMatch >= 0)
            {
                index = bobExactMatch;
                smallestDifference = 0;
                smallestIndex = bobExactMatch;
                return;
            }

            if (maxDiff < 0.2 || target.Width < 3 || target.Height < 5)
                return;

            int numberOfForegroundColors = bob.NumberOfColoredPixels;
            const int minForeColorMatch = 90;

            index = 0;
            foreach (var compareItem in binOcrDb.CompareImages)
            {
                if (compareItem.Width == target.Width && compareItem.Height == target.Height) // precise math in size
                {
                    if (Math.Abs(compareItem.NumberOfColoredPixels - numberOfForegroundColors) < 3)
                    {
                        int dif = NikseBitmapImageSplitter.IsBitmapsAlike(compareItem, target);
                        if (dif < smallestDifference)
                        {
                            smallestDifference = dif;
                            smallestIndex = index;
                            if (dif < 3)
                            {
                                break; // foreach ending
                            }
                        }
                    }
                }
                index++;
            }

            if (smallestDifference > 1)
            {
                index = 0;
                foreach (var compareItem in binOcrDb.CompareImages)
                {
                    if (compareItem.Width == target.Width && compareItem.Height == target.Height) // precise math in size
                    {
                        if (Math.Abs(compareItem.NumberOfColoredPixels - numberOfForegroundColors) < 40)
                        {
                            int dif = NikseBitmapImageSplitter.IsBitmapsAlike(compareItem, target);
                            if (dif < smallestDifference)
                            {
                                smallestDifference = dif;
                                smallestIndex = index;
                                if (dif == 0)
                                {
                                    break; // foreach ending
                                }
                            }
                        }
                    }
                    index++;
                }
            }

            if (target.Width > 16 && target.Height > 16 && smallestDifference > 2) // for other than very narrow letter (like 'i' and 'l' and 'I'), try more sizes
            {
                index = 0;
                foreach (var compareItem in binOcrDb.CompareImages)
                {
                    if (compareItem.Width == target.Width && compareItem.Height == target.Height - 1)
                    {
                        if (Math.Abs(compareItem.NumberOfColoredPixels - numberOfForegroundColors) < minForeColorMatch)
                        {
                            int dif = NikseBitmapImageSplitter.IsBitmapsAlike(compareItem, target);
                            if (dif < smallestDifference)
                            {
                                smallestDifference = dif;
                                smallestIndex = index;
                                if (dif == 0)
                                    break; // foreach ending
                            }
                        }
                    }
                    index++;
                }

                if (smallestDifference > 2)
                {
                    index = 0;
                    foreach (var compareItem in binOcrDb.CompareImages)
                    {
                        if (compareItem.Width == target.Width && compareItem.Height == target.Height + 1)
                        {
                            if (Math.Abs(compareItem.NumberOfColoredPixels - numberOfForegroundColors) < minForeColorMatch)
                            {
                                int dif = NikseBitmapImageSplitter.IsBitmapsAlike(target, compareItem);
                                if (dif < smallestDifference)
                                {
                                    smallestDifference = dif;
                                    smallestIndex = index;
                                    if (dif == 0)
                                        break; // foreach ending
                                }
                            }
                        }
                        index++;
                    }
                }

                if (smallestDifference > 3)
                {
                    index = 0;
                    foreach (var compareItem in binOcrDb.CompareImages)
                    {
                        if (compareItem.Width == target.Width + 1 && compareItem.Height == target.Height + 1)
                        {
                            if (Math.Abs(compareItem.NumberOfColoredPixels - numberOfForegroundColors) < minForeColorMatch)
                            {
                                int dif = NikseBitmapImageSplitter.IsBitmapsAlike(target, compareItem);
                                if (dif < smallestDifference)
                                {
                                    smallestDifference = dif;
                                    smallestIndex = index;
                                    if (dif == 0)
                                        break; // foreach ending
                                }
                            }
                        }
                        index++;
                    }
                }

                if (smallestDifference > 5)
                {
                    index = 0;
                    foreach (var compareItem in binOcrDb.CompareImages)
                    {
                        if (compareItem.Width == target.Width - 1 && compareItem.Height == target.Height - 1)
                        {
                            if (Math.Abs(compareItem.NumberOfColoredPixels - numberOfForegroundColors) < minForeColorMatch)
                            {
                                int dif = NikseBitmapImageSplitter.IsBitmapsAlike(compareItem, target);
                                if (dif < smallestDifference)
                                {
                                    smallestDifference = dif;
                                    smallestIndex = index;
                                    if (dif == 0)
                                        break; // foreach ending
                                }
                            }
                        }
                        index++;
                    }
                }

                if (smallestDifference > 5)
                {
                    index = 0;
                    foreach (var compareItem in binOcrDb.CompareImages)
                    {
                        if (compareItem.Width - 1 == target.Width && compareItem.Height == target.Height)
                        {
                            if (Math.Abs(compareItem.NumberOfColoredPixels - numberOfForegroundColors) < minForeColorMatch)
                            {
                                int dif = NikseBitmapImageSplitter.IsBitmapsAlike(target, compareItem);
                                if (dif < smallestDifference)
                                {
                                    smallestDifference = dif;
                                    smallestIndex = index;
                                    if (dif == 0)
                                        break; // foreach ending
                                }
                            }
                        }
                        index++;
                    }
                }

                if (smallestDifference > 9 && target.Width > 11)
                {
                    index = 0;
                    foreach (var compareItem in binOcrDb.CompareImages)
                    {
                        if (compareItem.Width == target.Width - 2 && compareItem.Height == target.Height)
                        {
                            if (Math.Abs(compareItem.NumberOfColoredPixels - numberOfForegroundColors) < minForeColorMatch)
                            {
                                int dif = NikseBitmapImageSplitter.IsBitmapsAlike(compareItem, target);
                                if (dif < smallestDifference)
                                {
                                    smallestDifference = dif;
                                    smallestIndex = index;
                                    if (dif == 0)
                                        break; // foreach ending
                                }
                            }
                        }
                        index++;
                    }
                }

                if (smallestDifference > 9 && target.Width > 14)
                {
                    index = 0;
                    foreach (var compareItem in binOcrDb.CompareImages)
                    {
                        if (compareItem.Width == target.Width - 3 && compareItem.Height == target.Height)
                        {
                            if (Math.Abs(compareItem.NumberOfColoredPixels - numberOfForegroundColors) < minForeColorMatch)
                            {
                                int dif = NikseBitmapImageSplitter.IsBitmapsAlike(compareItem, target);
                                if (dif < smallestDifference)
                                {
                                    smallestDifference = dif;
                                    smallestIndex = index;
                                    if (dif == 0)
                                        break; // foreach ending
                                }
                            }
                        }
                        index++;
                    }
                }

                if (smallestDifference > 9 && target.Width > 14)
                {
                    index = 0;
                    foreach (var compareItem in binOcrDb.CompareImages)
                    {
                        if (compareItem.Width == target.Width && compareItem.Height == target.Height - 3)
                        {
                            if (Math.Abs(compareItem.NumberOfColoredPixels - numberOfForegroundColors) < minForeColorMatch)
                            {
                                int dif = NikseBitmapImageSplitter.IsBitmapsAlike(compareItem, target);
                                if (dif < smallestDifference)
                                {
                                    smallestDifference = dif;
                                    smallestIndex = index;
                                    if (dif == 0)
                                        break; // foreach ending
                                }
                            }
                        }
                        index++;
                    }
                }

                if (smallestDifference > 9 && target.Width > 14)
                {
                    index = 0;
                    foreach (var compareItem in binOcrDb.CompareImages)
                    {
                        if (compareItem.Width - 2 == target.Width && compareItem.Height == target.Height)
                        {
                            if (Math.Abs(compareItem.NumberOfColoredPixels - numberOfForegroundColors) < minForeColorMatch)
                            {
                                int dif = NikseBitmapImageSplitter.IsBitmapsAlike(target, compareItem);
                                if (dif < smallestDifference)
                                {
                                    smallestDifference = dif;
                                    smallestIndex = index;
                                    if (dif == 0)
                                        break; // foreach ending
                                }
                            }
                        }
                        index++;
                    }
                }
            }

            if (smallestDifference == 0)
            {
                if (smallestIndex > 200)
                {
                    var hit = binOcrDb.CompareImages[smallestIndex];
                    binOcrDb.CompareImages.RemoveAt(smallestIndex);
                    binOcrDb.CompareImages.Insert(0, hit);
                    smallestIndex = 0;
                    index = 0;
                }
            }
        }
Пример #16
0
 public BinaryOcrBitmap(NikseBitmap nbmp)
 {
     InitializeViaNikseBmp(nbmp);
 }
Пример #17
0
        private Bitmap GenerateImageFromTextWithStyle(string text, bool bold, bool italic)
        {
            bool subtitleFontBold = bold;

            text = HtmlUtil.RemoveHtmlTags(text);

            Font font;

            try
            {
                var fontStyle = FontStyle.Regular;
                if (subtitleFontBold)
                {
                    fontStyle = FontStyle.Bold;
                }

                font = new Font(_subtitleFontName, _subtitleFontSize, fontStyle);
            }
            catch (Exception exception)
            {
                MessageBox.Show(exception.Message);
                font = new Font(FontFamily.Families[0].Name, _subtitleFontSize);
            }
            var bmp = new Bitmap(400, 300);
            var g   = Graphics.FromImage(bmp);

            SizeF textSize   = g.MeasureString("Hj!", font);
            var   lineHeight = (textSize.Height * 0.64f);

            textSize = g.MeasureString(HtmlUtil.RemoveHtmlTags(text), font);
            g.Dispose();
            bmp.Dispose();
            int sizeX = (int)(textSize.Width * 0.8) + 40;
            int sizeY = (int)(textSize.Height * 0.8) + 30;

            if (sizeX < 1)
            {
                sizeX = 1;
            }

            if (sizeY < 1)
            {
                sizeY = 1;
            }

            bmp = new Bitmap(sizeX, sizeY);
            g   = Graphics.FromImage(bmp);

            g.TextRenderingHint  = TextRenderingHint.AntiAliasGridFit;
            g.SmoothingMode      = SmoothingMode.AntiAlias;
            g.CompositingQuality = CompositingQuality.HighQuality;

            var sf = new StringFormat
            {
                Alignment     = StringAlignment.Near,
                LineAlignment = StringAlignment.Near
            };
            // draw the text to a path
            var path = new GraphicsPath();

            // display italic
            var         sb               = new StringBuilder();
            int         i                = 0;
            const float left             = 5f;
            float       top              = 5;
            bool        newLine          = false;
            const float leftMargin       = left;
            int         newLinePathPoint = -1;
            Color       c                = _subtitleColor;
            int         textLen          = text.Length;

            while (i < textLen)
            {
                char ch = text[i];
                if (ch == '\n' || ch == '\r')
                {
                    TextDraw.DrawText(font, sf, path, sb, italic, subtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint);

                    top    += lineHeight;
                    newLine = true;
                    if (i + 1 < textLen && text[i + 1] == '\n' && text[i] == '\r')
                    {
                        i += 2; // CR+LF (Microsoft Windows)
                    }
                    else
                    {
                        i++; // LF (Unix and Unix-like systems )
                    }
                }
                else
                {
                    sb.Append(ch);
                }
                i++;
            }
            if (sb.Length > 0)
            {
                TextDraw.DrawText(font, sf, path, sb, italic, subtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint);
            }

            sf.Dispose();

            g.DrawPath(new Pen(_borderColor, BorderWidth), path);
            g.FillPath(new SolidBrush(c), path);
            g.Dispose();
            var nbmp = new NikseBitmap(bmp);

            nbmp.CropTransparentSidesAndBottom(2, true);
            return(nbmp.GetBitmap());
        }
Пример #18
0
        protected override void GeneratePreviewReal()
        {
            if (_backgroundImage == null)
            {
                const int rectangleSize = 9;
                _backgroundImage = TextDesigner.MakeBackgroundImage(pictureBoxPreview.Width, pictureBoxPreview.Height, rectangleSize, _backgroundImageDark);
            }

            var outlineWidth = (float)numericUpDownOutline.Value;
            var shadowWidth  = (float)numericUpDownShadowWidth.Value;
            var outlineColor = _isSubStationAlpha ? panelBackColor.BackColor : panelOutlineColor.BackColor;

            Font font;

            try
            {
                font = new Font(comboBoxFontName.Text, (float)numericUpDownFontSize.Value * 1.1f, checkBoxFontBold.Checked ? FontStyle.Bold : FontStyle.Regular);
            }
            catch
            {
                font = new Font(Font, FontStyle.Regular);
            }

            var measureBmp = TextDesigner.MakeTextBitmapAssa(
                Configuration.Settings.General.PreviewAssaText,
                0,
                0,
                font,
                pictureBoxPreview.Width,
                pictureBoxPreview.Height,
                outlineWidth,
                shadowWidth,
                null,
                panelPrimaryColor.BackColor,
                outlineColor,
                panelBackColor.BackColor,
                radioButtonOpaqueBox.Checked);
            var nBmp           = new NikseBitmap(measureBmp);
            var measuredWidth  = nBmp.GetNonTransparentWidth();
            var measuredHeight = nBmp.GetNonTransparentHeight();

            float left;

            if (radioButtonTopLeft.Checked || radioButtonMiddleLeft.Checked || radioButtonBottomLeft.Checked)
            {
                left = (float)numericUpDownMarginLeft.Value;
            }
            else if (radioButtonTopRight.Checked || radioButtonMiddleRight.Checked || radioButtonBottomRight.Checked)
            {
                left = pictureBoxPreview.Width - (measuredWidth + (float)numericUpDownMarginRight.Value);
            }
            else
            {
                left = (pictureBoxPreview.Width - measuredWidth) / 2.0f;
            }

            float top;

            if (radioButtonTopLeft.Checked || radioButtonTopCenter.Checked || radioButtonTopRight.Checked)
            {
                top = (float)numericUpDownMarginVertical.Value;
            }
            else if (radioButtonMiddleLeft.Checked || radioButtonMiddleCenter.Checked || radioButtonMiddleRight.Checked)
            {
                top = (pictureBoxPreview.Height - measuredHeight) / 2.0f;
            }
            else
            {
                top = pictureBoxPreview.Height - measuredHeight - (int)numericUpDownMarginVertical.Value;
            }

            var designedText = TextDesigner.MakeTextBitmapAssa(
                Configuration.Settings.General.PreviewAssaText,
                (int)Math.Round(left),
                (int)Math.Round(top),
                font,
                pictureBoxPreview.Width,
                pictureBoxPreview.Height,
                outlineWidth,
                shadowWidth,
                _backgroundImage,
                panelPrimaryColor.BackColor,
                panelOutlineColor.BackColor,
                panelBackColor.BackColor,
                radioButtonOpaqueBox.Checked);

            pictureBoxPreview.Image?.Dispose();
            pictureBoxPreview.Image = designedText;
            font.Dispose();
        }
        private Bitmap GenerateImageFromTextWithStyle(string text)
        {
            const bool subtitleFontBold  = false;
            bool       subtitleAlignLeft = comboBoxHAlign.SelectedIndex == 0;

            // remove styles for display text (except italic)
            text = Utilities.RemoveSsaTags(text);
            text = text.Replace("<b>", string.Empty);
            text = text.Replace("</b>", string.Empty);
            text = text.Replace("<B>", string.Empty);
            text = text.Replace("</B>", string.Empty);
            text = text.Replace("<u>", string.Empty);
            text = text.Replace("</u>", string.Empty);
            text = text.Replace("<U>", string.Empty);
            text = text.Replace("</U>", string.Empty);

            Font font;

            try
            {
                font = new Font(_subtitleFontName, _subtitleFontSize, FontStyle.Regular);
            }
            catch (Exception exception)
            {
                MessageBox.Show(exception.Message);
                font = new Font(FontFamily.Families[0].Name, _subtitleFontSize);
            }
            var bmp = new Bitmap(400, 200);
            var g   = Graphics.FromImage(bmp);

            SizeF textSize   = g.MeasureString("Hj!", font);
            var   lineHeight = (textSize.Height * 0.64f);

            textSize = g.MeasureString(HtmlUtil.RemoveHtmlTags(text), font);
            g.Dispose();
            bmp.Dispose();
            int sizeX = (int)(textSize.Width * 0.8) + 40;
            int sizeY = (int)(textSize.Height * 0.8) + 30;

            if (sizeX < 1)
            {
                sizeX = 1;
            }
            if (sizeY < 1)
            {
                sizeY = 1;
            }
            bmp = new Bitmap(sizeX, sizeY);
            g   = Graphics.FromImage(bmp);

            var lefts = new List <float>();

            foreach (var line in HtmlUtil.RemoveOpenCloseTags(text, HtmlUtil.TagItalic, HtmlUtil.TagFont).SplitToLines())
            {
                if (subtitleAlignLeft)
                {
                    lefts.Add(5);
                }
                else
                {
                    lefts.Add((float)(bmp.Width - g.MeasureString(line, font).Width * 0.8 + 15) / 2);
                }
            }

            g.TextRenderingHint  = TextRenderingHint.AntiAliasGridFit;
            g.SmoothingMode      = SmoothingMode.AntiAlias;
            g.CompositingQuality = CompositingQuality.HighQuality;

            var sf = new StringFormat();

            sf.Alignment     = StringAlignment.Near;
            sf.LineAlignment = StringAlignment.Near;// draw the text to a path
            var path = new GraphicsPath();

            // display italic
            var   sb       = new StringBuilder();
            int   i        = 0;
            bool  isItalic = false;
            float left     = 5;

            if (lefts.Count > 0)
            {
                left = lefts[0];
            }
            float top              = 5;
            bool  newLine          = false;
            int   lineNumber       = 0;
            float leftMargin       = left;
            int   newLinePathPoint = -1;
            Color c          = _subtitleColor;
            var   colorStack = new Stack <Color>();
            var   lastText   = new StringBuilder();

            while (i < text.Length)
            {
                if (text.Substring(i).StartsWith("<font ", StringComparison.OrdinalIgnoreCase))
                {
                    float addLeft           = 0;
                    int   oldPathPointIndex = path.PointCount;
                    if (oldPathPointIndex < 0)
                    {
                        oldPathPointIndex = 0;
                    }

                    if (sb.Length > 0)
                    {
                        TextDraw.DrawText(font, sf, path, sb, isItalic, subtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint);
                    }
                    if (path.PointCount > 0)
                    {
                        PointF[] list = (PointF[])path.PathPoints.Clone(); // avoid using very slow path.PathPoints indexer!!!
                        for (int k = oldPathPointIndex; k < list.Length; k++)
                        {
                            if (list[k].X > addLeft)
                            {
                                addLeft = list[k].X;
                            }
                        }
                    }
                    if (addLeft == 0)
                    {
                        addLeft = left + 2;
                    }
                    left = addLeft;

                    if (_borderWidth > 0)
                    {
                        g.DrawPath(new Pen(_borderColor, _borderWidth), path);
                    }
                    g.FillPath(new SolidBrush(c), path);
                    path.Reset();
                    path = new GraphicsPath();
                    sb.Clear();

                    int endIndex = text.Substring(i).IndexOf('>');
                    if (endIndex < 0)
                    {
                        i += 9999;
                    }
                    else
                    {
                        string fontContent = text.Substring(i, endIndex);
                        if (fontContent.Contains(" color="))
                        {
                            var arr = fontContent.Substring(fontContent.IndexOf(" color=", StringComparison.Ordinal) + 7).Trim().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                            if (arr.Length > 0)
                            {
                                string fontColor = arr[0].Trim('\'').Trim('"').Trim('\'');
                                try
                                {
                                    colorStack.Push(c); // save old color
                                    if (fontColor.StartsWith("rgb("))
                                    {
                                        arr = fontColor.Remove(0, 4).TrimEnd(')').Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                                        c   = Color.FromArgb(int.Parse(arr[0]), int.Parse(arr[1]), int.Parse(arr[2]));
                                    }
                                    else
                                    {
                                        c = ColorTranslator.FromHtml(fontColor);
                                    }
                                }
                                catch
                                {
                                    c = _subtitleColor;
                                }
                            }
                        }
                        i += endIndex;
                    }
                }
                else if (text.Substring(i).StartsWith("</font>", StringComparison.OrdinalIgnoreCase))
                {
                    if (text.Substring(i).ToLower().Replace("</font>", string.Empty).Length > 0)
                    {
                        if (lastText.EndsWith(' ') && !sb.StartsWith(' '))
                        {
                            string t = sb.ToString();
                            sb.Clear();
                            sb.Append(' ');
                            sb.Append(t);
                        }

                        float addLeft           = 0;
                        int   oldPathPointIndex = path.PointCount - 1;
                        if (oldPathPointIndex < 0)
                        {
                            oldPathPointIndex = 0;
                        }
                        if (sb.Length > 0)
                        {
                            TextDraw.DrawText(font, sf, path, sb, isItalic, subtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint);
                        }
                        if (path.PointCount > 0)
                        {
                            PointF[] list = (PointF[])path.PathPoints.Clone(); // avoid using very slow path.PathPoints indexer!!!
                            for (int k = oldPathPointIndex; k < list.Length; k++)
                            {
                                if (list[k].X > addLeft)
                                {
                                    addLeft = list[k].X;
                                }
                            }
                        }
                        if (addLeft == 0)
                        {
                            addLeft = left + 2;
                        }
                        left = addLeft;

                        if (_borderWidth > 0)
                        {
                            g.DrawPath(new Pen(_borderColor, _borderWidth), path);
                        }
                        g.FillPath(new SolidBrush(c), path);
                        path.Reset();
                        sb.Clear();
                        if (colorStack.Count > 0)
                        {
                            c = colorStack.Pop();
                        }
                    }
                    i += 6;
                }
                else if (text.Substring(i).StartsWith("<i>", StringComparison.OrdinalIgnoreCase))
                {
                    if (sb.Length > 0)
                    {
                        TextDraw.DrawText(font, sf, path, sb, isItalic, subtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint);
                    }
                    isItalic = true;
                    i       += 2;
                }
                else if (text.Substring(i).StartsWith("</i>", StringComparison.OrdinalIgnoreCase) && isItalic)
                {
                    if (lastText.EndsWith(' ') && !sb.StartsWith(' '))
                    {
                        string t = sb.ToString();
                        sb.Clear();
                        sb.Append(' ');
                        sb.Append(t);
                    }
                    TextDraw.DrawText(font, sf, path, sb, isItalic, subtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint);
                    isItalic = false;
                    i       += 3;
                }
                else if (text.Substring(i).StartsWith(Environment.NewLine, StringComparison.Ordinal))
                {
                    TextDraw.DrawText(font, sf, path, sb, isItalic, subtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint);

                    top    += lineHeight;
                    newLine = true;
                    i      += Environment.NewLine.Length - 1;
                    lineNumber++;
                    if (lineNumber < lefts.Count)
                    {
                        leftMargin = lefts[lineNumber];
                        left       = leftMargin;
                    }
                }
                else
                {
                    sb.Append(text[i]);
                }
                i++;
            }
            if (sb.Length > 0)
            {
                TextDraw.DrawText(font, sf, path, sb, isItalic, subtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint);
            }
            sf.Dispose();

            if (_borderWidth > 0)
            {
                g.DrawPath(new Pen(_borderColor, _borderWidth), path);
            }
            g.FillPath(new SolidBrush(c), path);
            g.Dispose();
            var nbmp = new NikseBitmap(bmp);

            nbmp.CropTransparentSidesAndBottom(2, true);
            return(nbmp.GetBitmap());
        }
Пример #20
0
        public NOcrChar GetMatch(NikseBitmap bitmap, int topMargin, bool deepSeek, bool italic, double italicAngle)
        {
            // only very very accurate matches
            foreach (var oc in OcrCharacters)
            {
                if (bitmap.Width == oc.Width && bitmap.Height == oc.Height && Math.Abs(oc.MarginTop - topMargin) < 5)
                {
                    if (IsMatch(bitmap, oc, 0))
                    {
                        return(oc);
                    }
                }
            }

            // only very accurate matches
            double widthPercent = bitmap.Height * 100.0 / bitmap.Width;

            foreach (var oc in OcrCharacters)
            {
                if (Math.Abs(widthPercent - oc.WidthPercent) < 15 && Math.Abs(bitmap.Width - oc.Width) < 5 && Math.Abs(bitmap.Height - oc.Height) < 5 && Math.Abs(oc.MarginTop - topMargin) < 5)
                {
                    if (IsMatch(bitmap, oc, 0))
                    {
                        return(oc);
                    }
                }
            }

            foreach (var oc in OcrCharacters)
            {
                if (Math.Abs(bitmap.Width - oc.Width) < 8 && Math.Abs(bitmap.Height - oc.Height) < 8 && Math.Abs(oc.MarginTop - topMargin) < 8)
                {
                    if (IsMatch(bitmap, oc, 1))
                    {
                        return(oc);
                    }
                }
            }

            foreach (var oc in OcrCharacters)
            {
                if (Math.Abs(widthPercent - oc.WidthPercent) < 20 && Math.Abs(oc.MarginTop - topMargin) < 15)
                {
                    if (IsMatch(bitmap, oc, 2))
                    {
                        return(oc);
                    }
                }
            }

            foreach (var oc in OcrCharacters)
            {
                if (!oc.IsSensitive && Math.Abs(widthPercent - oc.WidthPercent) < 20 && Math.Abs(oc.MarginTop - topMargin) < 15 && oc.LinesForeground.Count + oc.LinesBackground.Count > 40)
                {
                    if (IsMatch(bitmap, oc, 20))
                    {
                        return(oc);
                    }
                }
            }

            foreach (var oc in OcrCharacters)
            {
                if (oc.IsSensitive && Math.Abs(widthPercent - oc.WidthPercent) < 30 && Math.Abs(oc.MarginTop - topMargin) < 15 && oc.LinesForeground.Count + oc.LinesBackground.Count > 40)
                {
                    if (IsMatch(bitmap, oc, 10))
                    {
                        return(oc);
                    }
                }
            }

            if (italic)
            {
                foreach (var oc in OcrCharacters)
                {
                    if (Math.Abs(widthPercent - oc.WidthPercent) < 60 && Math.Abs(oc.MarginTop - topMargin) < 17 && oc.LinesForeground.Count + oc.LinesBackground.Count > 50)
                    {
                        var italicOc = MakeItalicNOcrChar(oc, 0, italicAngle);
                        if (IsMatch(bitmap, italicOc, 25))
                        {
                            return(italicOc);
                        }
                    }
                }
            }

            if (deepSeek)
            {
                foreach (var oc in OcrCharacters)
                {
                    if (Math.Abs(widthPercent - oc.WidthPercent) < 60 && Math.Abs(oc.MarginTop - topMargin) < 17 && oc.LinesForeground.Count + oc.LinesBackground.Count > 50)
                    {
                        if (IsMatch(bitmap, oc, 25))
                        {
                            return(oc);
                        }
                    }
                }
            }

            return(null);
        }
Пример #21
0
        public static bool ConvertFromTsToBdnXml(string fileName, string outputFolder, bool overwrite, StreamWriter stdOutWriter, CommandLineConverter.BatchConvertProgress progressCallback, Point? resolution)
        {
            var programMapTableParser = new ProgramMapTableParser();
            programMapTableParser.Parse(fileName); // get languages from PMT if possible
            var tsParser = new TransportStreamParser();
            tsParser.Parse(fileName, (position, total) =>
            {
                var percent = (int)Math.Round(position * 100.0 / total);
                stdOutWriter?.Write("\rParsing transport stream: {0}%", percent);
                progressCallback?.Invoke($"{percent}%");
            });
            stdOutWriter?.Write("\r".PadRight(32, ' '));
            stdOutWriter?.Write("\r");

            var overrideScreenSize = Configuration.Settings.Tools.BatchConvertTsOverrideScreenSize &&
                                     Configuration.Settings.Tools.BatchConvertTsScreenHeight > 0 &&
                                     Configuration.Settings.Tools.BatchConvertTsScreenWidth > 0 ||
                                     resolution.HasValue;

            using (var form = new ExportPngXml())
            {
                if (tsParser.SubtitlePacketIds.Count == 0)
                {
                    stdOutWriter?.WriteLine("No subtitles found");
                    progressCallback?.Invoke("No subtitles found");
                    return false;
                }
                foreach (int pid in tsParser.SubtitlePacketIds)
                {
                    var language = TsToBluRaySup.GetFileNameEnding(programMapTableParser, pid);
                    var nameNoExt = Utilities.GetFileNameWithoutExtension(fileName) + "." + language;
                    var folder = Path.Combine(outputFolder, nameNoExt);
                    if (!Directory.Exists(folder))
                    {
                        Directory.CreateDirectory(folder);
                    }
                    var outputFileName = CommandLineConverter.FormatOutputFileNameForBatchConvert(nameNoExt + Path.GetExtension(fileName), ".xml", folder, overwrite);
                    stdOutWriter?.WriteLine($"Saving PID {pid} to {outputFileName}...");
                    progressCallback?.Invoke($"Save PID {pid}");
                    var sub = tsParser.GetDvbSubtitles(pid);
                    var subtitle = new Subtitle();
                    foreach (var p in sub)
                    {
                        subtitle.Paragraphs.Add(new Paragraph(string.Empty, p.StartMilliseconds, p.EndMilliseconds));
                    }

                    var res = TsToBluRaySup.GetSubtitleScreenSize(sub, overrideScreenSize, resolution);
                    var videoInfo = new VideoInfo { Success = true, Width = res.X, Height = res.Y };
                    form.Initialize(subtitle, new SubRip(), BatchConvert.BdnXmlSubtitle, fileName, videoInfo, fileName);
                    var sb = new StringBuilder();
                    var imagesSavedCount = 0;
                    for (int index = 0; index < sub.Count; index++)
                    {
                        var p = sub[index];
                        var pos = p.GetPosition();
                        var bmp = sub[index].GetBitmap();
                        var tsWidth = bmp.Width;
                        var tsHeight = bmp.Height;
                        var nBmp = new NikseBitmap(bmp);
                        pos.Top += nBmp.CropTopTransparent(0);
                        pos.Left += nBmp.CropSidesAndBottom(0, Color.FromArgb(0, 0, 0, 0), true);
                        bmp.Dispose();
                        bmp = nBmp.GetBitmap();
                        var mp = form.MakeMakeBitmapParameter(index, videoInfo.Width, videoInfo.Height);

                        if (overrideScreenSize)
                        {
                            var widthFactor = (double)videoInfo.Width / tsWidth;
                            var heightFactor = (double)videoInfo.Height / tsHeight;
                            var resizeBmp = ResizeBitmap(bmp, (int)Math.Round(bmp.Width * widthFactor), (int)Math.Round(bmp.Height * heightFactor));
                            bmp.Dispose();
                            bmp = resizeBmp;
                            pos.Left = (int)Math.Round(pos.Left * widthFactor);
                            pos.Top = (int)Math.Round(pos.Top * heightFactor);
                            progressCallback?.Invoke($"Save PID {pid}: {(index + 1) * 100 / sub.Count}%");
                        }

                        mp.Bitmap = bmp;
                        mp.P = new Paragraph(string.Empty, p.StartMilliseconds, p.EndMilliseconds);
                        mp.ScreenWidth = videoInfo.Width;
                        mp.ScreenHeight = videoInfo.Height;
                        int bottomMarginInPixels;
                        if (Configuration.Settings.Tools.BatchConvertTsOverrideXPosition || Configuration.Settings.Tools.BatchConvertTsOverrideYPosition)
                        {
                            if (Configuration.Settings.Tools.BatchConvertTsOverrideXPosition && Configuration.Settings.Tools.BatchConvertTsOverrideYPosition)
                            {
                                var x = (int)Math.Round(videoInfo.Width / 2.0 - mp.Bitmap.Width / 2.0);
                                if (Configuration.Settings.Tools.BatchConvertTsOverrideHAlign.Equals("left", StringComparison.OrdinalIgnoreCase))
                                {
                                    x = Configuration.Settings.Tools.BatchConvertTsOverrideHMargin;
                                }
                                else if (Configuration.Settings.Tools.BatchConvertTsOverrideHAlign.Equals("right", StringComparison.OrdinalIgnoreCase))
                                {
                                    x = videoInfo.Width - Configuration.Settings.Tools.BatchConvertTsOverrideHMargin - mp.Bitmap.Width;
                                }
                                var y = videoInfo.Height - Configuration.Settings.Tools.BatchConvertTsOverrideBottomMargin - mp.Bitmap.Height;
                                mp.OverridePosition = new Point(x, y);
                            }
                            else if (Configuration.Settings.Tools.BatchConvertTsOverrideXPosition)
                            {
                                var x = (int)Math.Round(videoInfo.Width / 2.0 - mp.Bitmap.Width / 2.0);
                                if (Configuration.Settings.Tools.BatchConvertTsOverrideHAlign.Equals("left", StringComparison.OrdinalIgnoreCase))
                                {
                                    x = Configuration.Settings.Tools.BatchConvertTsOverrideHMargin;
                                }
                                else if (Configuration.Settings.Tools.BatchConvertTsOverrideHAlign.Equals("right", StringComparison.OrdinalIgnoreCase))
                                {
                                    x = videoInfo.Width - Configuration.Settings.Tools.BatchConvertTsOverrideHMargin - mp.Bitmap.Width;
                                }
                                mp.OverridePosition = new Point(x, pos.Top);
                            }
                            else
                            {
                                var y = videoInfo.Height - Configuration.Settings.Tools.BatchConvertTsOverrideBottomMargin - mp.Bitmap.Height;
                                mp.OverridePosition = new Point(pos.Left, y);
                            }
                            bottomMarginInPixels = Configuration.Settings.Tools.BatchConvertTsScreenHeight - pos.Top - mp.Bitmap.Height;
                        }
                        else
                        {
                            mp.OverridePosition = new Point(pos.Left, pos.Top); // use original position
                            bottomMarginInPixels = Configuration.Settings.Tools.BatchConvertTsScreenHeight - pos.Top - mp.Bitmap.Height;
                        }

                        imagesSavedCount = form.WriteBdnXmlParagraph(videoInfo.Width, sb, bottomMarginInPixels, videoInfo.Height, imagesSavedCount, mp, index, Path.GetDirectoryName(outputFileName));
                    }
                    form.WriteBdnXmlFile(imagesSavedCount, sb, outputFileName);
                }
            }
            return true;
        }
Пример #22
0
        public Bitmap ToOldBitmap()
        {
            if (ExpandedList != null && ExpandedList.Count > 0)
            {
                int minX = X;
                int minY = Y;
                int maxX = X + Width;
                int maxY = Y + Height;
                var list = new List <BinaryOcrBitmap>();
                list.Add(this);
                foreach (BinaryOcrBitmap bob in ExpandedList)
                {
                    if (bob.X < minX)
                    {
                        minX = bob.X;
                    }
                    if (bob.Y < minY)
                    {
                        minY = bob.Y;
                    }
                    if (bob.X + bob.Width > maxX)
                    {
                        maxX = bob.X + bob.Width;
                    }
                    if (bob.Y + bob.Height > maxY)
                    {
                        maxY = bob.Y + bob.Height;
                    }
                    list.Add(bob);
                }
                var nbmp = new BinaryOcrBitmap(maxX - minX, maxY - minY);
                foreach (BinaryOcrBitmap bob in list)
                {
                    for (int y = 0; y < bob.Height; y++)
                    {
                        for (int x = 0; x < bob.Width; x++)
                        {
                            int c = bob.GetPixel(x, y);
                            if (c > 0)
                            {
                                nbmp.SetPixel(bob.X - minX + x, bob.Y - minY + y, 1);
                            }
                        }
                    }
                }

                return(nbmp.ToOldBitmap()); // Resursive
            }
            else
            {
                var nbmp = new NikseBitmap(Width, Height);
                for (int y = 0; y < Height; y++)
                {
                    for (int x = 0; x < Width; x++)
                    {
                        Color c = Color.Transparent;
                        if (GetPixel(x, y) > 0)
                        {
                            c = Color.White;
                        }
                        nbmp.SetPixel(x, y, c);
                    }
                }
                return(nbmp.GetBitmap());
            }
        }
Пример #23
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);
        }
Пример #24
0
        private string Tesseract3DoOcrViaExe(Bitmap bmp, string language, string psmMode)
        {
            // change yellow color to white - easier for Tesseract
            var nbmp = new NikseBitmap(bmp);
            nbmp.ReplaceYellowWithWhite(); // optimized replace

            string tempTiffFileName = Path.GetTempPath() + Guid.NewGuid() + ".png";
            string tempTextFileName;
            using (var b = nbmp.GetBitmap())
            {
                b.Save(tempTiffFileName, System.Drawing.Imaging.ImageFormat.Png);
                tempTextFileName = Path.GetTempPath() + Guid.NewGuid();
            }

            using (var process = new Process())
            {
                process.StartInfo = new ProcessStartInfo(Configuration.TesseractFolder + "tesseract.exe");
                process.StartInfo.UseShellExecute = true;
                process.StartInfo.Arguments = "\"" + tempTiffFileName + "\" \"" + tempTextFileName + "\" -l " + language;

                if (checkBoxTesseractMusicOn.Checked)
                    process.StartInfo.Arguments += "+music";

                if (!string.IsNullOrEmpty(psmMode))
                    process.StartInfo.Arguments += " " + psmMode.Trim();

                process.StartInfo.Arguments += " hocr";
                process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

                if (Configuration.IsRunningOnLinux() || Configuration.IsRunningOnMac())
                {
                    process.StartInfo.UseShellExecute = false;
                    process.StartInfo.RedirectStandardError = true;
                    process.StartInfo.FileName = "tesseract";
                }
                else
                {
                    process.StartInfo.WorkingDirectory = (Configuration.TesseractFolder);
                }

                try
                {
                    process.Start();
                }
                catch
                {
                    if (Configuration.IsRunningOnLinux() || Configuration.IsRunningOnMac())
                    {
                        MessageBox.Show("Unable to start 'Tesseract' - make sure tesseract-ocr 3.x is installed!");
                    }
                    else
                    {
                        MessageBox.Show("Unable to start 'Tesseract' (" + Configuration.TesseractFolder + "tesseract.exe) - make sure tesseract-ocr 3.x is installed!");
                    }
                    throw;
                }
                process.WaitForExit(5000);
            }

            string result = string.Empty;
            string outputFileName = tempTextFileName + ".html";
            if (!File.Exists(outputFileName))
                outputFileName = tempTextFileName + ".hocr";
            try
            {
                if (File.Exists(outputFileName))
                {
                    result = File.ReadAllText(outputFileName);
                    result = ParseHocr(result);
                    File.Delete(outputFileName);
                }
                File.Delete(tempTiffFileName);
            }
            catch
            {
            }
            return result;
        }
Пример #25
0
        public NOcrChar GetMatchExpanded(NikseBitmap nikseBitmap, ImageSplitterItem targetItem, int listIndex, List <ImageSplitterItem> list)
        {
            int w = targetItem.NikseBitmap.Width;

            for (var i = 0; i < OcrCharactersExpanded.Count; i++)
            {
                var oc = OcrCharactersExpanded[i];
                if (oc.ExpandCount > 1 && oc.Width > w && targetItem.X + oc.Width < nikseBitmap.Width)
                {
                    bool ok    = true;
                    var  index = 0;
                    while (index < oc.LinesForeground.Count && ok)
                    {
                        var op = oc.LinesForeground[index];
                        foreach (var point in op.GetPoints())
                        {
                            var p = new Point(point.X + targetItem.X, point.Y + targetItem.Y - oc.MarginTop);
                            if (p.X >= 0 && p.Y >= 0 && p.X < nikseBitmap.Width && p.Y < nikseBitmap.Height)
                            {
                                var a = nikseBitmap.GetAlpha(p.X, p.Y);
                                if (a <= 150)
                                {
                                    ok = false;
                                    break;
                                }
                            }
                            else if (p.X >= 0 && p.Y >= 0)
                            {
                                ok = false;
                                break;
                            }
                        }

                        index++;
                    }

                    index = 0;
                    while (index < oc.LinesBackground.Count && ok)
                    {
                        var op = oc.LinesBackground[index];
                        foreach (var point in op.GetPoints())
                        {
                            var p = new Point(point.X + targetItem.X, point.Y + targetItem.Y - oc.MarginTop);
                            if (p.X >= 0 && p.Y >= 0 && p.X < nikseBitmap.Width && p.Y < nikseBitmap.Height)
                            {
                                var a = nikseBitmap.GetAlpha(p.X, p.Y);
                                if (a > 150)
                                {
                                    ok = false;
                                    break;
                                }
                            }
                            else if (p.X >= 0 && p.Y >= 0)
                            {
                                ok = false;
                                break;
                            }
                        }

                        index++;
                    }

                    if (ok)
                    {
                        var size = GetTotalSize(listIndex, list, oc.ExpandCount);
                        if (Math.Abs(size.X - oc.Width) < 3 && Math.Abs(size.Y - oc.Height) < 3)
                        {
                            return(oc);
                        }
                    }
                }
            }

            for (var i = 0; i < OcrCharactersExpanded.Count; i++)
            {
                var oc = OcrCharactersExpanded[i];
                if (oc.ExpandCount > 1 && oc.Width > w && targetItem.X + oc.Width < nikseBitmap.Width)
                {
                    bool ok    = true;
                    var  index = 0;
                    while (index < oc.LinesForeground.Count && ok)
                    {
                        var op = oc.LinesForeground[index];
                        foreach (var point in op.ScaledGetPoints(oc, oc.Width, oc.Height - 1))
                        {
                            var p = new Point(point.X + targetItem.X, point.Y + targetItem.Y - oc.MarginTop);
                            if (p.X >= 0 && p.Y >= 0 && p.X < nikseBitmap.Width && p.Y < nikseBitmap.Height)
                            {
                                var a = nikseBitmap.GetAlpha(p.X, p.Y);
                                if (a <= 150)
                                {
                                    ok = false;
                                    break;
                                }
                            }
                            else if (p.X >= 0 && p.Y >= 0)
                            {
                                ok = false;
                                break;
                            }
                        }

                        index++;
                    }

                    index = 0;
                    while (index < oc.LinesBackground.Count && ok)
                    {
                        var op = oc.LinesBackground[index];
                        foreach (var point in op.ScaledGetPoints(oc, oc.Width, oc.Height - 1))
                        {
                            var p = new Point(point.X + targetItem.X, point.Y + targetItem.Y - oc.MarginTop);
                            if (p.X >= 0 && p.Y >= 0 && p.X < nikseBitmap.Width && p.Y < nikseBitmap.Height)
                            {
                                var a = nikseBitmap.GetAlpha(p.X, p.Y);
                                if (a > 150)
                                {
                                    ok = false;
                                    break;
                                }
                            }
                            else if (p.X >= 0 && p.Y >= 0)
                            {
                                ok = false;
                                break;
                            }
                        }

                        index++;
                    }

                    if (ok)
                    {
                        var size         = GetTotalSize(listIndex, list, oc.ExpandCount);
                        var widthPercent = size.Y * 100.0 / size.X;
                        if (Math.Abs(widthPercent - oc.WidthPercent) < 15 &&
                            Math.Abs(size.X - oc.Width) < 25 && Math.Abs(size.Y - oc.Height) < 20)
                        {
                            return(oc);
                        }
                    }
                }
            }

            return(null);
        }
Пример #26
0
        private static void FindBestMatch(ref int index, ref int smallestDifference, ref int smallestIndex, NikseBitmap target, List<CompareItem> compareBitmaps)
        {
            int numberOfForegroundColors = CalculateNumberOfForegroundColors(target);
            const int minForeColorMatch = 90;

            index = 0;
            foreach (CompareItem compareItem in compareBitmaps)
            {
                if (compareItem.Bitmap.Width == target.Width && compareItem.Bitmap.Height == target.Height) // precise math in size
                {
                    if (compareItem.NumberOfForegroundColors < 1)
                        compareItem.NumberOfForegroundColors = CalculateNumberOfForegroundColors(compareItem.Bitmap);

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

            if (smallestDifference > 1)
            {
                index = 0;
                foreach (CompareItem compareItem in compareBitmaps)
                {
                    if (compareItem.Bitmap.Width == target.Width && compareItem.Bitmap.Height == target.Height) // precise math in size
                    {
                        if (compareItem.NumberOfForegroundColors < 1)
                            compareItem.NumberOfForegroundColors = CalculateNumberOfForegroundColors(compareItem.Bitmap);

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

            if (target.Width > 5 && smallestDifference > 2) // for other than very narrow letter (like 'i' and 'l' and 'I'), try more sizes
            {
                index = 0;
                foreach (CompareItem compareItem in 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) < minForeColorMatch)
                        {
                            int dif = NikseBitmapImageSplitter.IsBitmapsAlike(compareItem.Bitmap, target);
                            if (dif < smallestDifference)
                            {
                                smallestDifference = dif;
                                smallestIndex = index;
                                if (dif == 0)
                                    break; // foreach ending
                            }
                        }
                    }
                    index++;
                }

                if (smallestDifference > 2)
                {
                    index = 0;
                    foreach (CompareItem compareItem in 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) < minForeColorMatch)
                            {
                                int dif = NikseBitmapImageSplitter.IsBitmapsAlike(target, compareItem.Bitmap);
                                if (dif < smallestDifference)
                                {
                                    smallestDifference = dif;
                                    smallestIndex = index;
                                    if (dif == 0)
                                        break; // foreach ending
                                }
                            }
                        }
                        index++;
                    }
                }

                if (smallestDifference > 3)
                {
                    index = 0;
                    foreach (CompareItem compareItem in compareBitmaps)
                    {
                        if (compareItem.Bitmap.Width == target.Width + 1 && compareItem.Bitmap.Height == target.Height + 1)
                        {
                            if (compareItem.NumberOfForegroundColors == -1)
                                compareItem.NumberOfForegroundColors = CalculateNumberOfForegroundColors(compareItem.Bitmap);

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

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

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

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

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

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

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

                if (smallestDifference > 9 && target.Width > 10)
                {
                    index = 0;
                    foreach (CompareItem compareItem in compareBitmaps)
                    {
                        if (compareItem.Bitmap.Width == target.Width - 2 && compareItem.Bitmap.Height == target.Height)
                        {
                            if (compareItem.NumberOfForegroundColors == -1)
                                compareItem.NumberOfForegroundColors = CalculateNumberOfForegroundColors(compareItem.Bitmap);

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

                if (smallestDifference > 9 && target.Width > 12)
                {
                    index = 0;
                    foreach (CompareItem compareItem in compareBitmaps)
                    {
                        if (compareItem.Bitmap.Width == target.Width - 3 && compareItem.Bitmap.Height == target.Height)
                        {
                            if (compareItem.NumberOfForegroundColors == -1)
                                compareItem.NumberOfForegroundColors = CalculateNumberOfForegroundColors(compareItem.Bitmap);

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

                if (smallestDifference > 9 && target.Width > 12)
                {
                    index = 0;
                    foreach (CompareItem compareItem in compareBitmaps)
                    {
                        if (compareItem.Bitmap.Width == target.Width && compareItem.Bitmap.Height == target.Height - 3)
                        {
                            if (compareItem.NumberOfForegroundColors == -1)
                                compareItem.NumberOfForegroundColors = CalculateNumberOfForegroundColors(compareItem.Bitmap);

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

                if (smallestDifference > 9)
                {
                    index = 0;
                    foreach (CompareItem compareItem in compareBitmaps)
                    {
                        if (compareItem.Bitmap.Width - 2 == target.Width && compareItem.Bitmap.Height == target.Height)
                        {
                            if (compareItem.NumberOfForegroundColors == -1)
                                compareItem.NumberOfForegroundColors = CalculateNumberOfForegroundColors(compareItem.Bitmap);

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

            if (smallestDifference == 0)
            {
                if (smallestIndex > 200)
                {
                    CompareItem hit = compareBitmaps[smallestIndex];
                    compareBitmaps.RemoveAt(smallestIndex);
                    compareBitmaps.Insert(0, hit);
                    smallestIndex = 0;
                    index = 0;
                }
            }
        }
        public static void GenerateLineSegments(int numberOfLines, bool veryPrecise, NOcrChar nOcrChar, NikseBitmap nbmp)
        {
            const int giveUpCount     = 10000;
            var       r               = new Random();
            int       count           = 0;
            int       hits            = 0;
            bool      tempVeryPrecise = veryPrecise;

            while (hits < numberOfLines && count < giveUpCount)
            {
                var start = new Point(r.Next(nOcrChar.Width), r.Next(nOcrChar.Height));
                var end   = new Point(r.Next(nOcrChar.Width), r.Next(nOcrChar.Height));

                if (hits < 5 && count < 100) // a few large lines
                {
                    for (int k = 0; k < 500; k++)
                    {
                        if (Math.Abs(start.X - end.X) + Math.Abs(start.Y - end.Y) > nOcrChar.Height / 2)
                        {
                            break;
                        }
                        else
                        {
                            end = new Point(r.Next(nOcrChar.Width), r.Next(nOcrChar.Height));
                        }
                    }
                }
                else // and a lot of small lines
                {
                    for (int k = 0; k < 500; k++)
                    {
                        if (Math.Abs(start.X - end.X) + Math.Abs(start.Y - end.Y) < 5)
                        {
                            break;
                        }
                        else
                        {
                            end = new Point(r.Next(nOcrChar.Width), r.Next(nOcrChar.Height));
                        }
                    }
                }

                var  op = new NOcrPoint(start, end);
                bool ok = true;
                foreach (NOcrPoint existingOp in nOcrChar.LinesForeground)
                {
                    if (existingOp.Start.X == op.Start.X && existingOp.Start.Y == op.Start.Y &&
                        existingOp.End.X == op.End.X && existingOp.End.Y == op.End.Y)
                    {
                        ok = false;
                    }
                }
                if (ok && IsMatchPointForeGround(op, !tempVeryPrecise, nbmp, nOcrChar))
                {
                    nOcrChar.LinesForeground.Add(op);
                    //AddHistoryItem(nOcrChar);
                    hits++;
                }
                count++;
                if (count > giveUpCount - 100 && !tempVeryPrecise)
                {
                    tempVeryPrecise = true;
                }
            }

            count           = 0;
            hits            = 0;
            tempVeryPrecise = veryPrecise;
            while (hits < numberOfLines && count < giveUpCount)
            {
                var start = new Point(r.Next(nOcrChar.Width), r.Next(nOcrChar.Height));
                var end   = new Point(r.Next(nOcrChar.Width), r.Next(nOcrChar.Height));

                if (hits < 5 && count < 100) // a few large lines
                {
                    for (int k = 0; k < 500; k++)
                    {
                        if (Math.Abs(start.X - end.X) + Math.Abs(start.Y - end.Y) > nOcrChar.Height / 2)
                        {
                            break;
                        }
                        else
                        {
                            end = new Point(r.Next(nOcrChar.Width), r.Next(nOcrChar.Height));
                        }
                    }
                }
                else // and a lot of small lines
                {
                    for (int k = 0; k < 500; k++)
                    {
                        if (Math.Abs(start.X - end.X) + Math.Abs(start.Y - end.Y) < 5)
                        {
                            break;
                        }
                        else
                        {
                            end = new Point(r.Next(nOcrChar.Width), r.Next(nOcrChar.Height));
                        }
                    }
                }

                var  op = new NOcrPoint(start, end);
                bool ok = true;
                foreach (NOcrPoint existingOp in nOcrChar.LinesBackground)
                {
                    if (existingOp.Start.X == op.Start.X && existingOp.Start.Y == op.Start.Y &&
                        existingOp.End.X == op.End.X && existingOp.End.Y == op.End.Y)
                    {
                        ok = false;
                    }
                }
                if (ok && IsMatchPointBackGround(op, !tempVeryPrecise, nbmp, nOcrChar))
                {
                    nOcrChar.LinesBackground.Add(op);
                    //AddHistoryItem(nOcrChar);
                    hits++;
                }
                count++;

                if (count > giveUpCount - 100 && !tempVeryPrecise)
                {
                    tempVeryPrecise = true;
                }
            }
        }
Пример #28
0
        private static NOcrChar NOcrFindExpandedMatch(NikseBitmap nbmp, ImageSplitterItem targetItem, List<NOcrChar> nOcrChars)
        {
            int w = targetItem.NikseBitmap.Width;
            foreach (NOcrChar oc in nOcrChars)
            {
                if (oc.ExpandCount > 1 && oc.Width > w && targetItem.X + oc.Width < nbmp.Width)
                {
                    bool ok = true;
                    var index = 0;
                    while (index < oc.LinesForeground.Count && ok)
                    {
                        NOcrPoint op = oc.LinesForeground[index];
                        foreach (Point point in op.GetPoints())
                        {
                            Point p = new Point(point.X + targetItem.X, point.Y + targetItem.Y);
                            if (p.X >= 0 && p.Y >= 0 && p.X < nbmp.Width && p.Y < nbmp.Height)
                            {
                                Color c = nbmp.GetPixel(p.X, p.Y);
                                if (c.A > 150 && c.R + c.G + c.B > NocrMinColor)
                                {
                                }
                                else
                                {
                                    ok = false;
                                    break;
                                }
                            }
                        }
                        index++;
                    }
                    index = 0;
                    while (index < oc.LinesBackground.Count && ok)
                    {
                        NOcrPoint op = oc.LinesBackground[index];
                        foreach (Point point in op.GetPoints())
                        {
                            Point p = new Point(point.X + targetItem.X, point.Y + targetItem.Y);
                            if (p.X >= 0 && p.Y >= 0 && p.X < nbmp.Width && p.Y < nbmp.Height)
                            {
                                Color c = nbmp.GetPixel(p.X, p.Y);
                                if (c.A > 150 && c.R + c.G + c.B > NocrMinColor)
                                {
                                    ok = false;
                                    break;
                                }
                            }
                        }
                        index++;
                    }
                    if (ok)
                        return oc;

                    ok = true;
                    index = 0;
                    while (index < oc.LinesForeground.Count && ok)
                    {
                        NOcrPoint op = oc.LinesForeground[index];
                        foreach (Point point in op.ScaledGetPoints(oc, oc.Width, oc.Height - 1))
                        {
                            Point p = new Point(point.X + targetItem.X, point.Y + targetItem.Y);
                            if (p.X >= 0 && p.Y >= 0 && p.X < nbmp.Width && p.Y < nbmp.Height)
                            {
                                Color c = nbmp.GetPixel(p.X, p.Y);
                                if (c.A > 150 && c.R + c.G + c.B > NocrMinColor)
                                {
                                }
                                else
                                {
                                    ok = false;
                                    break;
                                }
                            }
                        }
                        index++;
                    }
                    index = 0;
                    while (index < oc.LinesBackground.Count && ok)
                    {
                        NOcrPoint op = oc.LinesBackground[index];
                        foreach (Point point in op.ScaledGetPoints(oc, oc.Width, oc.Height - 1))
                        {
                            Point p = new Point(point.X + targetItem.X, point.Y + targetItem.Y);
                            if (p.X >= 0 && p.Y >= 0 && p.X < nbmp.Width && p.Y < nbmp.Height)
                            {
                                Color c = nbmp.GetPixel(p.X, p.Y);
                                if (c.A > 150 && c.R + c.G + c.B > NocrMinColor)
                                {
                                    ok = false;
                                    break;
                                }
                            }
                        }
                        index++;
                    }
                    if (ok)
                        return oc;
                }
            }
            return null;
        }
        private static bool IsMatchPointForeGround(NOcrPoint op, bool loose, NikseBitmap nbmp, NOcrChar nOcrChar)
        {
            if (Math.Abs(op.Start.X - op.End.X) < 2 && Math.Abs(op.End.Y - op.Start.Y) < 2)
            {
                return(false);
            }

            foreach (Point point in op.ScaledGetPoints(nOcrChar, 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 + 100 + c.G + c.B > VobSubOcr.NocrMinColor)
                    {
                    }
                    else
                    {
                        return(false);
                    }

                    if (loose)
                    {
                        if (nbmp.Width > 10 && point.X + 1 < nbmp.Width)
                        {
                            c = nbmp.GetPixel(point.X + 1, point.Y);
                            if (c.A > 150 && c.R + 100 + c.G + c.B > VobSubOcr.NocrMinColor)
                            {
                            }
                            else
                            {
                                return(false);
                            }
                        }

                        if (nbmp.Width > 10 && point.X >= 1)
                        {
                            c = nbmp.GetPixel(point.X - 1, point.Y);
                            if (c.A > 150 && c.R + 100 + c.G + c.B > VobSubOcr.NocrMinColor)
                            {
                            }
                            else
                            {
                                return(false);
                            }
                        }

                        if (nbmp.Height > 10 && point.Y + 1 < nbmp.Height)
                        {
                            c = nbmp.GetPixel(point.X, point.Y + 1);
                            if (c.A > 150 && c.R + 100 + c.G + c.B > VobSubOcr.NocrMinColor)
                            {
                            }
                            else
                            {
                                return(false);
                            }
                        }

                        if (nbmp.Height > 10 && point.Y >= 1)
                        {
                            c = nbmp.GetPixel(point.X, point.Y - 1);
                            if (c.A > 150 && c.R + 100 + c.G + c.B > VobSubOcr.NocrMinColor)
                            {
                            }
                            else
                            {
                                return(false);
                            }
                        }
                    }
                }
            }
            return(true);
        }
Пример #30
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;
        }
Пример #31
0
        private byte[] GetSubImageBuffer(RunLengthTwoParts twoPartBuffer, NikseBitmap nbmp, Paragraph p, ContentAlignment alignment, Point?overridePosition)
        {
            var ms = new MemoryStream();

            // sup picture datasize
            WriteEndianWord(twoPartBuffer.Length + 34, ms);

            // first display control sequence table address
            int startDisplayControlSequenceTableAddress = twoPartBuffer.Length + 4;

            WriteEndianWord(startDisplayControlSequenceTableAddress, ms);

            // Write image
            const int imageTopFieldDataAddress = 4;

            ms.Write(twoPartBuffer.Buffer1, 0, twoPartBuffer.Buffer1.Length);
            int imageBottomFieldDataAddress = 4 + twoPartBuffer.Buffer1.Length;

            ms.Write(twoPartBuffer.Buffer2, 0, twoPartBuffer.Buffer2.Length);

            // Write zero delay
            ms.WriteByte(0);
            ms.WriteByte(0);

            // next display control sequence table address (use current is last)
            WriteEndianWord(startDisplayControlSequenceTableAddress + 24, ms); // start of display control sequence table address

            // Control command start
            ms.WriteByte(p.Forced ? (byte)0 : (byte)1);

            // Control command 3 = SetColor
            WriteColors(ms); // 3 bytes

            // Control command 4 = SetContrast
            WriteContrast(ms); // 3 bytes

            // Control command 5 = SetDisplayArea
            WriteDisplayArea(ms, nbmp, alignment, overridePosition); // 7 bytes

            // Control command 6 = SetPixelDataAddress
            WritePixelDataAddress(ms, imageTopFieldDataAddress, imageBottomFieldDataAddress); // 5 bytes

            // Control command exit
            ms.WriteByte(255); // 1 byte

            // Control Sequence Table
            // Write delay - subtitle duration
            WriteEndianWord(Convert.ToInt32(p.Duration.TotalMilliseconds * 90.0) >> 10, ms);
            //            WriteEndianWord(Convert.ToInt32(p.Duration.TotalMilliseconds * 90.0 - 1023) >> 10, ms);

            // next display control sequence table address (use current is last)
            WriteEndianWord(startDisplayControlSequenceTableAddress + 24, ms); // start of display control sequence table address

            // Control command 2 = StopDisplay
            ms.WriteByte(2);

            // extra byte - for compatability with gpac/MP4BOX
            ms.WriteByte(255); // 1 byte

            return(ms.ToArray());
        }
Пример #32
0
        private void inspectImageCompareMatchesForCurrentImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (subtitleListView1.SelectedItems.Count != 1)
                return;

            if (_compareBitmaps == null)
                LoadImageCompareBitmaps();

            Cursor = Cursors.WaitCursor;
            Bitmap bitmap = GetSubtitleBitmap(subtitleListView1.SelectedItems[0].Index);
            NikseBitmap parentBitmap = new NikseBitmap(bitmap);
            var matches = new List<CompareMatch>();
            List<ImageSplitterItem> list;

            if (_binaryOcrDb == null)
            {
                list = NikseBitmapImageSplitter.SplitBitmapToLetters(parentBitmap, (int)numericUpDownPixelsIsSpace.Value, checkBoxRightToLeft.Checked, Configuration.Settings.VobSubOcr.TopToBottom);
            }
            else
            {
                int minLineHeight = _binOcrLastLowercaseHeight - 3;
                if (minLineHeight < 5)
                    minLineHeight = 5;
                list = NikseBitmapImageSplitter.SplitBitmapToLettersNew(parentBitmap, (int)numericUpDownPixelsIsSpace.Value, checkBoxRightToLeft.Checked, Configuration.Settings.VobSubOcr.TopToBottom, minLineHeight);
            }

            int index = 0;
            var imageSources = new List<Bitmap>();
            while (index < list.Count)
            {
                ImageSplitterItem item = list[index];
                if (item.NikseBitmap == null)
                {
                    matches.Add(new CompareMatch(item.SpecialCharacter, false, 0, null));
                    imageSources.Add(null);
                }
                else
                {
                    CompareMatch bestGuess;
                    CompareMatch match;
                    if (_binaryOcrDb != null)
                        match = GetCompareMatchNew(item, out bestGuess, list, index);
                    else
                        match = GetCompareMatch(item, parentBitmap, out bestGuess, list, index);
                    if (match == null)
                    {
                        matches.Add(new CompareMatch(Configuration.Settings.Language.VobSubOcr.NoMatch, false, 0, null));
                        imageSources.Add(item.NikseBitmap.GetBitmap());
                    }
                    else // found image match
                    {
                        if (match.ExpandCount > 0)
                        {
                            List<ImageSplitterItem> expandSelectionList = new List<ImageSplitterItem>();
                            for (int i = 0; i < match.ExpandCount; i++)
                            {
                                expandSelectionList.Add(list[index + i]);
                            }
                            item = GetExpandedSelectionNew(parentBitmap, expandSelectionList);
                            matches.Add(new CompareMatch(match.Text, match.Italic, 0, match.Name, item));
                            imageSources.Add(item.NikseBitmap.GetBitmap());
                        }
                        else
                        {
                            matches.Add(new CompareMatch(match.Text, match.Italic, 0, match.Name, item));
                            imageSources.Add(item.NikseBitmap.GetBitmap());
                        }

                        if (match.ExpandCount > 0)
                            index += match.ExpandCount - 1;
                    }
                }
                index++;
            }
            Cursor = Cursors.Default;
            using (var inspect = new VobSubOcrCharacterInspect())
            {
                inspect.Initialize(comboBoxCharacterDatabase.SelectedItem.ToString(), matches, imageSources, _binaryOcrDb);
                if (inspect.ShowDialog(this) == DialogResult.OK)
                {
                    Cursor = Cursors.WaitCursor;
                    if (_binaryOcrDb != null)
                    {
                        _binaryOcrDb.Save();
                        Cursor = Cursors.Default;
                        return;
                    }
                    _compareDoc = inspect.ImageCompareDocument;
                    string path = Configuration.VobSubCompareFolder + comboBoxCharacterDatabase.SelectedItem + Path.DirectorySeparatorChar;
                    _compareDoc.Save(path + "Images.xml");
                    LoadImageCompareBitmaps();
                    Cursor = Cursors.Default;
                }
            }
            if (_binaryOcrDb != null)
                _binaryOcrDb.LoadCompareImages();
            Cursor = Cursors.Default;
        }
Пример #33
0
        public void WriteParagraph(Paragraph p, Bitmap bmp, ContentAlignment alignment, Point?overridePosition = null)  // inspired by code from SubtitleCreator
        {
            // timestamp: 00:00:33:900, filepos: 000000000
            _idx.AppendLine($"timestamp: {p.StartTime.Hours:00}:{p.StartTime.Minutes:00}:{p.StartTime.Seconds:00}:{p.StartTime.Milliseconds:000}, filepos: {_subFile.Position.ToString("X").PadLeft(9, '0').ToLower()}");

            var nbmp = new NikseBitmap(bmp);

            _emphasis2 = nbmp.ConverToFourColors(_background, _pattern, _emphasis1, _useInnerAntialiasing);
            var twoPartBuffer = nbmp.RunLengthEncodeForDvd(_background, _pattern, _emphasis1, _emphasis2);
            var imageBuffer   = GetSubImageBuffer(twoPartBuffer, nbmp, p, alignment, overridePosition);

            int  bufferIndex = 0;
            byte vobSubId    = (byte)_languageStreamId;
            var  mwsub       = new MemWriter(200000);

            byte[] subHeader = new byte[30];
            byte[] ts        = new byte[4];

            // Lended from "Son2VobSub" by Alain Vielle and Petr Vyskocil
            // And also from Sup2VobSub by Emmel
            subHeader[0]  = 0x00; // MPEG 2 PACK HEADER
            subHeader[1]  = 0x00;
            subHeader[2]  = 0x01;
            subHeader[3]  = 0xba;
            subHeader[4]  = 0x44;
            subHeader[5]  = 0x02;
            subHeader[6]  = 0xc4;
            subHeader[7]  = 0x82;
            subHeader[8]  = 0x04;
            subHeader[9]  = 0xa9;
            subHeader[10] = 0x01;
            subHeader[11] = 0x89;
            subHeader[12] = 0xc3;
            subHeader[13] = 0xf8;

            subHeader[14] = 0x00; // PES
            subHeader[15] = 0x00;
            subHeader[16] = 0x01;
            subHeader[17] = 0xbd;

            int  packetSize = imageBuffer.Length;
            long toWrite    = packetSize; // Image buffer + control sequence length
            bool header0    = true;

            while (toWrite > 0)
            {
                long headerSize;
                if (header0)
                {
                    header0 = false;

                    // This is only for first packet
                    subHeader[20] = 0x81;   // mark as original
                    subHeader[21] = 0x80;   // first packet: PTS
                    subHeader[22] = 0x05;   // PES header data length

                    // PTS (90kHz):
                    //--------------
                    subHeader[23] = (byte)((ts[3] & 0xc0) >> 5 | 0x21);
                    subHeader[24] = (byte)((ts[3] & 0x3f) << 2 | (ts[2] & 0xc0) >> 6);
                    subHeader[25] = (byte)((ts[2] & 0x3f) << 2 | (ts[1] & 0x80) >> 6 | 0x01);
                    subHeader[26] = (byte)((ts[1] & 0x7f) << 1 | (ts[0] & 0x80) >> 7);
                    subHeader[27] = (byte)((ts[0] & 0x7f) << 1 | 0x01);

                    const string pre             = "0010"; // 0011 or 0010 ? (KMPlayer will not understand 0011!!!)
                    long         newPts          = (long)(p.StartTime.TotalSeconds * 90000.0);
                    string       bString         = Convert.ToString(newPts, 2).PadLeft(33, '0');
                    string       fiveBytesString = pre + bString.Substring(0, 3) + "1" + bString.Substring(3, 15) + "1" + bString.Substring(18, 15) + "1";
                    for (int i = 0; i < 5; i++)
                    {
                        subHeader[23 + i] = Convert.ToByte(fiveBytesString.Substring(i * 8, 8), 2);
                    }
                    subHeader[28] = vobSubId;
                    headerSize    = 29;
                }
                else
                {
                    subHeader[20] = 0x81; // mark as original
                    subHeader[21] = 0x00; // no PTS
                    subHeader[22] = 0x00; // header data length
                    subHeader[23] = vobSubId;
                    headerSize    = 24;
                }

                if ((toWrite + headerSize) <= 0x800)
                {
                    // write whole image in one 0x800 part

                    long j = (headerSize - 20) + toWrite;
                    subHeader[18] = (byte)(j / 0x100);
                    subHeader[19] = (byte)(j % 0x100);

                    // First Write header
                    for (int x = 0; x < headerSize; x++)
                    {
                        mwsub.WriteByte(subHeader[x]);
                    }

                    // Write Image Data
                    for (int x = 0; x < toWrite; x++)
                    {
                        mwsub.WriteByte(imageBuffer[bufferIndex++]);
                    }

                    // Pad remaining space
                    long paddingSize = 0x800 - headerSize - toWrite;
                    for (int x = 0; x < paddingSize; x++)
                    {
                        mwsub.WriteByte(0xff);
                    }

                    toWrite = 0;
                }
                else
                {
                    // write multiple parts

                    long blockSize = 0x800 - headerSize;
                    long j         = (headerSize - 20) + blockSize;
                    subHeader[18] = (byte)(j / 0x100);
                    subHeader[19] = (byte)(j % 0x100);

                    // First Write header
                    for (int x = 0; x < headerSize; x++)
                    {
                        mwsub.WriteByte(subHeader[x]);
                    }

                    // Write Image Data
                    for (int x = 0; x < blockSize; x++)
                    {
                        mwsub.WriteByte(imageBuffer[bufferIndex++]);
                    }

                    toWrite -= blockSize;
                }
            }

            // Write whole memory stream to file
            long endPosition = mwsub.GetPosition();

            mwsub.GotoBegin();
            _subFile.Write(mwsub.GetBuf(), 0, (int)endPosition);
        }
Пример #34
0
        private void NOCRIntialize(Bitmap bitmap)
        {
            var nikseBitmap = new NikseBitmap(bitmap);
            List<ImageSplitterItem> list = NikseBitmapImageSplitter.SplitBitmapToLetters(nikseBitmap, (int)numericUpDownNumberOfPixelsIsSpaceNOCR.Value, checkBoxRightToLeft.Checked, Configuration.Settings.VobSubOcr.TopToBottom);

            foreach (ImageSplitterItem item in list)
            {
                if (item.NikseBitmap != null)
                {
                    var nbmp = item.NikseBitmap;
                    nbmp.ReplaceNonWhiteWithTransparent();
                    item.Y += nbmp.CropTopTransparent(0);
                    nbmp.CropTransparentSidesAndBottom(0, true);
                    nbmp.ReplaceTransparentWith(Color.Black);
                    GetNOcrCompareMatch(item, nikseBitmap, _nOcrDb, false, false);
                }
            }
        }
Пример #35
0
 internal static ImageSplitterItem GetExpandedSelection(NikseBitmap bitmap, List<ImageSplitterItem> expandSelectionList, bool rightToLeft)
 {
     if (rightToLeft)
     {
         int minimumX = expandSelectionList[expandSelectionList.Count - 1].X - expandSelectionList[expandSelectionList.Count - 1].NikseBitmap.Width;
         int maximumX = expandSelectionList[0].X;
         int minimumY = expandSelectionList[0].Y;
         int maximumY = expandSelectionList[0].Y + expandSelectionList[0].NikseBitmap.Height;
         foreach (ImageSplitterItem item in expandSelectionList)
         {
             if (item.Y < minimumY)
                 minimumY = item.Y;
             if (item.Y + item.NikseBitmap.Height > maximumY)
                 maximumY = item.Y + item.NikseBitmap.Height;
         }
         var part = bitmap.CopyRectangle(new Rectangle(minimumX, minimumY, maximumX - minimumX, maximumY - minimumY));
         return new ImageSplitterItem(minimumX, minimumY, part);
     }
     else
     {
         int minimumX = expandSelectionList[0].X;
         int maximumX = expandSelectionList[expandSelectionList.Count - 1].X + expandSelectionList[expandSelectionList.Count - 1].NikseBitmap.Width;
         int minimumY = expandSelectionList[0].Y;
         int maximumY = expandSelectionList[0].Y + expandSelectionList[0].NikseBitmap.Height;
         foreach (ImageSplitterItem item in expandSelectionList)
         {
             if (item.Y < minimumY)
                 minimumY = item.Y;
             if (item.Y + item.NikseBitmap.Height > maximumY)
                 maximumY = item.Y + item.NikseBitmap.Height;
         }
         var part = bitmap.CopyRectangle(new Rectangle(minimumX, minimumY, maximumX - minimumX, maximumY - minimumY));
         return new ImageSplitterItem(minimumX, minimumY, part);
     }
 }
Пример #36
0
        private string OcrViaTesseract(Bitmap bitmap, int index)
        {
            if (bitmap == null)
                return string.Empty;

            if (_ocrFixEngine == null)
                comboBoxDictionaries_SelectedIndexChanged(null, null);

            const int badWords = 0;
            string textWithOutFixes;
            if (_tesseractAsyncStrings != null && !string.IsNullOrEmpty(_tesseractAsyncStrings[index]))
            {
                textWithOutFixes = _tesseractAsyncStrings[index];
            }
            else
            {
                if (_tesseractAsyncIndex <= index)
                    _tesseractAsyncIndex = index + 10;
                textWithOutFixes = Tesseract3DoOcrViaExe(bitmap, _languageId, "-psm 6"); // 6 = Assume a single uniform block of text.
            }

            if ((!textWithOutFixes.Contains(Environment.NewLine) || Utilities.CountTagInText(textWithOutFixes, '\n') > 2)
                && (textWithOutFixes.Length < 17 || bitmap.Height < 50))
            {
                string psm = Tesseract3DoOcrViaExe(bitmap, _languageId, "-psm 7"); // 7 = Treat the image as a single text line.
                if (textWithOutFixes != psm)
                {
                    if (string.IsNullOrWhiteSpace(textWithOutFixes))
                    {
                        textWithOutFixes = psm;
                    }
                    else if (psm.Length > textWithOutFixes.Length)
                    {
                        if (!psm.Contains('9') && textWithOutFixes.Contains('9') ||
                            !psm.Contains('6') && textWithOutFixes.Contains('6') ||
                            !psm.Contains('5') && textWithOutFixes.Contains('5') ||
                            !psm.Contains('3') && textWithOutFixes.Contains('3') ||
                            !psm.Contains('1') && textWithOutFixes.Contains('1') ||
                            !psm.Contains('$') && textWithOutFixes.Contains('$') ||
                            !psm.Contains('•') && textWithOutFixes.Contains('•') ||
                            !psm.Contains('Y') && textWithOutFixes.Contains('Y') ||
                            !psm.Contains('\'') && textWithOutFixes.Contains('\'') ||
                            !psm.Contains('€') && textWithOutFixes.Contains('€'))
                        {
                            textWithOutFixes = psm;
                        }
                        else if (_ocrFixEngine != null && !psm.Contains('$') && !psm.Contains('•') && !psm.Contains('€'))
                        {
                            int correctWordsNoFixes;
                            int wordsNotFoundNoFixes = _ocrFixEngine.CountUnknownWordsViaDictionary(textWithOutFixes, out correctWordsNoFixes);
                            int correctWordsPsm7;
                            int wordsNotFoundPsm7 = _ocrFixEngine.CountUnknownWordsViaDictionary(psm, out correctWordsPsm7);
                            if (wordsNotFoundPsm7 <= wordsNotFoundNoFixes && correctWordsPsm7 > correctWordsNoFixes)
                            {
                                textWithOutFixes = psm;
                            }
                        }
                    }
                    else if (psm.Length == textWithOutFixes.Length &&
                             (!psm.Contains('0') && textWithOutFixes.Contains('0') ||  // these chars are often mistaken
                              !psm.Contains('9') && textWithOutFixes.Contains('9') ||
                              !psm.Contains('8') && textWithOutFixes.Contains('8') ||
                              !psm.Contains('5') && textWithOutFixes.Contains('5') ||
                              !psm.Contains('3') && textWithOutFixes.Contains('3') ||
                              !psm.Contains('1') && textWithOutFixes.Contains('1') ||
                              !psm.Contains('$') && textWithOutFixes.Contains('$') ||
                              !psm.Contains('€') && textWithOutFixes.Contains('€') ||
                              !psm.Contains('•') && textWithOutFixes.Contains('•') ||
                              !psm.Contains('Y') && textWithOutFixes.Contains('Y') ||
                              !psm.Contains('\'') && textWithOutFixes.Contains('\'') ||
                              !psm.Contains('/') && textWithOutFixes.Contains('/') ||
                              !psm.Contains('(') && textWithOutFixes.Contains('(') ||
                              !psm.Contains(')') && textWithOutFixes.Contains(')') ||
                              !psm.Contains('_') && textWithOutFixes.Contains('_')))
                    {
                        textWithOutFixes = psm;
                    }
                    else if (psm.Length == textWithOutFixes.Length && psm.EndsWith('.') && !textWithOutFixes.EndsWith('.'))
                    {
                        textWithOutFixes = psm;
                    }
                }
            }
            if (!checkBoxTesseractItalicsOn.Checked)
                textWithOutFixes = HtmlUtil.RemoveOpenCloseTags(textWithOutFixes, HtmlUtil.TagItalic);

            // Sometimes Tesseract has problems with small fonts - it helps to make the image larger
            if (HtmlUtil.RemoveOpenCloseTags(textWithOutFixes, HtmlUtil.TagItalic).Replace("@", string.Empty).Replace("%", string.Empty).Replace("|", string.Empty).Trim().Length < 3
                || Utilities.CountTagInText(textWithOutFixes, '\n') > 2)
            {
                string rs = TesseractResizeAndRetry(bitmap);
                textWithOutFixes = rs;
                if (!checkBoxTesseractItalicsOn.Checked)
                    textWithOutFixes = HtmlUtil.RemoveOpenCloseTags(textWithOutFixes, HtmlUtil.TagItalic);
            }

            // fix italics
            textWithOutFixes = FixItalics(textWithOutFixes);

            int numberOfWords = textWithOutFixes.Split((" " + Environment.NewLine).ToCharArray(), StringSplitOptions.RemoveEmptyEntries).Length;

            string line = textWithOutFixes.Trim();
            if (_ocrFixEngine.IsDictionaryLoaded)
            {
                if (checkBoxAutoFixCommonErrors.Checked)
                    line = _ocrFixEngine.FixOcrErrors(line, index, _lastLine, true, GetAutoGuessLevel());
                int correctWords;
                int wordsNotFound = _ocrFixEngine.CountUnknownWordsViaDictionary(line, out correctWords);
                int oldCorrectWords = correctWords;

                if (wordsNotFound > 0 || correctWords == 0)
                {
                    List<string> oldUnkownWords = new List<string>();
                    oldUnkownWords.AddRange(_ocrFixEngine.UnknownWordsFound);
                    _ocrFixEngine.UnknownWordsFound.Clear();

                    string newUnfixedText = TesseractResizeAndRetry(bitmap);
                    string newText = _ocrFixEngine.FixOcrErrors(newUnfixedText, index, _lastLine, true, GetAutoGuessLevel());
                    int newWordsNotFound = _ocrFixEngine.CountUnknownWordsViaDictionary(newText, out correctWords);

                    if (wordsNotFound == 1 && newWordsNotFound == 1 && newUnfixedText.EndsWith("!!") && textWithOutFixes.EndsWith('u') && newText.Length > 1)
                    {
                        _ocrFixEngine.UnknownWordsFound.Clear();
                        newText = textWithOutFixes.Substring(0, textWithOutFixes.Length - 1) + "!!";
                        newWordsNotFound = _ocrFixEngine.CountUnknownWordsViaDictionary(newText, out correctWords);
                    }
                    else if (correctWords >= oldCorrectWords &&
                             (!newText.Contains('9') || textWithOutFixes.Contains('9')) &&
                             (!newText.Replace("</i>", string.Empty).Contains('/') || textWithOutFixes.Replace("</i>", string.Empty).Contains('/')) &&
                             !string.IsNullOrWhiteSpace(newUnfixedText) &&
                             newWordsNotFound < wordsNotFound || (newWordsNotFound == wordsNotFound && newText.EndsWith('!') && textWithOutFixes.EndsWith('l')))
                    {
                        wordsNotFound = newWordsNotFound;
                        if (textWithOutFixes.Length > 3 && textWithOutFixes.EndsWith("...") && !newText.EndsWith('.') && !newText.EndsWith(',') && !newText.EndsWith('!') &&
                            !newText.EndsWith('?') && !newText.EndsWith("</i>"))
                            newText = newText.TrimEnd() + "...";
                        else if (textWithOutFixes.Length > 0 && textWithOutFixes.EndsWith('.') && !newText.EndsWith('.') && !newText.EndsWith(',') && !newText.EndsWith('!') &&
                            !newText.EndsWith('?') && !newText.EndsWith("</i>"))
                            newText = newText.TrimEnd() + ".";
                        else if (textWithOutFixes.Length > 0 && textWithOutFixes.EndsWith('?') && !newText.EndsWith('.') && !newText.EndsWith(',') && !newText.EndsWith('!') &&
                            !newText.EndsWith('?') && !newText.EndsWith("</i>"))
                            newText = newText.TrimEnd() + "?";

                        textWithOutFixes = newUnfixedText;
                        line = FixItalics(newText);
                    }
                    else if (correctWords > oldCorrectWords + 1 || (correctWords > oldCorrectWords && !textWithOutFixes.Contains(' ')))
                    {
                        wordsNotFound = newWordsNotFound;
                        textWithOutFixes = newUnfixedText;
                        line = newText;
                    }
                    else
                    {
                        _ocrFixEngine.UnknownWordsFound.Clear();
                        _ocrFixEngine.UnknownWordsFound.AddRange(oldUnkownWords);
                    }
                }

                if (wordsNotFound > 0 || correctWords == 0 || textWithOutFixes != null && textWithOutFixes.Replace("~", string.Empty).Trim().Length < 2)
                {
                    if (_bluRaySubtitles != null && !line.Contains("<i>"))
                    {
                        _ocrFixEngine.AutoGuessesUsed.Clear();
                        _ocrFixEngine.UnknownWordsFound.Clear();

                        // which is best - normal image or one color image?
                        var nbmp = new NikseBitmap(bitmap);
                        nbmp.MakeOneColor(Color.White);
                        Bitmap oneColorBitmap = nbmp.GetBitmap();
                        string oneColorText = Tesseract3DoOcrViaExe(oneColorBitmap, _languageId, "-psm 6"); // 6 = Assume a single uniform block of text.
                        oneColorBitmap.Dispose();
                        nbmp = null;

                        if (oneColorText.Length > 1 &&
                            !oneColorText.Contains("CD") &&
                            (!oneColorText.Contains('0') || line.Contains('0')) &&
                            (!oneColorText.Contains('2') || line.Contains('2')) &&
                            (!oneColorText.Contains('3') || line.Contains('4')) &&
                            (!oneColorText.Contains('5') || line.Contains('5')) &&
                            (!oneColorText.Contains('9') || line.Contains('9')) &&
                            (!oneColorText.Contains('•') || line.Contains('•')) &&
                            (!oneColorText.Contains(')') || line.Contains(')')) &&
                            Utilities.CountTagInText(oneColorText, '(') < 2 && Utilities.CountTagInText(oneColorText, ')') < 2 &&
                            Utilities.GetNumberOfLines(oneColorText) < 4)
                        {
                            int modiCorrectWords;
                            int modiWordsNotFound = _ocrFixEngine.CountUnknownWordsViaDictionary(oneColorText, out modiCorrectWords);
                            string modiTextOcrFixed = oneColorText;
                            if (checkBoxAutoFixCommonErrors.Checked)
                                modiTextOcrFixed = _ocrFixEngine.FixOcrErrors(oneColorText, index, _lastLine, false, GetAutoGuessLevel());
                            int modiOcrCorrectedCorrectWords;
                            int modiOcrCorrectedWordsNotFound = _ocrFixEngine.CountUnknownWordsViaDictionary(modiTextOcrFixed, out modiOcrCorrectedCorrectWords);
                            if (modiOcrCorrectedWordsNotFound <= modiWordsNotFound)
                            {
                                oneColorText = modiTextOcrFixed;
                                modiWordsNotFound = modiOcrCorrectedWordsNotFound;
                                modiCorrectWords = modiOcrCorrectedCorrectWords;
                            }

                            if (modiWordsNotFound < wordsNotFound || (textWithOutFixes.Length == 1 && modiWordsNotFound == 0))
                            {
                                line = FixItalics(oneColorText); // use one-color text
                                wordsNotFound = modiWordsNotFound;
                                correctWords = modiCorrectWords;
                                if (checkBoxAutoFixCommonErrors.Checked)
                                    line = _ocrFixEngine.FixOcrErrors(line, index, _lastLine, true, GetAutoGuessLevel());
                            }
                            else if (wordsNotFound == modiWordsNotFound && oneColorText.EndsWith('!') && (line.EndsWith('l') || line.EndsWith('fl')))
                            {
                                line = FixItalics(oneColorText);
                                wordsNotFound = modiWordsNotFound;
                                correctWords = modiCorrectWords;
                                if (checkBoxAutoFixCommonErrors.Checked)
                                    line = _ocrFixEngine.FixOcrErrors(line, index, _lastLine, true, GetAutoGuessLevel());
                            }
                        }
                    }
                }

                if (checkBoxTesseractItalicsOn.Checked)
                {
                    if (line.Contains("<i>") || wordsNotFound > 0 || correctWords == 0 || textWithOutFixes != null && textWithOutFixes.Replace("~", string.Empty).Trim().Length < 2)
                    {
                        _ocrFixEngine.AutoGuessesUsed.Clear();
                        _ocrFixEngine.UnknownWordsFound.Clear();

                        // which is best - normal image or de-italic'ed? We find out here
                        var unItalicedBmp = UnItalic(bitmap, _unItalicFactor);
                        string unItalicText = Tesseract3DoOcrViaExe(unItalicedBmp, _languageId, "-psm 6"); // 6 = Assume a single uniform block of text.
                        unItalicedBmp.Dispose();

                        if (unItalicText.Length > 1)
                        {
                            int modiCorrectWords;
                            int modiWordsNotFound = _ocrFixEngine.CountUnknownWordsViaDictionary(unItalicText, out modiCorrectWords);
                            string modiTextOcrFixed = unItalicText;
                            if (checkBoxAutoFixCommonErrors.Checked)
                                modiTextOcrFixed = _ocrFixEngine.FixOcrErrors(unItalicText, index, _lastLine, false, GetAutoGuessLevel());
                            int modiOcrCorrectedCorrectWords;
                            int modiOcrCorrectedWordsNotFound = _ocrFixEngine.CountUnknownWordsViaDictionary(modiTextOcrFixed, out modiOcrCorrectedCorrectWords);
                            if (modiOcrCorrectedWordsNotFound <= modiWordsNotFound)
                            {
                                unItalicText = modiTextOcrFixed;
                                modiWordsNotFound = modiOcrCorrectedWordsNotFound;
                                modiCorrectWords = modiOcrCorrectedCorrectWords;
                            }

                            bool ok = modiWordsNotFound < wordsNotFound || (textWithOutFixes.Length == 1 && modiWordsNotFound == 0);

                            if (!ok)
                                ok = wordsNotFound == modiWordsNotFound && unItalicText.EndsWith('!') && (line.EndsWith('l') || line.EndsWith('fl'));

                            if (!ok)
                                ok = wordsNotFound == modiWordsNotFound && line.StartsWith("<i>") && line.EndsWith("</i>");

                            if (ok && Utilities.CountTagInText(unItalicText, '/') > Utilities.CountTagInText(line, '/') + 1)
                                ok = false;
                            if (ok && Utilities.CountTagInText(unItalicText, '\\') > Utilities.CountTagInText(line, '\\'))
                                ok = false;
                            if (ok && Utilities.CountTagInText(unItalicText, ')') > Utilities.CountTagInText(line, ')') + 1)
                                ok = false;
                            if (ok && Utilities.CountTagInText(unItalicText, '(') > Utilities.CountTagInText(line, '(') + 1)
                                ok = false;
                            if (ok && Utilities.CountTagInText(unItalicText, '$') > Utilities.CountTagInText(line, '$') + 1)
                                ok = false;
                            if (ok && Utilities.CountTagInText(unItalicText, '€') > Utilities.CountTagInText(line, '€') + 1)
                                ok = false;
                            if (ok && Utilities.CountTagInText(unItalicText, '•') > Utilities.CountTagInText(line, '•'))
                                ok = false;

                            if (ok)
                            {
                                wordsNotFound = modiWordsNotFound;
                                correctWords = modiCorrectWords;

                                line = HtmlUtil.RemoveOpenCloseTags(line, HtmlUtil.TagItalic).Trim();

                                if (line.Length > 7 && unItalicText.Length > 7 && unItalicText.StartsWith("I ") &&
                                    line.StartsWith(unItalicText.Remove(0, 2).Substring(0, 4)))
                                    unItalicText = unItalicText.Remove(0, 2);

                                if (checkBoxTesseractMusicOn.Checked)
                                {
                                    if ((line.StartsWith("J' ") || line.StartsWith("J“ ") || line.StartsWith("J* ") || line.StartsWith("♪ ")) && unItalicText.Length > 3 && HtmlUtil.RemoveOpenCloseTags(unItalicText, HtmlUtil.TagItalic).Substring(1, 2) == "' ")
                                    {
                                        unItalicText = "♪ " + unItalicText.Remove(0, 2).TrimStart();
                                    }
                                    if ((line.StartsWith("J' ") || line.StartsWith("J“ ") || line.StartsWith("J* ") || line.StartsWith("♪ ")) && unItalicText.Length > 3 && HtmlUtil.RemoveOpenCloseTags(unItalicText, HtmlUtil.TagItalic)[1] == ' ')
                                    {
                                        bool ita = unItalicText.StartsWith("<i>") && unItalicText.EndsWith("</i>");
                                        unItalicText = HtmlUtil.RemoveHtmlTags(unItalicText);
                                        unItalicText = "♪ " + unItalicText.Remove(0, 2).TrimStart();
                                        if (ita)
                                            unItalicText = "<i>" + unItalicText + "</i>";
                                    }
                                    if ((line.StartsWith("J' ") || line.StartsWith("J“ ") || line.StartsWith("J* ") || line.StartsWith("♪ ")) && unItalicText.Length > 3 && HtmlUtil.RemoveOpenCloseTags(unItalicText, HtmlUtil.TagItalic)[2] == ' ')
                                    {
                                        bool ita = unItalicText.StartsWith("<i>") && unItalicText.EndsWith("</i>");
                                        unItalicText = HtmlUtil.RemoveHtmlTags(unItalicText);
                                        unItalicText = "♪ " + unItalicText.Remove(0, 2).TrimStart();
                                        if (ita)
                                            unItalicText = "<i>" + unItalicText + "</i>";
                                    }
                                    if (unItalicText.StartsWith("J'") && (line.StartsWith('♪') || textWithOutFixes.StartsWith('♪') || textWithOutFixes.StartsWith("<i>♪") || unItalicText.EndsWith('♪')))
                                    {
                                        bool ita = unItalicText.StartsWith("<i>") && unItalicText.EndsWith("</i>");
                                        unItalicText = HtmlUtil.RemoveHtmlTags(unItalicText);
                                        unItalicText = "♪ " + unItalicText.Remove(0, 2).TrimStart();
                                        if (ita)
                                            unItalicText = "<i>" + unItalicText + "</i>";
                                    }
                                    if ((line.StartsWith("J` ") || line.StartsWith("J“ ") || line.StartsWith("J' ") || line.StartsWith("J* ")) && unItalicText.StartsWith("S "))
                                    {
                                        bool ita = unItalicText.StartsWith("<i>") && unItalicText.EndsWith("</i>");
                                        unItalicText = HtmlUtil.RemoveHtmlTags(unItalicText);
                                        unItalicText = "♪ " + unItalicText.Remove(0, 2).TrimStart();
                                        if (ita)
                                            unItalicText = "<i>" + unItalicText + "</i>";
                                    }
                                    if ((line.StartsWith("J` ") || line.StartsWith("J“ ") || line.StartsWith("J' ") || line.StartsWith("J* ")) && unItalicText.StartsWith("<i>S</i> "))
                                    {
                                        bool ita = unItalicText.StartsWith("<i>") && unItalicText.EndsWith("</i>");
                                        unItalicText = HtmlUtil.RemoveHtmlTags(unItalicText);
                                        unItalicText = "♪ " + unItalicText.Remove(0, 8).TrimStart();
                                        if (ita)
                                            unItalicText = "<i>" + unItalicText + "</i>";
                                    }
                                    if (unItalicText.StartsWith(";'") && (line.StartsWith('♪') || textWithOutFixes.StartsWith('♪') || textWithOutFixes.StartsWith("<i>♪") || unItalicText.EndsWith('♪')))
                                    {
                                        bool ita = unItalicText.StartsWith("<i>") && unItalicText.EndsWith("</i>");
                                        unItalicText = HtmlUtil.RemoveHtmlTags(unItalicText);
                                        unItalicText = "♪ " + unItalicText.Remove(0, 2).TrimStart();
                                        if (ita)
                                            unItalicText = "<i>" + unItalicText + "</i>";
                                    }
                                    if (unItalicText.StartsWith(",{*") && (line.StartsWith('♪') || textWithOutFixes.StartsWith('♪') || textWithOutFixes.StartsWith("<i>♪") || unItalicText.EndsWith('♪')))
                                    {
                                        bool ita = unItalicText.StartsWith("<i>") && unItalicText.EndsWith("</i>");
                                        unItalicText = HtmlUtil.RemoveHtmlTags(unItalicText);
                                        unItalicText = "♪ " + unItalicText.Remove(0, 3).TrimStart();
                                        if (ita)
                                            unItalicText = "<i>" + unItalicText + "</i>";
                                    }

                                    if (unItalicText.EndsWith("J'") && (line.EndsWith('♪') || textWithOutFixes.EndsWith('♪') || textWithOutFixes.EndsWith("♪</i>") || unItalicText.StartsWith('♪')))
                                    {
                                        bool ita = unItalicText.StartsWith("<i>") && unItalicText.EndsWith("</i>");
                                        unItalicText = HtmlUtil.RemoveHtmlTags(unItalicText);
                                        unItalicText = unItalicText.Remove(unItalicText.Length - 3, 2).TrimEnd() + " ♪";
                                        if (ita)
                                            unItalicText = "<i>" + unItalicText + "</i>";
                                    }
                                }

                                if (unItalicText.StartsWith('[') && !line.StartsWith('['))
                                {
                                    unItalicText = unItalicText.Remove(0, 1);
                                    if (unItalicText.EndsWith(']'))
                                        unItalicText = unItalicText.TrimEnd(']');
                                }
                                if (unItalicText.StartsWith('{') && !line.StartsWith('{'))
                                {
                                    unItalicText = unItalicText.Remove(0, 1);
                                    if (unItalicText.EndsWith('}'))
                                        unItalicText = unItalicText.TrimEnd('}');
                                }
                                if (unItalicText.EndsWith('}') && !line.EndsWith('}'))
                                    unItalicText = unItalicText.TrimEnd('}');

                                if (line.EndsWith("...") && unItalicText.EndsWith("”!"))
                                    unItalicText = unItalicText.TrimEnd('!').TrimEnd('”') + ".";
                                if (line.EndsWith("...") && unItalicText.EndsWith("\"!"))
                                    unItalicText = unItalicText.TrimEnd('!').TrimEnd('"') + ".";

                                if (line.EndsWith('.') && !unItalicText.EndsWith('.') && !unItalicText.EndsWith(".</i>"))
                                {
                                    string post = string.Empty;
                                    if (unItalicText.EndsWith("</i>"))
                                    {
                                        post = "</i>";
                                        unItalicText = unItalicText.Remove(unItalicText.Length - 4);
                                    }
                                    if (unItalicText.EndsWith('\'') && !line.EndsWith("'."))
                                        unItalicText = unItalicText.TrimEnd('\'');
                                    unItalicText += "." + post;
                                }
                                if (unItalicText.EndsWith('.') && !unItalicText.EndsWith("...") && !unItalicText.EndsWith("...</i>") && line.EndsWith("..."))
                                {
                                    string post = string.Empty;
                                    if (unItalicText.EndsWith("</i>"))
                                    {
                                        post = "</i>";
                                        unItalicText = unItalicText.Remove(unItalicText.Length - 4);
                                    }
                                    unItalicText += ".." + post;
                                }
                                if (unItalicText.EndsWith("..") && !unItalicText.EndsWith("...") && !unItalicText.EndsWith("...</i>") && line.EndsWith("..."))
                                {
                                    string post = string.Empty;
                                    if (unItalicText.EndsWith("</i>"))
                                    {
                                        post = "</i>";
                                        unItalicText = unItalicText.Remove(unItalicText.Length - 4);
                                    }
                                    unItalicText += "." + post;
                                }

                                if (line.EndsWith('!') && !unItalicText.EndsWith('!') && !unItalicText.EndsWith("!</i>"))
                                {
                                    if (unItalicText.EndsWith("!'"))
                                    {
                                        unItalicText = unItalicText.TrimEnd('\'');
                                    }
                                    else
                                    {
                                        if (unItalicText.EndsWith("l</i>") && _ocrFixEngine != null)
                                        {
                                            string w = unItalicText.Substring(0, unItalicText.Length - 4);
                                            int wIdx = w.Length - 1;
                                            while (wIdx >= 0 && !@" .,!?<>:;'-$@£()[]<>/""".Contains(w[wIdx]))
                                            {
                                                wIdx--;
                                            }
                                            if (wIdx + 1 < w.Length && unItalicText.Length > 5)
                                            {
                                                w = w.Substring(wIdx + 1);
                                                if (!_ocrFixEngine.DoSpell(w))
                                                    unItalicText = unItalicText.Remove(unItalicText.Length - 5, 1);
                                            }
                                            unItalicText = unItalicText.Insert(unItalicText.Length - 4, "!");
                                        }
                                        else if (unItalicText.EndsWith('l') && _ocrFixEngine != null)
                                        {
                                            string w = unItalicText;
                                            int wIdx = w.Length - 1;
                                            while (wIdx >= 0 && !@" .,!?<>:;'-$@£()[]<>/""".Contains(w[wIdx]))
                                            {
                                                wIdx--;
                                            }
                                            if (wIdx + 1 < w.Length && unItalicText.Length > 5)
                                            {
                                                w = w.Substring(wIdx + 1);
                                                if (!_ocrFixEngine.DoSpell(w))
                                                    unItalicText = unItalicText.Remove(unItalicText.Length - 1, 1);
                                            }
                                            unItalicText += "!";
                                        }
                                        else
                                        {
                                            unItalicText += "!";
                                        }
                                    }
                                }
                                if (line.EndsWith('?') && !unItalicText.EndsWith('?') && !unItalicText.EndsWith("?</i>"))
                                {
                                    if (unItalicText.EndsWith("?'"))
                                        unItalicText = unItalicText.TrimEnd('\'');
                                    else
                                        unItalicText += "?";
                                }

                                line = HtmlUtil.RemoveOpenCloseTags(unItalicText, HtmlUtil.TagItalic);
                                if (checkBoxAutoFixCommonErrors.Checked)
                                {
                                    if (line.Contains("'.") && !textWithOutFixes.Contains("'.") && textWithOutFixes.Contains(':') && !line.EndsWith("'.") && Configuration.Settings.Tools.OcrFixUseHardcodedRules)
                                    {
                                        line = line.Replace("'.", ":");
                                    }
                                    line = _ocrFixEngine.FixOcrErrors(line, index, _lastLine, true, GetAutoGuessLevel());
                                }
                                line = "<i>" + line + "</i>";
                            }
                            else
                            {
                                unItalicText = unItalicText.Replace("</i>", string.Empty);
                                if (line.EndsWith("</i>", StringComparison.Ordinal) && unItalicText.EndsWith('.'))
                                {
                                    line = line.Remove(line.Length - 4, 4);
                                    if (line.EndsWith('-'))
                                        line = line.TrimEnd('-') + ".";
                                    if (char.IsLetter(line[line.Length - 1]))
                                        line += ".";
                                    line += "</i>";
                                }
                            }
                        }
                    }
                }

                if (checkBoxTesseractMusicOn.Checked)
                {
                    if (line == "[J'J'J~]" || line == "[J'J'J']")
                        line = "[ ♪ ♪ ♪ ]";

                    line = line.Replace(" J' ", " ♪ ");

                    if (line.StartsWith("J'"))
                    {
                        line = "♪ " + line.Remove(0, 2).TrimStart();
                    }
                    if (line.StartsWith("<i>J'"))
                    {
                        line = "<i>♪ " + line.Remove(0, 5).TrimStart();
                    }
                    if (line.StartsWith("[J'"))
                    {
                        line = "[♪ " + line.Remove(0, 3).TrimStart();
                    }
                    if (line.StartsWith("<i>[J'"))
                    {
                        line = "<i>[♪ " + line.Remove(0, 6).TrimStart();
                    }
                    if (line.EndsWith("J'"))
                    {
                        line = line.Remove(line.Length - 2, 2).TrimEnd() + " ♪";
                    }
                    if (line.EndsWith("J'</i>"))
                    {
                        line = line.Remove(line.Length - 6, 6).TrimEnd() + " ♪</i>";
                    }
                    if (line.Contains(Environment.NewLine + "J'"))
                    {
                        line = line.Replace(Environment.NewLine + "J'", Environment.NewLine + "♪ ");
                        line = line.Replace("  ", " ");
                    }
                    if (line.Contains("J'" + Environment.NewLine))
                    {
                        line = line.Replace("J'" + Environment.NewLine, " ♪" + Environment.NewLine);
                        line = line.Replace("  ", " ");
                    }
                }

                if (wordsNotFound > 0 || correctWords == 0 || textWithOutFixes != null && textWithOutFixes.Replace("~", string.Empty).Trim().Length < 2)
                {
                    _ocrFixEngine.AutoGuessesUsed.Clear();
                    _ocrFixEngine.UnknownWordsFound.Clear();

                    if (_modiEnabled && checkBoxUseModiInTesseractForUnknownWords.Checked)
                    {
                        // which is best - modi or Tesseract - we find out here
                        string modiText = CallModi(index);

                        if (modiText.Length == 0)
                            modiText = CallModi(index); // retry... strange MODI
                        if (modiText.Length == 0)
                            modiText = CallModi(index); // retry... strange MODI

                        if (modiText.Length > 1 &&
                            !modiText.Contains("CD") &&
                            (!modiText.Contains('0') || line.Contains('0')) &&
                            (!modiText.Contains('2') || line.Contains('2')) &&
                            (!modiText.Contains('3') || line.Contains('4')) &&
                            (!modiText.Contains('5') || line.Contains('5')) &&
                            (!modiText.Contains('9') || line.Contains('9')) &&
                            (!modiText.Contains('•') || line.Contains('•')) &&
                            (!modiText.Contains(')') || line.Contains(')')) &&
                            Utilities.CountTagInText(modiText, '(') < 2 && Utilities.CountTagInText(modiText, ')') < 2 &&
                            Utilities.GetNumberOfLines(modiText) < 4)
                        {
                            int modiWordsNotFound = _ocrFixEngine.CountUnknownWordsViaDictionary(modiText, out correctWords);
                            //if (modiWordsNotFound > 0)
                            {
                                string modiTextOcrFixed = modiText;
                                if (checkBoxAutoFixCommonErrors.Checked)
                                    modiTextOcrFixed = _ocrFixEngine.FixOcrErrors(modiText, index, _lastLine, false, GetAutoGuessLevel());
                                int modiOcrCorrectedWordsNotFound = _ocrFixEngine.CountUnknownWordsViaDictionary(modiTextOcrFixed, out correctWords);
                                if (modiOcrCorrectedWordsNotFound <= modiWordsNotFound)
                                    modiText = modiTextOcrFixed;
                            }

                            if (modiWordsNotFound < wordsNotFound || (textWithOutFixes.Length == 1 && modiWordsNotFound == 0))
                                line = modiText; // use the modi OCR'ed text
                            else if (wordsNotFound == modiWordsNotFound && modiText.EndsWith('!') && (line.EndsWith('l') || line.EndsWith('fl')))
                                line = modiText;
                        }

                        // take the best option - before OCR fixing, which we do again to save suggestions and prompt for user input
                        line = _ocrFixEngine.FixUnknownWordsViaGuessOrPrompt(out wordsNotFound, line, index, bitmap, checkBoxAutoFixCommonErrors.Checked, checkBoxPromptForUnknownWords.Checked, true, GetAutoGuessLevel());
                    }
                    else
                    { // fix some error manually (modi not available)
                        line = _ocrFixEngine.FixUnknownWordsViaGuessOrPrompt(out wordsNotFound, line, index, bitmap, checkBoxAutoFixCommonErrors.Checked, checkBoxPromptForUnknownWords.Checked, true, GetAutoGuessLevel());
                    }
                }

                if (_ocrFixEngine.Abort)
                {
                    ButtonStopClick(null, null);
                    _ocrFixEngine.Abort = false;
                    return string.Empty;
                }

                //check Tesseract... find an other way to do this...
                //string tmp = HtmlUtil.RemoveHtmlTags(line).Trim();
                //if (!tmp.TrimEnd().EndsWith("..."))
                //{
                //    tmp = tmp.TrimEnd('.').TrimEnd();
                //    if (tmp.Length > 2 && Utilities.LowercaseLetters.Contains(tmp[tmp.Length - 1]))
                //    {
                //        if (_nocrChars == null)
                //            _nocrChars = LoadNOcrForTesseract("Nikse.SubtitleEdit.Resources.nOCR_TesseractHelper.xml.zip");
                //        string text = HtmlUtil.RemoveHtmlTags(NocrFastCheck(bitmap).TrimEnd());
                //        string post = string.Empty;
                //        if (line.EndsWith("</i>"))
                //        {
                //            post = "</i>";
                //            line = line.Remove(line.Length - 4, 4).Trim();
                //        }
                //        if (text.EndsWith('.'))
                //        {
                //            line = line.TrimEnd('.').Trim();
                //            while (text.EndsWith('.') || text.EndsWith(' '))
                //            {
                //                line += text.Substring(text.Length - 1).Trim();
                //                text = text.Remove(text.Length - 1, 1);
                //            }
                //        }
                //        else if (text.EndsWith('l') && text.EndsWith('!') && !text.EndsWith("l!"))
                //        {
                //            line = line.Remove(line.Length - 1, 1) + "!";
                //        }
                //        line += post;
                //    }
                //}

                // Log used word guesses (via word replace list)
                foreach (string guess in _ocrFixEngine.AutoGuessesUsed)
                    listBoxLogSuggestions.Items.Add(guess);
                _ocrFixEngine.AutoGuessesUsed.Clear();

                // Log unkown words guess (found via spelling dictionaries)
                LogUnknownWords();

                ColorLineByNumberOfUnknownWords(index, wordsNotFound, line);
            }
            else
            { // no dictionary :(
                if (checkBoxAutoFixCommonErrors.Checked)
                    line = _ocrFixEngine.FixOcrErrors(line, index, _lastLine, true, GetAutoGuessLevel());

                if (badWords >= numberOfWords)
                    subtitleListView1.SetBackgroundColor(index, Color.Red);
                else if (badWords >= numberOfWords / 2)
                    subtitleListView1.SetBackgroundColor(index, Color.Orange);
                else if (badWords > 0 || line.Contains('_') || HasSingleLetters(line))
                    subtitleListView1.SetBackgroundColor(index, Color.Yellow);
                else if (string.IsNullOrWhiteSpace(HtmlUtil.RemoveOpenCloseTags(line, HtmlUtil.TagItalic)))
                    subtitleListView1.SetBackgroundColor(index, Color.Orange);
                else
                    subtitleListView1.SetBackgroundColor(index, Color.LightGreen);
            }

            if (textWithOutFixes.Trim() != line.Trim())
            {
                _tesseractOcrAutoFixes++;
                labelFixesMade.Text = string.Format(" - {0}", _tesseractOcrAutoFixes);
                LogOcrFix(index, textWithOutFixes, line);
            }

            if (_vobSubMergedPackist != null)
                bitmap.Dispose();

            return line;
        }
Пример #37
0
        /// <summary>
        /// Create the binary stream representation of one caption
        /// </summary>
        /// <param name="pic">SubPicture object containing caption info</param>
        /// <param name="bmp">Bitmap</param>
        /// <param name="fps">Frames per second</param>
        /// <param name="bottomMargin">Image bottom margin</param>
        /// <param name="leftOrRightMargin">Image left/right margin</param>
        /// <param name="alignment">Alignment of image</param>
        /// <returns>Byte buffer containing the binary stream representation of one caption</returns>
        public static byte[] CreateSupFrame(BluRaySupPicture pic, Bitmap bmp, double fps, int bottomMargin, int leftOrRightMargin, ContentAlignment alignment)
        {
            var bm           = new NikseBitmap(bmp);
            var colorPalette = GetBitmapPalette(bm);
            var pal          = new BluRaySupPalette(colorPalette.Count);
            int k            = 0;

            foreach (var kvp in colorPalette)
            {
                pal.SetColor(k, kvp.Key);
                k++;
            }

            byte[] rleBuf = EncodeImage(bm, colorPalette);

            // for some obscure reason, a packet can be a maximum 0xfffc bytes
            // since 13 bytes are needed for the header("PG", PTS, DTS, ID, SIZE)
            // there are only 0xffef bytes available for the packet
            // since the first ODS packet needs an additional 11 bytes for info
            // and the following ODS packets need 4 additional bytes, the
            // first package can store only 0xffe4 RLE buffer bytes and the
            // following packets can store 0xffeb RLE buffer bytes
            int numAddPackets;

            if (rleBuf.Length <= 0xffe4)
            {
                numAddPackets = 0; // no additional packets needed;
            }
            else
            {
                numAddPackets = 1 + (rleBuf.Length - 0xffe4) / 0xffeb;
            }

            // a typical frame consists of 8 packets. It can be enlonged by additional
            // object frames
            int palSize = colorPalette.Count;

            var packetHeader = new byte[]
            {
                0x50, 0x47,             // 0:  "PG"
                0x00, 0x00, 0x00, 0x00, // 2:  PTS - presentation time stamp
                0x00, 0x00, 0x00, 0x00, // 6:  DTS - decoding time stamp
                0x00,                   // 10: segment_type
                0x00, 0x00              // 11: segment_length (bytes following till next PG)
            };
            var headerPcsStart = new byte[]
            {
                0x00, 0x00, 0x00, 0x00, // 0: video_width, video_height
                0x10,                   // 4: hi nibble: frame_rate (0x10=24p), lo nibble: reserved
                0x00, 0x00,             // 5: composition_number (increased by start and end header)
                0x80,                   // 7: composition_state (0x80: epoch start)
                0x00,                   // 8: palette_update_flag (0x80), 7bit reserved
                0x00,                   // 9: palette_id_ref (0..7)
                0x01,                   // 10: number_of_composition_objects (0..2)
                0x00, 0x00,             // 11: 16bit object_id_ref
                0x00,                   // 13: window_id_ref (0..1)
                0x00,                   // 14: object_cropped_flag: 0x80, forced_on_flag = 0x040, 6bit reserved
                0x00, 0x00, 0x00, 0x00  // 15: composition_object_horizontal_position, composition_object_vertical_position
            };
            var headerPcsEnd = new byte[]
            {
                0x00, 0x00, 0x00, 0x00, // 0: video_width, video_height
                0x10,                   // 4: hi nibble: frame_rate (0x10=24p), lo nibble: reserved
                0x00, 0x00,             // 5: composition_number (increased by start and end header)
                0x00,                   // 7: composition_state (0x00: normal)
                0x00,                   // 8: palette_update_flag (0x80), 7bit reserved
                0x00,                   // 9: palette_id_ref (0..7)
                0x00                    // 10: number_of_composition_objects (0..2)
            };
            var headerWds = new byte[]
            {
                0x01,                   // 0 : number of windows (currently assumed 1, 0..2 is legal)
                0x00,                   // 1 : window id (0..1)
                0x00, 0x00, 0x00, 0x00, // 2 : x-ofs, y-ofs
                0x00, 0x00, 0x00, 0x00  // 6 : width, height
            };
            var headerOdsFirst = new byte[]
            {
                0x00, 0x00,             // 0: object_id
                0x00,                   // 2: object_version_number
                0xC0,                   // 3: first_in_sequence (0x80), last_in_sequence (0x40), 6bits reserved
                0x00, 0x00, 0x00,       // 4: object_data_length - full RLE buffer length (including 4 bytes size info)
                0x00, 0x00, 0x00, 0x00  // 7: object_width, object_height
            };
            var headerOdsNext = new byte[]
            {
                0x00, 0x00,             // 0: object_id
                0x00,                   // 2: object_version_number
                0x40                    // 3: first_in_sequence (0x80), last_in_sequence (0x40), 6bits reserved
            };

            int size = packetHeader.Length * (8 + numAddPackets);

            size += headerPcsStart.Length + headerPcsEnd.Length;
            size += 2 * headerWds.Length + headerOdsFirst.Length;
            size += numAddPackets * headerOdsNext.Length;
            size += (2 + palSize * 5) /* PDS */;
            size += rleBuf.Length;

            switch (alignment)
            {
            case ContentAlignment.BottomLeft:
                pic.WindowXOffset = leftOrRightMargin;
                pic.WindowYOffset = pic.Height - (bm.Height + bottomMargin);
                break;

            case ContentAlignment.BottomRight:
                pic.WindowXOffset = pic.Width - bm.Width - bottomMargin;
                pic.WindowYOffset = pic.Height - (bm.Height + leftOrRightMargin);
                break;

            case ContentAlignment.MiddleCenter:
                pic.WindowXOffset = (pic.Width - bm.Width) / 2;
                pic.WindowYOffset = (pic.Height - bm.Height) / 2;
                break;

            case ContentAlignment.MiddleLeft:
                pic.WindowXOffset = leftOrRightMargin;
                pic.WindowYOffset = (pic.Height - bm.Height) / 2;
                break;

            case ContentAlignment.MiddleRight:
                pic.WindowXOffset = pic.Width - bm.Width - leftOrRightMargin;
                pic.WindowYOffset = (pic.Height - bm.Height) / 2;
                break;

            case ContentAlignment.TopCenter:
                pic.WindowXOffset = (pic.Width - bm.Width) / 2;
                pic.WindowYOffset = bottomMargin;
                break;

            case ContentAlignment.TopLeft:
                pic.WindowXOffset = leftOrRightMargin;
                pic.WindowYOffset = bottomMargin;
                break;

            case ContentAlignment.TopRight:
                pic.WindowXOffset = pic.Width - bm.Width - leftOrRightMargin;
                pic.WindowYOffset = bottomMargin;
                break;

            default:     // ContentAlignment.BottomCenter:
                pic.WindowXOffset = (pic.Width - bm.Width) / 2;
                pic.WindowYOffset = pic.Height - (bm.Height + bottomMargin);
                break;
            }

            int yOfs = pic.WindowYOffset - Core.CropOfsY;

            if (yOfs < 0)
            {
                yOfs = 0;
            }
            else
            {
                int yMax = pic.Height - pic.WindowHeight - 2 * Core.CropOfsY;
                if (yOfs > yMax)
                {
                    yOfs = yMax;
                }
            }

            int h = pic.Height - 2 * Core.CropOfsY;

            byte[] buf   = new byte[size];
            int    index = 0;

            int fpsId = GetFpsId(fps);

            /* time (in 90kHz resolution) needed to initialize (clear) the screen buffer
             *  based on the composition pixel rate of 256e6 bit/s - always rounded up */
            int frameInitTime = (pic.Width * pic.Height * 9 + 3199) / 3200; // better use default height here

            /* time (in 90kHz resolution) needed to initialize (clear) the window area
             *  based on the composition pixel rate of 256e6 bit/s - always rounded up
             *  Note: no cropping etc. -> window size == image size */
            int windowInitTime = (bm.Width * bm.Height * 9 + 3199) / 3200;

            /* time (in 90kHz resolution) needed to decode the image
             *  based on the decoding pixel rate of 128e6 bit/s - always rounded up  */
            int imageDecodeTime = (bm.Width * bm.Height * 9 + 1599) / 1600;

            // write PCS start
            packetHeader[10] = 0x16;                                                              // ID
            int dts = pic.StartTimeForWrite - (frameInitTime + windowInitTime + imageDecodeTime); //            int dts = pic.StartTimeForWrite - windowInitTime; ????

            ToolBox.SetDWord(packetHeader, 2, pic.StartTimeForWrite);                             // PTS
            ToolBox.SetDWord(packetHeader, 6, dts);                                               // DTS
            ToolBox.SetWord(packetHeader, 11, headerPcsStart.Length);                             // size
            for (int i = 0; i < packetHeader.Length; i++)
            {
                buf[index++] = packetHeader[i];
            }
            ToolBox.SetWord(headerPcsStart, 0, pic.Width);
            ToolBox.SetWord(headerPcsStart, 2, h);                              // cropped height
            ToolBox.SetByte(headerPcsStart, 4, fpsId);
            ToolBox.SetWord(headerPcsStart, 5, pic.CompositionNumber);
            headerPcsStart[14] = (byte)(pic.IsForced ? 0x40 : 0);
            ToolBox.SetWord(headerPcsStart, 15, pic.WindowXOffset);
            ToolBox.SetWord(headerPcsStart, 17, yOfs);
            for (int i = 0; i < headerPcsStart.Length; i++)
            {
                buf[index++] = headerPcsStart[i];
            }

            // write WDS
            packetHeader[10] = 0x17;                                            // ID
            int timestamp = pic.StartTimeForWrite - windowInitTime;

            ToolBox.SetDWord(packetHeader, 2, timestamp);                       // PTS (keep DTS)
            ToolBox.SetWord(packetHeader, 11, headerWds.Length);                // size
            for (int i = 0; i < packetHeader.Length; i++)
            {
                buf[index++] = packetHeader[i];
            }
            ToolBox.SetWord(headerWds, 2, pic.WindowXOffset);
            ToolBox.SetWord(headerWds, 4, yOfs);
            ToolBox.SetWord(headerWds, 6, bm.Width);
            ToolBox.SetWord(headerWds, 8, bm.Height);
            for (int i = 0; i < headerWds.Length; i++)
            {
                buf[index++] = headerWds[i];
            }

            // write PDS
            packetHeader[10] = 0x14;                                            // ID
            ToolBox.SetDWord(packetHeader, 2, dts);                             // PTS (=DTS of PCS/WDS)
            ToolBox.SetDWord(packetHeader, 6, 0);                               // DTS (0)
            ToolBox.SetWord(packetHeader, 11, (2 + palSize * 5));               // size
            for (int i = 0; i < packetHeader.Length; i++)
            {
                buf[index++] = packetHeader[i];
            }
            buf[index++] = 0;
            buf[index++] = 0;
            for (int i = 0; i < palSize; i++)
            {
                buf[index++] = (byte)i;                                         // index
                buf[index++] = pal.GetY()[i];                                   // Y
                buf[index++] = pal.GetCr()[i];                                  // Cr
                buf[index++] = pal.GetCb()[i];                                  // Cb
                buf[index++] = pal.GetAlpha()[i];                               // Alpha
            }

            // write first OBJ
            int bufSize  = rleBuf.Length;
            int rleIndex = 0;

            if (bufSize > 0xffe4)
            {
                bufSize = 0xffe4;
            }
            packetHeader[10] = 0x15;                                            // ID
            timestamp        = dts + imageDecodeTime;
            ToolBox.SetDWord(packetHeader, 2, timestamp);                       // PTS
            ToolBox.SetDWord(packetHeader, 6, dts);                             // DTS
            ToolBox.SetWord(packetHeader, 11, headerOdsFirst.Length + bufSize); // size
            for (int i = 0; i < packetHeader.Length; i++)
            {
                buf[index++] = packetHeader[i];
            }
            int marker = (int)((numAddPackets == 0) ? 0xC0000000 : 0x80000000);

            ToolBox.SetDWord(headerOdsFirst, 3, marker | (rleBuf.Length + 4));
            ToolBox.SetWord(headerOdsFirst, 7, bm.Width);
            ToolBox.SetWord(headerOdsFirst, 9, bm.Height);
            for (int i = 0; i < headerOdsFirst.Length; i++)
            {
                buf[index++] = headerOdsFirst[i];
            }
            for (int i = 0; i < bufSize; i++)
            {
                buf[index++] = rleBuf[rleIndex++];
            }

            // write additional OBJ packets
            bufSize = rleBuf.Length - bufSize; // remaining bytes to write
            for (int p = 0; p < numAddPackets; p++)
            {
                int psize = bufSize;
                if (psize > 0xffeb)
                {
                    psize = 0xffeb;
                }
                packetHeader[10] = 0x15;                                            // ID (keep DTS & PTS)
                ToolBox.SetWord(packetHeader, 11, headerOdsNext.Length + psize);    // size
                for (int i = 0; i < packetHeader.Length; i++)
                {
                    buf[index++] = packetHeader[i];
                }
                for (int i = 0; i < headerOdsNext.Length; i++)
                {
                    buf[index++] = headerOdsNext[i];
                }
                for (int i = 0; i < psize; i++)
                {
                    buf[index++] = rleBuf[rleIndex++];
                }
                bufSize -= psize;
            }

            // write END
            packetHeader[10] = 0x80;                                      // ID
            ToolBox.SetDWord(packetHeader, 6, 0);                         // DTS (0) (keep PTS of ODS)
            ToolBox.SetWord(packetHeader, 11, 0);                         // size
            for (int i = 0; i < packetHeader.Length; i++)
            {
                buf[index++] = packetHeader[i];
            }

            // write PCS end
            packetHeader[10] = 0x16;                                // ID
            ToolBox.SetDWord(packetHeader, 2, pic.EndTimeForWrite); // PTS
            dts = pic.EndTimeForWrite - 1;                          //dts = pic.StartTimeForWrite - 1;
            ToolBox.SetDWord(packetHeader, 6, dts);                 // DTS
            ToolBox.SetWord(packetHeader, 11, headerPcsEnd.Length); // size
            for (int i = 0; i < packetHeader.Length; i++)
            {
                buf[index++] = packetHeader[i];
            }
            ToolBox.SetWord(headerPcsEnd, 0, pic.Width);
            ToolBox.SetWord(headerPcsEnd, 2, h);                                // cropped height
            ToolBox.SetByte(headerPcsEnd, 4, fpsId);
            ToolBox.SetWord(headerPcsEnd, 5, pic.CompositionNumber + 1);
            for (int i = 0; i < headerPcsEnd.Length; i++)
            {
                buf[index++] = headerPcsEnd[i];
            }

            // write WDS
            packetHeader[10] = 0x17;                                            // ID
            timestamp        = pic.EndTimeForWrite - windowInitTime;
            ToolBox.SetDWord(packetHeader, 2, timestamp);                       // PTS (keep DTS of PCS)
            ToolBox.SetWord(packetHeader, 11, headerWds.Length);                // size
            for (int i = 0; i < packetHeader.Length; i++)
            {
                buf[index++] = packetHeader[i];
            }
            ToolBox.SetWord(headerWds, 2, pic.WindowXOffset);
            ToolBox.SetWord(headerWds, 4, yOfs);
            ToolBox.SetWord(headerWds, 6, bm.Width);
            ToolBox.SetWord(headerWds, 8, bm.Height);
            for (int i = 0; i < headerWds.Length; i++)
            {
                buf[index++] = headerWds[i];
            }

            // write END
            packetHeader[10] = 0x80;                                      // ID
            ToolBox.SetDWord(packetHeader, 2, dts);                       // PTS (DTS of end PCS)
            ToolBox.SetDWord(packetHeader, 6, 0);                         // DTS (0)
            ToolBox.SetWord(packetHeader, 11, 0);                         // size
            for (int i = 0; i < packetHeader.Length; i++)
            {
                buf[index++] = packetHeader[i];
            }

            return(buf);
        }
Пример #38
0
        /// <summary>
        /// Ocr via image compare
        /// </summary>
        private string SplitAndOcrBitmapNormal(Bitmap bitmap, int listViewIndex)
        {
            if (_ocrFixEngine == null)
                LoadOcrFixEngine(null, LanguageString);

            string threadText = null;
            if (_icThreadResults != null && !string.IsNullOrEmpty(_icThreadResults[listViewIndex]))
                threadText = _icThreadResults[listViewIndex];

            string line = string.Empty;
            if (threadText == null)
            {
                var matches = new List<CompareMatch>();
                var parentBitmap = new NikseBitmap(bitmap);
                List<ImageSplitterItem> list = NikseBitmapImageSplitter.SplitBitmapToLetters(parentBitmap, (int)numericUpDownPixelsIsSpace.Value, checkBoxRightToLeft.Checked, Configuration.Settings.VobSubOcr.TopToBottom);
                int index = 0;
                bool expandSelection = false;
                bool shrinkSelection = false;
                var expandSelectionList = new List<ImageSplitterItem>();
                while (index < list.Count)
                {
                    ImageSplitterItem item = list[index];
                    if (expandSelection || shrinkSelection)
                    {
                        expandSelection = false;
                        if (shrinkSelection && index > 0)
                        {
                            shrinkSelection = false;
                        }
                        else if (index + 1 < list.Count && list[index + 1].NikseBitmap != null) // only allow expand to EndOfLine or space
                        {
                            index++;
                            expandSelectionList.Add(list[index]);
                        }
                        item = GetExpandedSelection(parentBitmap, expandSelectionList, checkBoxRightToLeft.Checked);

                        _vobSubOcrCharacter.Initialize(bitmap, item, _manualOcrDialogPosition, _italicCheckedLast, expandSelectionList.Count > 1, null, _lastAdditions, this);
                        DialogResult result = _vobSubOcrCharacter.ShowDialog(this);
                        _manualOcrDialogPosition = _vobSubOcrCharacter.FormPosition;
                        if (result == DialogResult.OK && _vobSubOcrCharacter.ShrinkSelection)
                        {
                            shrinkSelection = true;
                            index--;
                            if (expandSelectionList.Count > 0)
                                expandSelectionList.RemoveAt(expandSelectionList.Count - 1);
                        }
                        else if (result == DialogResult.OK && _vobSubOcrCharacter.ExpandSelection)
                        {
                            expandSelection = true;
                        }
                        else if (result == DialogResult.OK)
                        {
                            string text = _vobSubOcrCharacter.ManualRecognizedCharacters;
                            string name = SaveCompareItem(item.NikseBitmap, text, _vobSubOcrCharacter.IsItalic, expandSelectionList.Count);
                            var addition = new ImageCompareAddition(name, text, item.NikseBitmap, _vobSubOcrCharacter.IsItalic, listViewIndex);
                            _lastAdditions.Add(addition);
                            matches.Add(new CompareMatch(text, _vobSubOcrCharacter.IsItalic, expandSelectionList.Count, null));
                            expandSelectionList = new List<ImageSplitterItem>();
                        }
                        else if (result == DialogResult.Abort)
                        {
                            _abort = true;
                        }
                        else
                        {
                            matches.Add(new CompareMatch("*", false, 0, null));
                        }
                        _italicCheckedLast = _vobSubOcrCharacter.IsItalic;
                    }
                    else if (item.NikseBitmap == null)
                    {
                        matches.Add(new CompareMatch(item.SpecialCharacter, false, 0, null));
                    }
                    else
                    {
                        CompareMatch bestGuess;
                        CompareMatch match = GetCompareMatch(item, parentBitmap, out bestGuess, list, index);
                        if (match == null)
                        {
                            _vobSubOcrCharacter.Initialize(bitmap, item, _manualOcrDialogPosition, _italicCheckedLast, false, bestGuess, _lastAdditions, this);
                            DialogResult result = _vobSubOcrCharacter.ShowDialog(this);
                            _manualOcrDialogPosition = _vobSubOcrCharacter.FormPosition;
                            if (result == DialogResult.OK && _vobSubOcrCharacter.ExpandSelection)
                            {
                                expandSelectionList.Add(item);
                                expandSelection = true;
                            }
                            else if (result == DialogResult.OK)
                            {
                                string text = _vobSubOcrCharacter.ManualRecognizedCharacters;
                                string name = SaveCompareItem(item.NikseBitmap, text, _vobSubOcrCharacter.IsItalic, 0);
                                var addition = new ImageCompareAddition(name, text, item.NikseBitmap, _vobSubOcrCharacter.IsItalic, listViewIndex);
                                _lastAdditions.Add(addition);
                                matches.Add(new CompareMatch(text, _vobSubOcrCharacter.IsItalic, 0, null));
                            }
                            else if (result == DialogResult.Abort)
                            {
                                _abort = true;
                            }
                            else
                            {
                                matches.Add(new CompareMatch("*", false, 0, null));
                            }
                            _italicCheckedLast = _vobSubOcrCharacter.IsItalic;
                        }
                        else // found image match
                        {
                            matches.Add(new CompareMatch(match.Text, match.Italic, 0, null));
                            if (match.ExpandCount > 0)
                                index += match.ExpandCount - 1;
                        }
                    }
                    if (_abort)
                        return string.Empty;
                    if (!expandSelection && !shrinkSelection)
                        index++;
                    if (shrinkSelection && expandSelectionList.Count < 2)
                    {
                        shrinkSelection = false;
                        expandSelectionList = new List<ImageSplitterItem>();
                    }
                }

                line = GetStringWithItalicTags(matches);
            }
            else
            {
                line = threadText;
            }
            if (checkBoxAutoFixCommonErrors.Checked && _ocrFixEngine != null)
                line = _ocrFixEngine.FixOcrErrorsViaHardcodedRules(line, _lastLine, null); // TODO: Add abbreviations list

            if (checkBoxRightToLeft.Checked)
                line = ReverseNumberStrings(line);

            //OCR fix engine
            string textWithOutFixes = line;
            //OCR fix engine not loaded, when no dictionary is selected
            if (_ocrFixEngine != null && _ocrFixEngine.IsDictionaryLoaded)
            {
                if (checkBoxAutoFixCommonErrors.Checked)
                    line = _ocrFixEngine.FixOcrErrors(line, listViewIndex, _lastLine, true, GetAutoGuessLevel());

                int correctWords;
                int wordsNotFound = _ocrFixEngine.CountUnknownWordsViaDictionary(line, out correctWords);

                if (wordsNotFound > 0 || correctWords == 0 || textWithOutFixes != null && string.IsNullOrWhiteSpace(textWithOutFixes.Replace("~", string.Empty)))
                {
                    _ocrFixEngine.AutoGuessesUsed.Clear();
                    _ocrFixEngine.UnknownWordsFound.Clear();
                    line = _ocrFixEngine.FixUnknownWordsViaGuessOrPrompt(out wordsNotFound, line, listViewIndex, bitmap, checkBoxAutoFixCommonErrors.Checked, checkBoxPromptForUnknownWords.Checked, true, GetAutoGuessLevel());
                }

                if (_ocrFixEngine.Abort)
                {
                    ButtonStopClick(null, null);
                    _ocrFixEngine.Abort = false;
                    return string.Empty;
                }

                // Log used word guesses (via word replace list)
                foreach (string guess in _ocrFixEngine.AutoGuessesUsed)
                    listBoxLogSuggestions.Items.Add(guess);
                _ocrFixEngine.AutoGuessesUsed.Clear();

                // Log unkown words guess (found via spelling dictionaries)
                LogUnknownWords();

                ColorLineByNumberOfUnknownWords(listViewIndex, wordsNotFound, line);
            }

            if (textWithOutFixes.Trim() != line.Trim())
            {
                _tesseractOcrAutoFixes++;
                labelFixesMade.Text = string.Format(" - {0}", _tesseractOcrAutoFixes);
                LogOcrFix(listViewIndex, textWithOutFixes, line);
            }

            return line;
        }
Пример #39
0
        internal CompareMatch GetNOcrCompareMatchNew(ImageSplitterItem targetItem, NikseBitmap parentBitmap, NOcrDb nOcrDb, bool tryItalicScaling, bool deepSeek)
        {
            var expandedResult = NOcrFindExpandedMatch(parentBitmap, targetItem, nOcrDb.OcrCharactersExpanded);
            if (expandedResult != null)
            {
                return new CompareMatch(expandedResult.Text, expandedResult.Italic, expandedResult.ExpandCount, null, expandedResult);
            }

            bool italic;
            var result = NOcrFindBestMatchNew(targetItem, targetItem.Y - targetItem.ParentY, out italic, nOcrDb, tryItalicScaling, deepSeek);
            if (result == null)
            {
                if (checkBoxNOcrCorrect.Checked)
                    return null;
                return new CompareMatch("*", false, 0, null);
            }

            // Fix uppercase/lowercase issues (not I/l)
            if (result.Text == "e")
                _nocrLastLowercaseHeight = targetItem.NikseBitmap.Height;
            else if (_nocrLastLowercaseHeight == -1 && result.Text == "a")
                _nocrLastLowercaseHeight = targetItem.NikseBitmap.Height;

            if (result.Text == "E" || result.Text == "H" || result.Text == "R" || result.Text == "D" || result.Text == "T")
                _nocrLastUppercaseHeight = targetItem.NikseBitmap.Height;
            else if (_nocrLastUppercaseHeight == -1 && result.Text == "M")
                _nocrLastUppercaseHeight = targetItem.NikseBitmap.Height;

            if (result.Text == "V" || result.Text == "W" || result.Text == "U" || result.Text == "S" || result.Text == "Z" || result.Text == "O" || result.Text == "X" || result.Text == "Ø" || result.Text == "C")
            {
                if (_nocrLastLowercaseHeight > 3 && targetItem.NikseBitmap.Height - _nocrLastLowercaseHeight < 2)
                    result.Text = result.Text.ToLower();
            }
            else if (result.Text == "v" || result.Text == "w" || result.Text == "u" || result.Text == "s" || result.Text == "z" || result.Text == "o" || result.Text == "x" || result.Text == "ø" || result.Text == "c")
            {
                if (_nocrLastUppercaseHeight > 3 && _nocrLastUppercaseHeight - targetItem.NikseBitmap.Height < 2)
                    result.Text = result.Text.ToUpper();
            }

            if (italic)
                return new CompareMatch(result.Text, true, 0, null, result);
            else
                return new CompareMatch(result.Text, result.Italic, 0, null, result);
        }
Пример #40
0
        private void SplitDvbForEachSubImage()
        {
            var list = new List<TransportStreamSubtitle>();
            foreach (var dvbSub in _dvbSubtitles)
            {
                if (dvbSub.ActiveImageIndex == null)
                {
                    var tempList = new List<TransportStreamSubtitle>();
                    for (int i = 0; i < dvbSub.Pes.ObjectDataList.Count; i++)
                    {
                        if (dvbSub.Pes.ObjectDataList[i].TopFieldDataBlockLength > 8)
                        {
                            tempList.Add(new TransportStreamSubtitle
                            {
                                Pes = dvbSub.Pes,
                                ActiveImageIndex = i,
                                StartMilliseconds = dvbSub.StartMilliseconds,
                                EndMilliseconds = dvbSub.EndMilliseconds
                            });
                        }
                    }

                    if (tempList.Count > 1)
                    {
                        var lastColor = Color.Transparent;
                        bool allAlike = true;
                        foreach (var item in tempList)
                        {
                            var dvbBmp = item.GetActiveImage();
                            var nDvbBmp = new NikseBitmap(dvbBmp);
                            var color = nDvbBmp.GetBrightestColor();
                            if (lastColor != Color.Transparent && (Math.Abs(color.R - lastColor.R) > 10 || Math.Abs(color.G - lastColor.G) > 10 || Math.Abs(color.B - lastColor.B) > 10))
                            {
                                allAlike = false;
                                break;
                            }
                            lastColor = color;
                        }
                        if (allAlike)
                        {
                            tempList.Clear();
                            tempList.Add(dvbSub);
                        }
                    }
                    list.AddRange(tempList);
                }
                else
                {
                    list.Add(dvbSub);
                }
            }
            _dvbSubtitles = list;
            _tesseractAsyncStrings = null;
            ShowDvbSubs();
        }
Пример #41
0
 private static int CalculateNumberOfForegroundColors(NikseBitmap nikseBitmap)
 {
     int count = 0;
     for (int y = 0; y < nikseBitmap.Height; y++)
     {
         for (int x = 0; x < nikseBitmap.Width; x++)
         {
             Color c = nikseBitmap.GetPixel(x, y);
             if (c.A > 100 && c.R + c.G + c.B > 200)
                 count++;
         }
     }
     return count;
 }
Пример #42
0
 public ImageCompareAddition(string name, string text, NikseBitmap image, bool italic, int index)
 {
     Name = name;
     Text = text;
     Image = image;
     Text = text;
     Italic = italic;
     Index = index;
 }
Пример #43
0
        public NOcrChar GetMatch(NikseBitmap bitmap, int topMargin, bool deepSeek, int maxWrongPixels)
        {
            // only very very accurate matches
            foreach (var oc in OcrCharacters)
            {
                if (bitmap.Width == oc.Width && bitmap.Height == oc.Height && Math.Abs(oc.MarginTop - topMargin) < 5)
                {
                    if (IsMatch(bitmap, oc, 0))
                    {
                        return(oc);
                    }
                }
            }

            // only very accurate matches
            double widthPercent = bitmap.Height * 100.0 / bitmap.Width;

            foreach (var oc in OcrCharacters)
            {
                if (Math.Abs(widthPercent - oc.WidthPercent) < 15 && Math.Abs(bitmap.Width - oc.Width) < 5 && Math.Abs(bitmap.Height - oc.Height) < 5 && Math.Abs(oc.MarginTop - topMargin) < 5)
                {
                    if (IsMatch(bitmap, oc, 0))
                    {
                        return(oc);
                    }
                }
            }

            if (maxWrongPixels >= 1)
            {
                foreach (var oc in OcrCharacters)
                {
                    if (Math.Abs(bitmap.Width - oc.Width) < 4 && Math.Abs(bitmap.Height - oc.Height) < 4 && Math.Abs(oc.MarginTop - topMargin) < 8)
                    {
                        if (IsMatch(bitmap, oc, 1))
                        {
                            return(oc);
                        }
                    }
                }
            }

            if (maxWrongPixels >= 1)
            {
                foreach (var oc in OcrCharacters)
                {
                    if (Math.Abs(bitmap.Width - oc.Width) < 8 && Math.Abs(bitmap.Height - oc.Height) < 8 && Math.Abs(oc.MarginTop - topMargin) < 8)
                    {
                        if (IsMatch(bitmap, oc, 1))
                        {
                            return(oc);
                        }
                    }
                }
            }

            if (maxWrongPixels >= 2)
            {
                var errorsAllowed = Math.Min(3, maxWrongPixels);
                foreach (var oc in OcrCharacters)
                {
                    if (Math.Abs(widthPercent - oc.WidthPercent) < 20 && Math.Abs(oc.MarginTop - topMargin) < 15)
                    {
                        if (IsMatch(bitmap, oc, errorsAllowed))
                        {
                            return(oc);
                        }
                    }
                }
            }

            if (maxWrongPixels >= 10)
            {
                var errorsAllowed = Math.Min(20, maxWrongPixels);
                foreach (var oc in OcrCharacters)
                {
                    if (!oc.IsSensitive && Math.Abs(widthPercent - oc.WidthPercent) < 20 && Math.Abs(oc.MarginTop - topMargin) < 15 && oc.LinesForeground.Count + oc.LinesBackground.Count > 40)
                    {
                        if (IsMatch(bitmap, oc, errorsAllowed))
                        {
                            return(oc);
                        }
                    }
                }
            }

            if (maxWrongPixels >= 10)
            {
                foreach (var oc in OcrCharacters)
                {
                    if (oc.IsSensitive && Math.Abs(widthPercent - oc.WidthPercent) < 30 && Math.Abs(oc.MarginTop - topMargin) < 15 && oc.LinesForeground.Count + oc.LinesBackground.Count > 40)
                    {
                        if (IsMatch(bitmap, oc, 10))
                        {
                            return(oc);
                        }
                    }
                }
            }

            if (deepSeek)
            {
                foreach (var oc in OcrCharacters)
                {
                    if (Math.Abs(widthPercent - oc.WidthPercent) < 60 && Math.Abs(oc.MarginTop - topMargin) < 17 && oc.LinesForeground.Count + oc.LinesBackground.Count > 50)
                    {
                        if (IsMatch(bitmap, oc, maxWrongPixels))
                        {
                            return(oc);
                        }
                    }
                }
            }

            return(null);
        }
Пример #44
0
        internal static ImageSplitterItem GetExpandedSelectionNew(NikseBitmap bitmap, List<ImageSplitterItem> expandSelectionList)
        {
            int minimumX = expandSelectionList[0].X;
            int maximumX = expandSelectionList[expandSelectionList.Count - 1].X + expandSelectionList[expandSelectionList.Count - 1].NikseBitmap.Width;
            int minimumY = expandSelectionList[0].Y;
            int maximumY = expandSelectionList[0].Y + expandSelectionList[0].NikseBitmap.Height;
            var nbmp = new NikseBitmap(bitmap.Width, bitmap.Height);
            foreach (ImageSplitterItem item in expandSelectionList)
            {
                for (int y = 0; y < item.NikseBitmap.Height; y++)
                {
                    for (int x = 0; x < item.NikseBitmap.Width; x++)
                    {
                        int a = item.NikseBitmap.GetAlpha(x, y);
                        if (a > 100)
                            nbmp.SetPixel(item.X + x, item.Y + y, Color.White);
                    }
                }
                if (item.Y < minimumY)
                    minimumY = item.Y;
                if (item.Y + item.NikseBitmap.Height > maximumY)
                    maximumY = item.Y + item.NikseBitmap.Height;
            }
            nbmp.CropTransparentSidesAndBottom(0, true);
            int topCropping;
            nbmp = NikseBitmapImageSplitter.CropTopAndBottom(nbmp, out topCropping);

            return new ImageSplitterItem(minimumX, minimumY, nbmp);
        }
Пример #45
0
        /// <summary>
        /// Create RLE buffer from bitmap
        /// </summary>
        /// <param name="bm">Bitmap to compress</param>
        /// <param name="palette">Palette used for bitmap encoding</param>
        /// <returns>RLE buffer</returns>
        private static byte[] EncodeImage(NikseBitmap bm, Dictionary <Color, int> palette)
        {
            var bytes = new List <Byte>();

            for (int y = 0; y < bm.Height; y++)
            {
                var ofs = y * bm.Width;
                //eol = false;
                int x;
                int len;
                for (x = 0; x < bm.Width; x += len, ofs += len)
                {
                    Color c = bm.GetPixel(x, y);
                    byte  color;
                    if (palette.ContainsKey(c))
                    {
                        color = (byte)palette[c];
                    }
                    else
                    {
                        color = FindBestMatch(c, palette);
                    }

                    for (len = 1; x + len < bm.Width; len++)
                    {
                        if (bm.GetPixel(x + len, y) != c)
                        {
                            break;
                        }
                    }

                    if (len <= 2 && color != 0)
                    {
                        // only a single occurrence -> add color
                        bytes.Add(color);
                        if (len == 2)
                        {
                            bytes.Add(color);
                        }
                    }
                    else
                    {
                        if (len > 0x3fff)
                        {
                            len = 0x3fff;
                        }
                        bytes.Add(0); // rle id
                        // commented out due to bug in SupRip

                        /*if (color == 0 && x+len == bm.Width)
                         * {
                         *  bytes.Add(0);
                         *  eol = true;
                         * }
                         * else */
                        if (color == 0 && len < 0x40)
                        {
                            // 00 xx -> xx times 0
                            bytes.Add((byte)len);
                        }
                        else if (color == 0)
                        {
                            // 00 4x xx -> xxx zeroes
                            bytes.Add((byte)(0x40 | (len >> 8)));
                            bytes.Add((byte)len);
                        }
                        else if (len < 0x40)
                        {
                            // 00 8x cc -> x times value cc
                            bytes.Add((byte)(0x80 | len));
                            bytes.Add(color);
                        }
                        else
                        {
                            // 00 cx yy cc -> xyy times value cc
                            bytes.Add((byte)(0xc0 | (len >> 8)));
                            bytes.Add((byte)len);
                            bytes.Add(color);
                        }
                    }
                }
                if (/*!eol &&*/ x == bm.Width)
                {
                    bytes.Add(0); // rle id
                    bytes.Add(0);
                }
            }
            int size = bytes.Count;

            byte[] retval = new byte[size];
            for (int i = 0; i < size; i++)
            {
                retval[i] = bytes[i];
            }
            return(retval);
        }