diff --git a/Changelog.txt b/Changelog.txt index eb0135c8e..e225191fd 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -6,6 +6,8 @@ * New Netflix quality checker - thx askolesov/pavel-belenko * Added optional list view column "Actor" for ASS/SSA - thx william * Added new subtitle format - thx Merwyn + * Added new subtitle format - thx Philippe + * Added new subtitle fomrat - thx Eddy * IMPROVED: * Updated Chinese translation - thx Leon * Updated French translation - thx JM GBT diff --git a/libse/LibSE.csproj b/libse/LibSE.csproj index 66841ec3c..cc9a92946 100644 --- a/libse/LibSE.csproj +++ b/libse/LibSE.csproj @@ -216,6 +216,7 @@ + diff --git a/libse/SubtitleFormats/Csv5.cs b/libse/SubtitleFormats/Csv5.cs new file mode 100644 index 000000000..3ecc1a46c --- /dev/null +++ b/libse/SubtitleFormats/Csv5.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.RegularExpressions; + +namespace Nikse.SubtitleEdit.Core.SubtitleFormats +{ + public class Csv5 : SubtitleFormat + { + private const string Separator = ","; + private static readonly Regex TimeCodeRegex = new Regex(@"^\d\d:\d\d:\d\d\.\d\d$", RegexOptions.Compiled); + + public override string Extension + { + get { return ".csv"; } + } + + public override string Name + { + get { return "Csv5"; } + } + + public override bool IsTimeBased + { + get { return true; } + } + + public override bool IsMine(List lines, string fileName) + { + if (!string.IsNullOrEmpty(fileName) && !fileName.EndsWith(".csv", StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + + var subtitle = new Subtitle(); + LoadSubtitle(subtitle, lines, fileName); + return subtitle.Paragraphs.Count > 0; + } + + public override string ToText(Subtitle subtitle, string title) + { + const string format = "{1}{0}{2}{0}{3}"; + var sb = new StringBuilder(); + foreach (var p in subtitle.Paragraphs) + { + string text = p.Text.Replace(Environment.NewLine, "///").Replace("\"", string.Empty); + if (text.Contains(',')) + { + text = "\"" + text + "\""; + } + sb.AppendLine(string.Format(format, Separator, EncodeTimeCode(p.StartTime), EncodeTimeCode(p.EndTime), text)); + } + return sb.ToString().Trim(); + } + + private static string EncodeTimeCode(TimeCode time) + { + return string.Format("{0:00}:{1:00}:{2:00}.{3:00}", time.Hours, time.Minutes, time.Seconds, MillisecondsToFramesMaxFrameRate(time.Milliseconds)); + } + + public override void LoadSubtitle(Subtitle subtitle, List lines, string fileName) + { + _errorCount = 0; + foreach (string line in lines) + { + var parts = line.Split(','); + if (parts.Length >= 3) + { + var start = parts[0].Replace(" ", string.Empty).Replace("-", string.Empty); + var end = parts[1].Replace(" ", string.Empty).Replace("-", string.Empty); + string text = line.Remove(0, parts[0].Length + 1 + parts[1].Length).Replace("///", Environment.NewLine).Replace("\"", string.Empty).Trim(); + if (text.StartsWith(",", StringComparison.Ordinal)) + { + text = text.Remove(0, 1); + if (TimeCodeRegex.IsMatch(start) && TimeCodeRegex.IsMatch(end)) + { + try + { + subtitle.Paragraphs.Add(new Paragraph(DecodeTimeCodeFrames(start, SplitCharColon), DecodeTimeCodeFrames(end, SplitCharColon), text)); + } + catch + { + _errorCount++; + } + } + } + else + { + _errorCount++; + } + } + else if (!string.IsNullOrWhiteSpace(line)) + { + _errorCount++; + if (line.StartsWith("$", StringComparison.Ordinal)) + { + _errorCount += 500; + } + } + } + subtitle.Renumber(); + } + + } +} diff --git a/libse/SubtitleFormats/SubtitleFormat.cs b/libse/SubtitleFormats/SubtitleFormat.cs index b0a622cf6..e91b7e1d6 100644 --- a/libse/SubtitleFormats/SubtitleFormat.cs +++ b/libse/SubtitleFormats/SubtitleFormat.cs @@ -46,6 +46,7 @@ namespace Nikse.SubtitleEdit.Core.SubtitleFormats new Csv2(), new Csv3(), new Csv4(), + new Csv5(), new DCSubtitle(), new DCinemaSmpte2010(), new DCinemaSmpte2007(), diff --git a/src/Forms/Ocr/VobSubOcr.cs b/src/Forms/Ocr/VobSubOcr.cs index 02c464589..3aa7f4988 100644 --- a/src/Forms/Ocr/VobSubOcr.cs +++ b/src/Forms/Ocr/VobSubOcr.cs @@ -5954,7 +5954,7 @@ namespace Nikse.SubtitleEdit.Forms.Ocr { if (File.Exists(outputFileName)) { - result = File.ReadAllText(outputFileName); + result = File.ReadAllText(outputFileName, Encoding.UTF8); result = ParseHocr(result); File.Delete(outputFileName); }