Add some support for Playstation portable subs format - thx Roland :)

This commit is contained in:
Nikolaj Olsson 2024-11-05 19:52:07 +01:00
parent 219056c11f
commit 642861e411
3 changed files with 308 additions and 0 deletions

View File

@ -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<string> 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<string> 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;
}
}
}

View File

@ -3323,6 +3323,28 @@ namespace Nikse.SubtitleEdit.Forms
} }
} }
if (format == null)
{
try
{
var f = new PlayStationSubs();
var list = new List<string>();
if (f.IsMine(list, fileName))
{
if (ContinueNewOrExit())
{
ImportAndOcrIBinaryParagraphList(fileName, f, list);
}
return;
}
}
catch
{
// ignore
}
}
if (format == null) if (format == null)
{ {
try try
@ -4519,6 +4541,7 @@ namespace Nikse.SubtitleEdit.Forms
using (var formSubOcr = new VobSubOcr()) using (var formSubOcr = new VobSubOcr())
{ {
var sub = new Subtitle(); var sub = new Subtitle();
sub.OriginalFormat = format;
format.LoadSubtitle(sub, list, fileName); format.LoadSubtitle(sub, list, fileName);
sub.FileName = fileName; sub.FileName = fileName;
formSubOcr.Initialize(sub, Configuration.Settings.VobSubOcr, false); formSubOcr.Initialize(sub, Configuration.Settings.VobSubOcr, false);
@ -4527,6 +4550,41 @@ namespace Nikse.SubtitleEdit.Forms
MakeHistoryForUndo(_language.BeforeImportingBdnXml); MakeHistoryForUndo(_language.BeforeImportingBdnXml);
FileNew(); FileNew();
_subtitle.Paragraphs.Clear(); _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<string> 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); SetCurrentFormat(Configuration.Settings.General.DefaultSubtitleFormat);
foreach (var p in formSubOcr.SubtitleFromOcr.Paragraphs) foreach (var p in formSubOcr.SubtitleFromOcr.Paragraphs)
{ {

View File

@ -31,6 +31,7 @@ using System.Xml;
using Nikse.SubtitleEdit.Core.Settings; using Nikse.SubtitleEdit.Core.Settings;
using MessageBox = Nikse.SubtitleEdit.Forms.SeMsgBox.MessageBox; using MessageBox = Nikse.SubtitleEdit.Forms.SeMsgBox.MessageBox;
using Timer = System.Windows.Forms.Timer; using Timer = System.Windows.Forms.Timer;
using System.Runtime.CompilerServices;
namespace Nikse.SubtitleEdit.Forms.Ocr namespace Nikse.SubtitleEdit.Forms.Ocr
{ {
@ -342,6 +343,7 @@ namespace Nikse.SubtitleEdit.Forms.Ocr
private XmlDocument _bdnXmlDocument; private XmlDocument _bdnXmlDocument;
private string _bdnFileName; private string _bdnFileName;
private bool _isSon; private bool _isSon;
private IBinaryParagraphList _binaryParagraphList;
private List<ImageCompareAddition> _lastAdditions = new List<ImageCompareAddition>(); private List<ImageCompareAddition> _lastAdditions = new List<ImageCompareAddition>();
private readonly VobSubOcrCharacter _vobSubOcrCharacter = new VobSubOcrCharacter(); 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) else if (_bdnXmlSubtitle != null)
{ {
if (index >= 0 && index < _bdnXmlSubtitle.Paragraphs.Count) if (index >= 0 && index < _bdnXmlSubtitle.Paragraphs.Count)
@ -2213,6 +2222,11 @@ namespace Nikse.SubtitleEdit.Forms.Ocr
return _binaryParagraphWithPositions.Count; return _binaryParagraphWithPositions.Count;
} }
if (_binaryParagraphList != null)
{
return _subtitle.Paragraphs.Count;
}
return _vobSubMergedPackList.Count; return _vobSubMergedPackList.Count;
} }
@ -4522,6 +4536,14 @@ namespace Nikse.SubtitleEdit.Forms.Ocr
SetButtonsEnabledAfterOcrDone(); SetButtonsEnabledAfterOcrDone();
buttonStartOcr.Focus(); buttonStartOcr.Focus();
} }
else if (_binaryParagraphList != null)
{
checkBoxShowOnlyForced.Visible = false;
checkBoxUseTimeCodesFromIdx.Visible = false;
SetButtonsEnabledAfterOcrDone();
buttonStartOcr.Focus();
}
else else
{ {
ReadyVobSubRip(); ReadyVobSubRip();
@ -7655,6 +7677,31 @@ namespace Nikse.SubtitleEdit.Forms.Ocr
LoadOcrFixEngine(threeLetterIsoLanguageName, LanguageString); 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) internal void Initialize(Subtitle bdnSubtitle, VobSubOcrSettings vobSubOcrSettings, bool isSon)
{ {
if (!string.IsNullOrEmpty(bdnSubtitle.FileName) && bdnSubtitle.FileName != new Subtitle().FileName) if (!string.IsNullOrEmpty(bdnSubtitle.FileName) && bdnSubtitle.FileName != new Subtitle().FileName)