diff --git a/Dictionaries/eng_OCRFixReplaceList.xml b/Dictionaries/eng_OCRFixReplaceList.xml index 2a94fc382..16eea4e43 100644 --- a/Dictionaries/eng_OCRFixReplaceList.xml +++ b/Dictionaries/eng_OCRFixReplaceList.xml @@ -2765,6 +2765,16 @@ + + + + + + + + + + diff --git a/LanguageMaster.xml b/LanguageMaster.xml index 988fbc9bd..fba1df93c 100644 --- a/LanguageMaster.xml +++ b/LanguageMaster.xml @@ -2532,7 +2532,7 @@ Keep changes? Edit image db - VobSub - Manual image to text + OCR - Manual image to text Shrink selection Expand selection Subtitle image diff --git a/Ocr/Latin.db b/Ocr/Latin.db index 3ef829a8f..66a71da61 100644 Binary files a/Ocr/Latin.db and b/Ocr/Latin.db differ diff --git a/libse/Language.cs b/libse/Language.cs index 793b27608..87ee8cb97 100644 --- a/libse/Language.cs +++ b/libse/Language.cs @@ -2869,7 +2869,7 @@ Keep changes?", VobSubOcrCharacter = new LanguageStructure.VobSubOcrCharacter { - Title = "VobSub - Manual image to text", + Title = "OCR - Manual image to text", Abort = "&Abort", Skip = "&Skip", SubtitleImage = "Subtitle image", diff --git a/src/Forms/Ocr/VobSubOcr.cs b/src/Forms/Ocr/VobSubOcr.cs index 0ac65554a..4fc245466 100644 --- a/src/Forms/Ocr/VobSubOcr.cs +++ b/src/Forms/Ocr/VobSubOcr.cs @@ -4031,9 +4031,14 @@ namespace Nikse.SubtitleEdit.Forms.Ocr _vobSubOcrCharacter.Initialize(bitmap, item, _manualOcrDialogPosition, _italicCheckedLast, expandSelectionList.Count > 1, null, _lastAdditions, this); DialogResult result = _vobSubOcrCharacter.ShowDialog(this); _manualOcrDialogPosition = _vobSubOcrCharacter.FormPosition; + if (result == DialogResult.Cancel && _vobSubOcrCharacter.SkipImage) + { + break; + } + if (result == DialogResult.OK && _vobSubOcrCharacter.ShrinkSelection) { - shrinkSelection = true; + shrinkSelection = true; index--; if (expandSelectionList.Count > 0) { @@ -4089,6 +4094,12 @@ namespace Nikse.SubtitleEdit.Forms.Ocr _vobSubOcrCharacter.Initialize(bitmap, item, _manualOcrDialogPosition, _italicCheckedLast, false, bestGuess, _lastAdditions, this, allowExpand); DialogResult result = _vobSubOcrCharacter.ShowDialog(this); _manualOcrDialogPosition = _vobSubOcrCharacter.FormPosition; + + if (result == DialogResult.Cancel && _vobSubOcrCharacter.SkipImage) + { + break; + } + if (result == DialogResult.OK && _vobSubOcrCharacter.ExpandSelection) { expandSelectionList.Add(item); @@ -4171,7 +4182,11 @@ namespace Nikse.SubtitleEdit.Forms.Ocr int wordsNotFound = _ocrFixEngine.CountUnknownWordsViaDictionary(line, out var correctWords); // smaller space pixels for italic - if (correctWords > 0 && wordsNotFound > 0 && line.Contains("", StringComparison.Ordinal) && matches.Any(p => p?.ImageSplitterItem?.CouldBeSpace == true)) + if (wordsNotFound > 0 && line.Contains("", StringComparison.Ordinal)) + { + AddItalicCouldBeSpace(matches, parentBitmap, _unItalicFactor); + } + if (wordsNotFound > 0 && line.Contains("", StringComparison.Ordinal) && matches.Any(p => p?.ImageSplitterItem?.CouldBeSpace == true)) { int j = 0; while (j < matches.Count) @@ -4196,7 +4211,8 @@ namespace Nikse.SubtitleEdit.Forms.Ocr } int tempWordsNotFound = _ocrFixEngine.CountUnknownWordsViaDictionary(tempLine, out var tempCorrectWords); - if (tempWordsNotFound == 0 && tempCorrectWords > 0) + //if (tempWordsNotFound == 0 && tempCorrectWords > 0) + if (tempWordsNotFound < wordsNotFound && tempCorrectWords > 0) { wordsNotFound = tempWordsNotFound; correctWords = tempCorrectWords; @@ -4253,6 +4269,74 @@ namespace Nikse.SubtitleEdit.Forms.Ocr return line; } + private void AddItalicCouldBeSpace(List matches, NikseBitmap parentBitmap, double unItalicFactor) + { + for (int i = 0; i < matches.Count - 1; i++) + { + var match = matches[i]; + var matchNext = matches[i + 1]; + if (!match.Italic || !matchNext.Italic || + string.IsNullOrWhiteSpace(match.Text) || string.IsNullOrWhiteSpace(matchNext.Text) || + match.ImageSplitterItem == null || match.ImageSplitterItem.CouldBeSpace) + { + continue; + } + + int blankVerticalLines = IsVerticalAngledLineTransparent(parentBitmap, match, matchNext, unItalicFactor); + if (blankVerticalLines >= _numericUpDownPixelsIsSpace) + { + matchNext.ImageSplitterItem.CouldBeSpace = true; // TODO: Rename to "could be space before" + } + } + } + + private int IsVerticalAngledLineTransparent(NikseBitmap parentBitmap, CompareMatch match, CompareMatch next, double unItalicFactor) + { + int blanks = 0; + var min = match.ImageSplitterItem.X + match.ImageSplitterItem.NikseBitmap.Width; + var max = next.ImageSplitterItem.X + next.ImageSplitterItem.NikseBitmap.Width / 2; + bool abort = false; + for (int startX = min; startX < max; startX++) + { + var lineBlank = true; + for (int y = match.ImageSplitterItem.Y; y < match.ImageSplitterItem.Y + match.ImageSplitterItem.NikseBitmap.Height; y++) + { + var x = startX - (y - match.ImageSplitterItem.Y) * unItalicFactor; + if (x >= 0) + { + var color = parentBitmap.GetPixel((int)Math.Round(x), y); + if (color.A == 0) + { + // parentBitmap.SetPixel((int)Math.Round(x), y, Color.LawnGreen); + } + else + { + // parentBitmap.SetPixel((int)Math.Round(x), y, Color.Red); + lineBlank = false; + if (blanks > 0) + { + abort = true; + break; + } + } + } + } + + if (abort) + { + break; + } + + if (lineBlank) + { + blanks++; + } + } + + //parentBitmap.GetBitmap().Save(@"J:\Temp\" + DateTime.UtcNow.Ticks + "_" + match.Text + "_" + blanks + ".bmp"); + return blanks; + } + private void SetBinOcrLowercaseUppercase(int height, string text) { if (text == "e" && (height < _binOcrLastLowercaseHeight || _binOcrLastLowercaseHeight < 0)) @@ -6513,10 +6597,7 @@ namespace Nikse.SubtitleEdit.Forms.Ocr } } - if (bmp != null) - { - bmp.Dispose(); - } + bmp?.Dispose(); if (mp.Text != null) { @@ -7003,6 +7084,31 @@ namespace Nikse.SubtitleEdit.Forms.Ocr form.ShowDialog(this); } } + else if (e.Modifiers == (Keys.Control | Keys.Shift) && e.KeyCode == Keys.I && _ocrMethodIndex == _ocrMethodBinaryImageCompare) + { + var bmp = (Bitmap)pictureBoxSubtitleImage.Image; + if (bmp != null) + { + var nBmp = new NikseBitmap(bmp); + bmp.Dispose(); + var italicFactor = _unItalicFactor; + + for (var startX = 20.0; startX < nBmp.Width; startX += 20.0) + { + var x = startX; + for (int y = 0; y < nBmp.Height; y++) + { + x = startX - y * italicFactor; + if (x >= 0) + { + nBmp.SetPixel((int)Math.Round(x), y, Color.Red); + } + } + } + + pictureBoxSubtitleImage.Image = nBmp.GetBitmap(); + } + } } private void ComboBoxTesseractLanguagesSelectedIndexChanged(object sender, EventArgs e) diff --git a/src/Forms/Ocr/VobSubOcrCharacter.Designer.cs b/src/Forms/Ocr/VobSubOcrCharacter.Designer.cs index 6686e39e7..f2fe73ad7 100644 --- a/src/Forms/Ocr/VobSubOcrCharacter.Designer.cs +++ b/src/Forms/Ocr/VobSubOcrCharacter.Designer.cs @@ -206,6 +206,7 @@ this.buttonSkip.TabIndex = 3; this.buttonSkip.Text = "&Skip"; this.buttonSkip.UseVisualStyleBackColor = true; + this.buttonSkip.Click += new System.EventHandler(this.buttonSkip_Click); // // pictureBoxSubtitleImage // diff --git a/src/Forms/Ocr/VobSubOcrCharacter.cs b/src/Forms/Ocr/VobSubOcrCharacter.cs index d50f67806..d9dea32d8 100644 --- a/src/Forms/Ocr/VobSubOcrCharacter.cs +++ b/src/Forms/Ocr/VobSubOcrCharacter.cs @@ -80,10 +80,13 @@ namespace Nikse.SubtitleEdit.Forms.Ocr public bool ShrinkSelection { get; private set; } + public bool SkipImage { get; private set; } + internal void Initialize(Bitmap vobSubImage, ImageSplitterItem character, Point position, bool italicChecked, bool showShrink, VobSubOcr.CompareMatch bestGuess, List additions, VobSubOcr vobSubForm, bool allowExpand = true) { ShrinkSelection = false; ExpandSelection = false; + SkipImage = false; textBoxCharacters.Text = string.Empty; if (bestGuess != null) @@ -292,6 +295,12 @@ namespace Nikse.SubtitleEdit.Forms.Ocr checkBoxItalic.Checked = !checkBoxItalic.Checked; e.SuppressKeyPress = true; } + else if (e.Modifiers == (Keys.Control | Keys.Shift) && e.KeyCode == Keys.S) + { + SkipImage = true; + DialogResult = DialogResult.Cancel; + e.SuppressKeyPress = true; + } } private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e) @@ -303,5 +312,10 @@ namespace Nikse.SubtitleEdit.Forms.Ocr { TaskbarList.StopBlink(_vobSubForm); } + + private void buttonSkip_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + } } } diff --git a/src/Forms/Ocr/VobSubOcrSetItalicFactor.Designer.cs b/src/Forms/Ocr/VobSubOcrSetItalicFactor.Designer.cs index 6bbc316dc..de59f0f81 100644 --- a/src/Forms/Ocr/VobSubOcrSetItalicFactor.Designer.cs +++ b/src/Forms/Ocr/VobSubOcrSetItalicFactor.Designer.cs @@ -34,19 +34,19 @@ this.pictureBoxSubtitleImage = new System.Windows.Forms.PictureBox(); this.contextMenuStripListview = new System.Windows.Forms.ContextMenuStrip(this.components); this.saveImageAsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.numericUpDownItalicFactor = new System.Windows.Forms.NumericUpDown(); this.labelDescription = new System.Windows.Forms.Label(); this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog(); ((System.ComponentModel.ISupportInitialize)(this.pictureBoxSubtitleImage)).BeginInit(); this.contextMenuStripListview.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDownItalicFactor)).BeginInit(); this.SuspendLayout(); // // buttonCancel // this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.buttonCancel.ImeMode = System.Windows.Forms.ImeMode.NoControl; - this.buttonCancel.Location = new System.Drawing.Point(680, 312); + this.buttonCancel.Location = new System.Drawing.Point(794, 366); this.buttonCancel.Name = "buttonCancel"; this.buttonCancel.Size = new System.Drawing.Size(75, 23); this.buttonCancel.TabIndex = 8; @@ -58,7 +58,7 @@ // this.buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.buttonOK.ImeMode = System.Windows.Forms.ImeMode.NoControl; - this.buttonOK.Location = new System.Drawing.Point(599, 312); + this.buttonOK.Location = new System.Drawing.Point(713, 366); this.buttonOK.Name = "buttonOK"; this.buttonOK.Size = new System.Drawing.Size(75, 23); this.buttonOK.TabIndex = 7; @@ -74,7 +74,7 @@ this.pictureBoxSubtitleImage.ContextMenuStrip = this.contextMenuStripListview; this.pictureBoxSubtitleImage.Location = new System.Drawing.Point(12, 47); this.pictureBoxSubtitleImage.Name = "pictureBoxSubtitleImage"; - this.pictureBoxSubtitleImage.Size = new System.Drawing.Size(743, 259); + this.pictureBoxSubtitleImage.Size = new System.Drawing.Size(857, 313); this.pictureBoxSubtitleImage.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; this.pictureBoxSubtitleImage.TabIndex = 9; this.pictureBoxSubtitleImage.TabStop = false; @@ -93,36 +93,37 @@ this.saveImageAsToolStripMenuItem.Text = "Save image as..."; this.saveImageAsToolStripMenuItem.Click += new System.EventHandler(this.saveImageAsToolStripMenuItem_Click); // - // numericUpDown1 + // numericUpDownItalicFactor // - this.numericUpDown1.DecimalPlaces = 2; - this.numericUpDown1.Increment = new decimal(new int[] { + this.numericUpDownItalicFactor.DecimalPlaces = 2; + this.numericUpDownItalicFactor.Increment = new decimal(new int[] { 1, 0, 0, 131072}); - this.numericUpDown1.Location = new System.Drawing.Point(12, 19); - this.numericUpDown1.Maximum = new decimal(new int[] { + this.numericUpDownItalicFactor.Location = new System.Drawing.Point(12, 19); + this.numericUpDownItalicFactor.Maximum = new decimal(new int[] { 10, 0, 0, 65536}); - this.numericUpDown1.Name = "numericUpDown1"; - this.numericUpDown1.Size = new System.Drawing.Size(57, 20); - this.numericUpDown1.TabIndex = 10; - this.numericUpDown1.Value = new decimal(new int[] { + this.numericUpDownItalicFactor.Name = "numericUpDownItalicFactor"; + this.numericUpDownItalicFactor.Size = new System.Drawing.Size(57, 20); + this.numericUpDownItalicFactor.TabIndex = 10; + this.numericUpDownItalicFactor.Value = new decimal(new int[] { 31, 0, 0, 131072}); - this.numericUpDown1.ValueChanged += new System.EventHandler(this.numericUpDown1_ValueChanged); + this.numericUpDownItalicFactor.ValueChanged += new System.EventHandler(this.numericUpDownItalicFactor_ValueChanged); // // labelDescription // this.labelDescription.AutoSize = true; + this.labelDescription.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.labelDescription.Location = new System.Drawing.Point(76, 21); this.labelDescription.Name = "labelDescription"; - this.labelDescription.Size = new System.Drawing.Size(431, 13); + this.labelDescription.Size = new System.Drawing.Size(529, 13); this.labelDescription.TabIndex = 11; this.labelDescription.Text = "Adjust value until text style is normal and not italic. Note that original image " + "should be italic."; @@ -131,24 +132,27 @@ // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(767, 345); + this.BackColor = System.Drawing.Color.DimGray; + this.ClientSize = new System.Drawing.Size(881, 399); this.Controls.Add(this.labelDescription); - this.Controls.Add(this.numericUpDown1); + this.Controls.Add(this.numericUpDownItalicFactor); this.Controls.Add(this.pictureBoxSubtitleImage); this.Controls.Add(this.buttonCancel); this.Controls.Add(this.buttonOK); this.KeyPreview = true; this.MaximizeBox = false; this.MinimizeBox = false; + this.MinimumSize = new System.Drawing.Size(783, 384); this.Name = "VobSubOcrSetItalicFactor"; this.ShowIcon = false; this.ShowInTaskbar = false; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Set un-italic factor"; + this.Shown += new System.EventHandler(this.VobSubOcrSetItalicFactor_Shown); this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.VobSubOcrSetItalicFactor_KeyDown); ((System.ComponentModel.ISupportInitialize)(this.pictureBoxSubtitleImage)).EndInit(); this.contextMenuStripListview.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDownItalicFactor)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -159,7 +163,7 @@ private System.Windows.Forms.Button buttonCancel; private System.Windows.Forms.Button buttonOK; private System.Windows.Forms.PictureBox pictureBoxSubtitleImage; - private System.Windows.Forms.NumericUpDown numericUpDown1; + private System.Windows.Forms.NumericUpDown numericUpDownItalicFactor; private System.Windows.Forms.Label labelDescription; private System.Windows.Forms.SaveFileDialog saveFileDialog1; private System.Windows.Forms.ContextMenuStrip contextMenuStripListview; diff --git a/src/Forms/Ocr/VobSubOcrSetItalicFactor.cs b/src/Forms/Ocr/VobSubOcrSetItalicFactor.cs index b70907f17..75339bbe8 100644 --- a/src/Forms/Ocr/VobSubOcrSetItalicFactor.cs +++ b/src/Forms/Ocr/VobSubOcrSetItalicFactor.cs @@ -19,7 +19,7 @@ namespace Nikse.SubtitleEdit.Forms.Ocr _bmp = bmp; _factor = factor; - numericUpDown1.Value = (decimal)factor; + numericUpDownItalicFactor.Value = (decimal)factor; Text = Configuration.Settings.Language.VobSubOcrSetItalicFactor.Title; labelDescription.Text = Configuration.Settings.Language.VobSubOcrSetItalicFactor.Description; @@ -28,9 +28,9 @@ namespace Nikse.SubtitleEdit.Forms.Ocr buttonCancel.Text = Configuration.Settings.Language.General.Cancel; } - private void numericUpDown1_ValueChanged(object sender, EventArgs e) + private void numericUpDownItalicFactor_ValueChanged(object sender, EventArgs e) { - pictureBoxSubtitleImage.Image = VobSubOcr.UnItalic(_bmp, (double)numericUpDown1.Value); + pictureBoxSubtitleImage.Image = VobSubOcr.UnItalic(_bmp, (double)numericUpDownItalicFactor.Value); } internal double GetUnItalicFactor() @@ -40,7 +40,7 @@ namespace Nikse.SubtitleEdit.Forms.Ocr private void buttonOK_Click(object sender, EventArgs e) { - _factor = (double)numericUpDown1.Value; + _factor = (double)numericUpDownItalicFactor.Value; DialogResult = DialogResult.OK; } @@ -101,5 +101,9 @@ namespace Nikse.SubtitleEdit.Forms.Ocr } } + private void VobSubOcrSetItalicFactor_Shown(object sender, EventArgs e) + { + numericUpDownItalicFactor_ValueChanged(null, null); + } } }