From 470e23291f0924c3f263c1e7c661b4ee5f452903 Mon Sep 17 00:00:00 2001 From: "Emrick, Joshua" Date: Tue, 9 Jun 2026 11:16:53 -0400 Subject: [PATCH] feat: add red-green 3D mode and Windows Forms GUI - add rg (red-green) anaglyph subtitle mode with configurable horizontal offset - extend CLI mode handling to support sbs, ou, and rg - add offsetx option for anaglyph subtitle positioning - add Windows Forms GUI project for configuring and running conversions - add file pickers for input/output paths in the GUI - add GUI controls for mode, resolution, font size, and offset - add status output and mode-aware UI behavior in the GUI - update mode selection handling to support user-friendly display labels --- ConvertSRTto3DASS.sln | 12 +- ConvertSRTto3DASS/Converter.cs | 217 +++++++++--- ConvertSRTto3DASSGUI/App.config | 6 + .../ConvertSRTto3DASSGUI.csproj | 89 +++++ ConvertSRTto3DASSGUI/Form1.Designer.cs | 330 ++++++++++++++++++ ConvertSRTto3DASSGUI/Form1.cs | 158 +++++++++ ConvertSRTto3DASSGUI/Form1.resx | 120 +++++++ ConvertSRTto3DASSGUI/Program.cs | 22 ++ .../Properties/AssemblyInfo.cs | 33 ++ .../Properties/Resources.Designer.cs | 71 ++++ .../Properties/Resources.resx | 117 +++++++ .../Properties/Settings.Designer.cs | 30 ++ .../Properties/Settings.settings | 7 + 13 files changed, 1168 insertions(+), 44 deletions(-) create mode 100644 ConvertSRTto3DASSGUI/App.config create mode 100644 ConvertSRTto3DASSGUI/ConvertSRTto3DASSGUI.csproj create mode 100644 ConvertSRTto3DASSGUI/Form1.Designer.cs create mode 100644 ConvertSRTto3DASSGUI/Form1.cs create mode 100644 ConvertSRTto3DASSGUI/Form1.resx create mode 100644 ConvertSRTto3DASSGUI/Program.cs create mode 100644 ConvertSRTto3DASSGUI/Properties/AssemblyInfo.cs create mode 100644 ConvertSRTto3DASSGUI/Properties/Resources.Designer.cs create mode 100644 ConvertSRTto3DASSGUI/Properties/Resources.resx create mode 100644 ConvertSRTto3DASSGUI/Properties/Settings.Designer.cs create mode 100644 ConvertSRTto3DASSGUI/Properties/Settings.settings diff --git a/ConvertSRTto3DASS.sln b/ConvertSRTto3DASS.sln index 5060727..c0a0217 100644 --- a/ConvertSRTto3DASS.sln +++ b/ConvertSRTto3DASS.sln @@ -1,9 +1,11 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30523.141 +# Visual Studio Version 17 +VisualStudioVersion = 17.11.35208.52 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConvertSRTto3DASS", "ConvertSRTto3DASS\ConvertSRTto3DASS.csproj", "{7D7925DE-ADBD-4A26-B12B-8F12B68D3BFE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConvertSRTto3DASS", "ConvertSRTto3DASS\ConvertSRTto3DASS.csproj", "{7D7925DE-ADBD-4A26-B12B-8F12B68D3BFE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConvertSRTto3DASSGUI", "ConvertSRTto3DASSGUI\ConvertSRTto3DASSGUI.csproj", "{8C44F434-2097-4FA3-BEE1-9569FB99F49C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -15,6 +17,10 @@ Global {7D7925DE-ADBD-4A26-B12B-8F12B68D3BFE}.Debug|Any CPU.Build.0 = Debug|Any CPU {7D7925DE-ADBD-4A26-B12B-8F12B68D3BFE}.Release|Any CPU.ActiveCfg = Release|Any CPU {7D7925DE-ADBD-4A26-B12B-8F12B68D3BFE}.Release|Any CPU.Build.0 = Release|Any CPU + {8C44F434-2097-4FA3-BEE1-9569FB99F49C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8C44F434-2097-4FA3-BEE1-9569FB99F49C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8C44F434-2097-4FA3-BEE1-9569FB99F49C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8C44F434-2097-4FA3-BEE1-9569FB99F49C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ConvertSRTto3DASS/Converter.cs b/ConvertSRTto3DASS/Converter.cs index 9d2e8cd..7f9bd58 100644 --- a/ConvertSRTto3DASS/Converter.cs +++ b/ConvertSRTto3DASS/Converter.cs @@ -10,12 +10,13 @@ using System.Text.RegularExpressions; namespace ConvertSRTto3DASS { - class Converter + public class Converter { private enum StereoMode { SBS, - OU + OU, + RG //Experimental } private class Options @@ -26,9 +27,10 @@ namespace ConvertSRTto3DASS public int ResX { get; set; } = 384; public int ResY { get; set; } = 288; public int FontSize { get; set; } = 16; + public int OffsetX { get; set; } = 4; // used for RG anaglyph } - static void Main(string[] args) + public static void Main(string[] args) { try { @@ -50,18 +52,19 @@ namespace ConvertSRTto3DASS Path.GetFileNameWithoutExtension(options.InputPath) + ".ass"); } - Console.WriteLine("Input: " + options.InputPath); - Console.WriteLine("Output: " + options.OutputPath); - Console.WriteLine("Mode: " + options.Mode); - Console.WriteLine("Resolution:" + " " + options.ResX + "x" + options.ResY); - Console.WriteLine("Font size: " + options.FontSize); + Console.WriteLine("Input: " + options.InputPath); + Console.WriteLine("Output: " + options.OutputPath); + Console.WriteLine("Mode: " + options.Mode); + Console.WriteLine("Resolution: " + options.ResX + "x" + options.ResY); + Console.WriteLine("Font size: " + options.FontSize); + Console.WriteLine("OffsetX: " + options.OffsetX); var extracted = ExtractSubFromSRT(options.InputPath); Console.WriteLine("Subtitle blocks parsed: " + extracted.Count); var style = CreateStandardStyle(options.Mode, options.FontSize); var header = CreateHeader(options.InputPath, options.ResY, options.ResX); - var eventsText = ProcessSubs(extracted, options.Mode); + var eventsText = ProcessSubs(extracted, options); var finished = "[Script Info]\n" + @@ -93,7 +96,6 @@ namespace ConvertSRTto3DASS var options = new Options(); int i = 0; - // First non-option argument is input file if (args[0].StartsWith("--")) { Console.Error.WriteLine("First argument must be the input .srt file."); @@ -140,6 +142,12 @@ namespace ConvertSRTto3DASS i += 2; break; + case "--offsetx": + EnsureValueExists(args, i, "--offsetx"); + options.OffsetX = ParseNonNegativeInt(args[i + 1], "--offsetx"); + i += 2; + break; + case "--help": case "-h": case "/?": @@ -168,23 +176,32 @@ namespace ConvertSRTto3DASS return parsed; } + private static int ParseNonNegativeInt(string value, string optionName) + { + if (!int.TryParse(value, out int parsed) || parsed < 0) + throw new ArgumentException("Invalid value for " + optionName + ": " + value); + + return parsed; + } + private static void PrintUsage() { Console.WriteLine("Usage:"); Console.WriteLine(" ConvertSRTto3DASS.exe [options]"); Console.WriteLine(); Console.WriteLine("Options:"); - Console.WriteLine(" --mode sbs|ou"); + Console.WriteLine(" --mode sbs|ou|rg"); Console.WriteLine(" --resx "); Console.WriteLine(" --resy "); Console.WriteLine(" --fontsize "); + Console.WriteLine(" --offsetx (used for rg mode)"); Console.WriteLine(" --output "); Console.WriteLine(); Console.WriteLine("Examples:"); Console.WriteLine(@" ConvertSRTto3DASS.exe ""movie.srt"" --mode sbs"); Console.WriteLine(@" ConvertSRTto3DASS.exe ""movie.srt"" --mode ou --resx 384 --resy 288"); - Console.WriteLine(@" ConvertSRTto3DASS.exe ""movie.srt"" --mode sbs --fontsize 20"); - Console.WriteLine(@" ConvertSRTto3DASS.exe ""movie.srt"" --mode ou --output ""movie_ou.ass"""); + Console.WriteLine(@" ConvertSRTto3DASS.exe ""movie.srt"" --mode rg --offsetx 4"); + Console.WriteLine(@" ConvertSRTto3DASS.exe ""movie.srt"" --mode rg --fontsize 20 --output ""movie_rg.ass"""); } private static StereoMode ParseStereoMode(string mode) @@ -207,9 +224,16 @@ namespace ConvertSRTto3DASS case "top-and-bottom": return StereoMode.OU; + case "rg": + case "redgreen": + case "red-green": + case "anaglyph": + case "anaglyph-rg": + return StereoMode.RG; + default: throw new ArgumentException( - "Invalid 3D type '" + mode + "'. Valid values are: sbs, ou"); + "Invalid 3D type '" + mode + "'. Valid values are: sbs, ou, rg"); } } @@ -259,22 +283,42 @@ namespace ConvertSRTto3DASS return replacement; } - private static string ProcessSubs(List> srt, StereoMode mode) + private static string ProcessSubs(List> srt, Options options) { string endResult = "Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\n"; - string style1 = mode == StereoMode.SBS ? "Right" : "Top"; - string style2 = mode == StereoMode.SBS ? "Left" : "Bottom"; - foreach (var events in srt) { var start = ConvertTimeStamp(events.Item1); var end = ConvertTimeStamp(events.Item2); + var text = events.Item3; - var line = "Dialogue: 0," + start + "," + end + "," + style1 + ",,0,0,0,," + events.Item3 + "\n"; - line += "Dialogue: 1," + start + "," + end + "," + style2 + ",,0,0,0,," + events.Item3; + if (options.Mode == StereoMode.SBS) + { + var line = "Dialogue: 0," + start + "," + end + ",Right,,0,0,0,," + text + "\n"; + line += "Dialogue: 1," + start + "," + end + ",Left,,0,0,0,," + text; + endResult += line + "\n"; + } + else if (options.Mode == StereoMode.OU) + { + var line = "Dialogue: 0," + start + "," + end + ",Top,,0,0,0,," + text + "\n"; + line += "Dialogue: 1," + start + "," + end + ",Bottom,,0,0,0,," + text; + endResult += line + "\n"; + } + else if (options.Mode == StereoMode.RG) + { + int centerX = options.ResX / 2; + int y = options.ResY - 18; // near bottom + int redX = centerX - options.OffsetX; + int greenX = centerX + options.OffsetX; - endResult += line + "\n"; + string redText = "{\\an2\\pos(" + redX + "," + y + ")}" + text; + string greenText = "{\\an2\\pos(" + greenX + "," + y + ")}" + text; + + var line = "Dialogue: 0," + start + "," + end + ",RedEye,,0,0,0,," + redText + "\n"; + line += "Dialogue: 1," + start + "," + end + ",GreenEye,,0,0,0,," + greenText; + endResult += line + "\n"; + } } return endResult; @@ -289,10 +333,17 @@ namespace ConvertSRTto3DASS private static string CreateStandardStyle(StereoMode stereoMode, int fontSize) { - if (stereoMode == StereoMode.SBS) - return CreateSbsStyle(fontSize); - - return CreateOuStyle(fontSize); + switch (stereoMode) + { + case StereoMode.SBS: + return CreateSbsStyle(fontSize); + case StereoMode.OU: + return CreateOuStyle(fontSize); + case StereoMode.RG: + return CreateRgStyle(fontSize); + default: + throw new ArgumentOutOfRangeException(nameof(stereoMode)); + } } private static string CreateSbsStyle(int fontSize) @@ -327,10 +378,10 @@ namespace ConvertSRTto3DASS "Right," + "Arial," + fontSize + "," + - "&Hffffff," + - "&Hffffff," + - "&H0," + - "&H0," + + "&HFFFFFF," + + "&HFFFFFF," + + "&H000000," + + "&H000000," + "0," + "0," + "0," + @@ -352,10 +403,10 @@ namespace ConvertSRTto3DASS "Left," + "Arial," + fontSize + "," + - "&Hffffff," + - "&Hffffff," + - "&H0," + - "&H0," + + "&HFFFFFF," + + "&HFFFFFF," + + "&H000000," + + "&H000000," + "0," + "0," + "0," + @@ -408,10 +459,10 @@ namespace ConvertSRTto3DASS "Top," + "Arial," + fontSize + "," + - "&Hffffff," + - "&Hffffff," + - "&H0," + - "&H0," + + "&HFFFFFF," + + "&HFFFFFF," + + "&H000000," + + "&H000000," + "0," + "0," + "0," + @@ -433,10 +484,94 @@ namespace ConvertSRTto3DASS "Bottom," + "Arial," + fontSize + "," + - "&Hffffff," + - "&Hffffff," + - "&H0," + - "&H0," + + "&HFFFFFF," + + "&HFFFFFF," + + "&H000000," + + "&H000000," + + "0," + + "0," + + "0," + + "0," + + "100," + + "100," + + "0," + + "0," + + "1," + + "1," + + "0," + + "2," + + "0," + + "0," + + "10," + + "0"; + + return style; + } + + private static string CreateRgStyle(int fontSize) + { + string style = + "Format: " + + "Name, " + + "Fontname, " + + "Fontsize, " + + "PrimaryColour, " + + "SecondaryColour, " + + "OutlineColour, " + + "BackColour, " + + "Bold, " + + "Italic, " + + "Underline, " + + "StrikeOut, " + + "ScaleX, " + + "ScaleY, " + + "Spacing, " + + "Angle, " + + "BorderStyle, " + + "Outline, " + + "Shadow, " + + "Alignment, " + + "MarginL, " + + "MarginR, " + + "MarginV, " + + "Encoding\n" + + + // ASS color format is BBGGRR + // Red = &H0000FF + "Style: " + + "RedEye," + + "Arial," + + fontSize + "," + + "&H0000FF," + + "&H0000FF," + + "&H000000," + + "&H000000," + + "0," + + "0," + + "0," + + "0," + + "100," + + "100," + + "0," + + "0," + + "1," + + "1," + + "0," + + "2," + + "0," + + "0," + + "10," + + "0\n" + + + // Green = &H00FF00 + "Style: " + + "GreenEye," + + "Arial," + + fontSize + "," + + "&H00FF00," + + "&H00FF00," + + "&H000000," + + "&H000000," + "0," + "0," + "0," + diff --git a/ConvertSRTto3DASSGUI/App.config b/ConvertSRTto3DASSGUI/App.config new file mode 100644 index 0000000..56efbc7 --- /dev/null +++ b/ConvertSRTto3DASSGUI/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/ConvertSRTto3DASSGUI/ConvertSRTto3DASSGUI.csproj b/ConvertSRTto3DASSGUI/ConvertSRTto3DASSGUI.csproj new file mode 100644 index 0000000..1e2adfe --- /dev/null +++ b/ConvertSRTto3DASSGUI/ConvertSRTto3DASSGUI.csproj @@ -0,0 +1,89 @@ + + + + + Debug + AnyCPU + {8C44F434-2097-4FA3-BEE1-9569FB99F49C} + WinExe + ConvertSRTto3DASSGUI + ConvertSRTto3DASSGUI + v4.7.2 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + Form + + + Form1.cs + + + + + Form1.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + {7d7925de-adbd-4a26-b12b-8f12b68d3bfe} + ConvertSRTto3DASS + + + + \ No newline at end of file diff --git a/ConvertSRTto3DASSGUI/Form1.Designer.cs b/ConvertSRTto3DASSGUI/Form1.Designer.cs new file mode 100644 index 0000000..5af3a36 --- /dev/null +++ b/ConvertSRTto3DASSGUI/Form1.Designer.cs @@ -0,0 +1,330 @@ +namespace ConvertSRTto3DASSGUI +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + private System.Windows.Forms.Label lblInputFile; + private System.Windows.Forms.TextBox txtInputFile; + private System.Windows.Forms.Button btnBrowseInput; + + private System.Windows.Forms.Label lblOutputFile; + private System.Windows.Forms.TextBox txtOutputFile; + private System.Windows.Forms.Button btnBrowseOutput; + + private System.Windows.Forms.Label lblMode; + private System.Windows.Forms.ComboBox cmbMode; + + private System.Windows.Forms.Label lblResX; + private System.Windows.Forms.NumericUpDown nudResX; + + private System.Windows.Forms.Label lblResY; + private System.Windows.Forms.NumericUpDown nudResY; + + private System.Windows.Forms.Label lblFontSize; + private System.Windows.Forms.NumericUpDown nudFontSize; + + private System.Windows.Forms.Label lblOffsetX; + private System.Windows.Forms.NumericUpDown nudOffsetX; + + private System.Windows.Forms.Button btnConvert; + private System.Windows.Forms.TextBox txtStatus; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.lblInputFile = new System.Windows.Forms.Label(); + this.txtInputFile = new System.Windows.Forms.TextBox(); + this.btnBrowseInput = new System.Windows.Forms.Button(); + this.lblOutputFile = new System.Windows.Forms.Label(); + this.txtOutputFile = new System.Windows.Forms.TextBox(); + this.btnBrowseOutput = new System.Windows.Forms.Button(); + this.lblMode = new System.Windows.Forms.Label(); + this.cmbMode = new System.Windows.Forms.ComboBox(); + this.lblResX = new System.Windows.Forms.Label(); + this.nudResX = new System.Windows.Forms.NumericUpDown(); + this.lblResY = new System.Windows.Forms.Label(); + this.nudResY = new System.Windows.Forms.NumericUpDown(); + this.lblFontSize = new System.Windows.Forms.Label(); + this.nudFontSize = new System.Windows.Forms.NumericUpDown(); + this.lblOffsetX = new System.Windows.Forms.Label(); + this.nudOffsetX = new System.Windows.Forms.NumericUpDown(); + this.btnConvert = new System.Windows.Forms.Button(); + this.txtStatus = new System.Windows.Forms.TextBox(); + ((System.ComponentModel.ISupportInitialize)(this.nudResX)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nudResY)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nudFontSize)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nudOffsetX)).BeginInit(); + this.SuspendLayout(); + // + // lblInputFile + // + this.lblInputFile.AutoSize = true; + this.lblInputFile.Location = new System.Drawing.Point(24, 28); + this.lblInputFile.Name = "lblInputFile"; + this.lblInputFile.Size = new System.Drawing.Size(94, 16); + this.lblInputFile.TabIndex = 0; + this.lblInputFile.Text = "Input SRT File:"; + // + // txtInputFile + // + this.txtInputFile.Location = new System.Drawing.Point(140, 25); + this.txtInputFile.Name = "txtInputFile"; + this.txtInputFile.Size = new System.Drawing.Size(780, 22); + this.txtInputFile.TabIndex = 1; + // + // btnBrowseInput + // + this.btnBrowseInput.Location = new System.Drawing.Point(940, 23); + this.btnBrowseInput.Name = "btnBrowseInput"; + this.btnBrowseInput.Size = new System.Drawing.Size(120, 28); + this.btnBrowseInput.TabIndex = 2; + this.btnBrowseInput.Text = "Browse..."; + this.btnBrowseInput.UseVisualStyleBackColor = true; + this.btnBrowseInput.Click += new System.EventHandler(this.btnBrowseInput_Click); + // + // lblOutputFile + // + this.lblOutputFile.AutoSize = true; + this.lblOutputFile.Location = new System.Drawing.Point(24, 72); + this.lblOutputFile.Name = "lblOutputFile"; + this.lblOutputFile.Size = new System.Drawing.Size(103, 16); + this.lblOutputFile.TabIndex = 3; + this.lblOutputFile.Text = "Output ASS File:"; + // + // txtOutputFile + // + this.txtOutputFile.Location = new System.Drawing.Point(140, 69); + this.txtOutputFile.Name = "txtOutputFile"; + this.txtOutputFile.Size = new System.Drawing.Size(780, 22); + this.txtOutputFile.TabIndex = 4; + // + // btnBrowseOutput + // + this.btnBrowseOutput.Location = new System.Drawing.Point(940, 67); + this.btnBrowseOutput.Name = "btnBrowseOutput"; + this.btnBrowseOutput.Size = new System.Drawing.Size(120, 28); + this.btnBrowseOutput.TabIndex = 5; + this.btnBrowseOutput.Text = "Browse..."; + this.btnBrowseOutput.UseVisualStyleBackColor = true; + this.btnBrowseOutput.Click += new System.EventHandler(this.btnBrowseOutput_Click); + // + // lblMode + // + this.lblMode.AutoSize = true; + this.lblMode.Location = new System.Drawing.Point(24, 125); + this.lblMode.Name = "lblMode"; + this.lblMode.Size = new System.Drawing.Size(65, 16); + this.lblMode.TabIndex = 6; + this.lblMode.Text = "3D Mode:"; + // + // cmbMode + // + this.cmbMode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cmbMode.FormattingEnabled = true; + this.cmbMode.Items.AddRange(new object[] { + "sbs (Side-By-Side)", + "ou (Over-Under)", + "rg (Red-Green)"}); + this.cmbMode.Location = new System.Drawing.Point(140, 122); + this.cmbMode.Name = "cmbMode"; + this.cmbMode.Size = new System.Drawing.Size(180, 24); + this.cmbMode.TabIndex = 7; + this.cmbMode.SelectedIndexChanged += new System.EventHandler(this.cmbMode_SelectedIndexChanged); + // + // lblResX + // + this.lblResX.AutoSize = true; + this.lblResX.Location = new System.Drawing.Point(24, 178); + this.lblResX.Name = "lblResX"; + this.lblResX.Size = new System.Drawing.Size(46, 16); + this.lblResX.TabIndex = 8; + this.lblResX.Text = "Res X:"; + // + // nudResX + // + this.nudResX.Location = new System.Drawing.Point(140, 176); + this.nudResX.Maximum = new decimal(new int[] { + 10000, + 0, + 0, + 0}); + this.nudResX.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.nudResX.Name = "nudResX"; + this.nudResX.Size = new System.Drawing.Size(120, 22); + this.nudResX.TabIndex = 9; + this.nudResX.Value = new decimal(new int[] { + 384, + 0, + 0, + 0}); + // + // lblResY + // + this.lblResY.AutoSize = true; + this.lblResY.Location = new System.Drawing.Point(300, 178); + this.lblResY.Name = "lblResY"; + this.lblResY.Size = new System.Drawing.Size(47, 16); + this.lblResY.TabIndex = 10; + this.lblResY.Text = "Res Y:"; + // + // nudResY + // + this.nudResY.Location = new System.Drawing.Point(360, 176); + this.nudResY.Maximum = new decimal(new int[] { + 10000, + 0, + 0, + 0}); + this.nudResY.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.nudResY.Name = "nudResY"; + this.nudResY.Size = new System.Drawing.Size(120, 22); + this.nudResY.TabIndex = 11; + this.nudResY.Value = new decimal(new int[] { + 288, + 0, + 0, + 0}); + // + // lblFontSize + // + this.lblFontSize.AutoSize = true; + this.lblFontSize.Location = new System.Drawing.Point(24, 228); + this.lblFontSize.Name = "lblFontSize"; + this.lblFontSize.Size = new System.Drawing.Size(65, 16); + this.lblFontSize.TabIndex = 12; + this.lblFontSize.Text = "Font Size:"; + // + // nudFontSize + // + this.nudFontSize.Location = new System.Drawing.Point(140, 226); + this.nudFontSize.Maximum = new decimal(new int[] { + 200, + 0, + 0, + 0}); + this.nudFontSize.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.nudFontSize.Name = "nudFontSize"; + this.nudFontSize.Size = new System.Drawing.Size(120, 22); + this.nudFontSize.TabIndex = 13; + this.nudFontSize.Value = new decimal(new int[] { + 16, + 0, + 0, + 0}); + // + // lblOffsetX + // + this.lblOffsetX.AutoSize = true; + this.lblOffsetX.Location = new System.Drawing.Point(300, 228); + this.lblOffsetX.Name = "lblOffsetX"; + this.lblOffsetX.Size = new System.Drawing.Size(55, 16); + this.lblOffsetX.TabIndex = 14; + this.lblOffsetX.Text = "Offset X:"; + // + // nudOffsetX + // + this.nudOffsetX.Location = new System.Drawing.Point(360, 226); + this.nudOffsetX.Maximum = new decimal(new int[] { + 1000, + 0, + 0, + 0}); + this.nudOffsetX.Name = "nudOffsetX"; + this.nudOffsetX.Size = new System.Drawing.Size(120, 22); + this.nudOffsetX.TabIndex = 15; + this.nudOffsetX.Value = new decimal(new int[] { + 4, + 0, + 0, + 0}); + // + // btnConvert + // + this.btnConvert.Location = new System.Drawing.Point(27, 283); + this.btnConvert.Name = "btnConvert"; + this.btnConvert.Size = new System.Drawing.Size(145, 40); + this.btnConvert.TabIndex = 16; + this.btnConvert.Text = "Convert"; + this.btnConvert.UseVisualStyleBackColor = true; + this.btnConvert.Click += new System.EventHandler(this.btnConvert_Click); + // + // txtStatus + // + this.txtStatus.Location = new System.Drawing.Point(27, 349); + this.txtStatus.Multiline = true; + this.txtStatus.Name = "txtStatus"; + this.txtStatus.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.txtStatus.Size = new System.Drawing.Size(1033, 225); + this.txtStatus.TabIndex = 17; + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1088, 609); + this.Controls.Add(this.txtStatus); + this.Controls.Add(this.btnConvert); + this.Controls.Add(this.nudOffsetX); + this.Controls.Add(this.lblOffsetX); + this.Controls.Add(this.nudFontSize); + this.Controls.Add(this.lblFontSize); + this.Controls.Add(this.nudResY); + this.Controls.Add(this.lblResY); + this.Controls.Add(this.nudResX); + this.Controls.Add(this.lblResX); + this.Controls.Add(this.cmbMode); + this.Controls.Add(this.lblMode); + this.Controls.Add(this.btnBrowseOutput); + this.Controls.Add(this.txtOutputFile); + this.Controls.Add(this.lblOutputFile); + this.Controls.Add(this.btnBrowseInput); + this.Controls.Add(this.txtInputFile); + this.Controls.Add(this.lblInputFile); + this.Name = "Form1"; + this.Text = "Convert SRT to 3D ASS"; + ((System.ComponentModel.ISupportInitialize)(this.nudResX)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nudResY)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nudFontSize)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nudOffsetX)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + } +} \ No newline at end of file diff --git a/ConvertSRTto3DASSGUI/Form1.cs b/ConvertSRTto3DASSGUI/Form1.cs new file mode 100644 index 0000000..5550cf3 --- /dev/null +++ b/ConvertSRTto3DASSGUI/Form1.cs @@ -0,0 +1,158 @@ +using System; +using System.IO; +using System.Windows.Forms; +using ConvertSRTto3DASS; + +namespace ConvertSRTto3DASSGUI +{ + public partial class Form1 : Form + { + public Form1() + { + InitializeComponent(); + + if (cmbMode.Items.Count > 0) + cmbMode.SelectedIndex = 0; + + UpdateModeUI(); + } + + private void btnBrowseInput_Click(object sender, EventArgs e) + { + using (var ofd = new OpenFileDialog()) + { + ofd.Filter = "SRT files (*.srt)|*.srt|All files (*.*)|*.*"; + ofd.Title = "Select input SRT file"; + + if (ofd.ShowDialog() == DialogResult.OK) + { + txtInputFile.Text = ofd.FileName; + + if (string.IsNullOrWhiteSpace(txtOutputFile.Text)) + { + txtOutputFile.Text = Path.ChangeExtension(ofd.FileName, ".ass"); + } + + AppendStatus("Selected input file: " + ofd.FileName); + } + } + } + + private void btnBrowseOutput_Click(object sender, EventArgs e) + { + using (var sfd = new SaveFileDialog()) + { + sfd.Filter = "ASS files (*.ass)|*.ass|All files (*.*)|*.*"; + sfd.Title = "Select output ASS file"; + sfd.DefaultExt = "ass"; + + if (!string.IsNullOrWhiteSpace(txtInputFile.Text)) + { + sfd.FileName = Path.GetFileNameWithoutExtension(txtInputFile.Text) + ".ass"; + sfd.InitialDirectory = Path.GetDirectoryName(txtInputFile.Text); + } + + if (sfd.ShowDialog() == DialogResult.OK) + { + txtOutputFile.Text = sfd.FileName; + AppendStatus("Selected output file: " + sfd.FileName); + } + } + } + + private void cmbMode_SelectedIndexChanged(object sender, EventArgs e) + { + UpdateModeUI(); + } + + private string GetSelectedModeValue() + { + string selected = cmbMode.SelectedItem?.ToString() ?? "sbs"; + int spaceIndex = selected.IndexOf(' '); + + if (spaceIndex > 0) + return selected.Substring(0, spaceIndex).Trim().ToLowerInvariant(); + + return selected.Trim().ToLowerInvariant(); + } + + private void btnConvert_Click(object sender, EventArgs e) + { + try + { + txtStatus.Clear(); + + string inputPath = txtInputFile.Text.Trim(); + string outputPath = txtOutputFile.Text.Trim(); + string mode = cmbMode.SelectedItem?.ToString() ?? "sbs"; + + if (string.IsNullOrWhiteSpace(inputPath)) + { + MessageBox.Show("Please select an input SRT file.", "Missing Input", MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + + if (!File.Exists(inputPath)) + { + MessageBox.Show("The selected input file does not exist.", "Invalid Input", MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + + if (string.IsNullOrWhiteSpace(outputPath)) + { + outputPath = Path.ChangeExtension(inputPath, ".ass"); + txtOutputFile.Text = outputPath; + } + + int resX = (int)nudResX.Value; + int resY = (int)nudResY.Value; + int fontSize = (int)nudFontSize.Value; + int offsetX = (int)nudOffsetX.Value; + + AppendStatus("Starting conversion..."); + AppendStatus("Input: " + inputPath); + AppendStatus("Output: " + outputPath); + AppendStatus("Mode: " + mode); + AppendStatus("Resolution: " + resX + "x" + resY); + AppendStatus("Font Size: " + fontSize); + AppendStatus("OffsetX: " + offsetX); + + ConvertSRTto3DASS.Converter.Main(new[] + { + txtInputFile.Text, + "--mode", GetSelectedModeValue(), + "--resx", nudResX.Value.ToString(), + "--resy", nudResY.Value.ToString(), + "--fontsize", nudFontSize.Value.ToString(), + "--offsetx", nudOffsetX.Value.ToString(), + "--output", txtOutputFile.Text + }); + + AppendStatus("Conversion complete."); + MessageBox.Show("Conversion complete.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + catch (Exception ex) + { + AppendStatus("ERROR: " + ex.Message); + MessageBox.Show(ex.Message, "Conversion Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void UpdateModeUI() + { + string mode = cmbMode.SelectedItem?.ToString() ?? "sbs"; + bool isRg = mode.Equals("rg", StringComparison.OrdinalIgnoreCase); + + nudOffsetX.Enabled = isRg; + lblOffsetX.Enabled = isRg; + } + + private void AppendStatus(string message) + { + if (txtStatus.TextLength > 0) + txtStatus.AppendText(Environment.NewLine); + + txtStatus.AppendText(message); + } + } +} \ No newline at end of file diff --git a/ConvertSRTto3DASSGUI/Form1.resx b/ConvertSRTto3DASSGUI/Form1.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/ConvertSRTto3DASSGUI/Form1.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ConvertSRTto3DASSGUI/Program.cs b/ConvertSRTto3DASSGUI/Program.cs new file mode 100644 index 0000000..967f155 --- /dev/null +++ b/ConvertSRTto3DASSGUI/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace ConvertSRTto3DASSGUI +{ + internal static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Form1()); + } + } +} diff --git a/ConvertSRTto3DASSGUI/Properties/AssemblyInfo.cs b/ConvertSRTto3DASSGUI/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..e2909cc --- /dev/null +++ b/ConvertSRTto3DASSGUI/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ConvertSRTto3DASSGUI")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Stanley Black & Decker inc.")] +[assembly: AssemblyProduct("ConvertSRTto3DASSGUI")] +[assembly: AssemblyCopyright("Copyright © Stanley Black & Decker inc. 2026")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("8c44f434-2097-4fa3-bee1-9569fb99f49c")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ConvertSRTto3DASSGUI/Properties/Resources.Designer.cs b/ConvertSRTto3DASSGUI/Properties/Resources.Designer.cs new file mode 100644 index 0000000..6f1a5cd --- /dev/null +++ b/ConvertSRTto3DASSGUI/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ConvertSRTto3DASSGUI.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ConvertSRTto3DASSGUI.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/ConvertSRTto3DASSGUI/Properties/Resources.resx b/ConvertSRTto3DASSGUI/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/ConvertSRTto3DASSGUI/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ConvertSRTto3DASSGUI/Properties/Settings.Designer.cs b/ConvertSRTto3DASSGUI/Properties/Settings.Designer.cs new file mode 100644 index 0000000..80b9f94 --- /dev/null +++ b/ConvertSRTto3DASSGUI/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ConvertSRTto3DASSGUI.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/ConvertSRTto3DASSGUI/Properties/Settings.settings b/ConvertSRTto3DASSGUI/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/ConvertSRTto3DASSGUI/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + +