mirror of
https://github.com/SubtitleEdit/subtitleedit.git
synced 2024-11-25 04:33:04 +01:00
Added Bluray sup import (thx to open source project bdsup2sub) + ocr
git-svn-id: https://subtitleedit.googlecode.com/svn/trunk@152 99eadd0c-20b8-1223-b5c4-2a2b2df33de2
This commit is contained in:
parent
5bc07de545
commit
4c1e5129ae
10
src/Forms/Main.Designer.cs
generated
10
src/Forms/Main.Designer.cs
generated
@ -73,6 +73,7 @@
|
||||
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.toolStripMenuItemImportDvdSubtitles = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItemSubIdx = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItemImportBluRaySup = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.matroskaImportStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItemManualAnsi = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItemImportText = new System.Windows.Forms.ToolStripMenuItem();
|
||||
@ -656,6 +657,7 @@
|
||||
this.toolStripSeparator1,
|
||||
this.toolStripMenuItemImportDvdSubtitles,
|
||||
this.toolStripMenuItemSubIdx,
|
||||
this.toolStripMenuItemImportBluRaySup,
|
||||
this.matroskaImportStripMenuItem,
|
||||
this.toolStripMenuItemManualAnsi,
|
||||
this.toolStripMenuItemImportText,
|
||||
@ -742,6 +744,13 @@
|
||||
this.toolStripMenuItemSubIdx.Text = "Import/OCR VobSub (sub/idx) subtitle...";
|
||||
this.toolStripMenuItemSubIdx.Click += new System.EventHandler(this.ToolStripMenuItemSubIdxClick1);
|
||||
//
|
||||
// toolStripMenuItemImportBluRaySup
|
||||
//
|
||||
this.toolStripMenuItemImportBluRaySup.Name = "toolStripMenuItemImportBluRaySup";
|
||||
this.toolStripMenuItemImportBluRaySup.Size = new System.Drawing.Size(334, 22);
|
||||
this.toolStripMenuItemImportBluRaySup.Text = "Import/OCR BluRay sup file...";
|
||||
this.toolStripMenuItemImportBluRaySup.Click += new System.EventHandler(this.toolStripMenuItemImportBluRaySup_Click);
|
||||
//
|
||||
// matroskaImportStripMenuItem
|
||||
//
|
||||
this.matroskaImportStripMenuItem.Name = "matroskaImportStripMenuItem";
|
||||
@ -3137,6 +3146,7 @@
|
||||
private System.Windows.Forms.TrackBar trackBarWaveFormPosition;
|
||||
private System.Windows.Forms.Label labelVideoInfo;
|
||||
private System.Windows.Forms.ToolStripMenuItem showhideWaveFormToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItemImportBluRaySup;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ using Nikse.SubtitleEdit.Logic.Enums;
|
||||
using Nikse.SubtitleEdit.Logic.SubtitleFormats;
|
||||
using Nikse.SubtitleEdit.Logic.VideoPlayers;
|
||||
using Nikse.SubtitleEdit.Logic.VobSub;
|
||||
using Nikse.SubtitleEdit.Logic.BluRaySup;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Forms
|
||||
{
|
||||
@ -139,6 +140,8 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
labelVideoInfo.Text = string.Empty;
|
||||
Text = Title;
|
||||
timeUpDownStartTime.TimeCode = new TimeCode(0, 0, 0, 0);
|
||||
checkBoxAutoRepeatOn.Checked = Configuration.Settings.General.AutoRepeatOn;
|
||||
checkBoxAutoContinue.Checked = Configuration.Settings.General.AutoContinueOn;
|
||||
|
||||
SetFormatToSubRip();
|
||||
|
||||
@ -450,6 +453,10 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
toolStripMenuItemCompare.Text = _language.Menu.File.Compare;
|
||||
toolStripMenuItemImportDvdSubtitles.Text = _language.Menu.File.ImportOcrFromDvd;
|
||||
toolStripMenuItemSubIdx.Text = _language.Menu.File.ImportOcrVobSubSubtitle;
|
||||
|
||||
//toolStripMenuItemImportBluRaySup.Visible = false; //TODO: add blu ray sup import/ocr
|
||||
toolStripMenuItemImportBluRaySup.Text = _language.Menu.File.ImportBluRaySupFile;
|
||||
|
||||
matroskaImportStripMenuItem.Text = _language.Menu.File.ImportSubtitleFromMatroskaFile;
|
||||
toolStripMenuItemManualAnsi.Text = _language.Menu.File.ImportSubtitleWithManualChosenEncoding;
|
||||
toolStripMenuItemImportText.Text = _language.Menu.File.ImportText;
|
||||
@ -844,7 +851,8 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
return;
|
||||
}
|
||||
|
||||
MakeHistoryForUndo(string.Format(_language.BeforeLoadOf, Path.GetFileName(fileName)));
|
||||
if (_subtitle.HistoryItems.Count > 0 || _subtitle.Paragraphs.Count > 0)
|
||||
MakeHistoryForUndo(string.Format(_language.BeforeLoadOf, Path.GetFileName(fileName)));
|
||||
|
||||
SubtitleFormat format = _subtitle.LoadSubtitle(fileName, out encoding, encoding);
|
||||
|
||||
@ -3454,6 +3462,9 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
|
||||
//TODO: save in adjust all lines ...Configuration.Settings.General.DefaultAdjustMilliseconds = (int)timeUpDownAdjust.TimeCode.TotalMilliseconds;
|
||||
|
||||
Configuration.Settings.General.AutoRepeatOn = checkBoxAutoRepeatOn.Checked;
|
||||
Configuration.Settings.General.AutoContinueOn = checkBoxAutoContinue.Checked;
|
||||
|
||||
Configuration.Settings.Save();
|
||||
}
|
||||
}
|
||||
@ -4078,6 +4089,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
|
||||
_fileName = Path.ChangeExtension(vobSubOcr.FileName, ".srt");
|
||||
Text = Title + " - " + _fileName;
|
||||
_converted = true;
|
||||
|
||||
Configuration.Settings.Save();
|
||||
}
|
||||
@ -4169,7 +4181,12 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
|
||||
private void Main_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.KeyCode == Keys.Right && e.Modifiers == Keys.Control)
|
||||
if (e.Modifiers == Keys.Control && e.KeyCode == Keys.Z)
|
||||
{
|
||||
ShowHistoryforUndoToolStripMenuItemClick(null, null);
|
||||
e.SuppressKeyPress = true;
|
||||
}
|
||||
else if (e.KeyCode == Keys.Right && e.Modifiers == Keys.Control)
|
||||
{
|
||||
if (!textBoxListViewText.Focused)
|
||||
{
|
||||
@ -4282,6 +4299,13 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
e.SuppressKeyPress = true;
|
||||
}
|
||||
}
|
||||
else if (e.Modifiers == Keys.None && e.KeyCode == Keys.F6)
|
||||
{
|
||||
if (mediaPlayer.VideoPlayer != null)
|
||||
{
|
||||
GotoSubPositionAndPause();
|
||||
}
|
||||
}
|
||||
else if (e.Modifiers == Keys.None && e.KeyCode == Keys.F7)
|
||||
{
|
||||
if (mediaPlayer.VideoPlayer != null)
|
||||
@ -4324,6 +4348,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
}
|
||||
else if (e.Modifiers == Keys.None && e.KeyCode == Keys.F12)
|
||||
{
|
||||
StopAutoDuration();
|
||||
buttonSetEnd_Click(null, null);
|
||||
e.SuppressKeyPress = true;
|
||||
}
|
||||
@ -4347,6 +4372,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
}
|
||||
else if (e.Modifiers == Keys.None && e.KeyCode == Keys.F12)
|
||||
{
|
||||
StopAutoDuration();
|
||||
buttonSetEnd_Click(null, null);
|
||||
e.SuppressKeyPress = true;
|
||||
}
|
||||
@ -6291,5 +6317,58 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
}
|
||||
}
|
||||
|
||||
private void toolStripMenuItemImportBluRaySup_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (ContinueNewOrExit())
|
||||
{
|
||||
openFileDialog1.Title = _language.OpenBluRaySupFile;
|
||||
openFileDialog1.FileName = string.Empty;
|
||||
openFileDialog1.Filter = _language.BluRaySupFiles + "|*.sup";
|
||||
if (openFileDialog1.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
ImportAndOcrBluRaySup(openFileDialog1.FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ImportAndOcrBluRaySup(string fileName)
|
||||
{
|
||||
StringBuilder log = new StringBuilder();
|
||||
var subtitles = BluRaySupParser.ParseBluRaySup(fileName, log);
|
||||
if (subtitles.Count > 0)
|
||||
{
|
||||
var vobSubOcr = new VobSubOcr();
|
||||
vobSubOcr.Initialize(subtitles, Configuration.Settings.VobSubOcr);
|
||||
vobSubOcr.FileName = Path.GetFileName(fileName);
|
||||
if (vobSubOcr.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
MakeHistoryForUndo(_language.BeforeImportingBluRaySupFile);
|
||||
|
||||
_subtitle.Paragraphs.Clear();
|
||||
SetCurrentFormat(new SubRip().FriendlyName);
|
||||
_subtitle.WasLoadedWithFrameNumbers = false;
|
||||
_subtitle.CalculateFrameNumbersFromTimeCodes(CurrentFrameRate);
|
||||
foreach (Paragraph p in vobSubOcr.SubtitleFromOcr.Paragraphs)
|
||||
{
|
||||
_subtitle.Paragraphs.Add(p);
|
||||
}
|
||||
|
||||
ShowSource();
|
||||
SubtitleListview1.Fill(_subtitle, _subtitleAlternate);
|
||||
_change = true;
|
||||
_subtitleListViewIndex = -1;
|
||||
SubtitleListview1.FirstVisibleIndex = -1;
|
||||
SubtitleListview1.SelectIndexAndEnsureVisible(0);
|
||||
|
||||
_fileName = Path.ChangeExtension(vobSubOcr.FileName, ".srt");
|
||||
Text = Title + " - " + _fileName;
|
||||
_converted = true;
|
||||
|
||||
Configuration.Settings.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -291,47 +291,47 @@
|
||||
<data name="toolStripButtonReplace.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
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
|
||||
RK5CYII=
|
||||
</value>
|
||||
</data>
|
||||
|
26
src/Forms/OCRSpellCheck.Designer.cs
generated
26
src/Forms/OCRSpellCheck.Designer.cs
generated
@ -63,7 +63,7 @@
|
||||
// buttonAbort
|
||||
//
|
||||
this.buttonAbort.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.buttonAbort.Location = new System.Drawing.Point(512, 404);
|
||||
this.buttonAbort.Location = new System.Drawing.Point(623, 442);
|
||||
this.buttonAbort.Name = "buttonAbort";
|
||||
this.buttonAbort.Size = new System.Drawing.Size(85, 21);
|
||||
this.buttonAbort.TabIndex = 24;
|
||||
@ -86,9 +86,9 @@
|
||||
this.groupBoxSuggestions.Controls.Add(this.buttonUseSuggestionAlways);
|
||||
this.groupBoxSuggestions.Controls.Add(this.buttonUseSuggestion);
|
||||
this.groupBoxSuggestions.Controls.Add(this.listBoxSuggestions);
|
||||
this.groupBoxSuggestions.Location = new System.Drawing.Point(320, 211);
|
||||
this.groupBoxSuggestions.Location = new System.Drawing.Point(320, 249);
|
||||
this.groupBoxSuggestions.Name = "groupBoxSuggestions";
|
||||
this.groupBoxSuggestions.Size = new System.Drawing.Size(277, 187);
|
||||
this.groupBoxSuggestions.Size = new System.Drawing.Size(388, 187);
|
||||
this.groupBoxSuggestions.TabIndex = 32;
|
||||
this.groupBoxSuggestions.TabStop = false;
|
||||
this.groupBoxSuggestions.Text = "Suggestions";
|
||||
@ -96,7 +96,7 @@
|
||||
// buttonUseSuggestionAlways
|
||||
//
|
||||
this.buttonUseSuggestionAlways.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.buttonUseSuggestionAlways.Location = new System.Drawing.Point(180, 16);
|
||||
this.buttonUseSuggestionAlways.Location = new System.Drawing.Point(291, 16);
|
||||
this.buttonUseSuggestionAlways.Name = "buttonUseSuggestionAlways";
|
||||
this.buttonUseSuggestionAlways.Size = new System.Drawing.Size(87, 21);
|
||||
this.buttonUseSuggestionAlways.TabIndex = 33;
|
||||
@ -107,7 +107,7 @@
|
||||
// buttonUseSuggestion
|
||||
//
|
||||
this.buttonUseSuggestion.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.buttonUseSuggestion.Location = new System.Drawing.Point(95, 16);
|
||||
this.buttonUseSuggestion.Location = new System.Drawing.Point(206, 16);
|
||||
this.buttonUseSuggestion.Name = "buttonUseSuggestion";
|
||||
this.buttonUseSuggestion.Size = new System.Drawing.Size(79, 21);
|
||||
this.buttonUseSuggestion.TabIndex = 32;
|
||||
@ -122,7 +122,7 @@
|
||||
this.listBoxSuggestions.FormattingEnabled = true;
|
||||
this.listBoxSuggestions.Location = new System.Drawing.Point(6, 39);
|
||||
this.listBoxSuggestions.Name = "listBoxSuggestions";
|
||||
this.listBoxSuggestions.Size = new System.Drawing.Size(261, 134);
|
||||
this.listBoxSuggestions.Size = new System.Drawing.Size(372, 134);
|
||||
this.listBoxSuggestions.TabIndex = 30;
|
||||
//
|
||||
// GroupBoxEditWord
|
||||
@ -135,7 +135,7 @@
|
||||
this.GroupBoxEditWord.Controls.Add(this.textBoxWord);
|
||||
this.GroupBoxEditWord.Controls.Add(this.buttonSkipOnce);
|
||||
this.GroupBoxEditWord.Controls.Add(this.buttonAddToNames);
|
||||
this.GroupBoxEditWord.Location = new System.Drawing.Point(12, 211);
|
||||
this.GroupBoxEditWord.Location = new System.Drawing.Point(12, 249);
|
||||
this.GroupBoxEditWord.Name = "GroupBoxEditWord";
|
||||
this.GroupBoxEditWord.Size = new System.Drawing.Size(302, 187);
|
||||
this.GroupBoxEditWord.TabIndex = 33;
|
||||
@ -217,7 +217,7 @@
|
||||
this.groupBoxEditWholeText.Controls.Add(this.buttonSkipText);
|
||||
this.groupBoxEditWholeText.Controls.Add(this.buttonChangeWholeText);
|
||||
this.groupBoxEditWholeText.Controls.Add(this.textBoxWholeText);
|
||||
this.groupBoxEditWholeText.Location = new System.Drawing.Point(12, 210);
|
||||
this.groupBoxEditWholeText.Location = new System.Drawing.Point(12, 248);
|
||||
this.groupBoxEditWholeText.Name = "groupBoxEditWholeText";
|
||||
this.groupBoxEditWholeText.Size = new System.Drawing.Size(302, 188);
|
||||
this.groupBoxEditWholeText.TabIndex = 37;
|
||||
@ -261,7 +261,7 @@
|
||||
this.groupBoxTextAsImage.Controls.Add(this.pictureBoxText);
|
||||
this.groupBoxTextAsImage.Location = new System.Drawing.Point(12, 12);
|
||||
this.groupBoxTextAsImage.Name = "groupBoxTextAsImage";
|
||||
this.groupBoxTextAsImage.Size = new System.Drawing.Size(585, 114);
|
||||
this.groupBoxTextAsImage.Size = new System.Drawing.Size(696, 152);
|
||||
this.groupBoxTextAsImage.TabIndex = 34;
|
||||
this.groupBoxTextAsImage.TabStop = false;
|
||||
this.groupBoxTextAsImage.Text = "Image text";
|
||||
@ -273,7 +273,7 @@
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.pictureBoxText.Location = new System.Drawing.Point(6, 18);
|
||||
this.pictureBoxText.Name = "pictureBoxText";
|
||||
this.pictureBoxText.Size = new System.Drawing.Size(573, 89);
|
||||
this.pictureBoxText.Size = new System.Drawing.Size(684, 127);
|
||||
this.pictureBoxText.TabIndex = 32;
|
||||
this.pictureBoxText.TabStop = false;
|
||||
//
|
||||
@ -284,9 +284,9 @@
|
||||
this.groupBoxText.Controls.Add(this.richTextBoxParagraph);
|
||||
this.groupBoxText.Controls.Add(this.buttonEditWholeText);
|
||||
this.groupBoxText.Controls.Add(this.buttonEditWord);
|
||||
this.groupBoxText.Location = new System.Drawing.Point(12, 132);
|
||||
this.groupBoxText.Location = new System.Drawing.Point(12, 170);
|
||||
this.groupBoxText.Name = "groupBoxText";
|
||||
this.groupBoxText.Size = new System.Drawing.Size(585, 72);
|
||||
this.groupBoxText.Size = new System.Drawing.Size(696, 72);
|
||||
this.groupBoxText.TabIndex = 38;
|
||||
this.groupBoxText.TabStop = false;
|
||||
this.groupBoxText.Text = "Text";
|
||||
@ -326,7 +326,7 @@
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(609, 435);
|
||||
this.ClientSize = new System.Drawing.Size(720, 473);
|
||||
this.Controls.Add(this.groupBoxText);
|
||||
this.Controls.Add(this.groupBoxTextAsImage);
|
||||
this.Controls.Add(this.buttonAbort);
|
||||
|
@ -82,6 +82,11 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
List<VobSubMergedPack> _vobSubMergedPackist;
|
||||
List<Color> _palette;
|
||||
|
||||
// BluRay sup
|
||||
List<Logic.BluRaySup.BluRaySupPicture> _bluRaySubtitlesOriginal;
|
||||
List<Logic.BluRaySup.BluRaySupPicture> _bluRaySubtitles;
|
||||
Nikse.SubtitleEdit.Logic.BluRaySup.BluRaySupPalette _defaultPaletteInfo;
|
||||
|
||||
// Tesseract OCR
|
||||
//tessnet2.Tesseract _tesseractOcrEngine;
|
||||
// object _tesseractOcrEngine;
|
||||
@ -220,6 +225,40 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
checkBoxCustomFourColors.Checked = true;
|
||||
}
|
||||
|
||||
internal void Initialize(List<Logic.BluRaySup.BluRaySupPicture> subtitles, VobSubOcrSettings vobSubOcrSettings)
|
||||
{
|
||||
buttonOK.Enabled = false;
|
||||
buttonCancel.Enabled = false;
|
||||
buttonStartOcr.Enabled = false;
|
||||
buttonStop.Enabled = false;
|
||||
buttonNewCharacterDatabase.Enabled = false;
|
||||
buttonEditCharacterDatabase.Enabled = false;
|
||||
labelStatus.Text = string.Empty;
|
||||
progressBar1.Visible = false;
|
||||
progressBar1.Maximum = 100;
|
||||
progressBar1.Value = 0;
|
||||
numericUpDownPixelsIsSpace.Value = 11; // vobSubOcrSettings.XOrMorePixelsMakesSpace;
|
||||
_vobSubOcrSettings = vobSubOcrSettings;
|
||||
|
||||
InitializeModi();
|
||||
InitializeTesseract();
|
||||
LoadImageCompareCharacterDatabaseList();
|
||||
|
||||
if (Configuration.Settings.VobSubOcr.LastOcrMethod == "BitmapCompare" && comboBoxOcrMethod.Items.Count > 1)
|
||||
comboBoxOcrMethod.SelectedIndex = 1;
|
||||
else if (Configuration.Settings.VobSubOcr.LastOcrMethod == "MODI" && comboBoxOcrMethod.Items.Count > 2)
|
||||
comboBoxOcrMethod.SelectedIndex = 2;
|
||||
else
|
||||
comboBoxOcrMethod.SelectedIndex = 0;
|
||||
|
||||
_bluRaySubtitlesOriginal = subtitles;
|
||||
|
||||
groupBoxImagePalette.Visible = false;
|
||||
|
||||
Text = Configuration.Settings.Language.VobSubOcr.TitleBluRay;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void LoadImageCompareCharacterDatabaseList()
|
||||
{
|
||||
@ -324,6 +363,45 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
return true;
|
||||
}
|
||||
|
||||
private void LoadBluRaySup()
|
||||
{
|
||||
_subtitle = new Subtitle();
|
||||
|
||||
_bluRaySubtitles = new List<Logic.BluRaySup.BluRaySupPicture>();
|
||||
int max = _bluRaySubtitlesOriginal.Count;
|
||||
for (int i = 0; i < max; i++)
|
||||
{
|
||||
var x = _bluRaySubtitlesOriginal[i];
|
||||
if ((checkBoxShowOnlyForced.Checked && x.IsForced) ||
|
||||
checkBoxShowOnlyForced.Checked == false)
|
||||
{
|
||||
_bluRaySubtitles.Add(x);
|
||||
Paragraph p = new Paragraph();
|
||||
p.StartTime = new TimeCode(TimeSpan.FromMilliseconds((x.StartTime + 45) / 90.0));
|
||||
p.EndTime = new TimeCode(TimeSpan.FromMilliseconds((x.EndTime + 45) / 90.0));
|
||||
_subtitle.Paragraphs.Add(p);
|
||||
}
|
||||
}
|
||||
_subtitle.Renumber(1);
|
||||
|
||||
FixShortDisplayTimes(_subtitle);
|
||||
|
||||
subtitleListView1.Fill(_subtitle);
|
||||
subtitleListView1.SelectIndexAndEnsureVisible(0);
|
||||
|
||||
numericUpDownStartNumber.Maximum = max;
|
||||
if (numericUpDownStartNumber.Maximum > 0 && numericUpDownStartNumber.Minimum <= 1)
|
||||
numericUpDownStartNumber.Value = 1;
|
||||
|
||||
buttonOK.Enabled = true;
|
||||
buttonCancel.Enabled = true;
|
||||
buttonStartOcr.Enabled = true;
|
||||
buttonStop.Enabled = false;
|
||||
buttonNewCharacterDatabase.Enabled = true;
|
||||
buttonEditCharacterDatabase.Enabled = true;
|
||||
buttonStartOcr.Focus();
|
||||
}
|
||||
|
||||
private void LoadVobRip()
|
||||
{
|
||||
_subtitle = new Subtitle();
|
||||
@ -385,7 +463,21 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
|
||||
private Bitmap GetSubtitleBitmap(int index)
|
||||
{
|
||||
if (checkBoxCustomFourColors.Checked)
|
||||
if (_bluRaySubtitlesOriginal != null)
|
||||
{
|
||||
if (_bluRaySubtitles[index].Palettes.Count == 0 && _defaultPaletteInfo == null)
|
||||
{
|
||||
for (int i = 0; i < _bluRaySubtitlesOriginal.Count; i++)
|
||||
{
|
||||
if (_bluRaySubtitlesOriginal[i].Palettes.Count > 0)
|
||||
{
|
||||
_defaultPaletteInfo = _bluRaySubtitlesOriginal[i].DecodePalette(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _bluRaySubtitles[index].DecodeImage(_defaultPaletteInfo);
|
||||
}
|
||||
else if (checkBoxCustomFourColors.Checked)
|
||||
{
|
||||
Color pattern = pictureBoxPattern.BackColor;
|
||||
Color emphasis1 = pictureBoxEmphasis1.BackColor;
|
||||
@ -405,22 +497,36 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
|
||||
private long GetSubtitleStartTimeMilliseconds(int index)
|
||||
{
|
||||
return (long)_vobSubMergedPackist[index].StartTime.TotalMilliseconds;
|
||||
if (_bluRaySubtitlesOriginal != null)
|
||||
return (_bluRaySubtitles[index].StartTime + 45) / 90;
|
||||
else
|
||||
return (long)_vobSubMergedPackist[index].StartTime.TotalMilliseconds;
|
||||
}
|
||||
|
||||
private long GetSubtitleEndTimeMilliseconds(int index)
|
||||
{
|
||||
return (long)_vobSubMergedPackist[index].EndTime.TotalMilliseconds;
|
||||
if (_bluRaySubtitlesOriginal != null)
|
||||
return (_bluRaySubtitles[index].EndTime + 45) / 90;
|
||||
else
|
||||
return (long)_vobSubMergedPackist[index].EndTime.TotalMilliseconds;
|
||||
}
|
||||
|
||||
private int GetSubtitleCount()
|
||||
{
|
||||
if (_bluRaySubtitlesOriginal != null)
|
||||
return _bluRaySubtitles.Count;
|
||||
else
|
||||
return _vobSubMergedPackist.Count;
|
||||
}
|
||||
|
||||
private void ShowSubtitleImage(int index)
|
||||
{
|
||||
int numberOfImages = _vobSubMergedPackist.Count;
|
||||
int numberOfImages = GetSubtitleCount();
|
||||
|
||||
if (index < numberOfImages)
|
||||
{
|
||||
groupBoxSubtitleImage.Text = string.Format(Configuration.Settings.Language.VobSubOcr.SubtitleImageXofY, index + 1, numberOfImages);
|
||||
pictureBoxSubtitleImage.Image = GetSubtitleBitmap(index); // SubtitleCreator.SUP.GetBitmap(index);
|
||||
pictureBoxSubtitleImage.Image = GetSubtitleBitmap(index);
|
||||
pictureBoxSubtitleImage.Refresh();
|
||||
}
|
||||
else
|
||||
@ -476,7 +582,10 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
if (smallestIndex >= 0)
|
||||
{
|
||||
double differencePercentage = smallestDifference * 100.0 / (target.Width * target.Height);
|
||||
if (differencePercentage < _vobSubOcrSettings.AllowDifferenceInPercent) // should be around 1.0...
|
||||
double maxDiff= _vobSubOcrSettings.AllowDifferenceInPercent; // should be around 1.0 for vob/sub...
|
||||
if (_bluRaySubtitlesOriginal != null)
|
||||
maxDiff = 14; // let bluray sup have a 14% diff
|
||||
if (differencePercentage < maxDiff) //_vobSubOcrSettings.AllowDifferenceInPercent) // should be around 1.0...
|
||||
{
|
||||
XmlNode node = _compareDoc.DocumentElement.SelectSingleNode("FileName[.='" + _compareBitmaps[smallestIndex].Name + "']");
|
||||
if (node != null)
|
||||
@ -789,28 +898,46 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
|
||||
private void FormVobSubOcr_Shown(object sender, EventArgs e)
|
||||
{
|
||||
_vobSubMergedPackistOriginal = new List<VobSubMergedPack>();
|
||||
bool hasIdxTimeCodes = false;
|
||||
bool hasForcedSubtitles = false;
|
||||
foreach (var x in _vobSubMergedPackist)
|
||||
if (_bluRaySubtitlesOriginal != null)
|
||||
{
|
||||
_vobSubMergedPackistOriginal.Add(x);
|
||||
if (x.IdxLine != null)
|
||||
hasIdxTimeCodes = true;
|
||||
if (x.SubPicture.Forced)
|
||||
hasForcedSubtitles = true;
|
||||
LoadBluRaySup();
|
||||
bool hasForcedSubtitles = false;
|
||||
foreach (var x in _bluRaySubtitlesOriginal)
|
||||
{
|
||||
if (x.IsForced)
|
||||
{
|
||||
hasForcedSubtitles = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
checkBoxShowOnlyForced.Enabled = hasForcedSubtitles;
|
||||
checkBoxUseTimeCodesFromIdx.Visible = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_vobSubMergedPackistOriginal = new List<VobSubMergedPack>();
|
||||
bool hasIdxTimeCodes = false;
|
||||
bool hasForcedSubtitles = false;
|
||||
foreach (var x in _vobSubMergedPackist)
|
||||
{
|
||||
_vobSubMergedPackistOriginal.Add(x);
|
||||
if (x.IdxLine != null)
|
||||
hasIdxTimeCodes = true;
|
||||
if (x.SubPicture.Forced)
|
||||
hasForcedSubtitles = true;
|
||||
}
|
||||
checkBoxUseTimeCodesFromIdx.CheckedChanged -= checkBoxUseTimeCodesFromIdx_CheckedChanged;
|
||||
checkBoxUseTimeCodesFromIdx.Visible = hasIdxTimeCodes;
|
||||
checkBoxUseTimeCodesFromIdx.Checked = hasIdxTimeCodes;
|
||||
checkBoxUseTimeCodesFromIdx.CheckedChanged += checkBoxUseTimeCodesFromIdx_CheckedChanged;
|
||||
checkBoxShowOnlyForced.Enabled = hasForcedSubtitles;
|
||||
LoadVobRip();
|
||||
}
|
||||
checkBoxUseTimeCodesFromIdx.CheckedChanged -= checkBoxUseTimeCodesFromIdx_CheckedChanged;
|
||||
checkBoxUseTimeCodesFromIdx.Visible = hasIdxTimeCodes;
|
||||
checkBoxUseTimeCodesFromIdx.Checked = hasIdxTimeCodes;
|
||||
checkBoxUseTimeCodesFromIdx.CheckedChanged += checkBoxUseTimeCodesFromIdx_CheckedChanged;
|
||||
checkBoxShowOnlyForced.Enabled = hasForcedSubtitles;
|
||||
LoadVobRip();
|
||||
}
|
||||
|
||||
private void ButtonOkClick(object sender, EventArgs e)
|
||||
{
|
||||
if (Configuration.Settings.VobSubOcr.XOrMorePixelsMakesSpace != (int)numericUpDownPixelsIsSpace.Value)
|
||||
if (Configuration.Settings.VobSubOcr.XOrMorePixelsMakesSpace != (int)numericUpDownPixelsIsSpace.Value && _bluRaySubtitlesOriginal == null)
|
||||
{
|
||||
Configuration.Settings.VobSubOcr.XOrMorePixelsMakesSpace = (int)numericUpDownPixelsIsSpace.Value;
|
||||
Configuration.Settings.Save();
|
||||
@ -843,7 +970,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
|
||||
_abort = false;
|
||||
|
||||
int max = _vobSubMergedPackist.Count;
|
||||
int max = GetSubtitleCount();
|
||||
|
||||
progressBar1.Maximum = max;
|
||||
progressBar1.Value = 0;
|
||||
@ -1093,6 +1220,8 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
subtitleListView1.SetBackgroundColor(index, Color.Orange);
|
||||
else if (wordsNotFound == 1)
|
||||
subtitleListView1.SetBackgroundColor(index, Color.Yellow);
|
||||
else if (line.Trim().Length == 0)
|
||||
subtitleListView1.SetBackgroundColor(index, Color.Orange);
|
||||
else
|
||||
subtitleListView1.SetBackgroundColor(index, Color.Green);
|
||||
}
|
||||
@ -1107,6 +1236,8 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
subtitleListView1.SetBackgroundColor(index, Color.Orange);
|
||||
else if (badWords > 0)
|
||||
subtitleListView1.SetBackgroundColor(index, Color.Yellow);
|
||||
else if (line.Trim().Length == 0)
|
||||
subtitleListView1.SetBackgroundColor(index, Color.Orange);
|
||||
else
|
||||
subtitleListView1.SetBackgroundColor(index, Color.Green);
|
||||
}
|
||||
@ -1598,7 +1729,10 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
{
|
||||
Subtitle oldSubtitle = new Subtitle(_subtitle);
|
||||
subtitleListView1.BeginUpdate();
|
||||
LoadVobRip();
|
||||
if (_bluRaySubtitlesOriginal != null)
|
||||
LoadBluRaySup();
|
||||
else
|
||||
LoadVobRip();
|
||||
for (int i = 0; i < _subtitle.Paragraphs.Count; i++)
|
||||
{
|
||||
Paragraph current = _subtitle.Paragraphs[i];
|
||||
@ -1634,5 +1768,6 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
subtitleListView1.EndUpdate();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
468
src/Logic/BluRaySup/BluRaySupPalette.cs
Normal file
468
src/Logic/BluRaySup/BluRaySupPalette.cs
Normal file
@ -0,0 +1,468 @@
|
||||
/*
|
||||
* Copyright 2009 Volker Oth (0xdeadbeef)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* NOTE: Converted to C# and modified by Nikse.dk@gmail.com
|
||||
*/
|
||||
|
||||
namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
{
|
||||
|
||||
public class BluRaySupPalette
|
||||
{
|
||||
/** Number of palette entries */
|
||||
private int size;
|
||||
/** Byte buffer for RED info */
|
||||
private byte[] r;
|
||||
/** Byte buffer for GREEN info */
|
||||
private byte[] g;
|
||||
/** Byte buffer for BLUE info */
|
||||
private byte[] b;
|
||||
/** Byte buffer for alpha info */
|
||||
private byte[] a;
|
||||
/** Byte buffer for Y (luminance) info */
|
||||
private byte[] y;
|
||||
/** Byte buffer for Cb (chrominance blue) info */
|
||||
private byte[] cb;
|
||||
/** Byte buffer for Cr (chrominance red) info */
|
||||
private byte[] cr;
|
||||
/** Use BT.601 color model instead of BT.709 */
|
||||
private bool useBT601;
|
||||
|
||||
/**
|
||||
* Convert YCBCr color info to RGB
|
||||
* @param y 8 bit luminance
|
||||
* @param cb 8 bit chrominance blue
|
||||
* @param cr 8 bit chrominance red
|
||||
* @return Integer array with red, blue, green component (in this order)
|
||||
*/
|
||||
static int[] YCbCr2Rgb(int y, int cb, int cr, bool useBt601)
|
||||
{
|
||||
int[] rgb = new int[3];
|
||||
double y1, r, g, b;
|
||||
|
||||
y -= 16;
|
||||
cb -= 128;
|
||||
cr -= 128;
|
||||
|
||||
y1 = y * 1.164383562;
|
||||
if (useBt601)
|
||||
{
|
||||
/* BT.601 for YCbCr 16..235 -> RGB 0..255 (PC) */
|
||||
r = y1 + cr * 1.596026317;
|
||||
g = y1 - cr * 0.8129674985 - cb * 0.3917615979;
|
||||
b = y1 + cb * 2.017232218;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* BT.709 for YCbCr 16..235 -> RGB 0..255 (PC) */
|
||||
r = y1 + cr * 1.792741071;
|
||||
g = y1 - cr * 0.5329093286 - cb * 0.2132486143;
|
||||
b = y1 + cb * 2.112401786;
|
||||
}
|
||||
rgb[0] = (int)(r + 0.5);
|
||||
rgb[1] = (int)(g + 0.5);
|
||||
rgb[2] = (int)(b + 0.5);
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (rgb[i] < 0)
|
||||
rgb[i] = 0;
|
||||
else if (rgb[i] > 255)
|
||||
rgb[i] = 255;
|
||||
}
|
||||
return rgb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert RGB color info to YCBCr
|
||||
* @param r 8 bit red component
|
||||
* @param g 8 bit green component
|
||||
* @param b 8 bit blue component
|
||||
* @return Integer array with luminance (Y), chrominance blue (Cb), chrominance red (Cr) (in this order)
|
||||
*/
|
||||
static int[] Rgb2YCbCr(int r, int g, int b, bool useBt601)
|
||||
{
|
||||
int[] yCbCr = new int[3];
|
||||
double y, cb, cr;
|
||||
|
||||
if (useBt601)
|
||||
{
|
||||
/* BT.601 for RGB 0..255 (PC) -> YCbCr 16..235 */
|
||||
y = r * 0.299 * 219 / 255 + g * 0.587 * 219 / 255 + b * 0.114 * 219 / 255;
|
||||
cb = -r * 0.168736 * 224 / 255 - g * 0.331264 * 224 / 255 + b * 0.5 * 224 / 255;
|
||||
cr = r * 0.5 * 224 / 255 - g * 0.418688 * 224 / 255 - b * 0.081312 * 224 / 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* BT.709 for RGB 0..255 (PC) -> YCbCr 16..235 */
|
||||
y = r * 0.2126 * 219 / 255 + g * 0.7152 * 219 / 255 + b * 0.0722 * 219 / 255;
|
||||
cb = -r * 0.2126 / 1.8556 * 224 / 255 - g * 0.7152 / 1.8556 * 224 / 255 + b * 0.5 * 224 / 255;
|
||||
cr = r * 0.5 * 224 / 255 - g * 0.7152 / 1.5748 * 224 / 255 - b * 0.0722 / 1.5748 * 224 / 255;
|
||||
}
|
||||
yCbCr[0] = 16 + (int)(y + 0.5);
|
||||
yCbCr[1] = 128 + (int)(cb + 0.5);
|
||||
yCbCr[2] = 128 + (int)(cr + 0.5);
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (yCbCr[i] < 16)
|
||||
yCbCr[i] = 16;
|
||||
else
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
if (yCbCr[i] > 235)
|
||||
yCbCr[i] = 235;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (yCbCr[i] > 240)
|
||||
yCbCr[i] = 240;
|
||||
}
|
||||
}
|
||||
}
|
||||
return yCbCr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ctor - initializes palette with transparent black (RGBA: 0x00000000)
|
||||
* @param palSize Number of palette entries
|
||||
* @param use601 Use BT.601 instead of BT.709
|
||||
*/
|
||||
public BluRaySupPalette(int palSize, bool use601)
|
||||
{
|
||||
size = palSize;
|
||||
useBT601 = use601;
|
||||
r = new byte[size];
|
||||
g = new byte[size];
|
||||
b = new byte[size];
|
||||
a = new byte[size];
|
||||
y = new byte[size];
|
||||
cb = new byte[size];
|
||||
cr = new byte[size];
|
||||
|
||||
// set at least all alpha values to invisible
|
||||
int[] yCbCr = Rgb2YCbCr(0, 0, 0, useBT601);
|
||||
for (int i = 0; i < palSize; i++)
|
||||
{
|
||||
a[i] = 0;
|
||||
r[i] = 0;
|
||||
g[i] = 0;
|
||||
b[i] = 0;
|
||||
y[i] = (byte)yCbCr[0];
|
||||
cb[i] = (byte)yCbCr[1];
|
||||
cr[i] = (byte)yCbCr[2];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ctor - initializes palette with transparent black (RGBA: 0x00000000)
|
||||
* @param palSize Number of palette entries
|
||||
*/
|
||||
public BluRaySupPalette(int palSize)
|
||||
: this(palSize, false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Ctor - construct palette from red, green blue and alpha buffers
|
||||
* @param red Byte buffer containing the red components
|
||||
* @param green Byte buffer containing the green components
|
||||
* @param blue Byte buffer containing the blue components
|
||||
* @param alpha Byte buffer containing the alpha components
|
||||
* @param use601 Use BT.601 instead of BT.709
|
||||
*/
|
||||
public BluRaySupPalette(byte[] red, byte[] green, byte[] blue, byte[] alpha, bool use601)
|
||||
{
|
||||
size = red.Length;
|
||||
useBT601 = use601;
|
||||
r = new byte[size];
|
||||
g = new byte[size];
|
||||
b = new byte[size];
|
||||
a = new byte[size];
|
||||
y = new byte[size];
|
||||
cb = new byte[size];
|
||||
cr = new byte[size];
|
||||
|
||||
int[] yCbCr;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
a[i] = alpha[i];
|
||||
r[i] = red[i];
|
||||
g[i] = green[i];
|
||||
b[i] = blue[i];
|
||||
yCbCr = Rgb2YCbCr(r[i] & 0xff, g[i] & 0xff, b[i] & 0xff, useBT601);
|
||||
y[i] = (byte)yCbCr[0];
|
||||
cb[i] = (byte)yCbCr[1];
|
||||
cr[i] = (byte)yCbCr[2];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ctor - construct palette from red, green blue and alpha buffers
|
||||
* @param red Byte buffer containing the red components
|
||||
* @param green Byte buffer containing the green components
|
||||
* @param blue Byte buffer containing the blue components
|
||||
* @param alpha Byte buffer containing the alpha components
|
||||
*/
|
||||
public BluRaySupPalette(byte[] red, byte[] green, byte[] blue, byte[] alpha)
|
||||
: this(red, green, blue, alpha, false)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Ctor - construct new (independent) palette from existing one
|
||||
* @param p Palette to copy values from
|
||||
*/
|
||||
public BluRaySupPalette(BluRaySupPalette p)
|
||||
{
|
||||
size = p.GetSize();
|
||||
useBT601 = p.UsesBt601();
|
||||
r = new byte[size];
|
||||
g = new byte[size];
|
||||
b = new byte[size];
|
||||
a = new byte[size];
|
||||
y = new byte[size];
|
||||
cb = new byte[size];
|
||||
cr = new byte[size];
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
a[i] = p.a[i];
|
||||
r[i] = p.r[i];
|
||||
g[i] = p.g[i];
|
||||
b[i] = p.b[i];
|
||||
y[i] = p.y[i];
|
||||
cb[i] = p.cb[i];
|
||||
cr[i] = p.cr[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set palette index "index" to color "c" in ARGB format
|
||||
* @param index Palette index
|
||||
* @param c Color in ARGB format
|
||||
*/
|
||||
public void SetArgb(int index, int c)
|
||||
{
|
||||
int a1 = (c >> 24) & 0xff;
|
||||
int r1 = (c >> 16) & 0xff;
|
||||
int g1 = (c >> 8) & 0xff;
|
||||
int b1 = c & 0xff;
|
||||
SetRgb(index, r1, g1, b1);
|
||||
SetAlpha(index, a1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return palette entry at index as Integer in ARGB format
|
||||
* @param index Palette index
|
||||
* @return Palette entry at index as Integer in ARGB format
|
||||
*/
|
||||
public int GetArgb(int index)
|
||||
{
|
||||
return ((a[index] & 0xff) << 24) | ((r[index] & 0xff) << 16) | ((g[index] & 0xff) << 8) | (b[index] & 0xff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set palette entry (RGB mode)
|
||||
* @param index Palette index
|
||||
* @param red 8bit red component
|
||||
* @param green 8bit green component
|
||||
* @param blue 8bit blue component
|
||||
*/
|
||||
public void SetRgb(int index, int red, int green, int blue)
|
||||
{
|
||||
r[index] = (byte)red;
|
||||
g[index] = (byte)green;
|
||||
b[index] = (byte)blue;
|
||||
// create yCbCr
|
||||
int[] yCbCr = Rgb2YCbCr(red, green, blue, useBT601);
|
||||
y[index] = (byte)yCbCr[0];
|
||||
cb[index] = (byte)yCbCr[1];
|
||||
cr[index] = (byte)yCbCr[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set palette entry (YCbCr mode)
|
||||
* @param index Palette index
|
||||
* @param yn 8bit Y component
|
||||
* @param cbn 8bit Cb component
|
||||
* @param crn 8bit Cr component
|
||||
*/
|
||||
public void SetYCbCr(int index, int yn, int cbn, int crn)
|
||||
{
|
||||
y[index] = (byte)yn;
|
||||
cb[index] = (byte)cbn;
|
||||
cr[index] = (byte)crn;
|
||||
// create RGB
|
||||
int[] rgb = YCbCr2Rgb(yn, cbn, crn, useBT601);
|
||||
r[index] = (byte)rgb[0];
|
||||
g[index] = (byte)rgb[1];
|
||||
b[index] = (byte)rgb[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set alpha channel
|
||||
* @param index Palette index
|
||||
* @param alpha 8bit alpha channel value
|
||||
*/
|
||||
public void SetAlpha(int index, int alpha)
|
||||
{
|
||||
a[index] = (byte)alpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get alpha channel
|
||||
* @param index Palette index
|
||||
* @return 8bit alpha channel value
|
||||
*/
|
||||
public int GetAlpha(int index)
|
||||
{
|
||||
return a[index] & 0xff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return byte array of alpha channel components
|
||||
* @return Byte array of alpha channel components (don't modify!)
|
||||
*/
|
||||
public byte[] GetAlpha()
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Integer array containing 8bit red, green, blue components (in this order)
|
||||
* @param index Palette index
|
||||
* @return Integer array containing 8bit red, green, blue components (in this order)
|
||||
*/
|
||||
public int[] GetRgb(int index)
|
||||
{
|
||||
int[] rgb = new int[3];
|
||||
rgb[0] = r[index] & 0xff;
|
||||
rgb[1] = g[index] & 0xff;
|
||||
rgb[2] = b[index] & 0xff;
|
||||
return rgb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Integer array containing 8bit Y, Cb, Cr components (in this order)
|
||||
* @param index Palette index
|
||||
* @return Integer array containing 8bit Y, Cb, Cr components (in this order)
|
||||
*/
|
||||
public int[] GetYCbCr(int index)
|
||||
{
|
||||
int[] yCbCr = new int[3];
|
||||
yCbCr[0] = y[index] & 0xff;
|
||||
yCbCr[1] = cb[index] & 0xff;
|
||||
yCbCr[2] = cr[index] & 0xff;
|
||||
return yCbCr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return byte array of red components
|
||||
* @return Byte array of red components (don't modify!)
|
||||
*/
|
||||
public byte[] GetR()
|
||||
{
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return byte array of green components
|
||||
* @return Byte array of green components (don't modify!)
|
||||
*/
|
||||
public byte[] GetG()
|
||||
{
|
||||
return g;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return byte array of blue components
|
||||
* @return Byte array of blue components (don't modify!)
|
||||
*/
|
||||
public byte[] GetB()
|
||||
{
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return byte array of Y components
|
||||
* @return Byte array of Y components (don't modify!)
|
||||
*/
|
||||
public byte[] GetY()
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return byte array of Cb components
|
||||
* @return Byte array of Cb components (don't modify!)
|
||||
*/
|
||||
public byte[] GetCb()
|
||||
{
|
||||
return cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return byte array of Cr components
|
||||
* @return Byte array of Cr components (don't modify!)
|
||||
*/
|
||||
public byte[] GetCr()
|
||||
{
|
||||
return cr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get size of palette (number of entries)
|
||||
* @return Size of palette (number of entries)
|
||||
*/
|
||||
public int GetSize()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return index of most transparent palette entry or the index of the first completely transparent color
|
||||
* @return Index of most transparent palette entry or the index of the first completely transparent color
|
||||
*/
|
||||
public int GetTransparentIndex()
|
||||
{
|
||||
// find (most) transparent index in palette
|
||||
int transpIdx = 0;
|
||||
int minAlpha = 0x100;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
if ((a[i] & 0xff) < minAlpha)
|
||||
{
|
||||
minAlpha = a[i] & 0xff;
|
||||
transpIdx = i;
|
||||
if (minAlpha == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return transpIdx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get: use of BT.601 color model instead of BT.709
|
||||
* @return True if BT.601 is used
|
||||
*/
|
||||
public bool UsesBt601()
|
||||
{
|
||||
return useBT601;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
660
src/Logic/BluRaySup/BluRaySupParser.cs
Normal file
660
src/Logic/BluRaySup/BluRaySupParser.cs
Normal file
@ -0,0 +1,660 @@
|
||||
/*
|
||||
* Copyright 2009 Volker Oth (0xdeadbeef)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* NOTE: Converted to C# and modified by Nikse.dk@gmail.com
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
{
|
||||
public static class BluRaySupParser
|
||||
{
|
||||
|
||||
private class SupSegment
|
||||
{
|
||||
/// <summary>
|
||||
/// Type of segment
|
||||
/// </summary>
|
||||
public int Type;
|
||||
|
||||
/// <summary>
|
||||
/// segment size in bytes
|
||||
/// </summary>
|
||||
public int Size;
|
||||
|
||||
/// <summary>
|
||||
/// segment PTS time stamp
|
||||
/// </summary>
|
||||
public long PtsTimestamp;
|
||||
|
||||
/// <summary>
|
||||
/// segment DTS time stamp
|
||||
/// </summary>
|
||||
public long DtsTimestamp;
|
||||
}
|
||||
|
||||
|
||||
/** PGS composition state */
|
||||
private enum CompositionState
|
||||
{
|
||||
/** normal: doesn't have to be complete */
|
||||
Normal,
|
||||
/** acquisition point */
|
||||
AcquPoint,
|
||||
/** epoch start - clears the screen */
|
||||
EpochStart,
|
||||
/** epoch continue */
|
||||
EpochContinue,
|
||||
/** unknown value */
|
||||
Invalid
|
||||
}
|
||||
|
||||
private static byte[] packetHeader =
|
||||
{
|
||||
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)
|
||||
};
|
||||
|
||||
private static byte[] headerPCSStart =
|
||||
{
|
||||
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)
|
||||
(byte)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
|
||||
};
|
||||
|
||||
private static byte[] headerPCSEnd =
|
||||
{
|
||||
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)
|
||||
};
|
||||
|
||||
private static byte[] headerODSFirst =
|
||||
{
|
||||
0x00, 0x00, // 0: object_id
|
||||
0x00, // 2: object_version_number
|
||||
(byte)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
|
||||
};
|
||||
|
||||
private static byte[] headerODSNext =
|
||||
{
|
||||
0x00, 0x00, // 0: object_id
|
||||
0x00, // 2: object_version_number
|
||||
(byte)0x40, // 3: first_in_sequence (0x80), last_in_sequence (0x40), 6bits reserved
|
||||
};
|
||||
|
||||
private static byte[] headerWDS =
|
||||
{
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Parses a BluRay sup file
|
||||
/// </summary>
|
||||
/// <param name="fileName">BluRay sup file name</param>
|
||||
/// <param name="log">Parsing info is logged here</param>
|
||||
/// <returns>List of BluRaySupPictures</returns>
|
||||
public static List<BluRaySupPicture> ParseBluRaySup(string fileName, StringBuilder log)
|
||||
{
|
||||
using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return ParseBluRaySup(fs, log);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Can be used with e.g. MemoryStream or FileStream
|
||||
/// </summary>
|
||||
/// <param name="ms">memory stream containing sup data</param>
|
||||
/// <param name="log">Text parser log</param>
|
||||
public static List<BluRaySupPicture> ParseBluRaySup(Stream ms, StringBuilder log)
|
||||
{
|
||||
SupSegment segment;
|
||||
BluRaySupPicture pic = null;
|
||||
BluRaySupPicture picLast = null;
|
||||
BluRaySupPicture picTmp = null;
|
||||
List<BluRaySupPicture> subPictures = new List<BluRaySupPicture>();
|
||||
int odsCtr = 0;
|
||||
int pdsCtr = 0;
|
||||
int odsCtrOld = 0;
|
||||
int pdsCtrOld = 0;
|
||||
int compNum = -1;
|
||||
int compNumOld = -1;
|
||||
int compCount = 0;
|
||||
long ptsPcs = 0;
|
||||
bool paletteUpdate = false;
|
||||
CompositionState cs = CompositionState.Invalid;
|
||||
ms.Position = 0;
|
||||
long position = 0;
|
||||
int i = 0;
|
||||
const int headerSize = 13;
|
||||
byte[] buffer;
|
||||
while (position < ms.Length)
|
||||
{
|
||||
string[] so = new string[1]; // hack to return string
|
||||
|
||||
ms.Seek(position, SeekOrigin.Begin);
|
||||
buffer = new byte[headerSize];
|
||||
ms.Read(buffer, 0, buffer.Length);
|
||||
segment = ReadSegment(buffer, log);
|
||||
position += headerSize;
|
||||
buffer = new byte[segment.Size];
|
||||
ms.Read(buffer, 0, buffer.Length);
|
||||
log.Append(i + ": ");
|
||||
switch (segment.Type)
|
||||
{
|
||||
case 0x14: // Palette
|
||||
log.AppendLine(string.Format("0x14 - Palette - PDS offset={0} size={1}", position, segment.Size));
|
||||
|
||||
if (compNum != compNumOld)
|
||||
{
|
||||
if (pic != null)
|
||||
{
|
||||
so[0] = null;
|
||||
int ps = ParsePds(buffer, segment, pic, so);
|
||||
if (ps >= 0)
|
||||
{
|
||||
log.AppendLine(", " + so[0]);
|
||||
if (ps > 0) // don't count empty palettes
|
||||
pdsCtr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
log.AppendLine();
|
||||
log.AppendLine(so[0]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log.AppendLine();
|
||||
log.AppendLine("missing PTS start -> ignored");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log.AppendLine(", comp # unchanged -> ignored");
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x15: // Image bitmap data
|
||||
log.AppendLine(string.Format("0x15 - bitmap data - ODS offset={0} size={1}", position, segment.Size));
|
||||
|
||||
if (compNum != compNumOld)
|
||||
{
|
||||
if (!paletteUpdate)
|
||||
{
|
||||
if (pic != null)
|
||||
{
|
||||
so[0] = null;
|
||||
if (ParseOds(buffer, segment, pic, so))
|
||||
odsCtr++;
|
||||
if (so[0] != null)
|
||||
log.Append(", " + so[0]);
|
||||
log.AppendLine(", img size: " + pic.Width + "*" + pic.Height);
|
||||
}
|
||||
else
|
||||
{
|
||||
log.AppendLine();
|
||||
log.AppendLine("missing PTS start -> ignored");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log.AppendLine();
|
||||
log.AppendLine("palette update only -> ignored");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log.AppendLine(", comp # unchanged -> ignored");
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x16:
|
||||
log.AppendLine(string.Format("0x16 - Time codes, offset={0} size={1}", position, segment.Size));
|
||||
|
||||
compNum = BigEndianInt16(buffer, 5);
|
||||
cs = GetCompositionState(buffer[7]);
|
||||
paletteUpdate = buffer[8] == 0x80;
|
||||
ptsPcs = segment.PtsTimestamp;
|
||||
if (segment.Size >= 0x13)
|
||||
compCount = 1; // could be also 2, but we'll ignore this for the moment
|
||||
else
|
||||
compCount = 0;
|
||||
if (cs == CompositionState.Invalid)
|
||||
{
|
||||
log.AppendLine("Illegal composition state at offset " + position);
|
||||
}
|
||||
else if (cs == CompositionState.EpochStart)
|
||||
{
|
||||
//new frame
|
||||
if (subPictures.Count > 0 && (odsCtr == 0 || pdsCtr == 0))
|
||||
{
|
||||
log.AppendLine("missing PDS/ODS: last epoch is discarded");
|
||||
subPictures.RemoveAt(subPictures.Count - 1);
|
||||
compNumOld = compNum - 1;
|
||||
if (subPictures.Count > 0)
|
||||
picLast = subPictures[subPictures.Count - 1];
|
||||
else
|
||||
picLast = null;
|
||||
}
|
||||
else
|
||||
picLast = pic;
|
||||
|
||||
pic = new BluRaySupPicture();
|
||||
subPictures.Add(pic); // add to list
|
||||
pic.StartTime = segment.PtsTimestamp;
|
||||
log.AppendLine("#> " + (subPictures.Count) + " (" + ToolBox.PtsToTimeString(pic.StartTime) + ")");
|
||||
|
||||
so[0] = null;
|
||||
ParsePcs(segment, pic, so, buffer);
|
||||
// fix end time stamp of previous pic if still missing
|
||||
if (picLast != null && picLast.EndTime == 0)
|
||||
picLast.EndTime = pic.StartTime;
|
||||
|
||||
if (so[0] != null)
|
||||
log.AppendLine(", " + so[0]);
|
||||
else
|
||||
log.AppendLine();
|
||||
log.Append(Environment.NewLine + "PTS start: " + ToolBox.PtsToTimeString(pic.StartTime));
|
||||
log.AppendLine(", screen size: " + pic.Width + "*" + pic.Height);
|
||||
odsCtr = 0;
|
||||
pdsCtr = 0;
|
||||
odsCtrOld = 0;
|
||||
pdsCtrOld = 0;
|
||||
picTmp = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pic == null)
|
||||
{
|
||||
log.AppendLine(" Missing start of epoch at offset " + position);
|
||||
break;
|
||||
}
|
||||
log.Append("PCS ofs:" + ToolBox.ToHex(buffer, 0, 8) + ", ");
|
||||
switch (cs)
|
||||
{
|
||||
case CompositionState.EpochContinue:
|
||||
log.AppendLine(" CONT, ");
|
||||
break;
|
||||
case CompositionState.AcquPoint:
|
||||
log.AppendLine(" ACQU, ");
|
||||
break;
|
||||
case CompositionState.Normal:
|
||||
log.AppendLine(" NORM, ");
|
||||
break;
|
||||
}
|
||||
log.AppendLine("size: " + segment.Size + ", comp#: " + compNum + ", forced: " + pic.IsForced);
|
||||
if (compNum != compNumOld)
|
||||
{
|
||||
so[0] = null;
|
||||
// store state to be able to revert to it
|
||||
picTmp = new BluRaySupPicture(pic); // deep copy
|
||||
picTmp.EndTime = ptsPcs;
|
||||
// create new pic
|
||||
ParsePcs(segment, pic, so, buffer);
|
||||
}
|
||||
if (so[0] != null)
|
||||
log.AppendLine(", " + so[0]);
|
||||
log.AppendLine(", pal update: " + paletteUpdate);
|
||||
log.AppendLine("PTS: " + ToolBox.PtsToTimeString(segment.PtsTimestamp));
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x17:
|
||||
log.AppendLine(string.Format("0x17 - WDS offset={0} size={1}", position, segment.Size));
|
||||
|
||||
int x = BigEndianInt16(buffer, 2);
|
||||
int y = BigEndianInt16(buffer, 4);
|
||||
int width = BigEndianInt16(buffer, 6);
|
||||
int height = BigEndianInt16(buffer, 8);
|
||||
|
||||
log.AppendLine(string.Format("width:{0}, height:{1}", width, height));
|
||||
break;
|
||||
|
||||
case 0x80:
|
||||
log.AppendLine(string.Format("0x18 - END offset={0} size={1}", position, segment.Size));
|
||||
|
||||
// decide whether to store this last composition section as caption or merge it
|
||||
if (cs == CompositionState.EpochStart)
|
||||
{
|
||||
if (compCount > 0 && odsCtr > odsCtrOld && compNum != compNumOld && IsPictureMergable(picLast, pic))
|
||||
{
|
||||
// the last start epoch did not contain any (new) content
|
||||
// and should be merged to the previous frame
|
||||
subPictures.RemoveAt(subPictures.Count - 1);
|
||||
pic = picLast;
|
||||
if (subPictures.Count > 0)
|
||||
picLast = subPictures[subPictures.Count - 1];
|
||||
else
|
||||
picLast = null;
|
||||
log.AppendLine("#< caption merged");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
long startTime = 0;
|
||||
if (pic != null)
|
||||
{
|
||||
startTime = pic.StartTime; // store
|
||||
pic.StartTime = ptsPcs; // set for testing merge
|
||||
}
|
||||
|
||||
if (compCount > 0 && odsCtr > odsCtrOld && compNum != compNumOld && !IsPictureMergable(picTmp, pic))
|
||||
{
|
||||
// last PCS should be stored as separate caption
|
||||
if (odsCtr - odsCtrOld > 1 || pdsCtr - pdsCtrOld > 1)
|
||||
log.AppendLine("multiple PDS/ODS definitions: result may be erratic");
|
||||
// replace pic with picTmp (deepCopy created before new PCS)
|
||||
subPictures[subPictures.Count - 1] = picTmp; // replace in list
|
||||
picLast = picTmp;
|
||||
subPictures.Add(pic); // add to list
|
||||
log.AppendLine("#< " + (subPictures.Count) + " (" + ToolBox.PtsToTimeString(pic.StartTime) + ")");
|
||||
odsCtrOld = odsCtr;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pic != null)
|
||||
{
|
||||
// merge with previous pic
|
||||
pic.StartTime = startTime; // restore
|
||||
pic.EndTime = ptsPcs;
|
||||
// for the unlikely case that forced flag changed during one captions
|
||||
if (picTmp != null && picTmp.IsForced)
|
||||
pic.IsForced = true;
|
||||
|
||||
if (pdsCtr > pdsCtrOld || paletteUpdate)
|
||||
log.AppendLine("palette animation: result may be erratic\n");
|
||||
}
|
||||
else
|
||||
log.AppendLine("end without at least one epoch start");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
pdsCtrOld = pdsCtr;
|
||||
compNumOld = compNum;
|
||||
break;
|
||||
default:
|
||||
log.AppendLine(string.Format("0x?? - END offset={0} UNKOWN SEGMENT TYPE={1}", position, segment.Type));
|
||||
break;
|
||||
}
|
||||
log.AppendLine();
|
||||
position += segment.Size;
|
||||
i++;
|
||||
}
|
||||
return subPictures;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if two SubPicture object can be merged because the time gap between them is rather small
|
||||
/// and the embedded objects seem to be identical
|
||||
/// </summary>
|
||||
/// <param name="a">first SubPicture object (earlier)</param>
|
||||
/// <param name="b">2nd SubPicture object (later)</param>
|
||||
/// <returns>return true if the SubPictures can be merged</returns>
|
||||
private static bool IsPictureMergable(BluRaySupPicture a, BluRaySupPicture b)
|
||||
{
|
||||
bool eq = false;
|
||||
if (a != null && b != null)
|
||||
{
|
||||
if (a.EndTime == 0 || b.StartTime - a.EndTime < Core.GetMergePtSdiff())
|
||||
{
|
||||
ImageObject ao = a.ObjectIdImage;
|
||||
ImageObject bo = b.ObjectIdImage;
|
||||
if (ao != null && bo != null)
|
||||
if (ao.BufferSize == bo.BufferSize && ao.Width == bo.Width && ao.Height == bo.Height)
|
||||
eq = true;
|
||||
}
|
||||
}
|
||||
return eq;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse an PCS packet which contains width/height info
|
||||
/// </summary>
|
||||
/// <param name="segment">object containing info about the current segment</param>
|
||||
/// <param name="pic">SubPicture object containing info about the current caption</param>
|
||||
/// <param name="msg">reference to message string</param>
|
||||
/// <param name="buffer">Raw data buffer, starting right after segment</param>
|
||||
private static void ParsePcs(SupSegment segment, BluRaySupPicture pic, string[] msg, byte[] buffer)
|
||||
{
|
||||
if (segment.Size >= 4)
|
||||
{
|
||||
pic.Width = BigEndianInt16(buffer, 0); // video_width
|
||||
pic.Height = BigEndianInt16(buffer, 2); // video_height
|
||||
int type = buffer[4]; // hi nibble: frame_rate, lo nibble: reserved
|
||||
int num = BigEndianInt16(buffer, 5); // composition_number
|
||||
// skipped:
|
||||
// 8bit composition_state: 0x00: normal, 0x40: acquisition point
|
||||
// 0x80: epoch start, 0xC0: epoch continue, 6bit reserved
|
||||
// 8bit palette_update_flag (0x80), 7bit reserved
|
||||
int palId = buffer[9]; // 8bit palette_id_ref
|
||||
int coNum = buffer[10]; // 8bit number_of_composition_objects (0..2)
|
||||
if (coNum > 0)
|
||||
{
|
||||
// composition_object:
|
||||
int objId = BigEndianInt16(buffer, 11); // 16bit object_id_ref
|
||||
msg[0] = "palID: " + palId + ", objID: " + objId;
|
||||
if (pic.ImageObjects == null)
|
||||
pic.ImageObjects = new List<ImageObject>();
|
||||
ImageObject imgObj;
|
||||
if (objId >= pic.ImageObjects.Count)
|
||||
{
|
||||
imgObj = new ImageObject();
|
||||
pic.ImageObjects.Add(imgObj);
|
||||
}
|
||||
else
|
||||
imgObj = pic.GetImageObject(objId);
|
||||
imgObj.PaletteId = palId;
|
||||
pic.ObjectId = objId;
|
||||
|
||||
// skipped: 8bit window_id_ref
|
||||
if (segment.Size >= 0x13)
|
||||
{
|
||||
pic.FramesPerSecondType = type;
|
||||
// object_cropped_flag: 0x80, forced_on_flag = 0x040, 6bit reserved
|
||||
int forcedCropped = buffer[14];
|
||||
pic.CompositionNumber = num;
|
||||
pic.IsForced = ((forcedCropped & 0x40) == 0x40);
|
||||
imgObj.XOffset = BigEndianInt16(buffer, 15); // composition_object_horizontal_position
|
||||
imgObj.YOffset = BigEndianInt16(buffer, 17); // composition_object_vertical_position
|
||||
// if (object_cropped_flag==1)
|
||||
// 16bit object_cropping_horizontal_position
|
||||
// 16bit object_cropping_vertical_position
|
||||
// 16bit object_cropping_width
|
||||
// object_cropping_height
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// parse an ODS packet which contain the image data
|
||||
/// </summary>
|
||||
/// <param name="buffer">raw byte date, starting right after segment</param>
|
||||
/// <param name="segment">object containing info about the current segment</param>
|
||||
/// <param name="pic">SubPicture object containing info about the current caption</param>
|
||||
/// <param name="msg">reference to message string</param>
|
||||
/// <returns>true if this is a valid new object (neither invalid nor a fragment)</returns>
|
||||
private static bool ParseOds(byte[] buffer, SupSegment segment, BluRaySupPicture pic, string[] msg)
|
||||
{
|
||||
ImageObjectFragment info;
|
||||
|
||||
int objId = BigEndianInt16(buffer, 0); // 16bit object_id
|
||||
int objVer = buffer[2]; // 16bit object_id nikse - index 2 or 1???
|
||||
int objSeq = buffer[3]; // 8bit first_in_sequence (0x80),
|
||||
// last_in_sequence (0x40), 6bits reserved
|
||||
bool first = (objSeq & 0x80) == 0x80;
|
||||
bool last = (objSeq & 0x40) == 0x40;
|
||||
|
||||
if (pic.ImageObjects == null)
|
||||
pic.ImageObjects = new List<ImageObject>();
|
||||
ImageObject imgObj;
|
||||
if (objId >= pic.ImageObjects.Count)
|
||||
{
|
||||
imgObj = new ImageObject();
|
||||
pic.ImageObjects.Add(imgObj);
|
||||
}
|
||||
else
|
||||
imgObj = pic.GetImageObject(objId);
|
||||
|
||||
if (imgObj.Fragments == null || first)
|
||||
{ // 8bit object_version_number
|
||||
// skipped:
|
||||
// 24bit object_data_length - full RLE buffer length (including 4 bytes size info)
|
||||
int width = BigEndianInt16(buffer, 7); // object_width
|
||||
int height = BigEndianInt16(buffer, 9); // object_height
|
||||
|
||||
if (width <= pic.Width && height <= pic.Height)
|
||||
{
|
||||
imgObj.Fragments = new List<ImageObjectFragment>();
|
||||
info = new ImageObjectFragment();
|
||||
info.ImagePacketSize = segment.Size - 11; // Image packet size (image bytes)
|
||||
info.ImageBuffer = new byte[info.ImagePacketSize];
|
||||
Buffer.BlockCopy(buffer, 11, info.ImageBuffer, 0, info.ImagePacketSize);
|
||||
imgObj.Fragments.Add(info);
|
||||
imgObj.BufferSize = info.ImagePacketSize;
|
||||
imgObj.Height = height;
|
||||
imgObj.Width = width;
|
||||
msg[0] = "ID: " + objId + ", update: " + objVer + ", seq: " + (first ? "first" : "") +
|
||||
((first && last) ? "/" : "") + (last ? "" + "last" : "");
|
||||
return true;
|
||||
}
|
||||
System.Diagnostics.Debug.Print("Invalid image size - ignored");
|
||||
return false;
|
||||
}
|
||||
// object_data_fragment
|
||||
// skipped:
|
||||
// 16bit object_id
|
||||
// 8bit object_version_number
|
||||
// 8bit first_in_sequence (0x80), last_in_sequence (0x40), 6bits reserved
|
||||
info = new ImageObjectFragment();
|
||||
info.ImagePacketSize = segment.Size - 4;
|
||||
info.ImageBuffer = new byte[info.ImagePacketSize];
|
||||
Buffer.BlockCopy(buffer, 4, info.ImageBuffer, 0, info.ImagePacketSize);
|
||||
imgObj.Fragments.Add(info);
|
||||
imgObj.BufferSize += info.ImagePacketSize; // total size (may contain several packets)
|
||||
msg[0] = "ID: " + objId + ", update: " + objVer + ", seq: " + (first ? "first" : "") + ((first && last) ? "/" : "") + (last ? "" + "last" : "");
|
||||
return false;
|
||||
}
|
||||
|
||||
private static CompositionState GetCompositionState(byte type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 0x00:
|
||||
return CompositionState.Normal;
|
||||
case 0x40:
|
||||
return CompositionState.AcquPoint;
|
||||
case 0x80:
|
||||
return CompositionState.EpochStart;
|
||||
case 0xC0:
|
||||
return CompositionState.EpochContinue;
|
||||
default:
|
||||
return CompositionState.Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
private static int BigEndianInt16(byte[] buffer, int index)
|
||||
{
|
||||
return (buffer[index + 1]) + (buffer[index + 0] << 8);
|
||||
}
|
||||
|
||||
private static uint BigEndianInt32(byte[] buffer, int index)
|
||||
{
|
||||
return (uint)((buffer[index + 3]) + (buffer[index + 2] << 8) + (buffer[index + 1] << 0x10) + (buffer[index + 0] << 0x18));
|
||||
}
|
||||
|
||||
private static SupSegment ReadSegment(byte[] buffer, StringBuilder log)
|
||||
{
|
||||
SupSegment segment = new SupSegment();
|
||||
if (buffer[0] == 0x50 && buffer[1] == 0x47) // 80 + 71 - P G
|
||||
{
|
||||
segment.PtsTimestamp = BigEndianInt32(buffer, 2); // read PTS
|
||||
segment.DtsTimestamp = BigEndianInt32(buffer, 6); // read PTS
|
||||
segment.Type = buffer[10];
|
||||
segment.Size = BigEndianInt16(buffer, 11);
|
||||
}
|
||||
else
|
||||
{
|
||||
log.AppendLine("Unable to read segment - PG missing!");
|
||||
}
|
||||
return segment;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// parse an PDS packet which contain palette info
|
||||
/// </summary>
|
||||
/// <param name="buffer">Buffer of raw byte data, starting right after segment</param>
|
||||
/// <param name="segment">object containing info about the current segment</param>
|
||||
/// <param name="pic">SubPicture object containing info about the current caption</param>
|
||||
/// <param name="msg">reference to message string</param>
|
||||
/// <returns>number of valid palette entries (-1 for fault)</returns>
|
||||
private static int ParsePds(byte[] buffer, SupSegment segment, BluRaySupPicture pic, string[] msg)
|
||||
{
|
||||
int paletteId = buffer[0]; // 8bit palette ID (0..7)
|
||||
// 8bit palette version number (incremented for each palette change)
|
||||
int paletteUpdate = buffer[1];
|
||||
if (pic.Palettes == null)
|
||||
{
|
||||
pic.Palettes = new List<List<PaletteInfo>>();
|
||||
for (int i = 0; i < 8; i++)
|
||||
pic.Palettes.Add(new List<PaletteInfo>());
|
||||
}
|
||||
if (paletteId > 7)
|
||||
{
|
||||
msg[0] = "Illegal palette id at offset " + ToolBox.ToHex(buffer, 0, 8);
|
||||
return -1;
|
||||
}
|
||||
List<PaletteInfo> al = pic.Palettes[paletteId];
|
||||
if (al == null)
|
||||
al = new List<PaletteInfo>();
|
||||
PaletteInfo p = new PaletteInfo();
|
||||
p.PaletteSize = (segment.Size - 2) / 5;
|
||||
p.PaletteBuffer = new byte[p.PaletteSize * 5];
|
||||
Buffer.BlockCopy(buffer, 2, p.PaletteBuffer, 0, p.PaletteSize * 5); // save palette buffer in palette object
|
||||
al.Add(p);
|
||||
msg[0] = "ID: " + paletteId + ", update: " + paletteUpdate + ", " + p.PaletteSize + " entries";
|
||||
return p.PaletteSize;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
403
src/Logic/BluRaySup/BluRaySupPicture.cs
Normal file
403
src/Logic/BluRaySup/BluRaySupPicture.cs
Normal file
@ -0,0 +1,403 @@
|
||||
/*
|
||||
* Copyright 2009 Volker Oth (0xdeadbeef)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* NOTE: Converted to C# and modified by Nikse.dk@gmail.com
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
{
|
||||
|
||||
public class BluRaySupPicture
|
||||
{
|
||||
/// <summary>
|
||||
/// screen width
|
||||
/// </summary>
|
||||
public int Width { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// screen height
|
||||
/// </summary>
|
||||
public int Height { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// start time in milliseconds
|
||||
/// </summary>
|
||||
public long StartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// end time in milliseconds
|
||||
/// </summary>
|
||||
public long EndTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// if true, this is a forced subtitle
|
||||
/// </summary>
|
||||
public bool IsForced { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// composition number - increased at start and end PCS
|
||||
/// </summary>
|
||||
public int CompositionNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// objectID used in decoded object
|
||||
/// </summary>
|
||||
public int ObjectId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// list of ODS packets containing image info
|
||||
/// </summary>
|
||||
public List<ImageObject> ImageObjects;
|
||||
|
||||
/// <summary>
|
||||
/// width of subtitle window (might be larger than image)
|
||||
/// </summary>
|
||||
public int WindowWidth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// height of subtitle window (might be larger than image)
|
||||
/// </summary>
|
||||
public int WindowHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// upper left corner of subtitle window x
|
||||
/// </summary>
|
||||
public int WindowXOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// upper left corner of subtitle window y
|
||||
/// </summary>
|
||||
public int WindowYOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// FPS type (e.g. 0x10 = 24p)
|
||||
/// </summary>
|
||||
public int FramesPerSecondType { get; set; }
|
||||
|
||||
/** list of (list of) palette info - there are up to 8 palettes per epoch, each can be updated several times */
|
||||
public List<List<PaletteInfo>> Palettes;
|
||||
|
||||
public BluRaySupPicture(BluRaySupPicture subPicture)
|
||||
{
|
||||
Width = subPicture.Width;
|
||||
Height = subPicture.Height;
|
||||
StartTime = subPicture.StartTime;
|
||||
EndTime = subPicture.EndTime;
|
||||
IsForced = subPicture.IsForced;
|
||||
CompositionNumber = subPicture.CompositionNumber;
|
||||
|
||||
ObjectId = subPicture.ObjectId;
|
||||
ImageObjects = new List<ImageObject>();
|
||||
foreach (ImageObject io in subPicture.ImageObjects)
|
||||
ImageObjects.Add(io);
|
||||
WindowWidth = subPicture.WindowWidth;
|
||||
WindowHeight = subPicture.WindowHeight;
|
||||
WindowXOffset = subPicture.WindowXOffset;
|
||||
WindowYOffset = subPicture.WindowYOffset;
|
||||
FramesPerSecondType = subPicture.FramesPerSecondType;
|
||||
Palettes = new List<List<PaletteInfo>>();
|
||||
foreach (List<PaletteInfo> palette in subPicture.Palettes)
|
||||
{
|
||||
List<PaletteInfo> p = new List<PaletteInfo>();
|
||||
foreach (PaletteInfo pi in palette)
|
||||
{
|
||||
p.Add(new PaletteInfo(pi));
|
||||
}
|
||||
Palettes.Add(p);
|
||||
}
|
||||
}
|
||||
|
||||
public BluRaySupPicture()
|
||||
{
|
||||
}
|
||||
|
||||
public ImageObject GetImageObject(int index)
|
||||
{
|
||||
return ImageObjects[index];
|
||||
}
|
||||
|
||||
internal ImageObject ObjectIdImage
|
||||
{
|
||||
get
|
||||
{
|
||||
return ImageObjects[ObjectId];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// decode palette from the input stream
|
||||
/// </summary>
|
||||
/// <param name="pic">SubPicture object containing info about the current caption</param>
|
||||
/// <returns>Palette object</returns>
|
||||
public BluRaySupPalette DecodePalette(BluRaySupPalette defaultPalette)
|
||||
{
|
||||
BluRaySupPicture pic = this;
|
||||
bool fadeOut = false;
|
||||
if (pic.Palettes.Count == 0 || pic.ObjectIdImage.PaletteId >= pic.Palettes.Count)
|
||||
{
|
||||
System.Diagnostics.Debug.Print("Palette not found in objectID=" + pic.ObjectId + " PaletteId=" + pic.ObjectIdImage.PaletteId + "!");
|
||||
if (defaultPalette == null)
|
||||
return new BluRaySupPalette(256, Core.UsesBt601());
|
||||
else
|
||||
return new BluRaySupPalette(defaultPalette);
|
||||
}
|
||||
List<PaletteInfo> pl = pic.Palettes[pic.ObjectIdImage.PaletteId];
|
||||
BluRaySupPalette palette = new BluRaySupPalette(256, Core.UsesBt601());
|
||||
// by definition, index 0xff is always completely transparent
|
||||
// also all entries must be fully transparent after initialization
|
||||
|
||||
for (int j = 0; j < pl.Count; j++)
|
||||
{
|
||||
PaletteInfo p = pl[j];
|
||||
int index = 0;
|
||||
|
||||
for (int i = 0; i < p.PaletteSize; i++)
|
||||
{
|
||||
// each palette entry consists of 5 bytes
|
||||
int palIndex = p.PaletteBuffer[index];
|
||||
int y = p.PaletteBuffer[++index];
|
||||
int cr, cb;
|
||||
if (Core.GetSwapCrCb())
|
||||
{
|
||||
cb = p.PaletteBuffer[++index];
|
||||
cr = p.PaletteBuffer[++index];
|
||||
}
|
||||
else
|
||||
{
|
||||
cr = p.PaletteBuffer[++index];
|
||||
cb = p.PaletteBuffer[++index];
|
||||
}
|
||||
int alpha = p.PaletteBuffer[++index];
|
||||
|
||||
int alphaOld = palette.GetAlpha(palIndex);
|
||||
// avoid fading out
|
||||
if (alpha >= alphaOld)
|
||||
{
|
||||
if (alpha < Core.GetAlphaCrop())
|
||||
{// to not mess with scaling algorithms, make transparent color black
|
||||
y = 16;
|
||||
cr = 128;
|
||||
cb = 128;
|
||||
}
|
||||
palette.SetAlpha(palIndex, alpha);
|
||||
}
|
||||
else fadeOut = true;
|
||||
|
||||
palette.SetYCbCr(palIndex, y, cb, cr);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
if (fadeOut)
|
||||
System.Diagnostics.Debug.Print("fade out detected -> patched palette\n");
|
||||
return palette;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decode caption from the input stream
|
||||
/// </summary>
|
||||
/// <param name="pic">SubPicture object containing info about the caption</param>
|
||||
/// <param name="transIdx">index of the transparent color</param>
|
||||
/// <returns>bitmap of the decoded caption</returns>
|
||||
public Bitmap DecodeImage(BluRaySupPalette defaultPalette)
|
||||
{
|
||||
int w = ObjectIdImage.Width;
|
||||
int h = ObjectIdImage.Height;
|
||||
|
||||
if (w > Width || h > Height)
|
||||
throw new Exception("Subpicture too large: " + w + "x" + h);
|
||||
|
||||
//Bitmap bm = new Bitmap(w, h);
|
||||
FastBitmap bm = new FastBitmap(new Bitmap(w, h));
|
||||
bm.LockImage();
|
||||
BluRaySupPalette pal = DecodePalette(defaultPalette);
|
||||
|
||||
int index = 0;
|
||||
int ofs = 0;
|
||||
int xpos = 0;
|
||||
|
||||
// just for multi-packet support, copy all of the image data in one common buffer
|
||||
byte[] buf = new byte[ObjectIdImage.BufferSize];
|
||||
foreach (ImageObjectFragment fragment in ObjectIdImage.Fragments)
|
||||
{
|
||||
Buffer.BlockCopy(fragment.ImageBuffer, 0, buf, index, fragment.ImagePacketSize);
|
||||
index += fragment.ImagePacketSize;
|
||||
}
|
||||
|
||||
|
||||
index = 0;
|
||||
do
|
||||
{
|
||||
int b = buf[index++] & 0xff;
|
||||
if (b == 0)
|
||||
{
|
||||
b = buf[index++] & 0xff;
|
||||
if (b == 0)
|
||||
{
|
||||
// next line
|
||||
ofs = (ofs / w) * w;
|
||||
if (xpos < w)
|
||||
ofs += w;
|
||||
xpos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int size;
|
||||
if ((b & 0xC0) == 0x40)
|
||||
{
|
||||
// 00 4x xx -> xxx zeroes
|
||||
size = ((b - 0x40) << 8) + (buf[index++] & 0xff);
|
||||
for (int i = 0; i < size; i++)
|
||||
PutPixel(bm, ofs++, 0, pal);
|
||||
xpos += size;
|
||||
}
|
||||
else if ((b & 0xC0) == 0x80)
|
||||
{
|
||||
// 00 8x yy -> x times value y
|
||||
size = (b - 0x80);
|
||||
b = buf[index++] & 0xff;
|
||||
for (int i = 0; i < size; i++)
|
||||
PutPixel(bm, ofs++, b, pal);
|
||||
xpos += size;
|
||||
}
|
||||
else if ((b & 0xC0) != 0)
|
||||
{
|
||||
// 00 cx yy zz -> xyy times value z
|
||||
size = ((b - 0xC0) << 8) + (buf[index++] & 0xff);
|
||||
b = buf[index++] & 0xff;
|
||||
for (int i = 0; i < size; i++)
|
||||
PutPixel(bm, ofs++, b, pal);
|
||||
xpos += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 00 xx -> xx times 0
|
||||
for (int i = 0; i < b; i++)
|
||||
PutPixel(bm, ofs++, 0, pal);
|
||||
xpos += b;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PutPixel(bm, ofs++, b, pal);
|
||||
xpos++;
|
||||
}
|
||||
} while (index < buf.Length);
|
||||
|
||||
bm.UnlockImage();
|
||||
return bm.GetBitmap();
|
||||
}
|
||||
|
||||
private static void PutPixel(FastBitmap bmp, int index, int color, BluRaySupPalette palette)
|
||||
{
|
||||
int x = index % bmp.Width;
|
||||
int y = index / bmp.Width;
|
||||
if (color > 0 && x < bmp.Width && y < bmp.Height)
|
||||
bmp.SetPixel(x, y, Color.FromArgb(palette.GetArgb(color)));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class ImageObject
|
||||
{
|
||||
/// <summary>
|
||||
/// list of ODS packets containing image info
|
||||
/// </summary>
|
||||
public List<ImageObjectFragment> Fragments;
|
||||
|
||||
/// <summary>
|
||||
/// palette identifier
|
||||
/// </summary>
|
||||
public int PaletteId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// overall size of RLE buffer (might be spread over several packages)
|
||||
/// </summary>
|
||||
public int BufferSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// with of subtitle image
|
||||
/// </summary>
|
||||
public int Width { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// height of subtitle image
|
||||
/// </summary>
|
||||
public int Height { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// upper left corner of subtitle x
|
||||
/// </summary>
|
||||
public int XOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// upper left corner of subtitle y
|
||||
/// </summary>
|
||||
public int YOffset { get; set; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// contains offset and size of one fragment containing (parts of the) RLE buffer
|
||||
/// </summary>
|
||||
public class ImageObjectFragment
|
||||
{
|
||||
/// <summary>
|
||||
/// size of this part of the RLE buffer
|
||||
/// </summary>
|
||||
public int ImagePacketSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Buffer for raw image data fragment
|
||||
/// </summary>
|
||||
public byte[] ImageBuffer { get; set; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// contains offset and size of one update of a palette
|
||||
/// </summary>
|
||||
public class PaletteInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// number of palette entries
|
||||
/// </summary>
|
||||
public int PaletteSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// raw palette data
|
||||
/// </summary>
|
||||
public byte[] PaletteBuffer { get; set; }
|
||||
|
||||
public PaletteInfo()
|
||||
{
|
||||
}
|
||||
|
||||
public PaletteInfo(PaletteInfo paletteInfo)
|
||||
{
|
||||
PaletteSize = paletteInfo.PaletteSize;
|
||||
PaletteBuffer = new byte[paletteInfo.PaletteBuffer.Length];
|
||||
Buffer.BlockCopy(paletteInfo.PaletteBuffer, 0, PaletteBuffer, 0, PaletteBuffer.Length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
87
src/Logic/BluRaySup/Core.cs
Normal file
87
src/Logic/BluRaySup/Core.cs
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2009 Volker Oth (0xdeadbeef)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* NOTE: Converted to C# and modified by Nikse.dk@gmail.com
|
||||
*/
|
||||
namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
{
|
||||
public static class Core
|
||||
{
|
||||
|
||||
/** Use BT.601 color model instead of BT.709 */
|
||||
private const bool UseBt601 = false;
|
||||
|
||||
/** Flag that defines whether to swap Cr/Cb components when loading a SUP */
|
||||
private const bool SwapCrCb = false;
|
||||
|
||||
/** Alpha threshold for cropping */
|
||||
private const int AlphaCrop = 14;
|
||||
|
||||
/** Two equal captions are merged of they are closer than 200ms (0.2*90000 = 18000) */
|
||||
private const int MergePtSdiff = 18000;
|
||||
|
||||
/** Frames per seconds for 24p (23.976) */
|
||||
public static double Fps24P = 24000.0 / 1001;
|
||||
/** Frames per seconds for wrong 24P (23.975) */
|
||||
public static double Fps23975 = 23.975;
|
||||
/** Frames per seconds for 24Hz (24.0) */
|
||||
public static double Fps24Hz = 24.0;
|
||||
/** Frames per seconds for PAL progressive (25.0) */
|
||||
public static double FpsPal = 25.0;
|
||||
/** Frames per seconds for NTSC progressive (29.97) */
|
||||
public static double FpsNtsc = 30000.0 / 1001;
|
||||
/** Frames per seconds for PAL interlaced (50.0) */
|
||||
public static double FpsPalI = 50.0;
|
||||
/** Frames per seconds for NTSC interlaced (59.94) */
|
||||
public static double FpsNtscI = 60000.0 / 1001;
|
||||
|
||||
/**
|
||||
* Get maximum time difference for merging captions.
|
||||
* @return Maximum time difference for merging captions
|
||||
*/
|
||||
public static int GetMergePtSdiff()
|
||||
{
|
||||
return MergePtSdiff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get: use of BT.601 color model instead of BT.709.
|
||||
* @return True if BT.601 is used
|
||||
*/
|
||||
public static bool UsesBt601()
|
||||
{
|
||||
return UseBt601;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get flag that defines whether to swap Cr/Cb components when loading a SUP.
|
||||
* @return True: swap cr/cb
|
||||
*/
|
||||
public static bool GetSwapCrCb()
|
||||
{
|
||||
return SwapCrCb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get alpha threshold for cropping.
|
||||
* @return Alpha threshold for cropping
|
||||
*/
|
||||
public static int GetAlphaCrop()
|
||||
{
|
||||
return AlphaCrop;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
98
src/Logic/BluRaySup/ToolBox.cs
Normal file
98
src/Logic/BluRaySup/ToolBox.cs
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2009 Volker Oth (0xdeadbeef)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* NOTE: Converted to C# and modified by Nikse.dk@gmail.com
|
||||
*/
|
||||
using System.Text;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
{
|
||||
public static class ToolBox
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Convert bytes to a C-style hex string with leading zeroes
|
||||
/// </summary>
|
||||
public static string ToHex(byte[] buffer, int index, int digits)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
for (int i = index; i < index + digits; i++)
|
||||
{
|
||||
string s = string.Format("{0:X}", buffer[i]);
|
||||
if (s.Length < 2)
|
||||
sb.Append("0");
|
||||
sb.Append(s);
|
||||
}
|
||||
return "0x" + sb;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a long integer to a C-style hex string with leading zeroes
|
||||
/// </summary>
|
||||
public static string ToHex(int number, int index, int digits)
|
||||
{
|
||||
string s = string.Format("{0:X}", number);
|
||||
if (s.Length < digits)
|
||||
s.PadLeft(digits, '0');
|
||||
return "0x" + s;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Convert an integer to a string with leading zeroes
|
||||
/// </summary>
|
||||
/// <param name="i">Integer value to convert</param>
|
||||
/// <param name="digits">Number of digits to display - note that a 32bit number can have only 10 digits</param>
|
||||
/// <returns>String version of integer with trailing zeroes</returns>
|
||||
public static string ZeroTrim(int i, int digits)
|
||||
{
|
||||
string s = i.ToString();
|
||||
return s.PadLeft(digits, '0');
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert time in milliseconds to array containing hours, minutes, seconds and milliseconds
|
||||
* @param ms Time in milliseconds
|
||||
* @return Array containing hours, minutes, seconds and milliseconds (in this order)
|
||||
*/
|
||||
public static int[] MillisecondsToTime(long ms)
|
||||
{
|
||||
int[] time = new int[4];
|
||||
// time[0] = hours
|
||||
time[0] = (int)(ms / (60 * 60 * 1000));
|
||||
ms -= time[0] * 60 * 60 * 1000;
|
||||
// time[1] = minutes
|
||||
time[1] = (int)(ms / (60 * 1000));
|
||||
ms -= time[1] * 60 * 1000;
|
||||
// time[2] = seconds
|
||||
time[2] = (int)(ms / 1000);
|
||||
ms -= time[2] * 1000;
|
||||
time[3] = (int)ms;
|
||||
return time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert time in 90kHz ticks to string hh:mm:ss.ms
|
||||
* @param pts Time in 90kHz resolution
|
||||
* @return String in format hh:mm:ss:ms
|
||||
*/
|
||||
public static string PtsToTimeString(long pts)
|
||||
{
|
||||
int[] time = MillisecondsToTime((pts + 45) / 90);
|
||||
return ZeroTrim(time[0], 2) + ":" + ZeroTrim(time[1], 2) + ":" + ZeroTrim(time[2], 2) + "." + ZeroTrim(time[3], 3);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -8,6 +8,13 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
{
|
||||
public static bool IsColorClose(Color a, Color b, int tolerance)
|
||||
{
|
||||
if (a.A < 120 && b.A < 120)
|
||||
return true; // transparent
|
||||
|
||||
if (a.A > 250 && a.R > 90 && a.G > 90 && a.B > 90 &&
|
||||
b.A > 250 && b.R > 90 && b.G > 90 && b.B > 90)
|
||||
return true; // dark, non transparent
|
||||
|
||||
int diff = (a.R + a.G + a.B) - (b.R + b.G + b.B);
|
||||
return diff < tolerance && diff > -tolerance;
|
||||
}
|
||||
@ -131,7 +138,9 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
for (int y = 1; y < bmp1.Height; y++)
|
||||
{
|
||||
if (!IsColorClose(bmp1.GetPixel(x, y), bmp2.GetPixel(x, y), 20))
|
||||
{
|
||||
different++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return different;
|
||||
|
@ -45,12 +45,10 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
|
||||
#Subtitle text begin";
|
||||
|
||||
const string Footer = @"#Subtitle text end
|
||||
|
||||
#Subtitle text attribute begin
|
||||
#/R:1,856 /FP:8 /FS:24
|
||||
#/R:1,{0} /FP:8 /FS:24
|
||||
#Subtitle text attribute end";
|
||||
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine(Header);
|
||||
int index = 0;
|
||||
@ -63,7 +61,7 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats
|
||||
sb.AppendLine(Utilities.RemoveHtmlTags(p.Text));
|
||||
index++;
|
||||
}
|
||||
sb.AppendLine(Footer);
|
||||
sb.AppendLine(string.Format(Footer, subtitle.Paragraphs.Count));
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
|
@ -372,6 +372,7 @@
|
||||
<Compare>Sammenlign...</Compare>
|
||||
<ImportOcrFromDvd>Import/OCR undertekster fra VOB/IFO (dvd) ...</ImportOcrFromDvd>
|
||||
<ImportOcrVobSubSubtitle>Importer/OCR VobSub (sub/idx) undertekst...</ImportOcrVobSubSubtitle>
|
||||
<ImportBluRaySupFile>Importer/OCR BluRay sup fil...</ImportBluRaySupFile>
|
||||
<ImportSubtitleFromMatroskaFile>Importer undertekster fra Matroska fil...</ImportSubtitleFromMatroskaFile>
|
||||
<ImportSubtitleWithManualChosenEncoding>Importer undertekst med manuel valgt tegnsæt...</ImportSubtitleWithManualChosenEncoding>
|
||||
<ImportText>Importer tekst...</ImportText>
|
||||
@ -672,7 +673,10 @@ Fortsæt?</SubtitleAppendPrompt>
|
||||
<InvalidVobSubHeader>Header ikke gyldig VobSub fil: {0}</InvalidVobSubHeader>
|
||||
<OpenVobSubFile>Åbn VobSub (sub/idx) undertekst...</OpenVobSubFile>
|
||||
<VobSubFiles>VobSub undertekst filer</VobSubFiles>
|
||||
<BeforeImportingVobSubFile>Før import af VobSub undertekster</BeforeImportingVobSubFile>
|
||||
<OpenBluRaySupFile>Åbn BluRay sup fil...</OpenBluRaySupFile>
|
||||
<BluRaySupFiles>BluRay sup filer</BluRaySupFiles>
|
||||
<BeforeImportingVobSubFile>Før import af VobSub undertekst</BeforeImportingVobSubFile>
|
||||
<BeforeImportingBluRaySupFile>Før import af BluRay sup undertekst</BeforeImportingBluRaySupFile>
|
||||
<BeforeShowSelectedLinesEarlierLater>Før vis udvalgte linjer tidligere/senere</BeforeShowSelectedLinesEarlierLater>
|
||||
<ShowSelectedLinesEarlierLaterPerformed>Vis tidligere/senere udført på udvalgte linjer</ShowSelectedLinesEarlierLaterPerformed>
|
||||
<DoubleWordsViaRegEx>Dobbelt ord via regex {0}</DoubleWordsViaRegEx>
|
||||
@ -973,7 +977,8 @@ Fortsæt?</SubtitleAppendPrompt>
|
||||
<Image>Billede</Image>
|
||||
</VobSubEditCharacters>
|
||||
<VobSubOcr>
|
||||
<Title>Importer/OCR VobSub (sub/idx) undertekster</Title>
|
||||
<Title>Importer/OCR VobSub (sub/idx) undertekst</Title>
|
||||
<TitleBluRay>Importer/OCR BluRay (.sup) undertekst</TitleBluRay>
|
||||
<OcrMethod>OCR-metoden</OcrMethod>
|
||||
<OcrViaModi>OCR via Microsoft Office Document Imaging (MODI). Kræver MS Office</OcrViaModi>
|
||||
<OcrViaTesseract>OCR via Tesseract</OcrViaTesseract>
|
||||
|
Binary file not shown.
@ -371,6 +371,7 @@ de inicio del próximo texto</Note>
|
||||
<Compare>&Comparar...</Compare>
|
||||
<ImportOcrFromDvd>Importar/OCR subtítulo desde vob/ifo (dvd) ...</ImportOcrFromDvd>
|
||||
<ImportOcrVobSubSubtitle>Importar/subtítuloOCR VobSub (sub/idx)...</ImportOcrVobSubSubtitle>
|
||||
<ImportBluRaySupFile>Importar/subtítuloOCR BluRay (.sup)...</ImportBluRaySupFile>
|
||||
<ImportSubtitleFromMatroskaFile>Importar subtítulo desde archivo Matroska...</ImportSubtitleFromMatroskaFile>
|
||||
<ImportSubtitleWithManualChosenEncoding>Importar subtítulo de modo manual eligiendo codificador...</ImportSubtitleWithManualChosenEncoding>
|
||||
<ImportText>Importar texto...</ImportText>
|
||||
@ -671,7 +672,10 @@ Continuar?</SubtitleAppendPrompt>
|
||||
<InvalidVobSubHeader>Encabezado de archivoVobSub inválido: {0}</InvalidVobSubHeader>
|
||||
<OpenVobSubFile>Abrir subtítulo VobSub (sub/idx)...</OpenVobSubFile>
|
||||
<VobSubFiles>Subtítulos de archivos VobSub</VobSubFiles>
|
||||
<OpenBluRaySupFile>Abrir subtítulo BluRay (.sup)...</OpenBluRaySupFile>
|
||||
<BluRaySupFiles>Subtítulos de archivos BluRay</BluRaySupFiles>
|
||||
<BeforeImportingVobSubFile>Antes de importar subtítulos VobSub</BeforeImportingVobSubFile>
|
||||
<BeforeImportingBluRaySupFile>Antes de importar subtítulos BluRay</BeforeImportingBluRaySupFile>
|
||||
<BeforeShowSelectedLinesEarlierLater>Antes de mostrar las líneas seleccionadas antes/después
|
||||
</BeforeShowSelectedLinesEarlierLater>
|
||||
<ShowSelectedLinesEarlierLaterPerformed>Mostrar el antes/después realizado sobre las líneas seleccionadas</ShowSelectedLinesEarlierLaterPerformed>
|
||||
@ -975,6 +979,7 @@ Continuar?</SubtitleAppendPrompt>
|
||||
</VobSubEditCharacters>
|
||||
<VobSubOcr>
|
||||
<Title>Importar/subtítuloOCR VobSub (sub/idx)</Title>
|
||||
<TitleBluRay>Importar/subtítuloOCR BluRay (.sup)</TitleBluRay>
|
||||
<OcrMethod>método OCR</OcrMethod>
|
||||
<OcrViaModi>OCR vía Microsoft Office Document Imaging (MODI). MS Office requerido</OcrViaModi>
|
||||
<OcrViaTesseract>OCR a traves de Tesseract</OcrViaTesseract>
|
||||
|
Binary file not shown.
@ -370,6 +370,7 @@ Email : mailto:nikse.dk@gmail.com</AboutText1>
|
||||
<Compare>&Comparer...</Compare>
|
||||
<ImportOcrFromDvd>Import/sous-titres OCR de VOB/IFO (DVD) ...</ImportOcrFromDvd>
|
||||
<ImportOcrVobSubSubtitle>Import/OCR VobSub (sub/idx) sous-titres...</ImportOcrVobSubSubtitle>
|
||||
<ImportBluRaySupFile>Import/OCR BluRay (.sup) sous-titres...</ImportBluRaySupFile>
|
||||
<ImportSubtitleFromMatroskaFile>Sous-titres d'importation de fichier Matroska...</ImportSubtitleFromMatroskaFile>
|
||||
<ImportSubtitleWithManualChosenEncoding>Sous-titres d'importation avec le codage choisi manuel...</ImportSubtitleWithManualChosenEncoding>
|
||||
<ImportText>Importer texte...</ImportText>
|
||||
@ -667,7 +668,10 @@ Poursuivre?</SubtitleAppendPrompt>
|
||||
<InvalidVobSubHeader>En-tête non valide fichier VobSub : {0}</InvalidVobSubHeader>
|
||||
<OpenVobSubFile>Ouvrir sous-titres VobSub (sub/idx)...</OpenVobSubFile>
|
||||
<VobSubFiles>Fichiers sous-titres VobSub</VobSubFiles>
|
||||
<OpenBluRaySupFile>Ouvrir sous-titres BluRay (.sup)...</OpenBluRaySupFile>
|
||||
<BluRaySupFiles>Fichiers sous-titres BluRay</BluRaySupFiles>
|
||||
<BeforeImportingVobSubFile>Avant d'importer des sous-titres VobSub</BeforeImportingVobSubFile>
|
||||
<BeforeImportingBluRaySupFile>Avant d'importer des sous-titres BluRay</BeforeImportingBluRaySupFile>
|
||||
<BeforeShowSelectedLinesEarlierLater>Avant de montrer les lignes précédentes/suivantes sélectionnées</BeforeShowSelectedLinesEarlierLater>
|
||||
<ShowSelectedLinesEarlierLaterPerformed>Montrer précédent/suivant effectué sur les lignes sélectionnées </ShowSelectedLinesEarlierLaterPerformed>
|
||||
<DoubleWordsViaRegEx>Double mots via regex {0}</DoubleWordsViaRegEx>
|
||||
@ -970,6 +974,7 @@ Poursuivre?</SubtitleAppendPrompt>
|
||||
</VobSubEditCharacters>
|
||||
<VobSubOcr>
|
||||
<Title>Import/OCR VobSub (sub/idx) sous-titres</Title>
|
||||
<TitleBluRay>Import/OCR BluRay (.sup) sous-titres</TitleBluRay>
|
||||
<OcrMethod>Méthode OCR</OcrMethod>
|
||||
<OcrViaModi>OCR par Microsoft Office Document Imaging (MODI). Nécessite MS Office</OcrViaModi>
|
||||
<OcrViaTesseract>OCR par Tesseract</OcrViaTesseract>
|
||||
|
Binary file not shown.
@ -371,6 +371,7 @@ Email: mailto:nikse.dk@gmail.com</AboutText1>
|
||||
<Compare>Po&równaj...</Compare>
|
||||
<ImportOcrFromDvd>Importuj/OCR napisy z VOB/IFO (DVD)...</ImportOcrFromDvd>
|
||||
<ImportOcrVobSubSubtitle>Importuj/OCR napisy z VobSub (sub/idx)...</ImportOcrVobSubSubtitle>
|
||||
<ImportBluRaySupFile>Importuj/OCR napisy z BluRay (.sup)...</ImportBluRaySupFile>
|
||||
<ImportSubtitleFromMatroskaFile>Importuj napisy z pliku Matroska...</ImportSubtitleFromMatroskaFile>
|
||||
<ImportSubtitleWithManualChosenEncoding>Importuj napisy z ręcznym wyborem kodowania...</ImportSubtitleWithManualChosenEncoding>
|
||||
<ImportText>Importuj tekst...</ImportText>
|
||||
@ -671,7 +672,10 @@ Kontynuować?</SubtitleAppendPrompt>
|
||||
<InvalidVobSubHeader>Błędny nagłówek pliku VobSub: {0}</InvalidVobSubHeader>
|
||||
<OpenVobSubFile>Otwórz napisy VobSub (sub/idx)...</OpenVobSubFile>
|
||||
<VobSubFiles>Pliki napisów VobSub</VobSubFiles>
|
||||
<OpenBluRaySupFile>Otwórz napisy BluRay (.sup)...</OpenBluRaySupFile>
|
||||
<BluRaySupFiles>Pliki napisów BluRay (.sup)</BluRaySupFiles>
|
||||
<BeforeImportingVobSubFile>Przed importowaniem napisów VobSub</BeforeImportingVobSubFile>
|
||||
<BeforeImportingBluRaySupFile>Przed importowaniem napisów BluRay (.sup)</BeforeImportingBluRaySupFile>
|
||||
<BeforeShowSelectedLinesEarlierLater>Przed wybraniem wcześniejszego/późniejszego ukazywania się linii</BeforeShowSelectedLinesEarlierLater>
|
||||
<ShowSelectedLinesEarlierLaterPerformed>Wykonanie na wybranych liniach wcześniejszego/późniejszego ukazywania się</ShowSelectedLinesEarlierLaterPerformed>
|
||||
<DoubleWordsViaRegEx>Podwójne wyrazy via regex {0}</DoubleWordsViaRegEx>
|
||||
@ -973,6 +977,7 @@ Kontynuować?</SubtitleAppendPrompt>
|
||||
</VobSubEditCharacters>
|
||||
<VobSubOcr>
|
||||
<Title>Import/OCR napisów VobSub (sub/idx)</Title>
|
||||
<TitleBluRay>Import/OCR napisów BluRay (.sup)</TitleBluRay>
|
||||
<OcrMethod>Metody OCR</OcrMethod>
|
||||
<OcrViaModi>OCR za pomocą MS MODI. Wymagany MS Office</OcrViaModi>
|
||||
<OcrViaTesseract>OCR przy użyciu Tesseract</OcrViaTesseract>
|
||||
|
Binary file not shown.
@ -368,6 +368,7 @@ E-mail: nikse.dk @gmail.com</AboutText1>
|
||||
<Compare>&Compara...</Compare>
|
||||
<ImportOcrFromDvd>Import/subtitrarea OCR din vob/IFO (DVD) ...</ImportOcrFromDvd>
|
||||
<ImportOcrVobSubSubtitle>Import/OCR VobSub (sub/idx) subtitrarea...</ImportOcrVobSubSubtitle>
|
||||
<ImportBluRaySupFile>Import/OCR BluRay (,sup) subtitrarea...</ImportBluRaySupFile>
|
||||
<ImportSubtitleFromMatroskaFile>Import subtitrare din fisier Matroska...</ImportSubtitleFromMatroskaFile>
|
||||
<ImportSubtitleWithManualChosenEncoding>Import subtitrare cu alegerea manuala a codarii...</ImportSubtitleWithManualChosenEncoding>
|
||||
<ImportText>Import text simplu...</ImportText>
|
||||
@ -668,7 +669,10 @@ E-mail: nikse.dk @gmail.com</AboutText1>
|
||||
<InvalidVobSubHeader>Antetul nu este valabil pentru fisier VobSubr: {0}</InvalidVobSubHeader>
|
||||
<OpenVobSubFile>Deschide subtitrare VobSub (sub/idx)...</OpenVobSubFile>
|
||||
<VobSubFiles>Fisier subtitrare VobSub</VobSubFiles>
|
||||
<OpenBluRaySupFile>Deschide subtitrare BluRay (.sup)...</OpenBluRaySupFile>
|
||||
<BluRaySupFiles>Fisier subtitrare BluRay</BluRaySupFiles>
|
||||
<BeforeImportingVobSubFile>Inainte de a importa subtitrare VobSub</BeforeImportingVobSubFile>
|
||||
<BeforeImportingBluRaySupFile>Inainte de a importa subtitrare BluRay (.sup)</BeforeImportingBluRaySupFile>
|
||||
<BeforeShowSelectedLinesEarlierLater>Inainte de a arata liniile selectate mai devreme/tarziu</BeforeShowSelectedLinesEarlierLater>
|
||||
<ShowSelectedLinesEarlierLaterPerformed>Arata mai devreme/tarziu efectuate pe liniile selectate</ShowSelectedLinesEarlierLaterPerformed>
|
||||
<DoubleWordsViaRegEx>Cuvinte dublate via regex {0}</DoubleWordsViaRegEx>
|
||||
@ -970,6 +974,7 @@ E-mail: nikse.dk @gmail.com</AboutText1>
|
||||
</VobSubEditCharacters>
|
||||
<VobSubOcr>
|
||||
<Title>Import subtitrare /OCR VobSub (sub/idx)</Title>
|
||||
<TitleBluRay>Import subtitrare /OCR BluRay (.sup)</TitleBluRay>
|
||||
<OcrMethod>OCR metoda</OcrMethod>
|
||||
<OcrViaModi>OCR, prin intermediul Microsoft Office Document Imaging (MODI). Necesita MS Office</OcrViaModi>
|
||||
<OcrViaTesseract>OCR prin Tesseract</OcrViaTesseract>
|
||||
|
Binary file not shown.
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Language Name="Српски">
|
||||
<General>
|
||||
<Title>Subtitle Edit</Title>
|
||||
@ -370,6 +370,7 @@ C# изворни кôд се налази на интернет страниц
|
||||
<Compare>&Упореди...</Compare>
|
||||
<ImportOcrFromDvd>Увези/препознај знакове титла из VOB/IFO датотеке (ДВД)...</ImportOcrFromDvd>
|
||||
<ImportOcrVobSubSubtitle>Увези/препознај знакове VobSub титла...</ImportOcrVobSubSubtitle>
|
||||
<ImportBluRaySupFile>Увези/препознај знакове BluRay титла...</ImportBluRaySupFile>
|
||||
<ImportSubtitleFromMatroskaFile>Увези титл из матрошка датотеке...</ImportSubtitleFromMatroskaFile>
|
||||
<ImportSubtitleWithManualChosenEncoding>Увези титл с ручно изабраним кодним распоредом...</ImportSubtitleWithManualChosenEncoding>
|
||||
<ImportText>Увези чист текст...</ImportText>
|
||||
@ -599,8 +600,7 @@ C# изворни кôд се налази на интернет страниц
|
||||
<SubtitleAppendPromptTitle>Качење титла</SubtitleAppendPromptTitle>
|
||||
<OpenSubtitleToAppend>Отвори титл за качење...</OpenSubtitleToAppend>
|
||||
<AppendViaVisualSyncTitle>Визуелна синхронизација — качење другог дела титла</AppendViaVisualSyncTitle>
|
||||
<AppendSynchronizedSubtitlePrompt>
|
||||
</AppendSynchronizedSubtitlePrompt>
|
||||
<AppendSynchronizedSubtitlePrompt>Додај овај синхронизовани титлове?</AppendSynchronizedSubtitlePrompt>
|
||||
<BeforeAppend>Пре качења</BeforeAppend>
|
||||
<SubtitleAppendedX>Прикачено титлова: {0}</SubtitleAppendedX>
|
||||
<SubtitleNotAppended>Титл није прикачен!</SubtitleNotAppended>
|
||||
@ -671,7 +671,10 @@ C# изворни кôд се налази на интернет страниц
|
||||
<InvalidVobSubHeader>Заглавље није исправна VobSub датотека: {0}</InvalidVobSubHeader>
|
||||
<OpenVobSubFile>Отварање VobSub титла...</OpenVobSubFile>
|
||||
<VobSubFiles>VobSub титлови</VobSubFiles>
|
||||
<OpenBluRaySupFile>Отварање BluRay (.sup) титла...</OpenBluRaySupFile>
|
||||
<BluRaySupFiles>BluRay титлови</BluRaySupFiles>
|
||||
<BeforeImportingVobSubFile>Пре увоза VobSub титла</BeforeImportingVobSubFile>
|
||||
<BeforeImportingBluRaySupFile>Пре увоза BluRay титла</BeforeImportingBluRaySupFile>
|
||||
<BeforeShowSelectedLinesEarlierLater>Пре приказивања изабране линије раније/касније</BeforeShowSelectedLinesEarlierLater>
|
||||
<ShowSelectedLinesEarlierLaterPerformed>Прикажи изабране линије раније или касније</ShowSelectedLinesEarlierLaterPerformed>
|
||||
<DoubleWordsViaRegEx>Дупле речи путем регекса {0}</DoubleWordsViaRegEx>
|
||||
@ -694,10 +697,8 @@ C# изворни кôд се налази на интернет страниц
|
||||
<XMinimumDisplayTimeBetweenParagraphsChanged>Измењено броја линија с минималним временом приказа између пасуса: {0}</XMinimumDisplayTimeBetweenParagraphsChanged>
|
||||
<BeforeImportText>Пре увоза чистог текста</BeforeImportText>
|
||||
<TextImported>Текст је увезен</TextImported>
|
||||
<BeforePointSynchronization>
|
||||
</BeforePointSynchronization>
|
||||
<PointSynchronizationDone>
|
||||
</PointSynchronizationDone>
|
||||
<BeforePointSynchronization>Пре тачка синхронизације</BeforePointSynchronization>
|
||||
<PointSynchronizationDone>Тачка синхронизације урадити</PointSynchronizationDone>
|
||||
<BeforeTimeCodeImport>Пре увоза временских одредница</BeforeTimeCodeImport>
|
||||
<TimeCodeImportedFromXY>Временске одреднице су увезене из {0}: {1}</TimeCodeImportedFromXY>
|
||||
<BeforeInsertSubtitleAtVideoPosition>Пре постављања титла у положај видео записа</BeforeInsertSubtitleAtVideoPosition>
|
||||
@ -975,6 +976,7 @@ C# изворни кôд се налази на интернет страниц
|
||||
</VobSubEditCharacters>
|
||||
<VobSubOcr>
|
||||
<Title>Увожење/препознавање знакова VobSub титла</Title>
|
||||
<TitleBluRay>Увожење/препознавање знакова BluRay титла</TitleBluRay>
|
||||
<OcrMethod>Метода препознавања знакова</OcrMethod>
|
||||
<OcrViaModi>Препознавање знакова путем Microsoft Office Document Imaging (MODI). Захтева MS Office</OcrViaModi>
|
||||
<OcrViaTesseract>Препознавање знакова путем хиперкоцке</OcrViaTesseract>
|
||||
|
Binary file not shown.
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Language Name="Srpski">
|
||||
<General>
|
||||
<Title>Subtitle Edit</Title>
|
||||
@ -370,6 +370,7 @@ E-pošta: mailto:nikse.dk@gmail.com</AboutText1>
|
||||
<Compare>&Uporedi...</Compare>
|
||||
<ImportOcrFromDvd>Uvezi/prepoznaj znakove titla iz VOB/IFO datoteke (DVD)...</ImportOcrFromDvd>
|
||||
<ImportOcrVobSubSubtitle>Uvezi/prepoznaj znakove VobSub titla...</ImportOcrVobSubSubtitle>
|
||||
<ImportBluRaySupFile>Uvezi/prepoznaj znakove BluRay (.sup) titla...</ImportBluRaySupFile>
|
||||
<ImportSubtitleFromMatroskaFile>Uvezi titl iz matroška datoteke...</ImportSubtitleFromMatroskaFile>
|
||||
<ImportSubtitleWithManualChosenEncoding>Uvezi titl s ručno izabranim kodnim rasporedom...</ImportSubtitleWithManualChosenEncoding>
|
||||
<ImportText>Uvezi čist tekst...</ImportText>
|
||||
@ -599,8 +600,7 @@ koji bi trebalo da je već sinhronizovan s video zapisom.
|
||||
<SubtitleAppendPromptTitle>Kačenje titla</SubtitleAppendPromptTitle>
|
||||
<OpenSubtitleToAppend>Otvori titl za kačenje...</OpenSubtitleToAppend>
|
||||
<AppendViaVisualSyncTitle>Vizuelna sinhronizacija — kačenje drugog dela titla</AppendViaVisualSyncTitle>
|
||||
<AppendSynchronizedSubtitlePrompt>
|
||||
</AppendSynchronizedSubtitlePrompt>
|
||||
<AppendSynchronizedSubtitlePrompt>Додај овај синхронизовани титлове?</AppendSynchronizedSubtitlePrompt>
|
||||
<BeforeAppend>Pre kačenja</BeforeAppend>
|
||||
<SubtitleAppendedX>Prikačeno titlova: {0}</SubtitleAppendedX>
|
||||
<SubtitleNotAppended>Titl nije prikačen!</SubtitleNotAppended>
|
||||
@ -671,7 +671,10 @@ koji bi trebalo da je već sinhronizovan s video zapisom.
|
||||
<InvalidVobSubHeader>Zaglavlje nije ispravna VobSub datoteka: {0}</InvalidVobSubHeader>
|
||||
<OpenVobSubFile>Otvaranje VobSub titla...</OpenVobSubFile>
|
||||
<VobSubFiles>VobSub titlovi</VobSubFiles>
|
||||
<OpenBluRaySupFile>Otvaranje BluRay titla...</OpenBluRaySupFile>
|
||||
<BluRaySupFiles>BluRay (.sup) titlovi</BluRaySupFiles>
|
||||
<BeforeImportingVobSubFile>Pre uvoza VobSub titla</BeforeImportingVobSubFile>
|
||||
<BeforeImportingBluRaySupFile>Pre uvoza BluRay titla</BeforeImportingBluRaySupFile>
|
||||
<BeforeShowSelectedLinesEarlierLater>Pre prikazivanja izabrane linije ranije/kasnije</BeforeShowSelectedLinesEarlierLater>
|
||||
<ShowSelectedLinesEarlierLaterPerformed>Prikaži izabrane linije ranije ili kasnije</ShowSelectedLinesEarlierLaterPerformed>
|
||||
<DoubleWordsViaRegEx>Duple reči putem regeksa {0}</DoubleWordsViaRegEx>
|
||||
@ -694,10 +697,8 @@ koji bi trebalo da je već sinhronizovan s video zapisom.
|
||||
<XMinimumDisplayTimeBetweenParagraphsChanged>Izmenjeno broja linija s minimalnim vremenom prikaza između pasusa: {0}</XMinimumDisplayTimeBetweenParagraphsChanged>
|
||||
<BeforeImportText>Pre uvoza čistog teksta</BeforeImportText>
|
||||
<TextImported>Tekst je uvezen</TextImported>
|
||||
<BeforePointSynchronization>
|
||||
</BeforePointSynchronization>
|
||||
<PointSynchronizationDone>
|
||||
</PointSynchronizationDone>
|
||||
<BeforePointSynchronization>Пре тачка синхронизације</BeforePointSynchronization>
|
||||
<PointSynchronizationDone>Тачка синхронизације урадити</PointSynchronizationDone>
|
||||
<BeforeTimeCodeImport>Pre uvoza vremenskih odrednica</BeforeTimeCodeImport>
|
||||
<TimeCodeImportedFromXY>Vremenske odrednice su uvezene iz {0}: {1}</TimeCodeImportedFromXY>
|
||||
<BeforeInsertSubtitleAtVideoPosition>Pre postavljanja titla u položaj video zapisa</BeforeInsertSubtitleAtVideoPosition>
|
||||
@ -975,6 +976,7 @@ koji bi trebalo da je već sinhronizovan s video zapisom.
|
||||
</VobSubEditCharacters>
|
||||
<VobSubOcr>
|
||||
<Title>Uvoženje/prepoznavanje znakova VobSub titla</Title>
|
||||
<TitleBluRay>Uvoženje/prepoznavanje znakova BluRay titla</TitleBluRay>
|
||||
<OcrMethod>Metoda prepoznavanja znakova</OcrMethod>
|
||||
<OcrViaModi>Prepoznavanje znakova putem Microsoft Office Document Imaging (MODI). Zahteva MS Office</OcrViaModi>
|
||||
<OcrViaTesseract>Prepoznavanje znakova putem hiperkocke</OcrViaTesseract>
|
||||
|
Binary file not shown.
@ -371,6 +371,7 @@
|
||||
<Compare>&Jämför...</Compare>
|
||||
<ImportOcrFromDvd>Importera/OCR textning från VOB/IFO (DVD) ...</ImportOcrFromDvd>
|
||||
<ImportOcrVobSubSubtitle>Importera/OCR VobSub (sub/idx) undertext...</ImportOcrVobSubSubtitle>
|
||||
<ImportBluRaySupFile>Importera/OCR BluRay (.sup) undertext...</ImportBluRaySupFile>
|
||||
<ImportSubtitleFromMatroskaFile>Importera undertext från Matroska fil...</ImportSubtitleFromMatroskaFile>
|
||||
<ImportSubtitleWithManualChosenEncoding>Importera undertext med manuell valda kodningen...</ImportSubtitleWithManualChosenEncoding>
|
||||
<ImportText>Importera enbart text...</ImportText>
|
||||
@ -671,7 +672,10 @@
|
||||
<InvalidVobSubHeader>Rubrik inte giltigt VobSub fil: {0}</InvalidVobSubHeader>
|
||||
<OpenVobSubFile>Öppna VobSub (sub/idx) undertext...</OpenVobSubFile>
|
||||
<VobSubFiles>VobSub undertext filer</VobSubFiles>
|
||||
<OpenBluRaySupFile>Öppna BluRay (.sup) undertext...</OpenBluRaySupFile>
|
||||
<BluRaySupFiles>BluRay undertext filer</BluRaySupFiles>
|
||||
<BeforeImportingVobSubFile>Innan du importerar VobSub undertext</BeforeImportingVobSubFile>
|
||||
<BeforeImportingBluRaySupFile>Innan du importerar BluRay undertext</BeforeImportingBluRaySupFile>
|
||||
<BeforeShowSelectedLinesEarlierLater>Före visa valda rader tidigare/senare</BeforeShowSelectedLinesEarlierLater>
|
||||
<ShowSelectedLinesEarlierLaterPerformed>Visa tidigare/senare utförs på utvalda rader</ShowSelectedLinesEarlierLaterPerformed>
|
||||
<DoubleWordsViaRegEx>Dubbel ord via regex {0}</DoubleWordsViaRegEx>
|
||||
@ -973,6 +977,7 @@
|
||||
</VobSubEditCharacters>
|
||||
<VobSubOcr>
|
||||
<Title>Import/OCR VobSub (sub/idx) undertext</Title>
|
||||
<TitleBluRay>Import/OCR BluRay (.sup) undertext</TitleBluRay>
|
||||
<OcrMethod>OCR-metod</OcrMethod>
|
||||
<OcrViaModi>OCR via Microsoft Office Document Imaging (MODI). Kräver MS Office</OcrViaModi>
|
||||
<OcrViaTesseract>OCR via Tesseract</OcrViaTesseract>
|
||||
|
Binary file not shown.
@ -369,6 +369,11 @@
|
||||
<Compile Include="Forms\VobSubOcrNewFolder.Designer.cs">
|
||||
<DependentUpon>VobSubOcrNewFolder.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Logic\BluRaySup\BluRaySupPalette.cs" />
|
||||
<Compile Include="Logic\BluRaySup\BluRaySupParser.cs" />
|
||||
<Compile Include="Logic\BluRaySup\BluRaySupPicture.cs" />
|
||||
<Compile Include="Logic\BluRaySup\Core.cs" />
|
||||
<Compile Include="Logic\BluRaySup\ToolBox.cs" />
|
||||
<Compile Include="Logic\DetectEncoding\EncodingTools.cs" />
|
||||
<Compile Include="Logic\DetectEncoding\Multilang\CMLangConvertCharset.cs" />
|
||||
<Compile Include="Logic\DetectEncoding\Multilang\CMLangConvertCharsetClass.cs" />
|
||||
@ -436,6 +441,8 @@
|
||||
<Compile Include="Logic\SubtitleFormats\Ebu.cs" />
|
||||
<Compile Include="Logic\SubtitleFormats\SonyDVDArchitect.cs" />
|
||||
<Compile Include="Logic\SubtitleFormats\Spruce.cs" />
|
||||
<Compile Include="Logic\SubtitleFormats\SubtitleEditorProject.cs" />
|
||||
<Compile Include="Logic\SubtitleFormats\UleadSubtitleFormat.cs" />
|
||||
<Compile Include="Logic\SubtitleFormats\UnknownSubtitle5.cs" />
|
||||
<Compile Include="Logic\SubtitleFormats\OpenDvt.cs" />
|
||||
<Compile Include="Logic\SubtitleFormats\YouTubeSbv.cs" />
|
||||
@ -670,7 +677,7 @@
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<EmbeddedResource Include="Resources\da-DK.xml.zip" />
|
||||
<None Include="Resources\es-ES.xml.zip" />
|
||||
<EmbeddedResource Include="Resources\es-ES.xml.zip" />
|
||||
<EmbeddedResource Include="Resources\pl-PL.xml.zip" />
|
||||
<EmbeddedResource Include="Resources\ro-RO.xml.zip" />
|
||||
<EmbeddedResource Include="Resources\sr-Cyrl-CS.xml.zip" />
|
||||
|
Loading…
Reference in New Issue
Block a user