SubtitleEdit/src/Forms/ExportPngXml.cs
2012-08-07 10:16:28 +00:00

1261 lines
59 KiB
C#

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Globalization;
using System.IO;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Xml;
using Nikse.SubtitleEdit.Logic;
using Nikse.SubtitleEdit.Logic.SubtitleFormats;
using Nikse.SubtitleEdit.Logic.VobSub;
namespace Nikse.SubtitleEdit.Forms
{
public sealed partial class ExportPngXml : Form
{
private class MakeBitmapParameter
{
public Bitmap Bitmap { get; set; }
public Paragraph P { get; set; }
public string Type { get; set; }
public Color SubtitleColor { get; set; }
public string SubtitleFontName { get; set; }
public float SubtitleFontSize { get; set; }
public bool SubtitleFontBold { get; set; }
public Color BorderColor { get; set; }
public float BorderWidth { get; set; }
public bool AntiAlias { get; set; }
public bool AlignLeft { get; set; }
public bool AlignRight { get; set; }
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; }
public ContentAlignment Alignment { get; set; }
}
private Subtitle _subtitle;
private SubtitleFormat _format;
private Color _subtitleColor = Color.White;
private string _subtitleFontName = "Verdana";
private float _subtitleFontSize = 75.0f;
private bool _subtitleFontBold;
private Color _borderColor = Color.Black;
private float _borderWidth = 2.0f;
private bool _isLoading = true;
private string _exportType = "BDNXML";
private string _fileName;
public ExportPngXml()
{
InitializeComponent();
comboBoxImageFormat.SelectedIndex = 4;
}
private double FrameRate
{
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);
}
private static ContentAlignment GetAlignmentFromParagraph(Paragraph p, SubtitleFormat format, Subtitle subtitle)
{
ContentAlignment alignment = ContentAlignment.BottomCenter;
if (format.HasStyleSupport && !string.IsNullOrEmpty(p.Extra))
{
if (format.GetType() == typeof(SubStationAlpha))
{
var style = AdvancedSubStationAlpha.GetSsaStyle(p.Extra, subtitle.Header);
alignment = GetSsaAlignment("{\\a" + style.Alignment + "}", alignment);
}
else if (format.GetType() == typeof(AdvancedSubStationAlpha))
{
var style = AdvancedSubStationAlpha.GetSsaStyle(p.Extra, subtitle.Header);
alignment = GetAssAlignment("{\\an" + style.Alignment + "}", alignment);
}
}
string text = p.Text;
if (format.GetType() == typeof(SubStationAlpha) && text.Length > 5)
{
text = p.Text.Substring(0, 6);
alignment = GetSsaAlignment(text, alignment);
}
else if (text.Length > 6)
{
text = p.Text.Substring(0, 6);
alignment = GetAssAlignment(text, alignment);
}
return alignment;
}
private static ContentAlignment GetSsaAlignment(string text, ContentAlignment defaultAlignment)
{
//1: Bottom left
//2: Bottom center
//3: Bottom right
//9: Middle left
//10: Middle center
//11: Middle right
//5: Top left
//6: Top center
//7: Top right
switch (text)
{
case "{\\a1}":
return ContentAlignment.BottomLeft;
case "{\\a2}":
return ContentAlignment.BottomCenter;
case "{\\a3}":
return ContentAlignment.BottomRight;
case "{\\a9}":
return ContentAlignment.MiddleLeft;
case "{\\a10}":
return ContentAlignment.MiddleCenter;
case "{\\a11}":
return ContentAlignment.MiddleRight;
case "{\\a5}":
return ContentAlignment.TopLeft;
case "{\\a6}":
return ContentAlignment.TopCenter;
case "{\\a7}":
return ContentAlignment.TopRight;
}
return defaultAlignment;
}
private static ContentAlignment GetAssAlignment(string text, ContentAlignment defaultAlignment)
{
//1: Bottom left
//2: Bottom center
//3: Bottom right
//4: Middle left
//5: Middle center
//6: Middle right
//7: Top left
//8: Top center
//9: Top right
switch (text)
{
case "{\\an1}":
return ContentAlignment.BottomLeft;
case "{\\an2}":
return ContentAlignment.BottomCenter;
case "{\\an3}":
return ContentAlignment.BottomRight;
case "{\\an4}":
return ContentAlignment.MiddleLeft;
case "{\\an5}":
return ContentAlignment.MiddleCenter;
case "{\\an6}":
return ContentAlignment.MiddleRight;
case "{\\an7}":
return ContentAlignment.TopLeft;
case "{\\an8}":
return ContentAlignment.TopCenter;
case "{\\an9}":
return ContentAlignment.TopRight;
}
return defaultAlignment;
}
public static void DoWork(object data)
{
var parameter = (MakeBitmapParameter)data;
parameter.Bitmap = GenerateImageFromTextWithStyle(parameter);
if (parameter.Type == "BLURAYSUP")
{
var brSub = new Logic.BluRaySup.BluRaySupPicture
{
StartTime = (long) parameter.P.StartTime.TotalMilliseconds,
EndTime = (long) parameter.P.EndTime.TotalMilliseconds,
Width = parameter.ScreenWidth,
Height = parameter.ScreenHeight
};
parameter.Buffer = Logic.BluRaySup.BluRaySupPicture.CreateSupFrame(brSub, parameter.Bitmap, parameter.FramesPerSeconds, parameter.BottomMargin, parameter.Alignment);
}
else if (parameter.Type == "VOBSUB")
{
}
else if (parameter.Type == "FAB")
{
}
}
private MakeBitmapParameter MakeMakeBitmapParameter(int index, int screenWidth,int screenHeight)
{
var parameter = new MakeBitmapParameter
{
Type = _exportType,
SubtitleColor = _subtitleColor,
SubtitleFontName = _subtitleFontName,
SubtitleFontSize = _subtitleFontSize,
SubtitleFontBold = _subtitleFontBold,
BorderColor = _borderColor,
BorderWidth = _borderWidth,
AntiAlias = checkBoxAntiAlias.Checked,
AlignLeft = comboBoxHAlign.SelectedIndex == 0,
AlignRight = comboBoxHAlign.SelectedIndex == 2,
ScreenWidth = screenWidth,
ScreenHeight = screenHeight,
Bitmap = null,
FramesPerSeconds = FrameRate,
BottomMargin = comboBoxBottomMargin.SelectedIndex,
Saved = false,
Alignment = ContentAlignment.BottomCenter,
};
if (index < _subtitle.Paragraphs.Count)
{
parameter.P = _subtitle.Paragraphs[index];
parameter.Alignment = GetAlignmentFromParagraph(parameter.P,_format, _subtitle);
}
else
{
parameter.P = null;
}
return parameter;
}
private void ButtonExportClick(object sender, EventArgs e)
{
buttonExport.Enabled = false;
SetupImageParameters();
if (!string.IsNullOrEmpty(_fileName))
saveFileDialog1.FileName = Path.GetFileNameWithoutExtension(_fileName);
if (_exportType == "BLURAYSUP")
{
saveFileDialog1.Title = "Choose Blu-ray sup file name...";
saveFileDialog1.DefaultExt = "*.sup";
saveFileDialog1.AddExtension = true;
saveFileDialog1.Filter = "Blu-Ray sup|*.sup";
}
else if (_exportType == "VOBSUB")
{
saveFileDialog1.Title = "Choose Vobsub file name...";
saveFileDialog1.DefaultExt = "*.sub";
saveFileDialog1.AddExtension = true;
saveFileDialog1.Filter = "VobSub|*.sub";
}
else if (_exportType == "FAB")
{
saveFileDialog1.Title = "Choose FAB image script file name...";
saveFileDialog1.DefaultExt = "*.txt";
saveFileDialog1.AddExtension = true;
saveFileDialog1.Filter = "FAB image scripts|*.txt";
}
if (_exportType == "BLURAYSUP" && saveFileDialog1.ShowDialog(this) == DialogResult.OK ||
_exportType == "VOBSUB" && saveFileDialog1.ShowDialog(this) == DialogResult.OK ||
_exportType == "BDNXML" && folderBrowserDialog1.ShowDialog(this) == DialogResult.OK ||
_exportType == "FAB" && folderBrowserDialog1.ShowDialog(this) == DialogResult.OK ||
_exportType == "IMAGE/FRAME" && folderBrowserDialog1.ShowDialog(this) == DialogResult.OK)
{
int width = 1920;
int height = 1080;
if (comboBoxResolution.SelectedIndex == 1)
{
width = 1440;
height = 1080;
}
else if (comboBoxResolution.SelectedIndex == 2)
{
width = 1280;
height = 720;
}
else if (comboBoxResolution.SelectedIndex == 3)
{
width = 960;
height = 720;
}
else if (comboBoxResolution.SelectedIndex == 4)
{
width = 848;
height = 480;
}
else if (comboBoxResolution.SelectedIndex == 5)
{
width = 720;
height = 576;
}
else if (comboBoxResolution.SelectedIndex == 6)
{
width = 720;
height = 480;
}
else if (comboBoxResolution.SelectedIndex == 7)
{
width = 640;
height = 352;
}
else if (comboBoxResolution.SelectedIndex == 8)
{
string[] arr = comboBoxResolution.Text.Split('x');
width = int.Parse(arr[0]);
height = int.Parse(arr[1]);
}
FileStream binarySubtitleFile = null;
VobSubWriter vobSubWriter = null;
if (_exportType == "BLURAYSUP")
binarySubtitleFile = new FileStream(saveFileDialog1.FileName, FileMode.Create);
else if (_exportType == "VOBSUB")
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;
int border = comboBoxBottomMargin.SelectedIndex;
int imagesSavedCount = 0;
var sb = new StringBuilder();
var threadEqual = new Thread(DoWork);
var paramEqual = MakeMakeBitmapParameter(0, width, height);
var threadUnEqual = new Thread(DoWork);
var paramUnEqual = MakeMakeBitmapParameter(1, width, height);
threadEqual.Start(paramEqual);
int i = 1;
for (; i < _subtitle.Paragraphs.Count; i++)
{
if (i % 2 == 0)
{
paramEqual = MakeMakeBitmapParameter(i, width, height);
threadEqual = new Thread(DoWork);
threadEqual.Start(paramEqual);
if (threadUnEqual.ThreadState == ThreadState.Running)
threadUnEqual.Join(3000);
imagesSavedCount = WriteParagraph(width, sb, border, height, imagesSavedCount, vobSubWriter, binarySubtitleFile, paramUnEqual, i);
}
else
{
paramUnEqual = MakeMakeBitmapParameter(i, width, height);
threadUnEqual = new Thread(DoWork);
threadUnEqual.Start(paramUnEqual);
if (threadEqual.ThreadState == ThreadState.Running)
threadEqual.Join(3000);
imagesSavedCount = WriteParagraph(width, sb, border, height, imagesSavedCount, vobSubWriter, binarySubtitleFile, paramEqual, i);
}
progressBar1.Refresh();
Application.DoEvents();
progressBar1.Value = i;
}
if (i % 2 == 0)
{
if (threadEqual.ThreadState == ThreadState.Running)
threadEqual.Join(3000);
imagesSavedCount = WriteParagraph(width, sb, border, height, imagesSavedCount, vobSubWriter, binarySubtitleFile, paramEqual, i);
if (threadUnEqual.ThreadState == ThreadState.Running)
threadUnEqual.Join(3000);
imagesSavedCount = WriteParagraph(width, sb, border, height, imagesSavedCount, vobSubWriter, binarySubtitleFile, paramUnEqual, i);
}
else
{
if (threadUnEqual.ThreadState == ThreadState.Running)
threadUnEqual.Join(3000);
imagesSavedCount = WriteParagraph(width, sb, border, height, imagesSavedCount, vobSubWriter,
binarySubtitleFile, paramUnEqual, i);
if (threadEqual.ThreadState == ThreadState.Running)
threadEqual.Join(3000);
imagesSavedCount = WriteParagraph(width, sb, border, height, imagesSavedCount, vobSubWriter,
binarySubtitleFile, paramEqual, i);
}
progressBar1.Visible = false;
if (_exportType == "BLURAYSUP")
{
binarySubtitleFile.Close();
MessageBox.Show(string.Format(Configuration.Settings.Language.Main.SavedSubtitleX, saveFileDialog1.FileName));
}
else if (_exportType == "VOBSUB")
{
vobSubWriter.CloseSubFile();
vobSubWriter.WriteIdxFile();
MessageBox.Show(string.Format(Configuration.Settings.Language.Main.SavedSubtitleX, saveFileDialog1.FileName));
}
else if (_exportType == "FAB")
{
File.WriteAllText(Path.Combine(folderBrowserDialog1.SelectedPath, "Fab_Image_script.txt"), sb.ToString());
MessageBox.Show(string.Format(Configuration.Settings.Language.ExportPngXml.XImagesSavedInY, imagesSavedCount, folderBrowserDialog1.SelectedPath));
}
else if (_exportType == "IMAGE/FRAME")
{
var empty = new Bitmap(width, height);
imagesSavedCount++;
string numberString = string.Format("{0:00000}", imagesSavedCount);
string fileName = Path.Combine(folderBrowserDialog1.SelectedPath, numberString + "." + comboBoxImageFormat.Text.ToLower());
empty.Save(fileName, ImageFormat);
MessageBox.Show(string.Format(Configuration.Settings.Language.ExportPngXml.XImagesSavedInY, imagesSavedCount, folderBrowserDialog1.SelectedPath));
}
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];
doc.LoadXml("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + Environment.NewLine +
"<BDN Version=\"0.93\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"BD-03-006-0093b BDN File Format.xsd\">" + Environment.NewLine +
"<Description>" + Environment.NewLine +
"<Name Title=\"subtitle_exp\" Content=\"\"/>" + Environment.NewLine +
"<Language Code=\"eng\"/>" + 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 +
"</Events>" + Environment.NewLine +
"</BDN>");
XmlNode events = doc.DocumentElement.SelectSingleNode("Events");
events.InnerXml = sb.ToString();
File.WriteAllText(Path.Combine(folderBrowserDialog1.SelectedPath, "BDN_Index.xml"), doc.OuterXml);
MessageBox.Show(string.Format(Configuration.Settings.Language.ExportPngXml.XImagesSavedInY, imagesSavedCount, folderBrowserDialog1.SelectedPath));
}
}
buttonExport.Enabled = true;
}
private int WriteParagraph(int width, StringBuilder sb, int border, int height, int imagesSavedCount,
VobSubWriter vobSubWriter, FileStream binarySubtitleFile, MakeBitmapParameter param,
int i)
{
if (param.Bitmap != null)
{
if (_exportType == "BLURAYSUP")
{
if (!param.Saved)
binarySubtitleFile.Write(param.Buffer, 0, param.Buffer.Length);
param.Saved = true;
}
else if (_exportType == "VOBSUB")
{
if (!param.Saved)
vobSubWriter.WriteParagraph(param.P, param.Bitmap);
param.Saved = true;
}
else if (_exportType == "FAB")
{
if (!param.Saved)
{
string numberString = string.Format("IMAGE{0:000}", i);
string fileName = Path.Combine(folderBrowserDialog1.SelectedPath, numberString + "." + comboBoxImageFormat.Text.ToLower());
param.Bitmap.Save(fileName, ImageFormat);
imagesSavedCount++;
//RACE001.TIF 00;00;02;02 00;00;03;15 000 000 720 480
//RACE002.TIF 00;00;05;18 00;00;09;20 000 000 720 480
int top = param.ScreenHeight - (param.Bitmap.Height + 20); // bottom margin=20 //TODO: Use combo bottom margin!
sb.AppendLine(string.Format("{0} {1} {2} {3} {4} {5} {6}", Path.GetFileName(fileName), FormatFabTime(param.P.StartTime, param), FormatFabTime(param.P.EndTime, param), 0, top, param.ScreenWidth, param.ScreenHeight));
param.Saved = true;
}
}
else if (_exportType == "IMAGE/FRAME")
{
if (!param.Saved)
{
var imageFormat = ImageFormat;
int lastFrame = imagesSavedCount;
int startFrame = (int)Math.Round(param.P.StartTime.TotalMilliseconds / (1000.0 / param.FramesPerSeconds));
var empty = new Bitmap(param.ScreenWidth, param.ScreenHeight);
if (imagesSavedCount == 0 && checkBoxSkipEmptyFrameAtStart.Checked)
{
}
else
{
// Save empty picture for each frame up to start frame
for (int k = lastFrame + 1; k < startFrame; k++)
{
string numberString = string.Format("{0:00000}", k);
string fileName = Path.Combine(folderBrowserDialog1.SelectedPath, numberString + "." + comboBoxImageFormat.Text.ToLower());
empty.Save(fileName, imageFormat);
imagesSavedCount++;
}
}
int endFrame = (int)Math.Round(param.P.EndTime.TotalMilliseconds / (1000.0 / param.FramesPerSeconds));
var fullSize = new Bitmap(param.ScreenWidth, param.ScreenHeight);
Graphics g = Graphics.FromImage(fullSize);
g.DrawImage(param.Bitmap, (param.ScreenWidth - param.Bitmap.Width) / 2, param.ScreenHeight - (param.Bitmap.Height + param.BottomMargin));
g.Dispose();
if (imagesSavedCount > startFrame)
startFrame = imagesSavedCount; // no overlapping
// Save sub picture for each frame in duration
for (int k = startFrame; k <= endFrame; k++)
{
string numberString = string.Format("{0:00000}", k);
string fileName = Path.Combine(folderBrowserDialog1.SelectedPath, numberString + "." + comboBoxImageFormat.Text.ToLower());
fullSize.Save(fileName, imageFormat);
imagesSavedCount++;
}
fullSize.Dispose();
param.Saved = true;
}
}
else
{
if (!param.Saved)
{
string numberString = string.Format("{0:0000}", i);
string fileName = Path.Combine(folderBrowserDialog1.SelectedPath, numberString + ".png");
param.Bitmap.Save(fileName, ImageFormat.Png);
imagesSavedCount++;
//<Event InTC="00:00:24:07" OutTC="00:00:31:13" Forced="False">
// <Graphic Width="696" Height="111" X="612" Y="930">subtitle_exp_0001.png</Graphic>
//</Event>
sb.AppendLine("<Event InTC=\"" + BdnXmlTimeCode(param.P.StartTime) + "\" OutTC=\"" +
BdnXmlTimeCode(param.P.EndTime) + "\" Forced=\"False\">");
int x = (width - param.Bitmap.Width) / 2;
int y = height - (param.Bitmap.Height + border);
switch (param.Alignment)
{
case ContentAlignment.BottomLeft:
x = border;
y = height - (param.Bitmap.Height + border);
break;
case ContentAlignment.BottomRight:
x = height - param.Bitmap.Width - border;
y = height - (param.Bitmap.Height + border);
break;
case ContentAlignment.MiddleCenter:
x = (width - param.Bitmap.Width) / 2;
y = (height - param.Bitmap.Height) / 2;
break;
case ContentAlignment.MiddleLeft:
x = border;
y = (height - param.Bitmap.Height) / 2;
break;
case ContentAlignment.MiddleRight:
x = width - param.Bitmap.Width - border;
y = (height - param.Bitmap.Height) / 2;
break;
case ContentAlignment.TopCenter:
x = (width - param.Bitmap.Width) / 2;
y = border;
break;
case ContentAlignment.TopLeft:
x = border;
y = border;
break;
case ContentAlignment.TopRight:
x = width - param.Bitmap.Width - border;
y = border;
break;
default: // ContentAlignment.BottomCenter:
break;
}
sb.AppendLine(" <Graphic Width=\"" + param.Bitmap.Width.ToString() + "\" Height=\"" +
param.Bitmap.Height.ToString() + "\" X=\"" + x.ToString() + "\" Y=\"" + y.ToString() +
"\">" + numberString + ".png</Graphic>");
sb.AppendLine("</Event>");
param.Saved = true;
}
}
}
return imagesSavedCount;
}
private ImageFormat ImageFormat
{
get
{
var imageFormat = ImageFormat.Png;
if (comboBoxImageFormat.SelectedIndex == 0)
imageFormat = ImageFormat.Bmp;
else if (comboBoxImageFormat.SelectedIndex == 1)
imageFormat = ImageFormat.Exif;
else if (comboBoxImageFormat.SelectedIndex == 2)
imageFormat = ImageFormat.Gif;
else if (comboBoxImageFormat.SelectedIndex == 3)
imageFormat = ImageFormat.Jpeg;
else if (comboBoxImageFormat.SelectedIndex == 4)
imageFormat = ImageFormat.Png;
else if (comboBoxImageFormat.SelectedIndex == 5)
imageFormat = ImageFormat.Tiff;
return imageFormat;
}
}
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, 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()
{
if (_isLoading)
return;
if (subtitleListView1.SelectedItems.Count > 0 && _format.HasStyleSupport)
{
Paragraph p = _subtitle.Paragraphs[subtitleListView1.SelectedItems[0].Index];
if (_format.GetType() == typeof(AdvancedSubStationAlpha) || _format.GetType() == typeof(SubStationAlpha))
{
if (!string.IsNullOrEmpty(p.Extra))
{
SsaStyle style = AdvancedSubStationAlpha.GetSsaStyle(p.Extra, _subtitle.Header);
if (style != null)
{
panelColor.BackColor = style.Primary;
if (_format.GetType() == typeof(AdvancedSubStationAlpha))
panelBorderColor.BackColor = style.Outline;
else
panelBorderColor.BackColor = style.Background;
int i;
for (i = 0; i < comboBoxSubtitleFont.Items.Count; i++)
{
if (string.Compare(comboBoxSubtitleFont.Items[i].ToString(), style.FontName, true) == 0)
comboBoxSubtitleFont.SelectedIndex = i;
}
for (i = 0; i < comboBoxSubtitleFontSize.Items.Count; i++)
{
if (string.Compare(comboBoxSubtitleFontSize.Items[i].ToString(), style.FontSize.ToString(), true) == 0)
comboBoxSubtitleFontSize.SelectedIndex = i;
}
checkBoxBold.Checked = style.Bold;
for (i = 0; i < comboBoxBorderWidth.Items.Count; i++)
{
if (string.Compare(comboBoxBorderWidth.Items[i].ToString(), style.OutlineWidth.ToString(), true) == 0)
comboBoxBorderWidth.SelectedIndex = i;
}
}
}
}
else if (_format.GetType() == typeof(TimedText10))
{
if (!string.IsNullOrEmpty(p.Extra))
{
}
}
}
_subtitleColor = panelColor.BackColor;
_borderColor = panelBorderColor.BackColor;
_subtitleFontName = comboBoxSubtitleFont.SelectedItem.ToString();
_subtitleFontSize = float.Parse(comboBoxSubtitleFontSize.SelectedItem.ToString());
_subtitleFontBold = checkBoxBold.Checked;
_borderWidth = float.Parse(comboBoxBorderWidth.SelectedItem.ToString());
}
private static Color GetOutlineColor(Color borderColor)
{
if (borderColor.R + borderColor.G + borderColor.B < 30)
return Color.FromArgb(200, 75, 75, 75);
return Color.FromArgb(150, borderColor.R, borderColor.G, borderColor.B);
}
private Bitmap GenerateImageFromTextWithStyle(string text)
{
var mbp = new MakeBitmapParameter();
mbp.AlignLeft = comboBoxHAlign.SelectedIndex == 0;
mbp.AlignRight = comboBoxHAlign.SelectedIndex == 2;
mbp.AntiAlias = checkBoxAntiAlias.Checked;
mbp.BorderWidth = _borderWidth;
mbp.BorderColor = _borderColor;
mbp.SubtitleFontName = _subtitleFontName;
mbp.SubtitleColor = _subtitleColor;
mbp.SubtitleFontSize = _subtitleFontSize;
mbp.SubtitleFontBold = _subtitleFontBold;
mbp.P = new Paragraph(text, 0, 0);
var bmp = GenerateImageFromTextWithStyle(mbp);
if (_exportType == "VOBSUB")
{
var nbmp = new NikseBitmap(bmp);
nbmp.ConverToFourColors(Color.Transparent, _subtitleColor, _borderColor, GetOutlineColor(_borderColor));
bmp = nbmp.GetBitmap();
}
return bmp;
}
private static Bitmap GenerateImageFromTextWithStyle(MakeBitmapParameter parameter)
{
string text = parameter.P.Text;
// remove styles for display text (except italic)
text = RemoveSubStationAlphaFormatting(text);
text = text.Replace("<b>", string.Empty);
text = text.Replace("</b>", string.Empty);
text = text.Replace("<B>", string.Empty);
text = text.Replace("</B>", string.Empty);
text = text.Replace("<u>", string.Empty);
text = text.Replace("</u>", string.Empty);
text = text.Replace("<U>", string.Empty);
text = text.Replace("</U>", string.Empty);
Font font;
try
{
var fontStyle = FontStyle.Regular;
if (parameter.SubtitleFontBold)
fontStyle = FontStyle.Bold;
font = new Font(parameter.SubtitleFontName, parameter.SubtitleFontSize, fontStyle);
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
font = new Font(FontFamily.Families[0].Name, parameter.SubtitleFontSize);
}
var bmp = new Bitmap(400, 200);
var g = Graphics.FromImage(bmp);
SizeF textSize = g.MeasureString("Hj!", font);
var lineHeight = (textSize.Height * 0.64f);
textSize = g.MeasureString(Utilities.RemoveHtmlTags(text), font);
g.Dispose();
bmp.Dispose();
int sizeX = (int)(textSize.Width * 0.8) + 40;
int sizeY = (int)(textSize.Height * 0.8) + 30;
if (sizeX < 1)
sizeX = 1;
if (sizeY < 1)
sizeY = 1;
bmp = new Bitmap(sizeX, sizeY);
g = Graphics.FromImage(bmp);
var lefts = new List<float>();
foreach (string line in Utilities.RemoveHtmlFontTag(text.Replace("<i>", string.Empty).Replace("</i>", string.Empty)).Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
{
if (parameter.AlignLeft)
lefts.Add(5);
else if (parameter.AlignRight)
lefts.Add(bmp.Width - (TextDraw.MeasureTextWidth(font, line, parameter.SubtitleFontBold) + 15));
else
lefts.Add((float)(bmp.Width - g.MeasureString(line, font).Width * 0.8+15) / 2);
}
if (parameter.AntiAlias)
{
g.TextRenderingHint = TextRenderingHint.AntiAlias;
g.SmoothingMode = SmoothingMode.AntiAlias;
}
var sf = new StringFormat();
sf.Alignment = StringAlignment.Near;
sf.LineAlignment = StringAlignment.Near;// draw the text to a path
var path = new GraphicsPath();
// display italic
var sb = new StringBuilder();
int i = 0;
bool isItalic = false;
float left = 5;
if (lefts.Count > 0)
left = lefts[0];
float top = 5;
bool newLine = false;
int lineNumber = 0;
float leftMargin = left;
bool italicFromStart = false;
int newLinePathPoint = -1;
Color c = parameter.SubtitleColor;
var colorStack = new Stack<Color>();
while (i < text.Length)
{
if (text.Substring(i).ToLower().StartsWith("<font "))
{
float addLeft = 0;
int oldPathPointIndex = path.PointCount - 1;
if (oldPathPointIndex < 0)
oldPathPointIndex = 0;
if (sb.Length > 0)
{
TextDraw.DrawText(font, sf, path, sb, isItalic, parameter.SubtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint);
}
if (path.PointCount > 0)
{
for (int k = oldPathPointIndex; k < path.PathPoints.Length; k++)
{
if (path.PathPoints[k].X > addLeft)
addLeft = path.PathPoints[k].X;
}
}
if (addLeft == 0)
addLeft = left + 2;
left = addLeft;
if (parameter.BorderWidth > 0)
g.DrawPath(new Pen(parameter.BorderColor, parameter.BorderWidth), path);
g.FillPath(new SolidBrush(c), path);
path.Reset();
path = new GraphicsPath();
sb = new StringBuilder();
int endIndex = text.Substring(i).IndexOf(">");
if (endIndex == -1)
{
i += 9999;
}
else
{
string fontContent = text.Substring(i, endIndex);
if (fontContent.Contains(" color="))
{
string[] arr = fontContent.Substring(fontContent.IndexOf(" color=") + 7).Trim().Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
if (arr.Length > 0)
{
string fontColor = arr[0].Trim('\'').Trim('"').Trim('\'');
try
{
colorStack.Push(c); // save old color
if (fontColor.StartsWith("rgb("))
{
arr = fontColor.Remove(0, 4).TrimEnd(')').Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
c = Color.FromArgb(int.Parse(arr[0]), int.Parse(arr[1]), int.Parse(arr[2]));
}
else
{
c = System.Drawing.ColorTranslator.FromHtml(fontColor);
}
}
catch
{
c = parameter.SubtitleColor;
}
}
}
i += endIndex;
}
}
else if (text.Substring(i).ToLower().StartsWith("</font>"))
{
if (text.Substring(i).ToLower().Replace("</font>", string.Empty).Length > 0)
{
float addLeft = 0;
int oldPathPointIndex = path.PointCount -1;
if (oldPathPointIndex < 0)
oldPathPointIndex = 0;
if (sb.Length > 0)
{
TextDraw.DrawText(font, sf, path, sb, isItalic, parameter.SubtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint);
}
if (path.PointCount > 0)
{
for (int k = oldPathPointIndex; k < path.PathPoints.Length; k++)
{
if (path.PathPoints[k].X > addLeft)
addLeft = path.PathPoints[k].X;
}
}
if (addLeft == 0)
addLeft = left + 2;
left = addLeft;
if (parameter.BorderWidth > 0)
g.DrawPath(new Pen(parameter.BorderColor, parameter.BorderWidth), path);
g.FillPath(new SolidBrush(c), path);
path.Reset();
//path = new GraphicsPath();
sb = new StringBuilder();
if (colorStack.Count > 0)
c = colorStack.Pop();
}
i += 6;
}
else if (text.Substring(i).ToLower().StartsWith("<i>"))
{
italicFromStart = i == 0;
if (sb.Length > 0)
{
TextDraw.DrawText(font, sf, path, sb, isItalic, parameter.SubtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint);
}
isItalic = true;
i += 2;
}
else if (text.Substring(i).ToLower().StartsWith("</i>") && isItalic)
{
TextDraw.DrawText(font, sf, path, sb, isItalic, parameter.SubtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint);
isItalic = false;
i += 3;
}
else if (text.Substring(i).StartsWith(Environment.NewLine))
{
TextDraw.DrawText(font, sf, path, sb, isItalic, parameter.SubtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint);
top += lineHeight;
newLine = true;
i += Environment.NewLine.Length - 1;
lineNumber++;
if (lineNumber < lefts.Count)
{
leftMargin = lefts[lineNumber];
left = leftMargin;
}
if (isItalic)
italicFromStart = true;
}
else
{
sb.Append(text.Substring(i, 1));
}
i++;
}
if (sb.Length > 0)
TextDraw.DrawText(font, sf, path, sb, isItalic, parameter.SubtitleFontBold, false, left, top, ref newLine, leftMargin, ref newLinePathPoint);
if (parameter.BorderWidth > 0)
g.DrawPath(new Pen(parameter.BorderColor, parameter.BorderWidth), path);
g.FillPath(new SolidBrush(c), path);
g.Dispose();
var nbmp = new NikseBitmap(bmp);
nbmp.CropTransparentSidesAndBottom(2);
return nbmp.GetBitmap();
}
private static string RemoveSubStationAlphaFormatting(string s)
{
int indexOfBegin = s.IndexOf("{");
while (indexOfBegin >= 0 && s.IndexOf("}") > indexOfBegin)
{
int indexOfEnd = s.IndexOf("}");
s = s.Remove(indexOfBegin, (indexOfEnd - indexOfBegin) + 1);
indexOfBegin = s.IndexOf("{");
}
return s;
}
internal void Initialize(Subtitle subtitle, SubtitleFormat format, string exportType, string fileName, VideoInfo videoInfo)
{
_exportType = exportType;
_fileName = fileName;
_format = format;
if (exportType == "BLURAYSUP")
Text = "Blu-ray SUP";
else if (exportType == "VOBSUB")
Text = "VobSub (sub/idx)";
else if (exportType == "FAB")
Text = "FAB Image Script";
else if (exportType == "IMAGE/FRAME")
Text = "Image per frame";
else
Text = Configuration.Settings.Language.ExportPngXml.Title;
groupBoxImageSettings.Text = Configuration.Settings.Language.ExportPngXml.ImageSettings;
labelSubtitleFont.Text = Configuration.Settings.Language.ExportPngXml.FontFamily;
labelSubtitleFontSize.Text = Configuration.Settings.Language.ExportPngXml.FontSize;
buttonColor.Text = Configuration.Settings.Language.ExportPngXml.FontColor;
checkBoxAntiAlias.Text = Configuration.Settings.Language.ExportPngXml.AntiAlias;
checkBoxBold.Text = Configuration.Settings.Language.General.Bold;
buttonBorderColor.Text = Configuration.Settings.Language.ExportPngXml.BorderColor;
labelBorderWidth.Text = Configuration.Settings.Language.ExportPngXml.BorderWidth;
buttonExport.Text = Configuration.Settings.Language.ExportPngXml.ExportAllLines;
buttonCancel.Text = Configuration.Settings.Language.General.OK;
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 &&
Configuration.Settings.Language.ExportPngXml.Right != null)
{
comboBoxHAlign.Items.Clear();
comboBoxHAlign.Items.Add(Configuration.Settings.Language.ExportPngXml.Left);
comboBoxHAlign.Items.Add(Configuration.Settings.Language.ExportPngXml.Center);
comboBoxHAlign.Items.Add(Configuration.Settings.Language.ExportPngXml.Right);
}
subtitleListView1.InitializeLanguage(Configuration.Settings.Language.General, Configuration.Settings);
Utilities.InitializeSubtitleFont(subtitleListView1);
subtitleListView1.AutoSizeAllColumns(this);
_subtitle = subtitle;
panelColor.BackColor = _subtitleColor;
panelBorderColor.BackColor = _borderColor;
comboBoxBorderWidth.SelectedIndex = 2;
comboBoxHAlign.SelectedIndex = 1;
comboBoxResolution.SelectedIndex = 0;
if (exportType == "VOBSUB")
{
comboBoxBorderWidth.SelectedIndex = 3;
comboBoxResolution.SelectedIndex = 5;
labelLanguage.Visible = true;
comboBoxLanguage.Visible = true;
comboBoxLanguage.Items.Clear();
string languageCode = Utilities.AutoDetectGoogleLanguage(subtitle);
for (int i = 0; i < IfoParser.ArrayOfLanguage.Count; i++)
{
comboBoxLanguage.Items.Add(IfoParser.ArrayOfLanguage[i]);
if (IfoParser.ArrayOfLanguageCode[i] == languageCode)
comboBoxLanguage.SelectedIndex = i;
}
comboBoxLanguage.SelectedIndex = 25;
}
comboBoxImageFormat.Visible = exportType == "FAB" || exportType == "IMAGE/FRAME";
labelImageFormat.Visible = exportType == "FAB" || exportType == "IMAGE/FRAME";
labelFrameRate.Visible = exportType == "BDNXML" || exportType == "BLURAYSUP" || exportType == "IMAGE/FRAME";
comboBoxFramerate.Visible = exportType == "BDNXML" || exportType == "BLURAYSUP" || exportType == "IMAGE/FRAME";
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("30");
comboBoxFramerate.Items.Add("50");
comboBoxFramerate.Items.Add("59.94");
comboBoxFramerate.SelectedIndex = 2;
}
else if (exportType == "IMAGE/FRAME")
{
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("30");
comboBoxFramerate.Items.Add("50");
comboBoxFramerate.Items.Add("59.94");
comboBoxFramerate.Items.Add("60");
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" || exportType == "IMAGE/FRAME")
comboBoxBottomMargin.SelectedIndex = 20;
if (_exportType == "BLURAYSUP" || _exportType == "VOBSUB" || _exportType == "IMAGE/FRAME")
{
comboBoxBottomMargin.Visible = true;
labelBottomMargin.Visible = true;
}
else
{
comboBoxBottomMargin.Visible = false;
labelBottomMargin.Visible = false;
}
checkBoxSkipEmptyFrameAtStart.Visible = exportType == "IMAGE/FRAME";
foreach (var x in FontFamily.Families)
{
comboBoxSubtitleFont.Items.Add(x.Name);
if (string.Compare(x.Name, _subtitleFontName, true) == 0)
comboBoxSubtitleFont.SelectedIndex = comboBoxSubtitleFont.Items.Count - 1;
}
if (comboBoxSubtitleFont.SelectedIndex == -1)
comboBoxSubtitleFont.SelectedIndex = 0; // take first font if default font not found (e.g. linux)
if (videoInfo != null && videoInfo.Height > 0 && videoInfo.Width > 0)
{
comboBoxResolution.Items[8] = videoInfo.Width + "x" + videoInfo.Height;
comboBoxResolution.SelectedIndex = 8;
}
subtitleListView1.Fill(_subtitle);
subtitleListView1.SelectIndexAndEnsureVisible(0);
}
private void subtitleListView1_SelectedIndexChanged(object sender, EventArgs e)
{
SetupImageParameters();
if (subtitleListView1.SelectedItems.Count > 0)
{
var bmp = GenerateImageFromTextWithStyle(_subtitle.Paragraphs[subtitleListView1.SelectedItems[0].Index].Text);
pictureBox1.Image = bmp;
int w = groupBoxExportImage.Width - 4;
pictureBox1.Width = bmp.Width;
pictureBox1.Height = bmp.Height;
pictureBox1.Top = groupBoxExportImage.Height - bmp.Height - int.Parse(comboBoxBottomMargin.Text);
pictureBox1.Left = (w - bmp.Width) / 2;
var alignment = GetAlignmentFromParagraph(_subtitle.Paragraphs[subtitleListView1.SelectedItems[0].Index], _format, _subtitle);
if (_exportType == "BDNXML" || _exportType == "BLURAYSUP")
{
if (alignment == ContentAlignment.BottomLeft || alignment == ContentAlignment.MiddleLeft || alignment == ContentAlignment.TopLeft)
pictureBox1.Left = int.Parse(comboBoxBottomMargin.Text);
else if (alignment == ContentAlignment.BottomRight || alignment == ContentAlignment.MiddleRight || alignment == ContentAlignment.TopRight)
pictureBox1.Left = w - bmp.Width - int.Parse(comboBoxBottomMargin.Text);
if (alignment == ContentAlignment.MiddleLeft || alignment == ContentAlignment.MiddleCenter || alignment == ContentAlignment.MiddleRight)
pictureBox1.Top = (groupBoxExportImage.Height - 4 - bmp.Height) / 2;
else if (alignment == ContentAlignment.TopLeft || alignment == ContentAlignment.TopCenter || alignment == ContentAlignment.TopRight)
pictureBox1.Top = int.Parse(comboBoxBottomMargin.Text);
}
groupBoxExportImage.Text = string.Format("{0}x{1}", bmp.Width, bmp.Height);
}
}
private void buttonColor_Click(object sender, EventArgs e)
{
colorDialog1.Color = panelColor.BackColor;
if (colorDialog1.ShowDialog() == DialogResult.OK)
{
panelColor.BackColor = colorDialog1.Color;
subtitleListView1_SelectedIndexChanged(null, null);
}
}
private void panelColor_MouseClick(object sender, MouseEventArgs e)
{
buttonColor_Click(null, null);
}
private void buttonBorderColor_Click(object sender, EventArgs e)
{
colorDialog1.Color = panelBorderColor.BackColor;
if (colorDialog1.ShowDialog() == DialogResult.OK)
{
panelBorderColor.BackColor = colorDialog1.Color;
subtitleListView1_SelectedIndexChanged(null, null);
}
}
private void panelBorderColor_MouseClick(object sender, MouseEventArgs e)
{
buttonBorderColor_Click(null, null);
}
private void comboBoxSubtitleFont_SelectedValueChanged(object sender, EventArgs e)
{
subtitleListView1_SelectedIndexChanged(null, null);
}
private void comboBoxSubtitleFontSize_SelectedIndexChanged(object sender, EventArgs e)
{
subtitleListView1_SelectedIndexChanged(null, null);
}
private void comboBoxBorderWidth_SelectedIndexChanged(object sender, EventArgs e)
{
subtitleListView1_SelectedIndexChanged(null, null);
}
private void checkBoxAntiAlias_CheckedChanged(object sender, EventArgs e)
{
subtitleListView1_SelectedIndexChanged(null, null);
}
private void ExportPngXml_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
DialogResult = DialogResult.Cancel;
}
else if (e.KeyCode == Keys.F1)
{
Utilities.ShowHelp(string.Empty);
e.SuppressKeyPress = true;
}
}
private void ExportPngXml_Shown(object sender, EventArgs e)
{
_isLoading = false;
if (_exportType == "VOBSUB")
comboBoxSubtitleFontSize.SelectedIndex = 7;
else
comboBoxSubtitleFontSize.SelectedIndex = 16;
}
private void comboBoxHAlign_SelectedIndexChanged(object sender, EventArgs e)
{
subtitleListView1_SelectedIndexChanged(null, null);
}
private void checkBoxBold_CheckedChanged(object sender, EventArgs e)
{
subtitleListView1_SelectedIndexChanged(null, null);
}
private void buttonCustomResolution_Click(object sender, EventArgs e)
{
ChooseResolution cr = new ChooseResolution();
if (cr.ShowDialog(this) == DialogResult.OK)
{
comboBoxResolution.Items[8] = cr.VideoWidth+ "x" + cr.VideoHeight;
comboBoxResolution.SelectedIndex = 8;
}
}
private void ExportPngXml_ResizeEnd(object sender, EventArgs e)
{
subtitleListView1_SelectedIndexChanged(null, null);
}
private void comboBoxBottomMargin_SelectedIndexChanged(object sender, EventArgs e)
{
subtitleListView1_SelectedIndexChanged(null, null);
}
}
}