diff --git a/src/libse/SubtitleFormats/PlayStationSubs.cs b/src/libse/SubtitleFormats/PlayStationSubs.cs new file mode 100644 index 000000000..0f6813582 --- /dev/null +++ b/src/libse/SubtitleFormats/PlayStationSubs.cs @@ -0,0 +1,203 @@ +using Nikse.SubtitleEdit.Core.Common; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Text; +using Nikse.SubtitleEdit.Core.Interfaces; + +namespace Nikse.SubtitleEdit.Core.SubtitleFormats +{ + public class PlayStationSubs : SubtitleFormat, IBinaryParagraphList + { + public override string Extension => ".subs"; + + public const string NameOfFormat = "PlayStation Subs"; + + public override string Name => NameOfFormat; + + private byte[] _buffer; + + public override bool IsMine(List lines, string fileName) + { + if (string.IsNullOrEmpty(fileName) || !File.Exists(fileName) || !fileName.EndsWith(".subs", StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + try + { + var fi = new FileInfo(fileName); + if (fi.Length > 100 && fi.Length < 50_000_000) // not too small or too big + { + _buffer = FileUtil.ReadAllBytesShared(fileName); + + if (_buffer[30] == 0x89 && + _buffer[31] == 0x50 && + _buffer[32] == 0x4E && + _buffer[33] == 0x47) + { + var sub = new Subtitle(); + LoadSubtitle(sub, null, fileName); + return sub.Paragraphs.Count > 0; + } + } + } + catch + { + return false; + } + + return false; + } + + public override string ToText(Subtitle subtitle, string title) + { + return "Not supported!"; + } + + public override void LoadSubtitle(Subtitle subtitle, List lines, string fileName) + { + subtitle.Paragraphs.Clear(); + subtitle.Header = null; + + var index = 30; + while (index < _buffer.Length - 14) + { + // PNG header: 89 50 4E 47 0D 0A 1A 0A + if (_buffer[index] == 0x89 && + _buffer[index + 1] == 0x50 && + _buffer[index + 2] == 0x4E && + _buffer[index + 3] == 0x47 && + _buffer[index + 4] == 0x0D && + _buffer[index + 5] == 0x0A && + _buffer[index + 6] == 0x1A && + _buffer[index + 7] == 0x0A) + { + var startHour = _buffer[index - 29]; + var startMinutes = _buffer[index - 28]; + var startSeconds = _buffer[index - 27]; + var startMilliseconds = _buffer[index - 26]; + + var durationHour = _buffer[index - 20]; + var durationMinutes = _buffer[index - 19]; + var durationSeconds = _buffer[index - 18]; + var durationMilliseconds = _buffer[index - 17]; + + var p = new Paragraph + { + Layer = index, + StartTime = new TimeCode(startHour, startMinutes, startSeconds, startMilliseconds), + EndTime = new TimeCode( durationHour, durationMinutes, durationSeconds, durationMilliseconds) + }; + + index += 8; + + p.StartTime.TotalMilliseconds /= 100; + + p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + p.EndTime.TotalMilliseconds / 10; + + + subtitle.Paragraphs.Add(p); + + while (index - 12 < _buffer.Length - 14) + { + if (_buffer[index] == 0 && + _buffer[index + 1] == 0 && + _buffer[index + 2] == 0 && + _buffer[index + 3] == 0) + { + // read chunk type + var chunkType = Encoding.ASCII.GetString(_buffer, index + 4, 4); + if (chunkType == "IEND") + { + index += 8; + break; + } + else + { + index++; + } + } + else + { + index++; + } + } + } + else + { + index++; + } + } + + subtitle.Renumber(); + } + + public Bitmap GetSubtitleBitmap(int index2, bool crop = true) + { + var index = 30; + var paragraphIndex = 0; + while (index < _buffer.Length - 14) + { + // PNG header: 89 50 4E 47 0D 0A 1A 0A + if (_buffer[index] == 0x89 && + _buffer[index + 1] == 0x50 && + _buffer[index + 2] == 0x4E && + _buffer[index + 3] == 0x47 && + _buffer[index + 4] == 0x0D && + _buffer[index + 5] == 0x0A && + _buffer[index + 6] == 0x1A && + _buffer[index + 7] == 0x0A) + { + var start = index; + index += 8; + + while (index - 12 < _buffer.Length - 14) + { + if (_buffer[index] == 0 && + _buffer[index + 1] == 0 && + _buffer[index + 2] == 0 && + _buffer[index + 3] == 0) + { + // read chunk type + var chunkType = Encoding.ASCII.GetString(_buffer, index + 4, 4); + if (chunkType == "IEND") + { + index += 8; + + if (paragraphIndex == index2) + { + index += 4; // CRC + var b = new byte[index - start]; + Array.Copy(_buffer, start, b, 0, b.Length); + return new Bitmap(new MemoryStream(b)); + } + + paragraphIndex++; + break; + } + + index++; + } + else + { + index++; + } + } + } + else + { + index++; + } + } + + return new Bitmap(1, 1); + } + + public bool GetIsForced(int index) + { + return false; + } + } +} diff --git a/src/ui/Forms/Main.cs b/src/ui/Forms/Main.cs index d628207e5..e0e1f01f4 100644 --- a/src/ui/Forms/Main.cs +++ b/src/ui/Forms/Main.cs @@ -3323,6 +3323,28 @@ namespace Nikse.SubtitleEdit.Forms } } + if (format == null) + { + try + { + var f = new PlayStationSubs(); + var list = new List(); + if (f.IsMine(list, fileName)) + { + if (ContinueNewOrExit()) + { + ImportAndOcrIBinaryParagraphList(fileName, f, list); + } + + return; + } + } + catch + { + // ignore + } + } + if (format == null) { try @@ -4519,6 +4541,7 @@ namespace Nikse.SubtitleEdit.Forms using (var formSubOcr = new VobSubOcr()) { var sub = new Subtitle(); + sub.OriginalFormat = format; format.LoadSubtitle(sub, list, fileName); sub.FileName = fileName; formSubOcr.Initialize(sub, Configuration.Settings.VobSubOcr, false); @@ -4527,6 +4550,41 @@ namespace Nikse.SubtitleEdit.Forms MakeHistoryForUndo(_language.BeforeImportingBdnXml); FileNew(); _subtitle.Paragraphs.Clear(); + _subtitle.OriginalFormat = format; + SetCurrentFormat(Configuration.Settings.General.DefaultSubtitleFormat); + foreach (var p in formSubOcr.SubtitleFromOcr.Paragraphs) + { + _subtitle.Paragraphs.Add(p); + } + + UpdateSourceView(); + SubtitleListview1.Fill(_subtitle, _subtitleOriginal); + _subtitleListViewIndex = -1; + SubtitleListview1.FirstVisibleIndex = -1; + SubtitleListview1.SelectIndexAndEnsureVisible(0, true); + + _fileName = Path.ChangeExtension(formSubOcr.FileName, GetCurrentSubtitleFormat().Extension); + SetTitle(); + _converted = true; + } + } + } + + private void ImportAndOcrIBinaryParagraphList(string fileName, SubtitleFormat format, List list) + { + using (var formSubOcr = new VobSubOcr()) + { + var sub = new Subtitle(); + sub.OriginalFormat = format; + format.LoadSubtitle(sub, list, fileName); + sub.FileName = fileName; + formSubOcr.InitializeIBinaryParagraphList(format as IBinaryParagraphList, sub); + if (formSubOcr.ShowDialog(this) == DialogResult.OK) + { + MakeHistoryForUndo(_language.BeforeImportingBdnXml); + FileNew(); + _subtitle.Paragraphs.Clear(); + _subtitle.OriginalFormat = format; SetCurrentFormat(Configuration.Settings.General.DefaultSubtitleFormat); foreach (var p in formSubOcr.SubtitleFromOcr.Paragraphs) { diff --git a/src/ui/Forms/Ocr/VobSubOcr.cs b/src/ui/Forms/Ocr/VobSubOcr.cs index 408a400d1..62766f817 100644 --- a/src/ui/Forms/Ocr/VobSubOcr.cs +++ b/src/ui/Forms/Ocr/VobSubOcr.cs @@ -31,6 +31,7 @@ using System.Xml; using Nikse.SubtitleEdit.Core.Settings; using MessageBox = Nikse.SubtitleEdit.Forms.SeMsgBox.MessageBox; using Timer = System.Windows.Forms.Timer; +using System.Runtime.CompilerServices; namespace Nikse.SubtitleEdit.Forms.Ocr { @@ -342,6 +343,7 @@ namespace Nikse.SubtitleEdit.Forms.Ocr private XmlDocument _bdnXmlDocument; private string _bdnFileName; private bool _isSon; + private IBinaryParagraphList _binaryParagraphList; private List _lastAdditions = new List(); private readonly VobSubOcrCharacter _vobSubOcrCharacter = new VobSubOcrCharacter(); @@ -1677,6 +1679,13 @@ namespace Nikse.SubtitleEdit.Forms.Ocr } } } + else if (_binaryParagraphList != null) + { + if (index >= 0) + { + returnBmp = _binaryParagraphList.GetSubtitleBitmap(index, crop); + } + } else if (_bdnXmlSubtitle != null) { if (index >= 0 && index < _bdnXmlSubtitle.Paragraphs.Count) @@ -2213,6 +2222,11 @@ namespace Nikse.SubtitleEdit.Forms.Ocr return _binaryParagraphWithPositions.Count; } + if (_binaryParagraphList != null) + { + return _subtitle.Paragraphs.Count; + } + return _vobSubMergedPackList.Count; } @@ -4522,6 +4536,14 @@ namespace Nikse.SubtitleEdit.Forms.Ocr SetButtonsEnabledAfterOcrDone(); buttonStartOcr.Focus(); } + else if (_binaryParagraphList != null) + { + checkBoxShowOnlyForced.Visible = false; + checkBoxUseTimeCodesFromIdx.Visible = false; + + SetButtonsEnabledAfterOcrDone(); + buttonStartOcr.Focus(); + } else { ReadyVobSubRip(); @@ -7655,6 +7677,31 @@ namespace Nikse.SubtitleEdit.Forms.Ocr LoadOcrFixEngine(threeLetterIsoLanguageName, LanguageString); } + + internal void InitializeIBinaryParagraphList(IBinaryParagraphList binaryParagraphList, Subtitle subtitle) + { + _binaryParagraphList = binaryParagraphList; + _subtitle = subtitle; + subtitleListView1.Fill(_subtitle); + subtitleListView1.SelectIndexAndEnsureVisible(0); + + SetButtonsStartOcr(); + progressBar1.Visible = false; + progressBar1.Maximum = 100; + progressBar1.Value = 0; + + InitializeTesseract(); + LoadImageCompareCharacterDatabaseList(Configuration.Settings.VobSubOcr.LastBinaryImageCompareDb); + SetOcrMethod(); + + groupBoxImagePalette.Visible = false; + + Text += "OCR - " + Path.GetFileName(_bdnFileName); + + autoTransparentBackgroundToolStripMenuItem.Visible = false; + _bdnXmlSubtitle = null; + } + internal void Initialize(Subtitle bdnSubtitle, VobSubOcrSettings vobSubOcrSettings, bool isSon) { if (!string.IsNullOrEmpty(bdnSubtitle.FileName) && bdnSubtitle.FileName != new Subtitle().FileName)