diff --git a/ConvertSRTto3DASS.Cli/Cli.cs b/ConvertSRTto3DASS.Cli/Cli.cs new file mode 100644 index 0000000..6008c13 --- /dev/null +++ b/ConvertSRTto3DASS.Cli/Cli.cs @@ -0,0 +1,151 @@ +using System.Text; + +namespace ConvertSRTto3DASS; + +internal static class Cli +{ + public static void Run(string[] args) + { + if (args.Length == 0 || args[0] is "--help" or "-h" or "/?") + { + PrintUsage(); + return; + } + + var inputPath = args[0]; + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"Input file not found: {inputPath}"); + return; + } + + // Parse options + var options = new ConversionOptions + { + InputPath = inputPath, + Mode = "sbs", + ResX = 1280, + ResY = 720, + BaseResX = 1280, + BaseResY = 720, + FontSize = 16, + OffsetX = 4, + BottomOffset = 18, + SbsSideMargin = 640, + OuTopMargin = 385, + VerticalMargin = 25, + }; + + int i = 1; + while (i < args.Length) + { + var arg = args[i].Trim().ToLowerInvariant(); + switch (arg) + { + case "--mode": + options.Mode = GetNextArg(i++); + break; + case "--resx": + options.ResX = ParseInt(i++); + break; + case "--resy": + options.ResY = ParseInt(i++); + break; + case "--baseresx": + options.BaseResX = ParseInt(i++); + break; + case "--baseresy": + options.BaseResY = ParseInt(i++); + break; + case "--fontsize": + options.FontSize = ParseInt(i++); + break; + case "--offsetx": + options.OffsetX = ParseInt(i++); + break; + case "--bottomoffset": + options.BottomOffset = ParseInt(i++); + break; + case "--sbssidemargin": + options.SbsSideMargin = ParseInt(i++); + break; + case "--outopmargin": + options.OuTopMargin = ParseInt(i++); + break; + case "--verticalmargin": + options.VerticalMargin = ParseInt(i++); + break; + case "--output": + options.OutputPath = GetNextArg(i++); + break; + default: + Console.Error.WriteLine($"Unknown argument: {args[i]}"); + return; + } + i++; + } + + // Default output path + if (string.IsNullOrEmpty(options.OutputPath)) + { + options.OutputPath = Path.Combine( + Path.GetDirectoryName(options.InputPath) ?? ".", + Path.GetFileNameWithoutExtension(options.InputPath) + ".ass"); + } + + // Run conversion + try + { + 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($"Base resolution: {options.BaseResX}x{options.BaseResY}"); + Console.WriteLine($"Font size: {options.FontSize}"); + + var result = SrtConverter.Convert(options); + Console.WriteLine($"Parsed: {result.SubtitleCount} subtitle blocks"); + Console.WriteLine("Conversion complete."); + } + catch (Exception ex) + { + Console.Error.WriteLine($"ERROR: {ex.Message}"); + Console.Error.WriteLine(ex.ToString()); + } + + string GetNextArg(int index) => index + 1 < args.Length ? args[index + 1] : throw new ArgumentException($"Missing value for {args[index]}"); + int ParseInt(int index) + { + var val = index + 1 < args.Length ? args[index + 1] : throw new ArgumentException($"Missing value for {args[index]}"); + return int.TryParse(val, out var n) ? n : throw new ArgumentException($"Invalid value for {args[index]}: {val}"); + } + } + + static void PrintUsage() + { + Console.WriteLine("Usage:"); + Console.WriteLine(" ConvertSRTto3DASS.exe [options]"); + Console.WriteLine(); + Console.WriteLine("Options:"); + Console.WriteLine(" --mode sbs|ou|rg"); + Console.WriteLine(" --resx "); + Console.WriteLine(" --resy "); + Console.WriteLine(" --baseresx (scaling reference width, default 1280)"); + Console.WriteLine(" --baseresy (scaling reference height, default 720)"); + Console.WriteLine(" --fontsize "); + Console.WriteLine(" --offsetx (RG eye separation)"); + Console.WriteLine(" --bottomoffset (RG bottom offset)"); + Console.WriteLine(" --sbssidemargin (SBS side margin)"); + Console.WriteLine(" --outopmargin (OU top subtitle margin)"); + Console.WriteLine(" --verticalmargin (general vertical/bottom margin)"); + 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 1280 --resy 720"); + Console.WriteLine(@" ConvertSRTto3DASS.exe ""movie.srt"" --mode rg --offsetx 6 --bottomoffset 24"); + Console.WriteLine(@" ConvertSRTto3DASS.exe ""movie.srt"" --resx 1920 --resy 1080 --baseresx 1280 --baseresy 720"); + Console.WriteLine(@" ConvertSRTto3DASS.exe ""movie.srt"" --sbssidemargin 220 --verticalmargin 16"); + Console.WriteLine(@" ConvertSRTto3DASS.exe ""movie.srt"" --outopmargin 180 --fontsize 20 --output ""movie_custom.ass"""); + } +} diff --git a/ConvertSRTto3DASS.Cli/ConvertSRTto3DASS.Cli.csproj b/ConvertSRTto3DASS.Cli/ConvertSRTto3DASS.Cli.csproj new file mode 100644 index 0000000..4d85371 --- /dev/null +++ b/ConvertSRTto3DASS.Cli/ConvertSRTto3DASS.Cli.csproj @@ -0,0 +1,22 @@ + + + + Exe + net8.0 + enable + enable + imrayya + Copyright © imrayya 2021-2026 + ConvertSRTto3DASS + ConvertSRTto3DASS + + + + true + + + + + + + diff --git a/ConvertSRTto3DASS.Cli/Program.cs b/ConvertSRTto3DASS.Cli/Program.cs new file mode 100644 index 0000000..0cd8ad3 --- /dev/null +++ b/ConvertSRTto3DASS.Cli/Program.cs @@ -0,0 +1,6 @@ +namespace ConvertSRTto3DASS; + +internal static class Program +{ + static void Main(string[] args) => Cli.Run(args); +} diff --git a/ConvertSRTto3DASS.Core/ConversionOptions.cs b/ConvertSRTto3DASS.Core/ConversionOptions.cs new file mode 100644 index 0000000..b103346 --- /dev/null +++ b/ConvertSRTto3DASS.Core/ConversionOptions.cs @@ -0,0 +1,21 @@ +namespace ConvertSRTto3DASS; + +public class ConversionOptions +{ + public string InputPath { get; set; } = ""; + public string OutputPath { get; set; } = ""; + + public string Mode { get; set; } = "sbs"; // sbs, ou, rg + + public int ResX { get; set; } = 1280; + public int ResY { get; set; } = 720; + public int BaseResX { get; set; } = 1280; + public int BaseResY { get; set; } = 720; + + public int FontSize { get; set; } = 16; + public int OffsetX { get; set; } = 4; + public int BottomOffset { get; set; } = 18; + public int SbsSideMargin { get; set; } = 640; + public int OuTopMargin { get; set; } = 385; + public int VerticalMargin { get; set; } = 25; +} diff --git a/ConvertSRTto3DASS.Core/ConvertSRTto3DASS.Core.csproj b/ConvertSRTto3DASS.Core/ConvertSRTto3DASS.Core.csproj new file mode 100644 index 0000000..2aed899 --- /dev/null +++ b/ConvertSRTto3DASS.Core/ConvertSRTto3DASS.Core.csproj @@ -0,0 +1,16 @@ + + + + net8.0 + enable + enable + imrayya + Copyright © imrayya 2021-2026 + ConvertSRTto3DASS + + + + true + + + diff --git a/ConvertSRTto3DASS.Core/SrtConverter.cs b/ConvertSRTto3DASS.Core/SrtConverter.cs new file mode 100644 index 0000000..21898de --- /dev/null +++ b/ConvertSRTto3DASS.Core/SrtConverter.cs @@ -0,0 +1,273 @@ +using System.Text; +using System.Text.RegularExpressions; + +namespace ConvertSRTto3DASS; + +/// +/// Core SRT-to-ASS conversion logic for 3D subtitle formats. +/// +public static class SrtConverter +{ + public class ConversionResult + { + public string OutputText { get; set; } = ""; + public int SubtitleCount { get; set; } + } + + public static ConversionResult Convert(ConversionOptions options) + { + var srtText = ReadSrt(options.InputPath); + var subtitles = ParseSrt(srtText); + var header = CreateHeader(options); + var styles = CreateStyles(options); + var events = GenerateEvents(subtitles, options); + + var output = + "[Script Info]\n" + + header + + "\n\n[V4+ Styles]\n" + + styles + + "\n\n[Events]\n" + + events; + + File.WriteAllText(options.OutputPath, output, new UTF8Encoding(encoderShouldEmitUTF8Identifier: true)); + + return new ConversionResult + { + OutputText = output, + SubtitleCount = subtitles.Count + }; + } + + #region SRT Parsing + + private static string ReadSrt(string path) + { + using var reader = new StreamReader(path, Encoding.UTF8, detectEncodingFromByteOrderMarks: true); + var text = reader.ReadToEnd(); + + // Fallback to Windows-1252 if we see replacement characters + if (text.Contains('\uFFFD')) + text = File.ReadAllText(path, Encoding.GetEncoding(1252)); + + return text; + } + + private static List ParseSrt(string srtText) + { + var results = new List(); + srtText = srtText.Replace("\r\n", "\n").Replace("\r", "\n").Trim(); + + var blocks = Regex.Split(srtText, @"\n\s*\n"); + int expectedNumber = 1; + + foreach (var block in blocks) + { + var lines = block.Split('\n', StringSplitOptions.TrimEntries) + .Where(l => l.Length > 0) + .ToList(); + + if (lines.Count < 3) continue; + + if (!int.TryParse(lines[0], out var number)) continue; + + if (number != expectedNumber) + { + Console.Error.WriteLine($"Warning: expected subtitle number {expectedNumber}, but found {number}."); + expectedNumber = number; + } + expectedNumber++; + + var timeMatch = Regex.Match(lines[1], + @"^(?\d{2}:\d{2}:\d{2},\d{3})\s*-->\s*(?\d{2}:\d{2}:\d{2},\d{3})$"); + if (!timeMatch.Success) + { + Console.Error.WriteLine($"Skipping malformed timestamp: [{lines[1]}]"); + continue; + } + + var text = string.Join("\\N", lines.Skip(2)); + text = NormalizeFormatting(text); + + results.Add(new SrtSubtitle + { + Start = timeMatch.Groups["start"].Value, + End = timeMatch.Groups["end"].Value, + Text = text + }); + } + + return results; + } + + #endregion + + #region Formatting + + private static readonly Dictionary _tagReplacements = new() + { + { new Regex("", RegexOptions.IgnoreCase), "{\\b1}" }, + { new Regex("", RegexOptions.IgnoreCase), "{\\b0}" }, + { new Regex("", RegexOptions.IgnoreCase), "{\\i1}" }, + { new Regex("", RegexOptions.IgnoreCase), "{\\i0}" }, + { new Regex("", RegexOptions.IgnoreCase), "{\\u1}" }, + { new Regex("", RegexOptions.IgnoreCase), "{\\u0}" }, + { new Regex("", RegexOptions.IgnoreCase), "{\\c&HFFFFFF&}" } + }; + + private static readonly Regex _colorRegex = + new Regex("", RegexOptions.IgnoreCase); + + private static readonly Regex _markupRegex = + new Regex("<.+?>|(\\r)", RegexOptions.IgnoreCase); + + private static string NormalizeFormatting(string text) + { + foreach (var (pattern, replacement) in _tagReplacements) + text = pattern.Replace(text, replacement); + + // Convert HTML color to ASS BBGGRR format + while (_colorRegex.IsMatch(text)) + { + var match = _colorRegex.Match(text); + var rgb = match.Groups[1].Value; + var assColor = rgb.Substring(4, 2) + rgb.Substring(2, 2) + rgb.Substring(0, 2); + text = _colorRegex.Replace(text, "{\\c&H" + assColor + "&}", 1); + } + + return _markupRegex.Replace(text, ""); + } + + #endregion + + #region Time & Scaling + + private static string ConvertTimestamp(string timestamp) + { + var tmp = timestamp.Substring(1); + tmp = tmp.Substring(0, tmp.Length - 1); + return tmp.Replace(",", "."); + } + + private static int ScaleX(int value, ConversionOptions o) => + (int)Math.Round(value * (o.ResX / (double)o.BaseResX)); + + private static int ScaleY(int value, ConversionOptions o) => + (int)Math.Round(value * (o.ResY / (double)o.BaseResY)); + + private static int ScaleFont(int fontSize, ConversionOptions o) => + Math.Max(1, ScaleY(fontSize, o)); + + #endregion + + #region ASS Output Generation + + private static string CreateHeader(ConversionOptions o) => + $"; Generated by SRTto3Dsubtitles\n" + + $"Title: {Path.GetFileNameWithoutExtension(o.InputPath)}\n" + + "ScriptType: v4.00+\n" + + "Collisions: Normal\n" + + $"PlayResX: {o.ResX}\n" + + $"PlayResY: {o.ResY}\n" + + "ScaledBorderAndShadow: yes"; + + private static string CreateStyles(ConversionOptions o) + { + var fontSize = ScaleFont(o.FontSize, o); + + return o.Mode.ToLowerInvariant() switch + { + "ou" => CreateOuStyles(fontSize, o), + "rg" => CreateRgStyles(fontSize, o), + _ => CreateSbsStyles(fontSize, o) + }; + } + + private static string CreateSbsStyles(int fontSize, ConversionOptions o) + { + var sideMargin = ScaleX(o.SbsSideMargin, o); + var verticalMargin = ScaleY(o.VerticalMargin, o); + + return FormatStyle("Right", fontSize, sideMargin, 0, verticalMargin) + "\n" + + FormatStyle("Left", fontSize, 0, sideMargin, verticalMargin); + } + + private static string CreateOuStyles(int fontSize, ConversionOptions o) + { + var topMargin = ScaleY(o.OuTopMargin, o); + var bottomMargin = ScaleY(o.VerticalMargin, o); + + return FormatStyle("Top", fontSize, 0, 0, topMargin) + "\n" + + FormatStyle("Bottom", fontSize, 0, 0, bottomMargin); + } + + private static string CreateRgStyles(int fontSize, ConversionOptions o) + { + var verticalMargin = ScaleY(o.VerticalMargin, o); + + // Red = &H0000FF, Green = &H00FF00 (ASS uses BBGGRR) + return FormatStyle("RedEye", fontSize, 0, 0, verticalMargin, primary: "&H0000FF") + "\n" + + FormatStyle("GreenEye", fontSize, 0, 0, verticalMargin, primary: "&H00FF00"); + } + + private static string FormatStyle(string name, int fontSize, int marginL, int marginR, int marginV, + string primary = "&HFFFFFF") + { + return $"Style: {name},Arial,{fontSize},{primary},{primary},&H000000,&H000000," + + $"0,0,0,0,100,100,0,0,1,1,0,2," + + $"{marginL},{marginR},{marginV},0"; + } + + private static string GenerateEvents(List subs, ConversionOptions o) + { + var sb = new StringBuilder(); + sb.AppendLine("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"); + + foreach (var sub in subs) + { + var start = ConvertTimestamp(sub.Start); + var end = ConvertTimestamp(sub.End); + var text = sub.Text; + + switch (o.Mode.ToLowerInvariant()) + { + case "sbs": + sb.AppendLine($"Dialogue: 0,{start},{end},Right,,0,0,0,,{text}"); + sb.AppendLine($"Dialogue: 1,{start},{end},Left,,0,0,0,,{text}"); + break; + + case "ou": + sb.AppendLine($"Dialogue: 0,{start},{end},Top,,0,0,0,,{text}"); + sb.AppendLine($"Dialogue: 1,{start},{end},Bottom,,0,0,0,,{text}"); + break; + + case "rg": + var centerX = o.ResX / 2; + var scaledBottomOffset = ScaleY(o.BottomOffset, o); + var y = o.ResY - scaledBottomOffset; + var scaledOffsetX = ScaleX(o.OffsetX, o); + var redX = centerX - scaledOffsetX; + var greenX = centerX + scaledOffsetX; + + sb.AppendLine($"Dialogue: 0,{start},{end},RedEye,,0,0,0,,{{\\an2\\pos({redX},{y})}}{text}"); + sb.AppendLine($"Dialogue: 1,{start},{end},GreenEye,,0,0,0,,{{\\an2\\pos({greenX},{y})}}{text}"); + break; + } + } + + return sb.ToString(); + } + + #endregion + + #region Data Classes + + private class SrtSubtitle + { + public string Start { get; set; } = ""; + public string End { get; set; } = ""; + public string Text { get; set; } = ""; + } + + #endregion +} diff --git a/ConvertSRTto3DASS.Gui/ConvertSRTto3DASS.Gui.csproj b/ConvertSRTto3DASS.Gui/ConvertSRTto3DASS.Gui.csproj new file mode 100644 index 0000000..1a1821f --- /dev/null +++ b/ConvertSRTto3DASS.Gui/ConvertSRTto3DASS.Gui.csproj @@ -0,0 +1,44 @@ + + + + WinExe + net8.0-windows + true + enable + enable + imrayya + Copyright © imrayya 2021-2026 + ConvertSRTto3DASS + ConvertSRTto3DASS + + + + true + + + + + + + + + Form1.cs + + + True + True + Resources.resx + + + + + + Form1.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + diff --git a/ConvertSRTto3DASS.Gui/Form1.Designer.cs b/ConvertSRTto3DASS.Gui/Form1.Designer.cs new file mode 100644 index 0000000..4b36059 --- /dev/null +++ b/ConvertSRTto3DASS.Gui/Form1.Designer.cs @@ -0,0 +1,197 @@ +namespace ConvertSRTto3DASS; + +partial class Form1 +{ + private System.ComponentModel.IContainer components = null; + private Label label_Title; + private GroupBox groupBox_File; + private Label label_InputFile; + private TextBox textBox_InputFile; + private Button button_BrowseInput; + private Label label_OutputFile; + private TextBox textBox_OutputFile; + private Button button_BrowseOutput; + private GroupBox groupBox_Mode; + private Label label_Mode; + private ComboBox comboBox_Mode; + private GroupBox groupBox_Resolution; + private Label label_ResX; + private NumericUpDown numericUpDown_ResX; + private Label label_ResY; + private NumericUpDown numericUpDown_ResY; + private Label label_BaseResX; + private NumericUpDown numericUpDown_BaseResX; + private Label label_BaseResY; + private NumericUpDown numericUpDown_BaseResY; + private GroupBox groupBox_Settings; + private Label label_FontSize; + private NumericUpDown numericUpDown_FontSize; + private Label label_OffsetX; + private NumericUpDown numericUpDown_OffsetX; + private Label label_BottomOffset; + private NumericUpDown numericUpDown_BottomOffset; + private Label label_SbsSideMargin; + private NumericUpDown numericUpDown_SbsSideMargin; + private Label label_OuTopMargin; + private NumericUpDown numericUpDown_OuTopMargin; + private Label label_VerticalMargin; + private NumericUpDown numericUpDown_VerticalMargin; + private Button button_Convert; + private TextBox textBox_Status; + + protected override void Dispose(bool disposing) + { + if (disposing && components != null) + components.Dispose(); + base.Dispose(disposing); + } + + private void InitializeComponent() + { + var segoe = new Font("Segoe UI", 9f); + + SuspendLayout(); + + // ---- Title ---- + label_Title = new Label + { + Text = "SRT to 3D Subtitles", + Font = new Font("Segoe UI", 14f, FontStyle.Bold), + ForeColor = Color.FromArgb(30, 30, 30), + Location = new Point(20, 15), + AutoSize = true + }; + + // ---- File section ---- + groupBox_File = new GroupBox + { + Text = "Files", + Font = segoe, + Location = new Point(20, 60), + Size = new Size(1040, 80) + }; + label_InputFile = new Label { Text = "Input SRT:", Font = segoe, Location = new Point(15, 25), AutoSize = true }; + textBox_InputFile = new TextBox { Location = new Point(100, 22), Size = new Size(780, 23), ReadOnly = true }; + button_BrowseInput = new Button { Text = "Browse...", Location = new Point(890, 20), Size = new Size(90, 25), Font = segoe, FlatStyle = FlatStyle.Flat }; + label_OutputFile = new Label { Text = "Output ASS:", Font = segoe, Location = new Point(15, 55), AutoSize = true }; + textBox_OutputFile = new TextBox { Location = new Point(100, 52), Size = new Size(780, 23), ReadOnly = true }; + button_BrowseOutput = new Button { Text = "Browse...", Location = new Point(890, 50), Size = new Size(90, 25), Font = segoe, FlatStyle = FlatStyle.Flat }; + groupBox_File.Controls.AddRange([label_InputFile, textBox_InputFile, button_BrowseInput, label_OutputFile, textBox_OutputFile, button_BrowseOutput]); + + // ---- Mode section ---- + groupBox_Mode = new GroupBox + { + Text = "3D Mode", + Font = segoe, + Location = new Point(20, 150), + Size = new Size(320, 60) + }; + label_Mode = new Label { Text = "Format:", Font = segoe, Location = new Point(15, 22), AutoSize = true }; + comboBox_Mode = new ComboBox + { + Location = new Point(85, 19), + Size = new Size(210, 25), + Font = segoe, + DropDownStyle = ComboBoxStyle.DropDownList + }; + comboBox_Mode.Items.AddRange(["SBS (Side-by-Side)", "OU (Over-Under)", "RG (Red-Green)"]); + groupBox_Mode.Controls.AddRange([label_Mode, comboBox_Mode]); + + // ---- Resolution section ---- + groupBox_Resolution = new GroupBox + { + Text = "Resolution", + Font = segoe, + Location = new Point(355, 150), + Size = new Size(320, 60) + }; + label_ResX = new Label { Text = "Output:", Font = segoe, Location = new Point(15, 22), AutoSize = true }; + numericUpDown_ResX = new NumericUpDown { Location = new Point(65, 20), Size = new Size(80, 23), Minimum = 1, Maximum = 10000, Value = 1280 }; + label_ResY = new Label { Text = "x", Font = segoe, Location = new Point(150, 22), AutoSize = true }; + numericUpDown_ResY = new NumericUpDown { Location = new Point(165, 20), Size = new Size(80, 23), Minimum = 1, Maximum = 10000, Value = 720 }; + label_BaseResX = new Label { Text = "Base:", Font = segoe, Location = new Point(255, 22), AutoSize = true }; + numericUpDown_BaseResX = new NumericUpDown { Location = new Point(290, 20), Size = new Size(80, 23), Minimum = 1, Maximum = 10000, Value = 1280 }; + label_BaseResY = new Label { Text = "x", Font = segoe, Location = new Point(375, 22), AutoSize = true }; + numericUpDown_BaseResY = new NumericUpDown { Location = new Point(390, 20), Size = new Size(80, 23), Minimum = 1, Maximum = 10000, Value = 720 }; + groupBox_Resolution.Controls.AddRange([label_ResX, numericUpDown_ResX, label_ResY, numericUpDown_ResY, label_BaseResX, numericUpDown_BaseResX, label_BaseResY, numericUpDown_BaseResY]); + + // ---- Settings section ---- + groupBox_Settings = new GroupBox + { + Text = "Settings", + Font = segoe, + Location = new Point(20, 220), + Size = new Size(1040, 120) + }; + + var col1 = 15; + var col2 = 160; + var col3 = 310; + var col4 = 460; + var col5 = 610; + var col6 = 760; + var row = 25; + var rowStep = 30; + + label_FontSize = new Label { Text = "Font Size:", Font = segoe, Location = new Point(col1, row), AutoSize = true }; + numericUpDown_FontSize = new NumericUpDown { Location = new Point(col2, row - 2), Size = new Size(80, 23), Minimum = 1, Maximum = 200, Value = 16 }; + label_OffsetX = new Label { Text = "Offset X:", Font = segoe, Location = new Point(col3, row), AutoSize = true }; + numericUpDown_OffsetX = new NumericUpDown { Location = new Point(col4, row - 2), Size = new Size(80, 23), Minimum = 0, Maximum = 1000, Value = 4 }; + label_BottomOffset = new Label { Text = "Bottom Offset:", Font = segoe, Location = new Point(col5, row), AutoSize = true }; + numericUpDown_BottomOffset = new NumericUpDown { Location = new Point(col6, row - 2), Size = new Size(80, 23), Minimum = 0, Maximum = 1000, Value = 18 }; + row += rowStep; + + label_SbsSideMargin = new Label { Text = "SBS Margin:", Font = segoe, Location = new Point(col1, row), AutoSize = true }; + numericUpDown_SbsSideMargin = new NumericUpDown { Location = new Point(col2, row - 2), Size = new Size(80, 23), Minimum = 0, Maximum = 5000, Value = 640 }; + label_OuTopMargin = new Label { Text = "OU Margin:", Font = segoe, Location = new Point(col3, row), AutoSize = true }; + numericUpDown_OuTopMargin = new NumericUpDown { Location = new Point(col4, row - 2), Size = new Size(80, 23), Minimum = 0, Maximum = 5000, Value = 385 }; + label_VerticalMargin = new Label { Text = "V Margin:", Font = segoe, Location = new Point(col5, row), AutoSize = true }; + numericUpDown_VerticalMargin = new NumericUpDown { Location = new Point(col6, row - 2), Size = new Size(80, 23), Minimum = 0, Maximum = 5000, Value = 25 }; + + groupBox_Settings.Controls.AddRange([ + label_FontSize, numericUpDown_FontSize, label_OffsetX, numericUpDown_OffsetX, label_BottomOffset, numericUpDown_BottomOffset, + label_SbsSideMargin, numericUpDown_SbsSideMargin, label_OuTopMargin, numericUpDown_OuTopMargin, label_VerticalMargin, numericUpDown_VerticalMargin + ]); + + // ---- Convert button ---- + button_Convert = new Button + { + Text = "Convert", + Font = new Font("Segoe UI", 10f, FontStyle.Bold), + Location = new Point(20, 355), + Size = new Size(140, 36), + FlatStyle = FlatStyle.Flat, + BackColor = Color.FromArgb(0, 120, 215), + ForeColor = Color.White, + FlatAppearance = { BorderSize = 0 } + }; + + // ---- Status ---- + textBox_Status = new TextBox + { + Location = new Point(20, 405), + Size = new Size(1040, 180), + Multiline = true, + ReadOnly = true, + ScrollBars = ScrollBars.Vertical, + Font = new Font("Consolas", 8.5f), + BackColor = Color.FromArgb(245, 245, 245) + }; + + // ---- Form ---- + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(1080, 610); + MinimumSize = new Size(1100, 650); + FormBorderStyle = FormBorderStyle.FixedSingle; + MaximizeBox = false; + AllowDrop = true; + Text = "SRT to 3D Subtitles"; + Font = segoe; + StartPosition = FormStartPosition.CenterScreen; + + Controls.AddRange([label_Title, groupBox_File, groupBox_Mode, groupBox_Resolution, groupBox_Settings, button_Convert, textBox_Status]); + + ResumeLayout(false); + PerformLayout(); + } +} diff --git a/ConvertSRTto3DASS.Gui/Form1.cs b/ConvertSRTto3DASS.Gui/Form1.cs new file mode 100644 index 0000000..38cebfc --- /dev/null +++ b/ConvertSRTto3DASS.Gui/Form1.cs @@ -0,0 +1,170 @@ +using System.IO; + +namespace ConvertSRTto3DASS; + +public partial class Form1 : Form +{ + public Form1() + { + InitializeComponent(); + comboBox_Mode.SelectedIndex = 0; + UpdateModeUI(); + + // Drag-and-drop + DragEnter += (s, e) => + { + if (e.Data!.GetDataPresent(DataFormats.FileDrop)) + e.Effect = DragDropEffects.Copy; + }; + + DragDrop += (s, e) => + { + var files = (string[])e.Data!.GetData(DataFormats.FileDrop)!; + if (files.Length > 0 && files[0].EndsWith(".srt", StringComparison.OrdinalIgnoreCase)) + { + textBox_InputFile.Text = files[0]; + if (string.IsNullOrWhiteSpace(textBox_OutputFile.Text)) + textBox_OutputFile.Text = Path.ChangeExtension(files[0], ".ass"); + AppendStatus("Dropped: " + files[0]); + } + }; + } + + private void button_BrowseInput_Click(object sender, EventArgs e) + { + using var ofd = new OpenFileDialog + { + Filter = "SRT files (*.srt)|*.srt|All files (*.*)|*.*", + Title = "Select input SRT file" + }; + + if (ofd.ShowDialog() == DialogResult.OK) + { + textBox_InputFile.Text = ofd.FileName; + + if (string.IsNullOrWhiteSpace(textBox_OutputFile.Text)) + textBox_OutputFile.Text = Path.ChangeExtension(ofd.FileName, ".ass"); + + AppendStatus("Selected input file: " + ofd.FileName); + } + } + + private void button_BrowseOutput_Click(object sender, EventArgs e) + { + using var sfd = new SaveFileDialog + { + Filter = "ASS files (*.ass)|*.ass|All files (*.*)|*.*", + Title = "Select output ASS file", + DefaultExt = "ass" + }; + + if (!string.IsNullOrWhiteSpace(textBox_InputFile.Text)) + { + sfd.FileName = Path.GetFileNameWithoutExtension(textBox_InputFile.Text) + ".ass"; + sfd.InitialDirectory = Path.GetDirectoryName(textBox_InputFile.Text); + } + + if (sfd.ShowDialog() == DialogResult.OK) + { + textBox_OutputFile.Text = sfd.FileName; + AppendStatus("Selected output file: " + sfd.FileName); + } + } + + private void comboBox_Mode_SelectedIndexChanged(object sender, EventArgs e) => UpdateModeUI(); + + private string GetSelectedModeValue() + { + var selected = comboBox_Mode.SelectedItem?.ToString() ?? "sbs"; + var spaceIndex = selected.IndexOf(' '); + return spaceIndex > 0 ? selected[..spaceIndex].Trim().ToLowerInvariant() : selected.Trim().ToLowerInvariant(); + } + + private void button_Convert_Click(object sender, EventArgs e) + { + try + { + textBox_Status.Clear(); + + var inputPath = textBox_InputFile.Text.Trim(); + var outputPath = textBox_OutputFile.Text.Trim(); + var mode = GetSelectedModeValue(); + + 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"); + textBox_OutputFile.Text = outputPath; + } + + var options = new ConversionOptions + { + InputPath = inputPath, + OutputPath = outputPath, + Mode = mode, + ResX = (int)numericUpDown_ResX.Value, + ResY = (int)numericUpDown_ResY.Value, + BaseResX = (int)numericUpDown_BaseResX.Value, + BaseResY = (int)numericUpDown_BaseResY.Value, + FontSize = (int)numericUpDown_FontSize.Value, + OffsetX = (int)numericUpDown_OffsetX.Value, + BottomOffset = (int)numericUpDown_BottomOffset.Value, + SbsSideMargin = (int)numericUpDown_SbsSideMargin.Value, + OuTopMargin = (int)numericUpDown_OuTopMargin.Value, + VerticalMargin = (int)numericUpDown_VerticalMargin.Value + }; + + AppendStatus("Starting conversion..."); + AppendStatus($"Input: {options.InputPath}"); + AppendStatus($"Output: {options.OutputPath}"); + AppendStatus($"Mode: {options.Mode}"); + AppendStatus($"Resolution: {options.ResX}x{options.ResY}"); + AppendStatus($"Base resolution: {options.BaseResX}x{options.BaseResY}"); + AppendStatus($"Font size: {options.FontSize}"); + + var result = SrtConverter.Convert(options); + + AppendStatus($"Parsed: {result.SubtitleCount} subtitle blocks"); + 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() + { + var mode = GetSelectedModeValue(); + + numericUpDown_OffsetX.Enabled = mode == "rg"; + label_OffsetX.Enabled = mode == "rg"; + numericUpDown_BottomOffset.Enabled = mode == "rg"; + label_BottomOffset.Enabled = mode == "rg"; + numericUpDown_SbsSideMargin.Enabled = mode == "sbs"; + label_SbsSideMargin.Enabled = mode == "sbs"; + numericUpDown_OuTopMargin.Enabled = mode == "ou"; + label_OuTopMargin.Enabled = mode == "ou"; + } + + private void AppendStatus(string message) + { + if (textBox_Status.TextLength > 0) + textBox_Status.AppendText(Environment.NewLine); + + textBox_Status.AppendText(message); + } +} diff --git a/ConvertSRTto3DASSGUI/Form1.resx b/ConvertSRTto3DASS.Gui/Form1.resx similarity index 100% rename from ConvertSRTto3DASSGUI/Form1.resx rename to ConvertSRTto3DASS.Gui/Form1.resx diff --git a/ConvertSRTto3DASS.Gui/Program.cs b/ConvertSRTto3DASS.Gui/Program.cs new file mode 100644 index 0000000..7d2f21b --- /dev/null +++ b/ConvertSRTto3DASS.Gui/Program.cs @@ -0,0 +1,11 @@ +namespace ConvertSRTto3DASS; + +internal static class Program +{ + [STAThread] + static void Main() + { + ApplicationConfiguration.Initialize(); + Application.Run(new Form1()); + } +} diff --git a/ConvertSRTto3DASSGUI/Properties/Resources.Designer.cs b/ConvertSRTto3DASS.Gui/Properties/Resources.Designer.cs similarity index 98% rename from ConvertSRTto3DASSGUI/Properties/Resources.Designer.cs rename to ConvertSRTto3DASS.Gui/Properties/Resources.Designer.cs index 6f1a5cd..58c5edb 100644 --- a/ConvertSRTto3DASSGUI/Properties/Resources.Designer.cs +++ b/ConvertSRTto3DASS.Gui/Properties/Resources.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace ConvertSRTto3DASSGUI.Properties +namespace ConvertSRTto3DASS.Properties { diff --git a/ConvertSRTto3DASSGUI/Properties/Resources.resx b/ConvertSRTto3DASS.Gui/Properties/Resources.resx similarity index 100% rename from ConvertSRTto3DASSGUI/Properties/Resources.resx rename to ConvertSRTto3DASS.Gui/Properties/Resources.resx diff --git a/ConvertSRTto3DASSGUI/Properties/Settings.Designer.cs b/ConvertSRTto3DASS.Gui/Properties/Settings.Designer.cs similarity index 96% rename from ConvertSRTto3DASSGUI/Properties/Settings.Designer.cs rename to ConvertSRTto3DASS.Gui/Properties/Settings.Designer.cs index 80b9f94..db3d10b 100644 --- a/ConvertSRTto3DASSGUI/Properties/Settings.Designer.cs +++ b/ConvertSRTto3DASS.Gui/Properties/Settings.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace ConvertSRTto3DASSGUI.Properties +namespace ConvertSRTto3DASS.Properties { diff --git a/ConvertSRTto3DASSGUI/Properties/Settings.settings b/ConvertSRTto3DASS.Gui/Properties/Settings.settings similarity index 100% rename from ConvertSRTto3DASSGUI/Properties/Settings.settings rename to ConvertSRTto3DASS.Gui/Properties/Settings.settings diff --git a/ConvertSRTto3DASS.sln b/ConvertSRTto3DASS.sln index c0a0217..b7e7c95 100644 --- a/ConvertSRTto3DASS.sln +++ b/ConvertSRTto3DASS.sln @@ -1,11 +1,13 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 -VisualStudioVersion = 17.11.35208.52 +VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConvertSRTto3DASS", "ConvertSRTto3DASS\ConvertSRTto3DASS.csproj", "{7D7925DE-ADBD-4A26-B12B-8F12B68D3BFE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConvertSRTto3DASS.Core", "ConvertSRTto3DASS.Core\ConvertSRTto3DASS.Core.csproj", "{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConvertSRTto3DASSGUI", "ConvertSRTto3DASSGUI\ConvertSRTto3DASSGUI.csproj", "{8C44F434-2097-4FA3-BEE1-9569FB99F49C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConvertSRTto3DASS.Cli", "ConvertSRTto3DASS.Cli\ConvertSRTto3DASS.Cli.csproj", "{B2C3D4E5-F6A7-8901-BCDE-F12345678901}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConvertSRTto3DASS.Gui", "ConvertSRTto3DASS.Gui\ConvertSRTto3DASS.Gui.csproj", "{C3D4E5F6-A7B8-9012-CDEF-123456789012}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -13,19 +15,17 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7D7925DE-ADBD-4A26-B12B-8F12B68D3BFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {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 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {B5E10CFB-7432-4C4B-80FB-1B9349811932} + {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|Any CPU.Build.0 = Release|Any CPU + {B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Release|Any CPU.Build.0 = Release|Any CPU + {C3D4E5F6-A7B8-9012-CDEF-123456789012}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C3D4E5F6-A7B8-9012-CDEF-123456789012}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C3D4E5F6-A7B8-9012-CDEF-123456789012}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C3D4E5F6-A7B8-9012-CDEF-123456789012}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/ConvertSRTto3DASS/ConvertSRTto3DASS.csproj b/ConvertSRTto3DASS/ConvertSRTto3DASS.csproj deleted file mode 100644 index 9917ed2..0000000 --- a/ConvertSRTto3DASS/ConvertSRTto3DASS.csproj +++ /dev/null @@ -1,30 +0,0 @@ - - - - Exe - net48 - ConvertSRTto3DASS.Converter - imrayya - Copyright © imrayya 2021-2026 - - - - true - - - - - True - True - Settings.settings - - - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - - diff --git a/ConvertSRTto3DASS/Converter.cs b/ConvertSRTto3DASS/Converter.cs deleted file mode 100644 index 07ed217..0000000 --- a/ConvertSRTto3DASS/Converter.cs +++ /dev/null @@ -1,799 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; - -// SSA/ASS specification v4+ http://www.tcax.org/docs/ass-specs.htm -// SRT (SubRip) specification https://en.wikipedia.org/wiki/SubRip - -namespace ConvertSRTto3DASS -{ - public class Converter - { - private enum StereoMode - { - SBS, - OU, - RG // Experimental - } - - public static class ConverterDefaults - { - /// - ///720 as default is arbitary,it's my favorite resolution for space saving and most mobile 3d viewing doesn't benefit from much higher (IE google cardboard or Meta Quest Headset). - /// - public const int ResX = 1280; - public const int ResY = 720; - - public const int BaseResX = 1280; - public const int BaseResY = 720; - - public const int FontSize = 16; - public const int OffsetX = 4; - public const int BottomOffset = 18; - public const int SbsSideMargin = 640; - public const int OuTopMargin = 385; - public const int VerticalMargin = 25; - - public const string DefaultMode = "sbs"; - } - - private class Options - { - public string InputPath { get; set; } - public string OutputPath { get; set; } - - public StereoMode Mode { get; set; } = StereoMode.SBS; - - public int ResX { get; set; } = ConverterDefaults.ResX; - public int ResY { get; set; } = ConverterDefaults.ResY; - public int BaseResX { get; set; } = ConverterDefaults.BaseResX; - public int BaseResY { get; set; } = ConverterDefaults.BaseResY; - public int FontSize { get; set; } = ConverterDefaults.FontSize; - public int OffsetX { get; set; } = ConverterDefaults.OffsetX; - public int BottomOffset { get; set; } = ConverterDefaults.BottomOffset; - public int SbsSideMargin { get; set; } = ConverterDefaults.SbsSideMargin; - public int OuTopMargin { get; set; } = ConverterDefaults.OuTopMargin; - public int VerticalMargin { get; set; } = ConverterDefaults.VerticalMargin; - } - - private static readonly Dictionary RegexReplacementDict = - new Dictionary - { - { new Regex("", RegexOptions.IgnoreCase), "{\\b1}" }, - { new Regex("", RegexOptions.IgnoreCase), "{\\b0}" }, - { new Regex("", RegexOptions.IgnoreCase), "{\\i1}" }, - { new Regex("", RegexOptions.IgnoreCase), "{\\i0}" }, - { new Regex("", RegexOptions.IgnoreCase), "{\\u1}" }, - { new Regex("", RegexOptions.IgnoreCase), "{\\u0}" }, - { new Regex("", RegexOptions.IgnoreCase), "{\\c&HFFFFFF&}" } - }; - - private static readonly Regex ColorRegex = - new Regex("", RegexOptions.IgnoreCase); - - private static readonly Regex RemoveFormattingRegex = - new Regex("<.+?>|(\\r)", RegexOptions.IgnoreCase); - - public static void Main(string[] args) - { - try - { - var options = ParseArguments(args); - - if (options == null) - return; - - if (!File.Exists(options.InputPath)) - { - Console.Error.WriteLine("Input file not found: " + options.InputPath); - return; - } - - if (string.IsNullOrWhiteSpace(options.OutputPath)) - { - options.OutputPath = Path.Combine( - Path.GetDirectoryName(options.InputPath) ?? string.Empty, - 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("Base Res: " + options.BaseResX + "x" + options.BaseResY); - Console.WriteLine("Font size: " + options.FontSize); - Console.WriteLine("OffsetX: " + options.OffsetX); - Console.WriteLine("BottomOffset: " + options.BottomOffset); - Console.WriteLine("SbsSideMargin: " + options.SbsSideMargin); - Console.WriteLine("OuTopMargin: " + options.OuTopMargin); - Console.WriteLine("VerticalMargin: " + options.VerticalMargin); - - var extracted = ExtractSubFromSRT(options.InputPath); - Console.WriteLine("Subtitle blocks parsed: " + extracted.Count); - - var style = CreateStandardStyle(options); - var header = CreateHeader(options.InputPath, options.ResY, options.ResX); - var eventsText = ProcessSubs(extracted, options); - - var finished = - "[Script Info]\n" + - header + - "\n\n[V4+ Styles]\n" + - style + - "\n\n[Events]\n" + - eventsText; - - File.WriteAllText( - options.OutputPath, - finished, - new UTF8Encoding(encoderShouldEmitUTF8Identifier: true)); - - Console.WriteLine("Conversion complete."); - } - catch (Exception ex) - { - Console.Error.WriteLine("ERROR: " + ex.Message); - Console.Error.WriteLine(ex.ToString()); - } - } - - private static Options ParseArguments(string[] args) - { - if (args == null || args.Length == 0) - { - PrintUsage(); - return null; - } - - var options = new Options(); - int i = 0; - - if (args[0].StartsWith("--")) - { - Console.Error.WriteLine("First argument must be the input .srt file."); - PrintUsage(); - return null; - } - - options.InputPath = args[0]; - i = 1; - - while (i < args.Length) - { - string arg = args[i].Trim(); - - switch (arg.ToLowerInvariant()) - { - case "--mode": - EnsureValueExists(args, i, "--mode"); - options.Mode = ParseStereoMode(args[i + 1]); - i += 2; - break; - - case "--resx": - EnsureValueExists(args, i, "--resx"); - options.ResX = ParsePositiveInt(args[i + 1], "--resx"); - i += 2; - break; - - case "--resy": - EnsureValueExists(args, i, "--resy"); - options.ResY = ParsePositiveInt(args[i + 1], "--resy"); - i += 2; - break; - - case "--baseresx": - EnsureValueExists(args, i, "--baseresx"); - options.BaseResX = ParsePositiveInt(args[i + 1], "--baseresx"); - i += 2; - break; - - case "--baseresy": - EnsureValueExists(args, i, "--baseresy"); - options.BaseResY = ParsePositiveInt(args[i + 1], "--baseresy"); - i += 2; - break; - - case "--fontsize": - EnsureValueExists(args, i, "--fontsize"); - options.FontSize = ParsePositiveInt(args[i + 1], "--fontsize"); - i += 2; - break; - - case "--offsetx": - EnsureValueExists(args, i, "--offsetx"); - options.OffsetX = ParseNonNegativeInt(args[i + 1], "--offsetx"); - i += 2; - break; - - case "--bottomoffset": - EnsureValueExists(args, i, "--bottomoffset"); - options.BottomOffset = ParseNonNegativeInt(args[i + 1], "--bottomoffset"); - i += 2; - break; - - case "--sbssidemargin": - EnsureValueExists(args, i, "--sbssidemargin"); - options.SbsSideMargin = ParseNonNegativeInt(args[i + 1], "--sbssidemargin"); - i += 2; - break; - - case "--outopmargin": - EnsureValueExists(args, i, "--outopmargin"); - options.OuTopMargin = ParseNonNegativeInt(args[i + 1], "--outopmargin"); - i += 2; - break; - - case "--verticalmargin": - EnsureValueExists(args, i, "--verticalmargin"); - options.VerticalMargin = ParseNonNegativeInt(args[i + 1], "--verticalmargin"); - i += 2; - break; - - case "--output": - EnsureValueExists(args, i, "--output"); - options.OutputPath = args[i + 1]; - i += 2; - break; - - case "--help": - case "-h": - case "/?": - PrintUsage(); - return null; - - default: - throw new ArgumentException("Unknown argument: " + arg); - } - } - - return options; - } - - private static void EnsureValueExists(string[] args, int index, string optionName) - { - if (index + 1 >= args.Length || args[index + 1].StartsWith("--")) - throw new ArgumentException("Missing value for " + optionName); - } - - private static int ParsePositiveInt(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 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|rg"); - Console.WriteLine(" --resx "); - Console.WriteLine(" --resy "); - Console.WriteLine(" --baseresx (scaling reference width, default 1280)"); - Console.WriteLine(" --baseresy (scaling reference height, default 720)"); - Console.WriteLine(" --fontsize "); - Console.WriteLine(" --offsetx (RG eye separation)"); - Console.WriteLine(" --bottomoffset (RG bottom offset)"); - Console.WriteLine(" --sbssidemargin (SBS side margin)"); - Console.WriteLine(" --outopmargin (OU top subtitle margin)"); - Console.WriteLine(" --verticalmargin (general vertical/bottom margin)"); - 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 1280 --resy 720"); - Console.WriteLine(@" ConvertSRTto3DASS.exe ""movie.srt"" --mode rg --offsetx 6 --bottomoffset 24"); - Console.WriteLine(@" ConvertSRTto3DASS.exe ""movie.srt"" --resx 1920 --resy 1080 --baseresx 1280 --baseresy 720"); - Console.WriteLine(@" ConvertSRTto3DASS.exe ""movie.srt"" --sbssidemargin 220 --verticalmargin 16"); - Console.WriteLine(@" ConvertSRTto3DASS.exe ""movie.srt"" --outopmargin 180 --fontsize 20 --output ""movie_custom.ass"""); - } - - private static StereoMode ParseStereoMode(string mode) - { - if (string.IsNullOrWhiteSpace(mode)) - return StereoMode.SBS; - - switch (mode.Trim().ToLowerInvariant()) - { - case "sbs": - case "sidebyside": - case "side-by-side": - return StereoMode.SBS; - - case "ou": - case "overunder": - case "over-under": - case "tab": - case "topandbottom": - 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, rg"); - } - } - - private static int ScaleX(int value, Options options) - { - return (int)Math.Round(value * (options.ResX / (double)options.BaseResX)); - } - - private static int ScaleY(int value, Options options) - { - return (int)Math.Round(value * (options.ResY / (double)options.BaseResY)); - } - - private static int ScaleFont(int fontSize, Options options) - { - return Math.Max(1, ScaleY(fontSize, options)); - } - - private static string ChangeFormatting(string line) - { - foreach (var tuple in RegexReplacementDict) - { - line = tuple.Key.Replace(line, tuple.Value); - } - - while (ColorRegex.IsMatch(line)) - { - var match = ColorRegex.Match(line); - string rgb = match.Groups[1].Value; // RRGGBB - - string rr = rgb.Substring(0, 2); - string gg = rgb.Substring(2, 2); - string bb = rgb.Substring(4, 2); - - // ASS expects BBGGRR - string assColor = bb + gg + rr; - - line = ColorRegex.Replace(line, "{\\c&H" + assColor + "&}", 1); - } - - return RemoveFormatting(line); - } - - private static string RemoveFormatting(string line) - { - return RemoveFormattingRegex.Replace(line, ""); - } - - private static string ProcessSubs(List> srt, Options options) - { - string endResult = "Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\n"; - - foreach (var events in srt) - { - var start = ConvertTimeStamp(events.Item1); - var end = ConvertTimeStamp(events.Item2); - var text = 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 scaledBottomOffset = ScaleY(options.BottomOffset, options); - int y = options.ResY - scaledBottomOffset; - - int scaledOffsetX = ScaleX(options.OffsetX, options); - int redX = centerX - scaledOffsetX; - int greenX = centerX + scaledOffsetX; - - 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; - } - - private static string ConvertTimeStamp(string timeStamp) - { - var tmp = timeStamp.Substring(1); - tmp = tmp.Substring(0, tmp.Length - 1); - return tmp.Replace(",", "."); - } - - private static string CreateStandardStyle(Options options) - { - int scaledFontSize = ScaleFont(options.FontSize, options); - - switch (options.Mode) - { - case StereoMode.SBS: - return CreateSbsStyle(scaledFontSize, options); - - case StereoMode.OU: - return CreateOuStyle(scaledFontSize, options); - - case StereoMode.RG: - return CreateRgStyle(scaledFontSize, options); - - default: - throw new ArgumentOutOfRangeException(nameof(options.Mode)); - } - } - - private static string CreateSbsStyle(int fontSize, Options options) - { - int sideMargin = ScaleX(options.SbsSideMargin, options); - int verticalMargin = ScaleY(options.VerticalMargin, options); - - 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" + - - "Style: " + - "Right," + - "Arial," + - fontSize + "," + - "&HFFFFFF," + - "&HFFFFFF," + - "&H000000," + - "&H000000," + - "0," + - "0," + - "0," + - "0," + - "100," + - "100," + - "0," + - "0," + - "1," + - "1," + - "0," + - "2," + - sideMargin + "," + - "0," + - verticalMargin + "," + - "0\n" + - - "Style: " + - "Left," + - "Arial," + - fontSize + "," + - "&HFFFFFF," + - "&HFFFFFF," + - "&H000000," + - "&H000000," + - "0," + - "0," + - "0," + - "0," + - "100," + - "100," + - "0," + - "0," + - "1," + - "1," + - "0," + - "2," + - "0," + - sideMargin + "," + - verticalMargin + "," + - "0"; - - return style; - } - - private static string CreateOuStyle(int fontSize, Options options) - { - int bottomMargin = ScaleY(options.VerticalMargin, options); - int topMargin = ScaleY(options.OuTopMargin, options); - - 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" + - - "Style: " + - "Top," + - "Arial," + - fontSize + "," + - "&HFFFFFF," + - "&HFFFFFF," + - "&H000000," + - "&H000000," + - "0," + - "0," + - "0," + - "0," + - "100," + - "100," + - "0," + - "0," + - "1," + - "1," + - "0," + - "2," + - "0," + - "0," + - topMargin + "," + - "0\n" + - - "Style: " + - "Bottom," + - "Arial," + - fontSize + "," + - "&HFFFFFF," + - "&HFFFFFF," + - "&H000000," + - "&H000000," + - "0," + - "0," + - "0," + - "0," + - "100," + - "100," + - "0," + - "0," + - "1," + - "1," + - "0," + - "2," + - "0," + - "0," + - bottomMargin + "," + - "0"; - - return style; - } - - private static string CreateRgStyle(int fontSize, Options options) - { - int verticalMargin = ScaleY(options.VerticalMargin, options); - - 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," + - verticalMargin + "," + - "0\n" + - - // Green = &H00FF00 - "Style: " + - "GreenEye," + - "Arial," + - fontSize + "," + - "&H00FF00," + - "&H00FF00," + - "&H000000," + - "&H000000," + - "0," + - "0," + - "0," + - "0," + - "100," + - "100," + - "0," + - "0," + - "1," + - "1," + - "0," + - "2," + - "0," + - "0," + - verticalMargin + "," + - "0"; - - return style; - } - - private static string CreateHeader(string file, int resY = 720, int resX = 1280) - { - var name = Path.GetFileNameWithoutExtension(file); - - string scriptInfo = - "; Generated by ConvertSRTto3D\n" + - "Title: " + name + "\n" + - "ScriptType: v4.00+\n" + - "Collisions: Normal\n" + - "PlayResX: " + resX + "\n" + - "PlayResY: " + resY + "\n" + - "ScaledBorderAndShadow: yes"; - - return scriptInfo; - } - - private static string ReadTextSmart(string path) - { - using (var reader = new StreamReader(path, Encoding.UTF8, detectEncodingFromByteOrderMarks: true)) - { - string text = reader.ReadToEnd(); - - if (text.Contains('\uFFFD')) - text = File.ReadAllText(path, Encoding.GetEncoding(1252)); - - return text; - } - } - - private static List> ExtractSubFromSRT(string file) - { - var results = new List>(); - string srt = ReadTextSmart(file); - - srt = srt.Replace("\r\n", "\n").Replace("\r", "\n"); - - var blocks = Regex.Split(srt.Trim(), @"\n\s*\n"); - - int expectedDialogNumber = 1; - - foreach (var block in blocks) - { - var lines = block - .Split(new[] { '\n' }, StringSplitOptions.None) - .Select(l => l.Trim()) - .Where(l => l.Length > 0) - .ToList(); - - if (lines.Count < 3) - continue; - - if (!int.TryParse(lines[0], out int dialogNumber)) - { - Console.Error.WriteLine($"Skipping malformed block: expected subtitle number, got [{lines[0]}]"); - continue; - } - - if (dialogNumber != expectedDialogNumber) - { - Console.Error.WriteLine( - $"Warning: expected subtitle number {expectedDialogNumber}, but found {dialogNumber}."); - expectedDialogNumber = dialogNumber; - } - - expectedDialogNumber++; - - var timeMatch = Regex.Match( - lines[1], - @"^(?\d{2}:\d{2}:\d{2},\d{3})\s*-->\s*(?\d{2}:\d{2}:\d{2},\d{3})$"); - - if (!timeMatch.Success) - { - Console.Error.WriteLine($"Skipping malformed timestamp line: [{lines[1]}]"); - continue; - } - - string timestampStart = timeMatch.Groups["start"].Value; - string timestampEnd = timeMatch.Groups["end"].Value; - string subtitleText = string.Join("\\N", lines.Skip(2)); - - results.Add(new Tuple( - timestampStart, - timestampEnd, - ChangeFormatting(subtitleText), - "")); - } - - return results; - } - } -} \ No newline at end of file diff --git a/ConvertSRTto3DASS/Properties/Settings.Designer.cs b/ConvertSRTto3DASS/Properties/Settings.Designer.cs deleted file mode 100644 index ce6f161..0000000 --- a/ConvertSRTto3DASS/Properties/Settings.Designer.cs +++ /dev/null @@ -1,26 +0,0 @@ -//------------------------------------------------------------------------------ -// -// 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 ConvertSRTto3DASS.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.7.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/ConvertSRTto3DASS/Properties/Settings.settings b/ConvertSRTto3DASS/Properties/Settings.settings deleted file mode 100644 index 049245f..0000000 --- a/ConvertSRTto3DASS/Properties/Settings.settings +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/ConvertSRTto3DASSGUI/App.config b/ConvertSRTto3DASSGUI/App.config deleted file mode 100644 index 193aecc..0000000 --- a/ConvertSRTto3DASSGUI/App.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/ConvertSRTto3DASSGUI/ConvertSRTto3DASSGUI.csproj b/ConvertSRTto3DASSGUI/ConvertSRTto3DASSGUI.csproj deleted file mode 100644 index 00ef69e..0000000 --- a/ConvertSRTto3DASSGUI/ConvertSRTto3DASSGUI.csproj +++ /dev/null @@ -1,89 +0,0 @@ - - - - - Debug - AnyCPU - {8C44F434-2097-4FA3-BEE1-9569FB99F49C} - WinExe - ConvertSRTto3DASSGUI - ConvertSRTto3DASSGUI - v4.8 - 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 deleted file mode 100644 index 96dc207..0000000 --- a/ConvertSRTto3DASSGUI/Form1.Designer.cs +++ /dev/null @@ -1,551 +0,0 @@ -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 lblBaseResX; - private System.Windows.Forms.NumericUpDown nudBaseResX; - - private System.Windows.Forms.Label lblBaseResY; - private System.Windows.Forms.NumericUpDown nudBaseResY; - - 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.Label lblBottomOffset; - private System.Windows.Forms.NumericUpDown nudBottomOffset; - - private System.Windows.Forms.Label lblSbsSideMargin; - private System.Windows.Forms.NumericUpDown nudSbsSideMargin; - - private System.Windows.Forms.Label lblOuTopMargin; - private System.Windows.Forms.NumericUpDown nudOuTopMargin; - - private System.Windows.Forms.Label lblVerticalMargin; - private System.Windows.Forms.NumericUpDown nudVerticalMargin; - - 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.lblBaseResX = new System.Windows.Forms.Label(); - this.nudBaseResX = new System.Windows.Forms.NumericUpDown(); - this.lblBaseResY = new System.Windows.Forms.Label(); - this.nudBaseResY = 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.lblBottomOffset = new System.Windows.Forms.Label(); - this.nudBottomOffset = new System.Windows.Forms.NumericUpDown(); - this.lblSbsSideMargin = new System.Windows.Forms.Label(); - this.nudSbsSideMargin = new System.Windows.Forms.NumericUpDown(); - this.lblOuTopMargin = new System.Windows.Forms.Label(); - this.nudOuTopMargin = new System.Windows.Forms.NumericUpDown(); - this.lblVerticalMargin = new System.Windows.Forms.Label(); - this.nudVerticalMargin = 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.nudBaseResX)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.nudBaseResY)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.nudFontSize)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.nudOffsetX)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.nudBottomOffset)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.nudSbsSideMargin)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.nudOuTopMargin)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.nudVerticalMargin)).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[] { - 1280, - 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[] { - 720, - 0, - 0, - 0}); - // - // lblBaseResX - // - this.lblBaseResX.AutoSize = true; - this.lblBaseResX.Location = new System.Drawing.Point(520, 178); - this.lblBaseResX.Name = "lblBaseResX"; - this.lblBaseResX.Size = new System.Drawing.Size(81, 16); - this.lblBaseResX.TabIndex = 12; - this.lblBaseResX.Text = "Base Res X:"; - // - // nudBaseResX - // - this.nudBaseResX.Location = new System.Drawing.Point(620, 176); - this.nudBaseResX.Maximum = new decimal(new int[] { - 10000, - 0, - 0, - 0}); - this.nudBaseResX.Minimum = new decimal(new int[] { - 1, - 0, - 0, - 0}); - this.nudBaseResX.Name = "nudBaseResX"; - this.nudBaseResX.Size = new System.Drawing.Size(120, 22); - this.nudBaseResX.TabIndex = 13; - this.nudBaseResX.Value = new decimal(new int[] { - 1280, - 0, - 0, - 0}); - // - // lblBaseResY - // - this.lblBaseResY.AutoSize = true; - this.lblBaseResY.Location = new System.Drawing.Point(760, 178); - this.lblBaseResY.Name = "lblBaseResY"; - this.lblBaseResY.Size = new System.Drawing.Size(82, 16); - this.lblBaseResY.TabIndex = 14; - this.lblBaseResY.Text = "Base Res Y:"; - // - // nudBaseResY - // - this.nudBaseResY.Location = new System.Drawing.Point(860, 176); - this.nudBaseResY.Maximum = new decimal(new int[] { - 10000, - 0, - 0, - 0}); - this.nudBaseResY.Minimum = new decimal(new int[] { - 1, - 0, - 0, - 0}); - this.nudBaseResY.Name = "nudBaseResY"; - this.nudBaseResY.Size = new System.Drawing.Size(120, 22); - this.nudBaseResY.TabIndex = 15; - this.nudBaseResY.Value = new decimal(new int[] { - 720, - 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 = 16; - 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 = 17; - 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 = 18; - 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 = 19; - this.nudOffsetX.Value = new decimal(new int[] { - 4, - 0, - 0, - 0}); - // - // lblBottomOffset - // - this.lblBottomOffset.AutoSize = true; - this.lblBottomOffset.Location = new System.Drawing.Point(520, 228); - this.lblBottomOffset.Name = "lblBottomOffset"; - this.lblBottomOffset.Size = new System.Drawing.Size(89, 16); - this.lblBottomOffset.TabIndex = 20; - this.lblBottomOffset.Text = "Bottom Offset:"; - // - // nudBottomOffset - // - this.nudBottomOffset.Location = new System.Drawing.Point(620, 226); - this.nudBottomOffset.Maximum = new decimal(new int[] { - 1000, - 0, - 0, - 0}); - this.nudBottomOffset.Name = "nudBottomOffset"; - this.nudBottomOffset.Size = new System.Drawing.Size(120, 22); - this.nudBottomOffset.TabIndex = 21; - this.nudBottomOffset.Value = new decimal(new int[] { - 18, - 0, - 0, - 0}); - // - // lblSbsSideMargin - // - this.lblSbsSideMargin.AutoSize = true; - this.lblSbsSideMargin.Location = new System.Drawing.Point(24, 278); - this.lblSbsSideMargin.Name = "lblSbsSideMargin"; - this.lblSbsSideMargin.Size = new System.Drawing.Size(112, 16); - this.lblSbsSideMargin.TabIndex = 22; - this.lblSbsSideMargin.Text = "SBS Side Margin:"; - // - // nudSbsSideMargin - // - this.nudSbsSideMargin.Location = new System.Drawing.Point(140, 276); - this.nudSbsSideMargin.Maximum = new decimal(new int[] { - 5000, - 0, - 0, - 0}); - this.nudSbsSideMargin.Name = "nudSbsSideMargin"; - this.nudSbsSideMargin.Size = new System.Drawing.Size(120, 22); - this.nudSbsSideMargin.TabIndex = 23; - this.nudSbsSideMargin.Value = new decimal(new int[] { - 192, - 0, - 0, - 0}); - // - // lblOuTopMargin - // - this.lblOuTopMargin.AutoSize = true; - this.lblOuTopMargin.Location = new System.Drawing.Point(300, 278); - this.lblOuTopMargin.Name = "lblOuTopMargin"; - this.lblOuTopMargin.Size = new System.Drawing.Size(102, 16); - this.lblOuTopMargin.TabIndex = 24; - this.lblOuTopMargin.Text = "OU Top Margin:"; - // - // nudOuTopMargin - // - this.nudOuTopMargin.Location = new System.Drawing.Point(410, 276); - this.nudOuTopMargin.Maximum = new decimal(new int[] { - 5000, - 0, - 0, - 0}); - this.nudOuTopMargin.Name = "nudOuTopMargin"; - this.nudOuTopMargin.Size = new System.Drawing.Size(120, 22); - this.nudOuTopMargin.TabIndex = 25; - this.nudOuTopMargin.Value = new decimal(new int[] { - 154, - 0, - 0, - 0}); - // - // lblVerticalMargin - // - this.lblVerticalMargin.AutoSize = true; - this.lblVerticalMargin.Location = new System.Drawing.Point(560, 278); - this.lblVerticalMargin.Name = "lblVerticalMargin"; - this.lblVerticalMargin.Size = new System.Drawing.Size(99, 16); - this.lblVerticalMargin.TabIndex = 26; - this.lblVerticalMargin.Text = "Vertical Margin:"; - // - // nudVerticalMargin - // - this.nudVerticalMargin.Location = new System.Drawing.Point(670, 276); - this.nudVerticalMargin.Maximum = new decimal(new int[] { - 5000, - 0, - 0, - 0}); - this.nudVerticalMargin.Name = "nudVerticalMargin"; - this.nudVerticalMargin.Size = new System.Drawing.Size(120, 22); - this.nudVerticalMargin.TabIndex = 27; - this.nudVerticalMargin.Value = new decimal(new int[] { - 10, - 0, - 0, - 0}); - // - // btnConvert - // - this.btnConvert.Location = new System.Drawing.Point(27, 329); - this.btnConvert.Name = "btnConvert"; - this.btnConvert.Size = new System.Drawing.Size(145, 40); - this.btnConvert.TabIndex = 28; - 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, 392); - 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 = 29; - // - // Form1 - // - this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(1088, 640); - this.Controls.Add(this.txtStatus); - this.Controls.Add(this.btnConvert); - this.Controls.Add(this.nudVerticalMargin); - this.Controls.Add(this.lblVerticalMargin); - this.Controls.Add(this.nudOuTopMargin); - this.Controls.Add(this.lblOuTopMargin); - this.Controls.Add(this.nudSbsSideMargin); - this.Controls.Add(this.lblSbsSideMargin); - this.Controls.Add(this.nudBottomOffset); - this.Controls.Add(this.lblBottomOffset); - this.Controls.Add(this.nudOffsetX); - this.Controls.Add(this.lblOffsetX); - this.Controls.Add(this.nudFontSize); - this.Controls.Add(this.lblFontSize); - this.Controls.Add(this.nudBaseResY); - this.Controls.Add(this.lblBaseResY); - this.Controls.Add(this.nudBaseResX); - this.Controls.Add(this.lblBaseResX); - 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"; - this.Load += new System.EventHandler(this.Form1_Load); - ((System.ComponentModel.ISupportInitialize)(this.nudResX)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.nudResY)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.nudBaseResX)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.nudBaseResY)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.nudFontSize)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.nudOffsetX)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.nudBottomOffset)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.nudSbsSideMargin)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.nudOuTopMargin)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.nudVerticalMargin)).EndInit(); - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - } -} \ No newline at end of file diff --git a/ConvertSRTto3DASSGUI/Form1.cs b/ConvertSRTto3DASSGUI/Form1.cs deleted file mode 100644 index e909b0c..0000000 --- a/ConvertSRTto3DASSGUI/Form1.cs +++ /dev/null @@ -1,241 +0,0 @@ -using ConvertSRTto3DASS; -using System; -using System.IO; -using System.Windows.Forms; -using static ConvertSRTto3DASS.Converter; - -namespace ConvertSRTto3DASSGUI -{ - public partial class Form1 : Form - { - // Keep these in sync with Converter.cs defaults - private const int DefaultResX = Converter.ConverterDefaults.ResX;//1280 - private const int DefaultResY = 720; - private const int DefaultBaseResX = 1280; - private const int DefaultBaseResY = 720; - private const int DefaultFontSize = 16; - private const int DefaultOffsetX = 4; - private const int DefaultBottomOffset = 18; - private const int DefaultSbsSideMargin = 192; - private const int DefaultOuTopMargin = 154; - private const int DefaultVerticalMargin = 10; - - public Form1() - { - InitializeComponent(); - InitializeDefaults(); - - if (cmbMode.Items.Count > 0) - cmbMode.SelectedIndex = 0; - - UpdateModeUI(); - } - - private void InitializeDefaults() - { - txtInputFile.Text = string.Empty; - txtOutputFile.Text = string.Empty; - - nudResX.Value = ConverterDefaults.ResX; - nudResY.Value = ConverterDefaults.ResY; - nudBaseResX.Value = ConverterDefaults.BaseResX; - nudBaseResY.Value = ConverterDefaults.BaseResY; - nudFontSize.Value = ConverterDefaults.FontSize; - nudOffsetX.Value = ConverterDefaults.OffsetX; - nudBottomOffset.Value = ConverterDefaults.BottomOffset; - nudSbsSideMargin.Value = ConverterDefaults.SbsSideMargin; - nudOuTopMargin.Value = ConverterDefaults.OuTopMargin; - nudVerticalMargin.Value = ConverterDefaults.VerticalMargin; - - switch (ConverterDefaults.DefaultMode.ToLowerInvariant()) - { - case "sbs": - cmbMode.SelectedIndex = 0; - break; - case "ou": - cmbMode.SelectedIndex = 1; - break; - case "rg": - cmbMode.SelectedIndex = 2; - break; - default: - cmbMode.SelectedIndex = 0; - break; - } - } - - 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 = GetSelectedModeValue(); - - 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 baseResX = (int)nudBaseResX.Value; - int baseResY = (int)nudBaseResY.Value; - int fontSize = (int)nudFontSize.Value; - int offsetX = (int)nudOffsetX.Value; - int bottomOffset = (int)nudBottomOffset.Value; - int sbsSideMargin = (int)nudSbsSideMargin.Value; - int ouTopMargin = (int)nudOuTopMargin.Value; - int verticalMargin = (int)nudVerticalMargin.Value; - - AppendStatus("Starting conversion..."); - AppendStatus("Input: " + inputPath); - AppendStatus("Output: " + outputPath); - AppendStatus("Mode: " + mode); - AppendStatus("Resolution: " + resX + "x" + resY); - AppendStatus("Base Resolution: " + baseResX + "x" + baseResY); - AppendStatus("Font Size: " + fontSize); - AppendStatus("OffsetX: " + offsetX); - AppendStatus("BottomOffset: " + bottomOffset); - AppendStatus("SbsSideMargin: " + sbsSideMargin); - AppendStatus("OuTopMargin: " + ouTopMargin); - AppendStatus("VerticalMargin: " + verticalMargin); - - Converter.Main(new[] - { - inputPath, - "--mode", mode, - "--resx", resX.ToString(), - "--resy", resY.ToString(), - "--baseresx", baseResX.ToString(), - "--baseresy", baseResY.ToString(), - "--fontsize", fontSize.ToString(), - "--offsetx", offsetX.ToString(), - "--bottomoffset", bottomOffset.ToString(), - "--sbssidemargin", sbsSideMargin.ToString(), - "--outopmargin", ouTopMargin.ToString(), - "--verticalmargin", verticalMargin.ToString(), - "--output", outputPath - }); - - 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 = GetSelectedModeValue(); - - bool isSbs = mode == "sbs"; - bool isOu = mode == "ou"; - bool isRg = mode == "rg"; - - nudOffsetX.Enabled = isRg; - lblOffsetX.Enabled = isRg; - - nudBottomOffset.Enabled = isRg; - lblBottomOffset.Enabled = isRg; - - nudSbsSideMargin.Enabled = isSbs; - lblSbsSideMargin.Enabled = isSbs; - - nudOuTopMargin.Enabled = isOu; - lblOuTopMargin.Enabled = isOu; - - nudVerticalMargin.Enabled = true; - lblVerticalMargin.Enabled = true; - } - - private void AppendStatus(string message) - { - if (txtStatus.TextLength > 0) - txtStatus.AppendText(Environment.NewLine); - - txtStatus.AppendText(message); - } - - private void Form1_Load(object sender, EventArgs e) - { - } - } -} \ No newline at end of file diff --git a/ConvertSRTto3DASSGUI/Program.cs b/ConvertSRTto3DASSGUI/Program.cs deleted file mode 100644 index 967f155..0000000 --- a/ConvertSRTto3DASSGUI/Program.cs +++ /dev/null @@ -1,22 +0,0 @@ -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 deleted file mode 100644 index a4f9d01..0000000 --- a/ConvertSRTto3DASSGUI/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,33 +0,0 @@ -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("imrayya")] -[assembly: AssemblyProduct("SRTto3Dsubtitles")] -[assembly: AssemblyCopyright("Copyright © imrayya 2021-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/README.md b/README.md index bf02d99..f7870d7 100644 --- a/README.md +++ b/README.md @@ -18,20 +18,26 @@ When watching 3D movies (Side-by-Side, Over-Under, Anaglyph), centered subtitles ## Usage -### Command Line (CLI) +The application runs in two modes — **GUI** (no arguments) and **CLI** (with arguments). -**Drag and drop:** +### GUI -1. Drag and drop an `.srt` file onto `ConvertSRTto3DASS.exe` - - Uses default settings (SBS mode, 1280x720) -2. The resulting `.ass` file will be saved in the same directory with the same name +1. Launch `ConvertSRTto3DASS.exe` (or the Linux/macOS binary) +2. Select your `.srt` input file +3. Choose your 3D mode (SBS, OU, or Anaglyph) +4. Adjust settings as needed +5. Click **Convert** -**Command line:** +### Command Line + +Pass any argument to trigger CLI mode: ``` ConvertSRTto3DASS.exe input.srt [options] ``` +Or drag and drop an `.srt` file onto the executable. + Available options: ``` @@ -58,14 +64,6 @@ ConvertSRTto3DASS.exe movie.srt --mode ou --resx 1920 --resy 1080 ConvertSRTto3DASS.exe movie.srt --mode rg --offsetx 6 --bottomoffset 24 ``` -### GUI - -1. Launch `ConvertSRTto3DASSGUI.exe` -2. Select your `.srt` input file -3. Choose your 3D mode (SBS, OU, or Anaglyph) -4. Adjust settings as needed -5. Click **Convert** - > **Note:** The GUI is experimental. Feedback and bug reports are welcome! ## Known Issues @@ -75,8 +73,24 @@ ConvertSRTto3DASS.exe movie.srt --mode rg --offsetx 6 --bottomoffset 24 ## Requirements -- **Windows** — the GUI requires Windows (.NET Framework 4.8) -- **CLI** — the core converter is a .NET Framework 4.8 console application +- **.NET 8 SDK** — required to build +- **Windows** — the GUI runs on Windows +- **Linux/macOS** — the CLI runs cross-platform + +## Building + +```bash +# Build all projects +dotnet build + +# Publish CLI (cross-platform) +dotnet publish ConvertSRTto3DASS.Cli -c Release -r linux-x64 --self-contained false -p:PublishSingleFile=true +dotnet publish ConvertSRTto3DASS.Cli -c Release -r osx-x64 --self-contained false -p:PublishSingleFile=true +dotnet publish ConvertSRTto3DASS.Cli -c Release -r win-x64 --self-contained false -p:PublishSingleFile=true + +# Publish GUI (Windows only) +dotnet publish ConvertSRTto3DASS.Gui -c Release -r win-x64 --self-contained false -p:PublishSingleFile=true +``` ## License