mirror of
https://github.com/SubtitleEdit/subtitleedit.git
synced 2024-10-27 22:42:38 +01:00
Added fps and bottom margin to export bluraysup/bdn xml
git-svn-id: https://subtitleedit.googlecode.com/svn/trunk@1042 99eadd0c-20b8-1223-b5c4-2a2b2df33de2
This commit is contained in:
parent
17f4b29f56
commit
bafd53ebc8
125
src/Forms/ExportPngXml.Designer.cs
generated
125
src/Forms/ExportPngXml.Designer.cs
generated
@ -34,6 +34,8 @@
|
||||
this.folderBrowserDialog1 = new System.Windows.Forms.FolderBrowserDialog();
|
||||
this.progressBar1 = new System.Windows.Forms.ProgressBar();
|
||||
this.groupBoxImageSettings = new System.Windows.Forms.GroupBox();
|
||||
this.labelLanguage = new System.Windows.Forms.Label();
|
||||
this.comboBoxLanguage = new System.Windows.Forms.ComboBox();
|
||||
this.labelImageFormat = new System.Windows.Forms.Label();
|
||||
this.comboBoxImageFormat = new System.Windows.Forms.ComboBox();
|
||||
this.checkBoxBold = new System.Windows.Forms.CheckBox();
|
||||
@ -55,9 +57,11 @@
|
||||
this.colorDialog1 = new System.Windows.Forms.ColorDialog();
|
||||
this.labelImageResolution = new System.Windows.Forms.Label();
|
||||
this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog();
|
||||
this.labelLanguage = new System.Windows.Forms.Label();
|
||||
this.comboBoxLanguage = new System.Windows.Forms.ComboBox();
|
||||
this.comboBoxFramerate = new System.Windows.Forms.ComboBox();
|
||||
this.labelFrameRate = new System.Windows.Forms.Label();
|
||||
this.subtitleListView1 = new Nikse.SubtitleEdit.Controls.SubtitleListView();
|
||||
this.comboBoxBottomMargin = new System.Windows.Forms.ComboBox();
|
||||
this.labelBottomMargin = new System.Windows.Forms.Label();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
|
||||
this.groupBoxImageSettings.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
@ -67,9 +71,9 @@
|
||||
this.pictureBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.pictureBox1.Location = new System.Drawing.Point(12, 375);
|
||||
this.pictureBox1.Location = new System.Drawing.Point(12, 399);
|
||||
this.pictureBox1.Name = "pictureBox1";
|
||||
this.pictureBox1.Size = new System.Drawing.Size(712, 181);
|
||||
this.pictureBox1.Size = new System.Drawing.Size(712, 249);
|
||||
this.pictureBox1.TabIndex = 1;
|
||||
this.pictureBox1.TabStop = false;
|
||||
//
|
||||
@ -77,7 +81,7 @@
|
||||
//
|
||||
this.buttonExport.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.buttonExport.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||
this.buttonExport.Location = new System.Drawing.Point(517, 562);
|
||||
this.buttonExport.Location = new System.Drawing.Point(517, 654);
|
||||
this.buttonExport.Name = "buttonExport";
|
||||
this.buttonExport.Size = new System.Drawing.Size(126, 21);
|
||||
this.buttonExport.TabIndex = 2;
|
||||
@ -90,7 +94,7 @@
|
||||
this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.buttonCancel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||
this.buttonCancel.Location = new System.Drawing.Point(649, 562);
|
||||
this.buttonCancel.Location = new System.Drawing.Point(649, 654);
|
||||
this.buttonCancel.Name = "buttonCancel";
|
||||
this.buttonCancel.Size = new System.Drawing.Size(75, 21);
|
||||
this.buttonCancel.TabIndex = 3;
|
||||
@ -101,7 +105,7 @@
|
||||
//
|
||||
this.progressBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.progressBar1.Location = new System.Drawing.Point(12, 562);
|
||||
this.progressBar1.Location = new System.Drawing.Point(12, 654);
|
||||
this.progressBar1.Name = "progressBar1";
|
||||
this.progressBar1.Size = new System.Drawing.Size(499, 21);
|
||||
this.progressBar1.TabIndex = 20;
|
||||
@ -111,6 +115,10 @@
|
||||
//
|
||||
this.groupBoxImageSettings.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.groupBoxImageSettings.Controls.Add(this.comboBoxBottomMargin);
|
||||
this.groupBoxImageSettings.Controls.Add(this.labelBottomMargin);
|
||||
this.groupBoxImageSettings.Controls.Add(this.labelFrameRate);
|
||||
this.groupBoxImageSettings.Controls.Add(this.comboBoxFramerate);
|
||||
this.groupBoxImageSettings.Controls.Add(this.labelLanguage);
|
||||
this.groupBoxImageSettings.Controls.Add(this.comboBoxLanguage);
|
||||
this.groupBoxImageSettings.Controls.Add(this.labelImageFormat);
|
||||
@ -133,14 +141,42 @@
|
||||
this.groupBoxImageSettings.Controls.Add(this.buttonColor);
|
||||
this.groupBoxImageSettings.Location = new System.Drawing.Point(12, 218);
|
||||
this.groupBoxImageSettings.Name = "groupBoxImageSettings";
|
||||
this.groupBoxImageSettings.Size = new System.Drawing.Size(712, 137);
|
||||
this.groupBoxImageSettings.Size = new System.Drawing.Size(712, 161);
|
||||
this.groupBoxImageSettings.TabIndex = 1;
|
||||
this.groupBoxImageSettings.TabStop = false;
|
||||
this.groupBoxImageSettings.Text = "Image settings";
|
||||
//
|
||||
// labelLanguage
|
||||
//
|
||||
this.labelLanguage.Location = new System.Drawing.Point(421, 108);
|
||||
this.labelLanguage.Name = "labelLanguage";
|
||||
this.labelLanguage.RightToLeft = System.Windows.Forms.RightToLeft.No;
|
||||
this.labelLanguage.Size = new System.Drawing.Size(110, 13);
|
||||
this.labelLanguage.TabIndex = 30;
|
||||
this.labelLanguage.Text = "Language";
|
||||
this.labelLanguage.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
this.labelLanguage.Visible = false;
|
||||
//
|
||||
// comboBoxLanguage
|
||||
//
|
||||
this.comboBoxLanguage.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.comboBoxLanguage.FormattingEnabled = true;
|
||||
this.comboBoxLanguage.Items.AddRange(new object[] {
|
||||
"Bmp",
|
||||
"Exif",
|
||||
"Gif",
|
||||
"Jpg",
|
||||
"Png",
|
||||
"Tiff"});
|
||||
this.comboBoxLanguage.Location = new System.Drawing.Point(537, 105);
|
||||
this.comboBoxLanguage.Name = "comboBoxLanguage";
|
||||
this.comboBoxLanguage.Size = new System.Drawing.Size(121, 21);
|
||||
this.comboBoxLanguage.TabIndex = 29;
|
||||
this.comboBoxLanguage.Visible = false;
|
||||
//
|
||||
// labelImageFormat
|
||||
//
|
||||
this.labelImageFormat.Location = new System.Drawing.Point(416, 81);
|
||||
this.labelImageFormat.Location = new System.Drawing.Point(421, 81);
|
||||
this.labelImageFormat.Name = "labelImageFormat";
|
||||
this.labelImageFormat.RightToLeft = System.Windows.Forms.RightToLeft.No;
|
||||
this.labelImageFormat.Size = new System.Drawing.Size(110, 13);
|
||||
@ -167,7 +203,7 @@
|
||||
// checkBoxBold
|
||||
//
|
||||
this.checkBoxBold.AutoSize = true;
|
||||
this.checkBoxBold.Location = new System.Drawing.Point(276, 59);
|
||||
this.checkBoxBold.Location = new System.Drawing.Point(276, 53);
|
||||
this.checkBoxBold.Name = "checkBoxBold";
|
||||
this.checkBoxBold.Size = new System.Drawing.Size(47, 17);
|
||||
this.checkBoxBold.TabIndex = 5;
|
||||
@ -231,7 +267,7 @@
|
||||
this.checkBoxAntiAlias.AutoSize = true;
|
||||
this.checkBoxAntiAlias.Checked = true;
|
||||
this.checkBoxAntiAlias.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.checkBoxAntiAlias.Location = new System.Drawing.Point(276, 86);
|
||||
this.checkBoxAntiAlias.Location = new System.Drawing.Point(276, 76);
|
||||
this.checkBoxAntiAlias.Name = "checkBoxAntiAlias";
|
||||
this.checkBoxAntiAlias.Size = new System.Drawing.Size(66, 17);
|
||||
this.checkBoxAntiAlias.TabIndex = 6;
|
||||
@ -345,7 +381,7 @@
|
||||
//
|
||||
// labelBorderWidth
|
||||
//
|
||||
this.labelBorderWidth.Location = new System.Drawing.Point(416, 55);
|
||||
this.labelBorderWidth.Location = new System.Drawing.Point(421, 54);
|
||||
this.labelBorderWidth.Name = "labelBorderWidth";
|
||||
this.labelBorderWidth.RightToLeft = System.Windows.Forms.RightToLeft.No;
|
||||
this.labelBorderWidth.Size = new System.Drawing.Size(110, 13);
|
||||
@ -412,40 +448,31 @@
|
||||
//
|
||||
this.labelImageResolution.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.labelImageResolution.BackColor = System.Drawing.Color.Transparent;
|
||||
this.labelImageResolution.Location = new System.Drawing.Point(651, 358);
|
||||
this.labelImageResolution.Location = new System.Drawing.Point(651, 382);
|
||||
this.labelImageResolution.Name = "labelImageResolution";
|
||||
this.labelImageResolution.Size = new System.Drawing.Size(73, 14);
|
||||
this.labelImageResolution.TabIndex = 22;
|
||||
this.labelImageResolution.Text = "320x240";
|
||||
this.labelImageResolution.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||
//
|
||||
// labelLanguage
|
||||
// comboBoxFramerate
|
||||
//
|
||||
this.labelLanguage.Location = new System.Drawing.Point(416, 108);
|
||||
this.labelLanguage.Name = "labelLanguage";
|
||||
this.labelLanguage.RightToLeft = System.Windows.Forms.RightToLeft.No;
|
||||
this.labelLanguage.Size = new System.Drawing.Size(110, 13);
|
||||
this.labelLanguage.TabIndex = 30;
|
||||
this.labelLanguage.Text = "Language";
|
||||
this.labelLanguage.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
this.labelLanguage.Visible = false;
|
||||
this.comboBoxFramerate.FormattingEnabled = true;
|
||||
this.comboBoxFramerate.Location = new System.Drawing.Point(537, 134);
|
||||
this.comboBoxFramerate.Name = "comboBoxFramerate";
|
||||
this.comboBoxFramerate.Size = new System.Drawing.Size(121, 21);
|
||||
this.comboBoxFramerate.TabIndex = 33;
|
||||
//
|
||||
// comboBoxLanguage
|
||||
// labelFrameRate
|
||||
//
|
||||
this.comboBoxLanguage.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.comboBoxLanguage.FormattingEnabled = true;
|
||||
this.comboBoxLanguage.Items.AddRange(new object[] {
|
||||
"Bmp",
|
||||
"Exif",
|
||||
"Gif",
|
||||
"Jpg",
|
||||
"Png",
|
||||
"Tiff"});
|
||||
this.comboBoxLanguage.Location = new System.Drawing.Point(537, 105);
|
||||
this.comboBoxLanguage.Name = "comboBoxLanguage";
|
||||
this.comboBoxLanguage.Size = new System.Drawing.Size(121, 21);
|
||||
this.comboBoxLanguage.TabIndex = 29;
|
||||
this.comboBoxLanguage.Visible = false;
|
||||
this.labelFrameRate.Location = new System.Drawing.Point(421, 137);
|
||||
this.labelFrameRate.Name = "labelFrameRate";
|
||||
this.labelFrameRate.RightToLeft = System.Windows.Forms.RightToLeft.No;
|
||||
this.labelFrameRate.Size = new System.Drawing.Size(110, 13);
|
||||
this.labelFrameRate.TabIndex = 34;
|
||||
this.labelFrameRate.Text = "Frame rate";
|
||||
this.labelFrameRate.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
this.labelFrameRate.Visible = false;
|
||||
//
|
||||
// subtitleListView1
|
||||
//
|
||||
@ -464,11 +491,29 @@
|
||||
this.subtitleListView1.View = System.Windows.Forms.View.Details;
|
||||
this.subtitleListView1.SelectedIndexChanged += new System.EventHandler(this.subtitleListView1_SelectedIndexChanged);
|
||||
//
|
||||
// comboBoxBottomMargin
|
||||
//
|
||||
this.comboBoxBottomMargin.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.comboBoxBottomMargin.FormattingEnabled = true;
|
||||
this.comboBoxBottomMargin.Location = new System.Drawing.Point(100, 132);
|
||||
this.comboBoxBottomMargin.Name = "comboBoxBottomMargin";
|
||||
this.comboBoxBottomMargin.Size = new System.Drawing.Size(121, 21);
|
||||
this.comboBoxBottomMargin.TabIndex = 35;
|
||||
//
|
||||
// labelBottomMargin
|
||||
//
|
||||
this.labelBottomMargin.AutoSize = true;
|
||||
this.labelBottomMargin.Location = new System.Drawing.Point(10, 135);
|
||||
this.labelBottomMargin.Name = "labelBottomMargin";
|
||||
this.labelBottomMargin.Size = new System.Drawing.Size(74, 13);
|
||||
this.labelBottomMargin.TabIndex = 36;
|
||||
this.labelBottomMargin.Text = "Bottom margin";
|
||||
//
|
||||
// ExportPngXml
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(730, 588);
|
||||
this.ClientSize = new System.Drawing.Size(730, 680);
|
||||
this.Controls.Add(this.labelImageResolution);
|
||||
this.Controls.Add(this.groupBoxImageSettings);
|
||||
this.Controls.Add(this.progressBar1);
|
||||
@ -524,5 +569,9 @@
|
||||
private System.Windows.Forms.ComboBox comboBoxImageFormat;
|
||||
private System.Windows.Forms.Label labelLanguage;
|
||||
private System.Windows.Forms.ComboBox comboBoxLanguage;
|
||||
private System.Windows.Forms.Label labelFrameRate;
|
||||
private System.Windows.Forms.ComboBox comboBoxFramerate;
|
||||
private System.Windows.Forms.ComboBox comboBoxBottomMargin;
|
||||
private System.Windows.Forms.Label labelBottomMargin;
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Text;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
@ -19,7 +20,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
private class MakeBitmapParameter
|
||||
{
|
||||
public Bitmap Bitmap { get; set; }
|
||||
public Paragraph P { get; set; }
|
||||
public Paragraph P { get; set; }
|
||||
public string Type { get; set; }
|
||||
public Color SubtitleColor { get; set; }
|
||||
public string SubtitleFontName { get; set; }
|
||||
@ -33,19 +34,21 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
public byte[] Buffer { get; set; }
|
||||
public int ScreenWidth { get; set; }
|
||||
public int ScreenHeight { get; set; }
|
||||
public double FramesPerSeconds { get; set; }
|
||||
public int BottomMargin { get; set; }
|
||||
public bool Saved { get; set; }
|
||||
}
|
||||
|
||||
Subtitle _subtitle;
|
||||
Color _subtitleColor = Color.White;
|
||||
string _subtitleFontName = "Verdana";
|
||||
float _subtitleFontSize = 75.0f;
|
||||
bool _subtitleFontBold = false;
|
||||
Color _borderColor = Color.Black;
|
||||
float _borderWidth = 2.0f;
|
||||
bool _isLoading = true;
|
||||
string _exportType = "BDNXML";
|
||||
string _fileName;
|
||||
private Subtitle _subtitle;
|
||||
private Color _subtitleColor = Color.White;
|
||||
private string _subtitleFontName = "Verdana";
|
||||
private float _subtitleFontSize = 75.0f;
|
||||
private bool _subtitleFontBold = false;
|
||||
private Color _borderColor = Color.Black;
|
||||
private float _borderWidth = 2.0f;
|
||||
private bool _isLoading = true;
|
||||
private string _exportType = "BDNXML";
|
||||
private string _fileName;
|
||||
|
||||
public ExportPngXml()
|
||||
{
|
||||
@ -53,9 +56,25 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
comboBoxImageFormat.SelectedIndex = 4;
|
||||
}
|
||||
|
||||
private static string BdnXmlTimeCode(TimeCode timecode)
|
||||
private double FrameRate
|
||||
{
|
||||
int frames = timecode.Milliseconds / 40; // 40==25fps (1000/25)
|
||||
get
|
||||
{
|
||||
if (comboBoxFramerate.SelectedItem == null)
|
||||
return 25;
|
||||
|
||||
string s = comboBoxFramerate.SelectedItem.ToString();
|
||||
s = s.Replace(",", ".").Trim();
|
||||
double d;
|
||||
if (double.TryParse(s, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out d))
|
||||
return d;
|
||||
return 25;
|
||||
}
|
||||
}
|
||||
|
||||
private string BdnXmlTimeCode(TimeCode timecode)
|
||||
{
|
||||
int frames = (int)Math.Round(timecode.Milliseconds / (1000.0 / FrameRate));
|
||||
return string.Format("{0:00}:{1:00}:{2:00}:{3:00}", timecode.Hours, timecode.Minutes, timecode.Seconds, frames);
|
||||
}
|
||||
|
||||
@ -72,7 +91,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
Width = paramter.ScreenWidth,
|
||||
Height = paramter.ScreenHeight
|
||||
};
|
||||
paramter.Buffer = Logic.BluRaySup.BluRaySupPicture.CreateSupFrame(brSub, paramter.Bitmap);
|
||||
paramter.Buffer = Logic.BluRaySup.BluRaySupPicture.CreateSupFrame(brSub, paramter.Bitmap, paramter.FramesPerSeconds, paramter.BottomMargin);
|
||||
}
|
||||
else if (paramter.Type == "VOBSUB")
|
||||
{
|
||||
@ -101,6 +120,8 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
ScreenWidth = screenWidth,
|
||||
ScreenHeight = screenHeight,
|
||||
Bitmap = null,
|
||||
FramesPerSeconds = FrameRate,
|
||||
BottomMargin = comboBoxBottomMargin.SelectedIndex,
|
||||
Saved = false,
|
||||
};
|
||||
if (index < _subtitle.Paragraphs.Count)
|
||||
@ -197,13 +218,13 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
if (_exportType == "BLURAYSUP")
|
||||
binarySubtitleFile = new FileStream(saveFileDialog1.FileName, FileMode.Create);
|
||||
else if (_exportType == "VOBSUB")
|
||||
vobSubWriter = new VobSubWriter(saveFileDialog1.FileName, width, height, 15, 32, _subtitleColor, _borderColor, GetOutlineColor(_borderColor), IfoParser.ArrayOfLanguage[comboBoxLanguage.SelectedIndex], IfoParser.ArrayOfLanguageCode[comboBoxLanguage.SelectedIndex]);
|
||||
vobSubWriter = new VobSubWriter(saveFileDialog1.FileName, width, height, comboBoxBottomMargin.SelectedIndex, 32, _subtitleColor, _borderColor, GetOutlineColor(_borderColor), IfoParser.ArrayOfLanguage[comboBoxLanguage.SelectedIndex], IfoParser.ArrayOfLanguageCode[comboBoxLanguage.SelectedIndex]);
|
||||
|
||||
progressBar1.Value = 0;
|
||||
progressBar1.Maximum = _subtitle.Paragraphs.Count-1;
|
||||
progressBar1.Visible = true;
|
||||
|
||||
const int border = 25;
|
||||
int border = comboBoxBottomMargin.SelectedIndex;
|
||||
int imagesSavedCount = 0;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
@ -282,6 +303,22 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
}
|
||||
else
|
||||
{
|
||||
string videoFormat = "1080p";
|
||||
if (comboBoxResolution.SelectedIndex == 2)
|
||||
videoFormat = "720p";
|
||||
else if (comboBoxResolution.SelectedIndex == 3)
|
||||
videoFormat = "960x720";
|
||||
else if (comboBoxResolution.SelectedIndex == 4)
|
||||
videoFormat = "480p";
|
||||
else if (comboBoxResolution.SelectedIndex == 5)
|
||||
videoFormat = "720x576";
|
||||
else if (comboBoxResolution.SelectedIndex == 6)
|
||||
videoFormat = "720x480";
|
||||
else if (comboBoxResolution.SelectedIndex == 7)
|
||||
videoFormat = "640x352";
|
||||
else if (comboBoxResolution.SelectedIndex == 8)
|
||||
videoFormat = "640x272";
|
||||
|
||||
var doc = new XmlDocument();
|
||||
Paragraph first = _subtitle.Paragraphs[0];
|
||||
Paragraph last = _subtitle.Paragraphs[_subtitle.Paragraphs.Count - 1];
|
||||
@ -290,7 +327,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
"<Description>" + Environment.NewLine +
|
||||
"<Name Title=\"subtitle_exp\" Content=\"\"/>" + Environment.NewLine +
|
||||
"<Language Code=\"eng\"/>" + Environment.NewLine +
|
||||
"<Format VideoFormat=\"1080p\" FrameRate=\"25\" DropFrame=\"False\"/>" + Environment.NewLine +
|
||||
"<Format VideoFormat=\""+videoFormat + "\" FrameRate=\""+ FrameRate.ToString(CultureInfo.InvariantCulture) + "\" DropFrame=\"False\"/>" + Environment.NewLine +
|
||||
"<Events Type=\"Graphic\" FirstEventInTC=\"" + BdnXmlTimeCode(first.StartTime) + "\" LastEventOutTC=\"" + BdnXmlTimeCode(last.EndTime) + "\" NumberofEvents=\"" + imagesSavedCount.ToString() + "\"/>" + Environment.NewLine +
|
||||
"</Description>" + Environment.NewLine +
|
||||
"<Events>" + Environment.NewLine +
|
||||
@ -329,7 +366,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
{
|
||||
string numberString = string.Format("IMAGE{0:000}", i);
|
||||
string fileName = Path.Combine(folderBrowserDialog1.SelectedPath, numberString + "." + comboBoxImageFormat.Text.ToLower());
|
||||
var imageFormat = System.Drawing.Imaging.ImageFormat.Png; ;
|
||||
var imageFormat = System.Drawing.Imaging.ImageFormat.Png;
|
||||
if (comboBoxImageFormat.SelectedIndex == 0)
|
||||
imageFormat = System.Drawing.Imaging.ImageFormat.Bmp;
|
||||
else if (comboBoxImageFormat.SelectedIndex == 1)
|
||||
@ -383,9 +420,8 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
private string FormatFabTime(TimeCode time, MakeBitmapParameter param)
|
||||
{
|
||||
if (param.Bitmap.Width == 720 && param.Bitmap.Width == 480) // NTSC
|
||||
return string.Format("{0:00};{1:00};{2:00};{3:00}", time.Hours, time.Minutes, time.Seconds, Nikse.SubtitleEdit.Logic.SubtitleFormats.SubtitleFormat.MillisecondsToFrames(time.Milliseconds));
|
||||
else
|
||||
return string.Format("{0:00}:{1:00}:{2:00}:{3:00}", time.Hours, time.Minutes, time.Seconds, Nikse.SubtitleEdit.Logic.SubtitleFormats.SubtitleFormat.MillisecondsToFrames(time.Milliseconds));
|
||||
return string.Format("{0:00};{1:00};{2:00};{3:00}", time.Hours, time.Minutes, time.Seconds, Logic.SubtitleFormats.SubtitleFormat.MillisecondsToFrames(time.Milliseconds));
|
||||
return string.Format("{0:00}:{1:00}:{2:00}:{3:00}", time.Hours, time.Minutes, time.Seconds, Logic.SubtitleFormats.SubtitleFormat.MillisecondsToFrames(time.Milliseconds));
|
||||
}
|
||||
|
||||
private void SetupImageParameters()
|
||||
@ -410,7 +446,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
|
||||
private Bitmap GenerateImageFromTextWithStyle(string text)
|
||||
{
|
||||
MakeBitmapParameter mbp = new MakeBitmapParameter();
|
||||
var mbp = new MakeBitmapParameter();
|
||||
mbp.AlignLeft = comboBoxHAlign.SelectedIndex == 0;
|
||||
mbp.AlignRight = comboBoxHAlign.SelectedIndex == 2;
|
||||
mbp.AntiAlias = checkBoxAntiAlias.Checked;
|
||||
@ -425,7 +461,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
var bmp = GenerateImageFromTextWithStyle(mbp);
|
||||
if (_exportType == "VOBSUB")
|
||||
{
|
||||
NikseBitmap nbmp = new NikseBitmap(bmp);
|
||||
var nbmp = new NikseBitmap(bmp);
|
||||
nbmp.ConverToFourColors(Color.Transparent, _subtitleColor, _borderColor, GetOutlineColor(_borderColor));
|
||||
bmp = nbmp.GetBitmap();
|
||||
}
|
||||
@ -434,9 +470,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
|
||||
private static float MeasureTextWidth(Font font, string text, bool bold)
|
||||
{
|
||||
var sf = new StringFormat();
|
||||
sf.Alignment = StringAlignment.Near;
|
||||
sf.LineAlignment = StringAlignment.Near;
|
||||
var sf = new StringFormat {Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Near};
|
||||
var path = new GraphicsPath();
|
||||
|
||||
var sb = new StringBuilder(text);
|
||||
@ -515,7 +549,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
if (parameter.AlignLeft)
|
||||
lefts.Add(5);
|
||||
else if (parameter.AlignRight)
|
||||
lefts.Add((float)(bmp.Width - (MeasureTextWidth(font, line, parameter.SubtitleFontBold) + 15)));
|
||||
lefts.Add(bmp.Width - (MeasureTextWidth(font, line, parameter.SubtitleFontBold) + 15));
|
||||
else
|
||||
lefts.Add((float)(bmp.Width - g.MeasureString(line, font).Width * 0.8+15) / 2);
|
||||
}
|
||||
@ -654,6 +688,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
buttonCancel.Text = Configuration.Settings.Language.General.OK;
|
||||
labelImageResolution.Text = string.Empty;
|
||||
labelLanguage.Text = Configuration.Settings.Language.ChooseLanguage.Language;
|
||||
labelFrameRate.Text = Configuration.Settings.Language.General.FrameRate;
|
||||
labelHorizontalAlign.Text = Configuration.Settings.Language.ExportPngXml.Align;
|
||||
if (Configuration.Settings.Language.ExportPngXml.Left != null &&
|
||||
Configuration.Settings.Language.ExportPngXml.Center != null &&
|
||||
@ -694,6 +729,49 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
}
|
||||
comboBoxImageFormat.Visible = exportType == "FAB";
|
||||
labelImageFormat.Visible = exportType == "FAB";
|
||||
labelFrameRate.Visible = exportType == "BDNXML" || exportType == "BLURAYSUP";
|
||||
comboBoxFramerate.Visible = exportType == "BDNXML" || exportType == "BLURAYSUP";
|
||||
if (exportType == "BDNXML")
|
||||
{
|
||||
labelFrameRate.Top = labelLanguage.Top;
|
||||
comboBoxFramerate.Top = comboBoxLanguage.Top;
|
||||
comboBoxFramerate.Items.Add("23.976");
|
||||
comboBoxFramerate.Items.Add("24");
|
||||
comboBoxFramerate.Items.Add("25");
|
||||
comboBoxFramerate.Items.Add("29.97");
|
||||
comboBoxFramerate.Items.Add("50");
|
||||
comboBoxFramerate.Items.Add("59.94");
|
||||
comboBoxFramerate.SelectedIndex = 2;
|
||||
}
|
||||
else if (exportType == "BLURAYSUP")
|
||||
{
|
||||
labelFrameRate.Top = labelLanguage.Top;
|
||||
comboBoxFramerate.Top = comboBoxLanguage.Top;
|
||||
comboBoxFramerate.Items.Add("23.976");
|
||||
comboBoxFramerate.Items.Add("24");
|
||||
comboBoxFramerate.Items.Add("25");
|
||||
comboBoxFramerate.Items.Add("29.97");
|
||||
comboBoxFramerate.Items.Add("50");
|
||||
comboBoxFramerate.Items.Add("59.94");
|
||||
comboBoxFramerate.SelectedIndex = 1;
|
||||
comboBoxFramerate.DropDownStyle = ComboBoxStyle.DropDownList;
|
||||
}
|
||||
|
||||
for (int i=0; i<1000; i++)
|
||||
comboBoxBottomMargin.Items.Add(i);
|
||||
comboBoxBottomMargin.SelectedIndex = 15;
|
||||
if (exportType == "BLURAYSUP")
|
||||
comboBoxBottomMargin.SelectedIndex = 20;
|
||||
if (_exportType == "BLURAYSUP" || _exportType == "VOBSUB")
|
||||
{
|
||||
comboBoxBottomMargin.Visible = true;
|
||||
labelBottomMargin.Visible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
comboBoxBottomMargin.Visible = false;
|
||||
labelBottomMargin.Visible = false;
|
||||
}
|
||||
|
||||
foreach (var x in FontFamily.Families)
|
||||
{
|
||||
|
@ -103,7 +103,7 @@ namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
/** 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;
|
||||
|
||||
private static byte[] packetHeader =
|
||||
private static readonly byte[] PacketHeader =
|
||||
{
|
||||
0x50, 0x47, // 0: "PG"
|
||||
0x00, 0x00, 0x00, 0x00, // 2: PTS - presentation time stamp
|
||||
@ -112,7 +112,7 @@ namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
0x00, 0x00, // 11: segment_length (bytes following till next PG)
|
||||
};
|
||||
|
||||
private static byte[] headerPCSStart =
|
||||
private static readonly byte[] HeaderPCSStart =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, // 0: video_width, video_height
|
||||
0x10, // 4: hi nibble: frame_rate (0x10=24p), lo nibble: reserved
|
||||
@ -127,7 +127,7 @@ namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
0x00, 0x00, 0x00, 0x00 // 15: composition_object_horizontal_position, composition_object_vertical_position
|
||||
};
|
||||
|
||||
private static byte[] headerPCSEnd =
|
||||
private static readonly byte[] HeaderPCSEnd =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, // 0: video_width, video_height
|
||||
0x10, // 4: hi nibble: frame_rate (0x10=24p), lo nibble: reserved
|
||||
@ -138,7 +138,7 @@ namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
0x00, // 10: number_of_composition_objects (0..2)
|
||||
};
|
||||
|
||||
private static byte[] headerODSFirst =
|
||||
private static readonly byte[] HeaderODSFirst =
|
||||
{
|
||||
0x00, 0x00, // 0: object_id
|
||||
0x00, // 2: object_version_number
|
||||
@ -147,14 +147,14 @@ namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
0x00, 0x00, 0x00, 0x00, // 7: object_width, object_height
|
||||
};
|
||||
|
||||
private static byte[] headerODSNext =
|
||||
private static readonly byte[] HeaderODSNext =
|
||||
{
|
||||
0x00, 0x00, // 0: object_id
|
||||
0x00, // 2: object_version_number
|
||||
0x40, // 3: first_in_sequence (0x80), last_in_sequence (0x40), 6bits reserved
|
||||
};
|
||||
|
||||
private static byte[] headerWDS =
|
||||
private static readonly byte[] HeaderWds =
|
||||
{
|
||||
0x01, // 0 : number of windows (currently assumed 1, 0..2 is legal)
|
||||
0x00, // 1 : window id (0..1)
|
||||
@ -183,7 +183,7 @@ namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
Palettes = new List<List<PaletteInfo>>();
|
||||
foreach (List<PaletteInfo> palette in subPicture.Palettes)
|
||||
{
|
||||
List<PaletteInfo> p = new List<PaletteInfo>();
|
||||
var p = new List<PaletteInfo>();
|
||||
foreach (PaletteInfo pi in palette)
|
||||
{
|
||||
p.Add(new PaletteInfo(pi));
|
||||
@ -210,22 +210,18 @@ namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
System.Diagnostics.Debug.WriteLine("Invalid Blu-ray SupPicture - ImageObjects is null - BluRaySupPictures.cs: internal ImageObject ObjectIdImage");
|
||||
return null;
|
||||
}
|
||||
else if (ObjectId < ImageObjects.Count)
|
||||
if (ObjectId < ImageObjects.Count)
|
||||
{
|
||||
return ImageObjects[ObjectId];
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("Invalid Blu-ray SupPicture index - BluRaySupPictures.cs: internal ImageObject ObjectIdImage");
|
||||
return ImageObjects[ImageObjects.Count - 1];
|
||||
}
|
||||
System.Diagnostics.Debug.WriteLine("Invalid Blu-ray SupPicture index - BluRaySupPictures.cs: internal ImageObject ObjectIdImage");
|
||||
return ImageObjects[ImageObjects.Count - 1];
|
||||
}
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
@ -240,7 +236,7 @@ namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
return new BluRaySupPalette(defaultPalette);
|
||||
}
|
||||
List<PaletteInfo> pl = pic.Palettes[pic.ObjectIdImage.PaletteId];
|
||||
BluRaySupPalette palette = new BluRaySupPalette(256, Core.UsesBt601());
|
||||
var palette = new BluRaySupPalette(256, Core.UsesBt601());
|
||||
// by definition, index 0xff is always completely transparent
|
||||
// also all entries must be fully transparent after initialization
|
||||
|
||||
@ -296,8 +292,6 @@ namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
/// <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)
|
||||
{
|
||||
@ -311,7 +305,7 @@ namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
throw new Exception("Subpicture too large: " + w + "x" + h);
|
||||
|
||||
//Bitmap bm = new Bitmap(w, h);
|
||||
FastBitmap bm = new FastBitmap(new Bitmap(w, h));
|
||||
var bm = new FastBitmap(new Bitmap(w, h));
|
||||
bm.LockImage();
|
||||
BluRaySupPalette pal = DecodePalette(defaultPalette);
|
||||
|
||||
@ -327,7 +321,6 @@ namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
index += fragment.ImagePacketSize;
|
||||
}
|
||||
|
||||
|
||||
index = 0;
|
||||
do
|
||||
{
|
||||
@ -407,7 +400,7 @@ namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
/// <returns>RLE buffer</returns>
|
||||
private static byte[] EncodeImage(Bitmap bm, Dictionary<Color, int> palette)
|
||||
{
|
||||
List<Byte> bytes = new List<Byte>();
|
||||
var bytes = new List<Byte>();
|
||||
byte color = 0;
|
||||
int ofs = 0;
|
||||
int len = 0;
|
||||
@ -505,7 +498,7 @@ namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
|
||||
private static Dictionary<Color, int> GetBitmapPalette(Bitmap bitmap)
|
||||
{
|
||||
Dictionary<Color, int> pal = new Dictionary<Color, int>();
|
||||
var pal = new Dictionary<Color, int>();
|
||||
for (int y = 0; y < bitmap.Height; y++)
|
||||
{
|
||||
for (int x = 0; x < bitmap.Width; x++)
|
||||
@ -524,17 +517,17 @@ namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
/// </summary>
|
||||
/// <param name="fps">frame rate</param>
|
||||
/// <returns>byte ID for the given frame rate</returns>
|
||||
private static int getFpsId(double fps)
|
||||
private static int GetFpsId(double fps)
|
||||
{
|
||||
if (fps == Core.Fps24Hz)
|
||||
return 0x20;
|
||||
if (fps == Core.FpsPal)
|
||||
return 0x30;
|
||||
if (fps == Core.FpsNtsc)
|
||||
if (Math.Abs(fps - Core.FpsNtsc) < 0.05)
|
||||
return 0x40;
|
||||
if (fps == Core.FpsPalI)
|
||||
return 0x60;
|
||||
if (fps == Core.FpsNtscI)
|
||||
if (Math.Abs(fps - Core.FpsNtscI) < 0.05)
|
||||
return 0x70;
|
||||
// assume FPS_24P (also for FPS_23_975)
|
||||
return 0x10;
|
||||
@ -545,13 +538,13 @@ namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
/// </summary>
|
||||
/// <param name="pic">SubPicture object containing caption info</param>
|
||||
/// <param name="bm">bitmap</param>
|
||||
/// <param name="pal">palette</param>
|
||||
/// <param name="fps">frames per second</param>
|
||||
/// <param name="bottomMargin">image bottom margin</param>
|
||||
/// <returns>byte buffer containing the binary stream representation of one caption</returns>
|
||||
public static byte[] CreateSupFrame(BluRaySupPicture pic, Bitmap bm)
|
||||
public static byte[] CreateSupFrame(BluRaySupPicture pic, Bitmap bm, double fps, int bottomMargin)
|
||||
{
|
||||
int size = 0;
|
||||
var colorPalette = GetBitmapPalette(bm);
|
||||
BluRaySupPalette pal = new BluRaySupPalette(colorPalette.Count);
|
||||
var pal = new BluRaySupPalette(colorPalette.Count);
|
||||
int k = 0;
|
||||
foreach (var kvp in colorPalette)
|
||||
{
|
||||
@ -578,16 +571,16 @@ namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
// object frames
|
||||
int palSize = colorPalette.Count;
|
||||
|
||||
size = packetHeader.Length * (8 + numAddPackets);
|
||||
size += headerPCSStart.Length + headerPCSEnd.Length;
|
||||
size += 2 * headerWDS.Length + headerODSFirst.Length;
|
||||
size += numAddPackets * headerODSNext.Length;
|
||||
int size = PacketHeader.Length * (8 + numAddPackets);
|
||||
size += HeaderPCSStart.Length + HeaderPCSEnd.Length;
|
||||
size += 2 * HeaderWds.Length + HeaderODSFirst.Length;
|
||||
size += numAddPackets * HeaderODSNext.Length;
|
||||
size += (2 + palSize * 5) /* PDS */;
|
||||
size += rleBuf.Length;
|
||||
|
||||
pic.WindowXOffset = (pic.Width - bm.Width) / 2;
|
||||
pic.WindowYOffset = pic.Height - (bm.Height + (pic.Height / 12));
|
||||
|
||||
pic.WindowYOffset = pic.Height - (bm.Height + bottomMargin);
|
||||
|
||||
int yOfs = pic.WindowYOffset - Core.CropOfsY;
|
||||
if (yOfs < 0)
|
||||
{
|
||||
@ -603,153 +596,153 @@ namespace Nikse.SubtitleEdit.Logic.BluRaySup
|
||||
int h = pic.Height - 2 * Core.CropOfsY;
|
||||
|
||||
byte[] buf = new byte[size];
|
||||
int index = 0;
|
||||
int index = 0;
|
||||
|
||||
|
||||
int fpsId = getFpsId(Core.fpsTrg);
|
||||
int fpsId = GetFpsId(fps);
|
||||
|
||||
/* time (in 90kHz resolution) needed to initialize (clear) the screen buffer
|
||||
based on the composition pixel rate of 256e6 bit/s - always rounded up */
|
||||
int frameInitTime = (pic.Width * pic.Height * 9 + 3199) / 3200; // better use default height here
|
||||
/* time (in 90kHz resolution) needed to initialize (clear) the window area
|
||||
based on the composition pixel rate of 256e6 bit/s - always rounded up
|
||||
Note: no cropping etc. -> window size == image size */
|
||||
int windowInitTime = (bm.Width * bm.Height * 9 + 3199) / 3200;
|
||||
/* time (in 90kHz resolution) needed to decode the image
|
||||
based on the decoding pixel rate of 128e6 bit/s - always rounded up */
|
||||
int imageDecodeTime = (bm.Width * bm.Height * 9 + 1599) / 1600;
|
||||
// write PCS start
|
||||
packetHeader[10] = 0x16; // ID
|
||||
int dts = pic.StartTimeForWrite - (frameInitTime + windowInitTime);
|
||||
ToolBox.SetDWord(packetHeader, 2, pic.StartTimeForWrite); // PTS
|
||||
ToolBox.SetDWord(packetHeader, 6, dts); // DTS
|
||||
ToolBox.SetWord(packetHeader, 11, headerPCSStart.Length); // size
|
||||
for (int i = 0; i < packetHeader.Length; i++)
|
||||
buf[index++] = packetHeader[i];
|
||||
ToolBox.SetWord(headerPCSStart, 0, pic.Width);
|
||||
ToolBox.SetWord(headerPCSStart, 2, h); // cropped height
|
||||
ToolBox.SetByte(headerPCSStart, 4, fpsId);
|
||||
ToolBox.SetWord(headerPCSStart, 5, pic.CompositionNumber);
|
||||
headerPCSStart[14] = (byte)(pic.IsForced ? 0x40 : 0);
|
||||
ToolBox.SetWord(headerPCSStart, 15, pic.WindowXOffset);
|
||||
ToolBox.SetWord(headerPCSStart, 17, yOfs);
|
||||
for (int i = 0; i < headerPCSStart.Length; i++)
|
||||
buf[index++] = headerPCSStart[i];
|
||||
/* time (in 90kHz resolution) needed to initialize (clear) the screen buffer
|
||||
based on the composition pixel rate of 256e6 bit/s - always rounded up */
|
||||
int frameInitTime = (pic.Width * pic.Height * 9 + 3199) / 3200; // better use default height here
|
||||
/* time (in 90kHz resolution) needed to initialize (clear) the window area
|
||||
based on the composition pixel rate of 256e6 bit/s - always rounded up
|
||||
Note: no cropping etc. -> window size == image size */
|
||||
int windowInitTime = (bm.Width * bm.Height * 9 + 3199) / 3200;
|
||||
/* time (in 90kHz resolution) needed to decode the image
|
||||
based on the decoding pixel rate of 128e6 bit/s - always rounded up */
|
||||
int imageDecodeTime = (bm.Width * bm.Height * 9 + 1599) / 1600;
|
||||
// write PCS start
|
||||
PacketHeader[10] = 0x16; // ID
|
||||
int dts = pic.StartTimeForWrite - (frameInitTime + windowInitTime);
|
||||
ToolBox.SetDWord(PacketHeader, 2, pic.StartTimeForWrite); // PTS
|
||||
ToolBox.SetDWord(PacketHeader, 6, dts); // DTS
|
||||
ToolBox.SetWord(PacketHeader, 11, HeaderPCSStart.Length); // size
|
||||
for (int i = 0; i < PacketHeader.Length; i++)
|
||||
buf[index++] = PacketHeader[i];
|
||||
ToolBox.SetWord(HeaderPCSStart, 0, pic.Width);
|
||||
ToolBox.SetWord(HeaderPCSStart, 2, h); // cropped height
|
||||
ToolBox.SetByte(HeaderPCSStart, 4, fpsId);
|
||||
ToolBox.SetWord(HeaderPCSStart, 5, pic.CompositionNumber);
|
||||
HeaderPCSStart[14] = (byte)(pic.IsForced ? 0x40 : 0);
|
||||
ToolBox.SetWord(HeaderPCSStart, 15, pic.WindowXOffset);
|
||||
ToolBox.SetWord(HeaderPCSStart, 17, yOfs);
|
||||
for (int i = 0; i < HeaderPCSStart.Length; i++)
|
||||
buf[index++] = HeaderPCSStart[i];
|
||||
|
||||
// write WDS
|
||||
packetHeader[10] = 0x17; // ID
|
||||
int timeStamp = pic.StartTimeForWrite - windowInitTime;
|
||||
ToolBox.SetDWord(packetHeader, 2, timeStamp); // PTS (keep DTS)
|
||||
ToolBox.SetWord(packetHeader, 11, headerWDS.Length); // size
|
||||
for (int i = 0; i < packetHeader.Length; i++)
|
||||
buf[index++] = packetHeader[i];
|
||||
ToolBox.SetWord(headerWDS, 2, pic.WindowXOffset);
|
||||
ToolBox.SetWord(headerWDS, 4, yOfs);
|
||||
ToolBox.SetWord(headerWDS, 6, bm.Width);
|
||||
ToolBox.SetWord(headerWDS, 8, bm.Height);
|
||||
for (int i = 0; i < headerWDS.Length; i++)
|
||||
buf[index++] = headerWDS[i];
|
||||
// write WDS
|
||||
PacketHeader[10] = 0x17; // ID
|
||||
int timeStamp = pic.StartTimeForWrite - windowInitTime;
|
||||
ToolBox.SetDWord(PacketHeader, 2, timeStamp); // PTS (keep DTS)
|
||||
ToolBox.SetWord(PacketHeader, 11, HeaderWds.Length); // size
|
||||
for (int i = 0; i < PacketHeader.Length; i++)
|
||||
buf[index++] = PacketHeader[i];
|
||||
ToolBox.SetWord(HeaderWds, 2, pic.WindowXOffset);
|
||||
ToolBox.SetWord(HeaderWds, 4, yOfs);
|
||||
ToolBox.SetWord(HeaderWds, 6, bm.Width);
|
||||
ToolBox.SetWord(HeaderWds, 8, bm.Height);
|
||||
for (int i = 0; i < HeaderWds.Length; i++)
|
||||
buf[index++] = HeaderWds[i];
|
||||
|
||||
// write PDS
|
||||
packetHeader[10] = 0x14; // ID
|
||||
ToolBox.SetDWord(packetHeader, 2, dts); // PTS (=DTS of PCS/WDS)
|
||||
ToolBox.SetDWord(packetHeader, 6, 0); // DTS (0)
|
||||
ToolBox.SetWord(packetHeader, 11, (2 + palSize * 5)); // size
|
||||
for (int i = 0; i < packetHeader.Length; i++)
|
||||
buf[index++] = packetHeader[i];
|
||||
buf[index++] = 0;
|
||||
buf[index++] = 0;
|
||||
for (int i = 0; i < palSize; i++)
|
||||
{
|
||||
buf[index++] = (byte)i; // index
|
||||
buf[index++] = pal.GetY()[i]; // Y
|
||||
buf[index++] = pal.GetCr()[i]; // Cr
|
||||
buf[index++] = pal.GetCb()[i]; // Cb
|
||||
buf[index++] = pal.GetAlpha()[i]; // Alpha
|
||||
}
|
||||
// write PDS
|
||||
PacketHeader[10] = 0x14; // ID
|
||||
ToolBox.SetDWord(PacketHeader, 2, dts); // PTS (=DTS of PCS/WDS)
|
||||
ToolBox.SetDWord(PacketHeader, 6, 0); // DTS (0)
|
||||
ToolBox.SetWord(PacketHeader, 11, (2 + palSize * 5)); // size
|
||||
for (int i = 0; i < PacketHeader.Length; i++)
|
||||
buf[index++] = PacketHeader[i];
|
||||
buf[index++] = 0;
|
||||
buf[index++] = 0;
|
||||
for (int i = 0; i < palSize; i++)
|
||||
{
|
||||
buf[index++] = (byte)i; // index
|
||||
buf[index++] = pal.GetY()[i]; // Y
|
||||
buf[index++] = pal.GetCr()[i]; // Cr
|
||||
buf[index++] = pal.GetCb()[i]; // Cb
|
||||
buf[index++] = pal.GetAlpha()[i]; // Alpha
|
||||
}
|
||||
|
||||
// write first OBJ
|
||||
int bufSize = rleBuf.Length;
|
||||
int rleIndex = 0;
|
||||
if (bufSize > 0xffe4)
|
||||
bufSize = 0xffe4;
|
||||
packetHeader[10] = 0x15; // ID
|
||||
timeStamp = dts + imageDecodeTime;
|
||||
ToolBox.SetDWord(packetHeader, 2, timeStamp); // PTS
|
||||
ToolBox.SetDWord(packetHeader, 6, dts); // DTS
|
||||
ToolBox.SetWord(packetHeader, 11, headerODSFirst.Length + bufSize); // size
|
||||
for (int i = 0; i < packetHeader.Length; i++)
|
||||
buf[index++] = packetHeader[i];
|
||||
int marker = (int)((numAddPackets == 0) ? 0xC0000000 : 0x80000000);
|
||||
ToolBox.SetDWord(headerODSFirst, 3, marker | (rleBuf.Length + 4));
|
||||
ToolBox.SetWord(headerODSFirst, 7, bm.Width);
|
||||
ToolBox.SetWord(headerODSFirst, 9, bm.Height);
|
||||
for (int i = 0; i < headerODSFirst.Length; i++)
|
||||
buf[index++] = headerODSFirst[i];
|
||||
for (int i = 0; i < bufSize; i++)
|
||||
// write first OBJ
|
||||
int bufSize = rleBuf.Length;
|
||||
int rleIndex = 0;
|
||||
if (bufSize > 0xffe4)
|
||||
bufSize = 0xffe4;
|
||||
PacketHeader[10] = 0x15; // ID
|
||||
timeStamp = dts + imageDecodeTime;
|
||||
ToolBox.SetDWord(PacketHeader, 2, timeStamp); // PTS
|
||||
ToolBox.SetDWord(PacketHeader, 6, dts); // DTS
|
||||
ToolBox.SetWord(PacketHeader, 11, HeaderODSFirst.Length + bufSize); // size
|
||||
for (int i = 0; i < PacketHeader.Length; i++)
|
||||
buf[index++] = PacketHeader[i];
|
||||
int marker = (int)((numAddPackets == 0) ? 0xC0000000 : 0x80000000);
|
||||
ToolBox.SetDWord(HeaderODSFirst, 3, marker | (rleBuf.Length + 4));
|
||||
ToolBox.SetWord(HeaderODSFirst, 7, bm.Width);
|
||||
ToolBox.SetWord(HeaderODSFirst, 9, bm.Height);
|
||||
for (int i = 0; i < HeaderODSFirst.Length; i++)
|
||||
buf[index++] = HeaderODSFirst[i];
|
||||
for (int i = 0; i < bufSize; i++)
|
||||
buf[index++] = rleBuf[rleIndex++];
|
||||
|
||||
// write additional OBJ packets
|
||||
bufSize = rleBuf.Length - bufSize; // remaining bytes to write
|
||||
for (int p = 0; p < numAddPackets; p++)
|
||||
{
|
||||
int psize = bufSize;
|
||||
if (psize > 0xffeb)
|
||||
psize = 0xffeb;
|
||||
PacketHeader[10] = 0x15; // ID (keep DTS & PTS)
|
||||
ToolBox.SetWord(PacketHeader, 11, HeaderODSNext.Length + psize); // size
|
||||
for (int i = 0; i < PacketHeader.Length; i++)
|
||||
buf[index++] = PacketHeader[i];
|
||||
for (int i = 0; i < HeaderODSNext.Length; i++)
|
||||
buf[index++] = HeaderODSNext[i];
|
||||
for (int i = 0; i < psize; i++)
|
||||
buf[index++] = rleBuf[rleIndex++];
|
||||
bufSize -= psize;
|
||||
}
|
||||
|
||||
// write additional OBJ packets
|
||||
bufSize = rleBuf.Length - bufSize; // remaining bytes to write
|
||||
for (int p = 0; p < numAddPackets; p++)
|
||||
{
|
||||
int psize = bufSize;
|
||||
if (psize > 0xffeb)
|
||||
psize = 0xffeb;
|
||||
packetHeader[10] = 0x15; // ID (keep DTS & PTS)
|
||||
ToolBox.SetWord(packetHeader, 11, headerODSNext.Length + psize); // size
|
||||
for (int i = 0; i < packetHeader.Length; i++)
|
||||
buf[index++] = packetHeader[i];
|
||||
for (int i = 0; i < headerODSNext.Length; i++)
|
||||
buf[index++] = headerODSNext[i];
|
||||
for (int i = 0; i < psize; i++)
|
||||
buf[index++] = rleBuf[rleIndex++];
|
||||
bufSize -= psize;
|
||||
}
|
||||
// write END
|
||||
PacketHeader[10] = 0x80; // ID
|
||||
ToolBox.SetDWord(PacketHeader, 6, 0); // DTS (0) (keep PTS of ODS)
|
||||
ToolBox.SetWord(PacketHeader, 11, 0); // size
|
||||
for (int i = 0; i < PacketHeader.Length; i++)
|
||||
buf[index++] = PacketHeader[i];
|
||||
|
||||
// write END
|
||||
packetHeader[10] = (byte)0x80; // ID
|
||||
ToolBox.SetDWord(packetHeader, 6, 0); // DTS (0) (keep PTS of ODS)
|
||||
ToolBox.SetWord(packetHeader, 11, 0); // size
|
||||
for (int i = 0; i < packetHeader.Length; i++)
|
||||
buf[index++] = packetHeader[i];
|
||||
// write PCS end
|
||||
PacketHeader[10] = 0x16; // ID
|
||||
ToolBox.SetDWord(PacketHeader, 2, pic.EndTimeForWrite); // PTS
|
||||
dts = pic.StartTimeForWrite - 1;
|
||||
ToolBox.SetDWord(PacketHeader, 6, dts); // DTS
|
||||
ToolBox.SetWord(PacketHeader, 11, HeaderPCSEnd.Length); // size
|
||||
for (int i = 0; i < PacketHeader.Length; i++)
|
||||
buf[index++] = PacketHeader[i];
|
||||
ToolBox.SetWord(HeaderPCSEnd, 0, pic.Width);
|
||||
ToolBox.SetWord(HeaderPCSEnd, 2, h); // cropped height
|
||||
ToolBox.SetByte(HeaderPCSEnd, 4, fpsId);
|
||||
ToolBox.SetWord(HeaderPCSEnd, 5, pic.CompositionNumber + 1);
|
||||
for (int i = 0; i < HeaderPCSEnd.Length; i++)
|
||||
buf[index++] = HeaderPCSEnd[i];
|
||||
|
||||
// write PCS end
|
||||
packetHeader[10] = 0x16; // ID
|
||||
ToolBox.SetDWord(packetHeader, 2, pic.EndTimeForWrite); // PTS
|
||||
dts = (int)pic.StartTimeForWrite - 1;
|
||||
ToolBox.SetDWord(packetHeader, 6, dts); // DTS
|
||||
ToolBox.SetWord(packetHeader, 11, headerPCSEnd.Length); // size
|
||||
for (int i = 0; i < packetHeader.Length; i++)
|
||||
buf[index++] = packetHeader[i];
|
||||
ToolBox.SetWord(headerPCSEnd, 0, pic.Width);
|
||||
ToolBox.SetWord(headerPCSEnd, 2, h); // cropped height
|
||||
ToolBox.SetByte(headerPCSEnd, 4, fpsId);
|
||||
ToolBox.SetWord(headerPCSEnd, 5, pic.CompositionNumber + 1);
|
||||
for (int i = 0; i < headerPCSEnd.Length; i++)
|
||||
buf[index++] = headerPCSEnd[i];
|
||||
// write WDS
|
||||
PacketHeader[10] = 0x17; // ID
|
||||
timeStamp = pic.EndTimeForWrite - windowInitTime;
|
||||
ToolBox.SetDWord(PacketHeader, 2, timeStamp); // PTS (keep DTS of PCS)
|
||||
ToolBox.SetWord(PacketHeader, 11, HeaderWds.Length); // size
|
||||
for (int i = 0; i < PacketHeader.Length; i++)
|
||||
buf[index++] = PacketHeader[i];
|
||||
ToolBox.SetWord(HeaderWds, 2, pic.WindowXOffset);
|
||||
ToolBox.SetWord(HeaderWds, 4, yOfs);
|
||||
ToolBox.SetWord(HeaderWds, 6, bm.Width);
|
||||
ToolBox.SetWord(HeaderWds, 8, bm.Height);
|
||||
for (int i = 0; i < HeaderWds.Length; i++)
|
||||
buf[index++] = HeaderWds[i];
|
||||
|
||||
// write WDS
|
||||
packetHeader[10] = 0x17; // ID
|
||||
timeStamp = pic.EndTimeForWrite - windowInitTime;
|
||||
ToolBox.SetDWord(packetHeader, 2, timeStamp); // PTS (keep DTS of PCS)
|
||||
ToolBox.SetWord(packetHeader, 11, headerWDS.Length); // size
|
||||
for (int i = 0; i < packetHeader.Length; i++)
|
||||
buf[index++] = packetHeader[i];
|
||||
ToolBox.SetWord(headerWDS, 2, pic.WindowXOffset);
|
||||
ToolBox.SetWord(headerWDS, 4, yOfs);
|
||||
ToolBox.SetWord(headerWDS, 6, bm.Width);
|
||||
ToolBox.SetWord(headerWDS, 8, bm.Height);
|
||||
for (int i = 0; i < headerWDS.Length; i++)
|
||||
buf[index++] = headerWDS[i];
|
||||
|
||||
// write END
|
||||
packetHeader[10] = (byte)0x80; // ID
|
||||
ToolBox.SetDWord(packetHeader, 2, dts); // PTS (DTS of end PCS)
|
||||
ToolBox.SetDWord(packetHeader, 6, 0); // DTS (0)
|
||||
ToolBox.SetWord(packetHeader, 11, 0); // size
|
||||
for (int i = 0; i < packetHeader.Length; i++)
|
||||
buf[index++] = packetHeader[i];
|
||||
// write END
|
||||
PacketHeader[10] = 0x80; // ID
|
||||
ToolBox.SetDWord(PacketHeader, 2, dts); // PTS (DTS of end PCS)
|
||||
ToolBox.SetDWord(PacketHeader, 6, 0); // DTS (0)
|
||||
ToolBox.SetWord(PacketHeader, 11, 0); // size
|
||||
for (int i = 0; i < PacketHeader.Length; i++)
|
||||
buf[index++] = PacketHeader[i];
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
@ -10,67 +10,67 @@ namespace Nikse.SubtitleEdit.Logic.VobSub
|
||||
/// <summary>
|
||||
/// 14 bytes Mpeg 2 pack header
|
||||
/// </summary>
|
||||
private static byte[] Mpeg2PackHeaderBuffer =
|
||||
private static readonly byte[] Mpeg2PackHeaderBuffer =
|
||||
{
|
||||
0x00, 0x00, 0x01, // Start code
|
||||
0xba, // MPEG-2 Pack ID
|
||||
0x44, 0x02, 0xec, 0xdf, // System clock reference
|
||||
0xfe, 0x57,
|
||||
0x01, 0x89, 0xc3, // Program mux rate
|
||||
0xf8, // stuffing byte
|
||||
0xf8 // stuffing byte
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 9 bytes packetized elementary stream header (PES)
|
||||
/// </summary>
|
||||
private static byte[] PacketizedElementaryStreamHeaderBufferFirst =
|
||||
private static readonly byte[] PacketizedElementaryStreamHeaderBufferFirst =
|
||||
{
|
||||
0x00, 0x00, 0x01, // Start code
|
||||
0xbd, // bd = Private stream 1 (non MPEG audio, subpictures)
|
||||
0x00, 0x00, // 18-19=PES packet length
|
||||
0x81, // 20=Flags: PES scrambling control, PES priority, data alignment indicator, copyright, original or copy
|
||||
0x81, // 21=Flags: PTS DTS flags, ESCR flag, ES rate flag, DSM trick mode flag, additional copy info flag, PES CRC flag, PES extension flag
|
||||
0x08, // 22=PES header data length
|
||||
0x08 // 22=PES header data length
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 9 bytes packetized elementary stream header (PES)
|
||||
/// </summary>
|
||||
private static byte[] PacketizedElementaryStreamHeaderBufferNext =
|
||||
private static readonly byte[] PacketizedElementaryStreamHeaderBufferNext =
|
||||
{
|
||||
0x00, 0x00, 0x01, // Start code
|
||||
0xbd, // bd = Private stream 1 (non MPEG audio, subpictures)
|
||||
0x00, 0x00, // PES packet length
|
||||
0x81, // 20=Flags: PES scrambling control, PES priority, data alignment indicator, copyright, original or copy
|
||||
0x00, // 21=Flags: PTS DTS flags, ESCR flag, ES rate flag, DSM trick mode flag, additional copy info flag, PES CRC flag, PES extension flag
|
||||
0x00, // 22=PES header data length
|
||||
0x00 // 22=PES header data length
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 5 bytes presentation time stamp (PTS)
|
||||
/// </summary>
|
||||
private static byte[] PresentationTimeStampBuffer =
|
||||
private static readonly byte[] PresentationTimeStampBuffer =
|
||||
{
|
||||
0x21, // 0010 3=PTS 32..30 1
|
||||
0x00, 0x01, // 15=PTS 29..15 1
|
||||
0x00, 0x01, // 15=PTS 14..00 1
|
||||
0x00, 0x01 // 15=PTS 14..00 1
|
||||
};
|
||||
|
||||
private const int PacketizedElementaryStreamMaximumLength = 2028;
|
||||
|
||||
private string _subFileName;
|
||||
private readonly string _subFileName;
|
||||
private FileStream _subFile;
|
||||
StringBuilder _idx = new StringBuilder();
|
||||
int _screenWidth = 720;
|
||||
int _screenHeight = 480;
|
||||
int _bottomMargin = 15;
|
||||
int _languageStreamId = 32;
|
||||
readonly StringBuilder _idx = new StringBuilder();
|
||||
readonly int _screenWidth = 720;
|
||||
readonly int _screenHeight = 480;
|
||||
readonly int _bottomMargin = 15;
|
||||
readonly int _languageStreamId = 32;
|
||||
Color _background = Color.Transparent;
|
||||
Color _pattern = Color.White;
|
||||
Color _emphasis1 = Color.Black;
|
||||
Color _emphasis2 = Color.FromArgb(240, Color.Black);
|
||||
string _languageName = "English";
|
||||
string _languageNameShort = "en";
|
||||
readonly string _languageName = "English";
|
||||
readonly string _languageNameShort = "en";
|
||||
|
||||
public VobSubWriter(string subFileName, int screenWidth, int screenHeight, int bottomMargin, int languageStreamId, Color pattern, Color emphasis1, Color emphasis2,
|
||||
string languageName, string languageNameShort)
|
||||
@ -107,7 +107,7 @@ namespace Nikse.SubtitleEdit.Logic.VobSub
|
||||
WriteEndianWord(startDisplayControlSequenceTableAddress, ms);
|
||||
|
||||
// Write image
|
||||
int imageTopFieldDataAddress = (int)(4);
|
||||
const int imageTopFieldDataAddress = 4;
|
||||
ms.Write(twoPartBuffer.Buffer1, 0, twoPartBuffer.Buffer1.Length);
|
||||
int imageBottomFieldDataAddress = 4 + twoPartBuffer.Buffer1.Length;
|
||||
ms.Write(twoPartBuffer.Buffer2, 0, twoPartBuffer.Buffer2.Length);
|
||||
@ -139,7 +139,7 @@ namespace Nikse.SubtitleEdit.Logic.VobSub
|
||||
|
||||
// Control Sequence Table
|
||||
// Write delay - subtitle duration
|
||||
WriteEndianWord((int)((Convert.ToInt32(p.Duration.TotalMilliseconds * 90.0 - 1023) >> 10)), ms);
|
||||
WriteEndianWord(Convert.ToInt32(p.Duration.TotalMilliseconds * 90.0 - 1023) >> 10, ms);
|
||||
|
||||
// next display control sequence table address (use current is last)
|
||||
WriteEndianWord(startDisplayControlSequenceTableAddress + 24, ms); // start of display control sequence table address
|
||||
@ -207,8 +207,8 @@ namespace Nikse.SubtitleEdit.Logic.VobSub
|
||||
int length = Mpeg2PackHeaderBuffer.Length + imageBuffer.Length - subtract;
|
||||
if (length > PacketizedElementaryStreamMaximumLength)
|
||||
{
|
||||
writeBuffer[4] = (byte)(PacketizedElementaryStreamMaximumLength / 256);
|
||||
writeBuffer[5] = (byte)(PacketizedElementaryStreamMaximumLength % 256);
|
||||
writeBuffer[4] = PacketizedElementaryStreamMaximumLength / 256;
|
||||
writeBuffer[5] = PacketizedElementaryStreamMaximumLength % 256;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -242,7 +242,6 @@ namespace Nikse.SubtitleEdit.Logic.VobSub
|
||||
/// <summary>
|
||||
/// Directly provides the four contrast (alpha blend) values to associate with the four pixel values. One nibble per pixel value for a total of 2 bytes. 0x0 = transparent, 0xF = opaque
|
||||
/// </summary>
|
||||
/// <param name="_subFile"></param>
|
||||
private void WriteContrast(Stream stream)
|
||||
{
|
||||
stream.WriteByte(4);
|
||||
@ -256,14 +255,14 @@ namespace Nikse.SubtitleEdit.Logic.VobSub
|
||||
private void WriteColors(Stream stream)
|
||||
{
|
||||
// Index to palette
|
||||
byte emphasis2 = 3;
|
||||
byte emphasis1 = 2;
|
||||
byte pattern = 1;
|
||||
byte background = 0;
|
||||
const byte emphasis2 = 3;
|
||||
const byte emphasis1 = 2;
|
||||
const byte pattern = 1;
|
||||
const byte background = 0;
|
||||
|
||||
stream.WriteByte(3);
|
||||
stream.WriteByte((byte)((emphasis2 << 4) | emphasis1)); // emphasis2 + emphasis1
|
||||
stream.WriteByte((byte)((pattern << 4) | background)); // pattern + background
|
||||
stream.WriteByte((emphasis2 << 4) | emphasis1); // emphasis2 + emphasis1
|
||||
stream.WriteByte((pattern << 4) | background); // pattern + background
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -271,7 +270,7 @@ namespace Nikse.SubtitleEdit.Logic.VobSub
|
||||
/// </summary>
|
||||
private void FillPTS(TimeCode timeCode)
|
||||
{
|
||||
string pre = "0011"; // 0011 or 0010 ?
|
||||
const string pre = "0011"; // 0011 or 0010 ?
|
||||
long newPts = (long)(timeCode.TotalSeconds * 90000.0 + 0.5);
|
||||
string bString = Convert.ToString(newPts, 2).PadLeft(33, '0');
|
||||
string fiveBytesString = pre + bString.Substring(0, 3) + "1" + bString.Substring(3, 15) + "1" + bString.Substring(18, 15) + "1";
|
||||
@ -292,7 +291,7 @@ namespace Nikse.SubtitleEdit.Logic.VobSub
|
||||
public void WriteIdxFile()
|
||||
{
|
||||
string idxFileName = _subFileName.Substring(0, _subFileName.Length - 3) + "idx";
|
||||
System.IO.File.WriteAllText(idxFileName, _idx.ToString().Trim());
|
||||
File.WriteAllText(idxFileName, _idx.ToString().Trim());
|
||||
}
|
||||
|
||||
private StringBuilder CreateIdxHeader()
|
||||
|
Loading…
Reference in New Issue
Block a user