mirror of
https://github.com/SubtitleEdit/subtitleedit.git
synced 2024-11-22 19:22:53 +01:00
258 lines
9.0 KiB
C#
258 lines
9.0 KiB
C#
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Text;
|
|||
|
|
|||
|
namespace Nikse.SubtitleEdit.Core.SubtitleFormats
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// .CHK subtitle file format - 128 bytes blocks, first byte in block is id (01==text)
|
|||
|
/// </summary>
|
|||
|
public class Chk : SubtitleFormat
|
|||
|
{
|
|||
|
private readonly Encoding _codePage = Encoding.GetEncoding(850);
|
|||
|
// private string _languageId = "DEN"; // English
|
|||
|
|
|||
|
public override string Extension
|
|||
|
{
|
|||
|
get { return ".chk"; }
|
|||
|
}
|
|||
|
|
|||
|
public const string NameOfFormat = "CHK";
|
|||
|
|
|||
|
public override string Name
|
|||
|
{
|
|||
|
get { return NameOfFormat; }
|
|||
|
}
|
|||
|
|
|||
|
public override bool IsTimeBased
|
|||
|
{
|
|||
|
get { return true; }
|
|||
|
}
|
|||
|
|
|||
|
public override bool IsMine(List<string> lines, string fileName)
|
|||
|
{
|
|||
|
if (fileName.EndsWith(".chk", StringComparison.OrdinalIgnoreCase))
|
|||
|
{
|
|||
|
var buffer = FileUtil.ReadAllBytesShared(fileName);
|
|||
|
return buffer.Length > 0 && buffer[0] == 0x1d;
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
public override string ToText(Subtitle subtitle, string title)
|
|||
|
{
|
|||
|
return "Not implemented!";
|
|||
|
}
|
|||
|
|
|||
|
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName)
|
|||
|
{
|
|||
|
var buffer = FileUtil.ReadAllBytesShared(fileName);
|
|||
|
int index = 256;
|
|||
|
_errorCount = 0;
|
|||
|
subtitle.Paragraphs.Clear();
|
|||
|
while (index < buffer.Length)
|
|||
|
{
|
|||
|
Paragraph p = ReadParagraph(buffer, index);
|
|||
|
if (p != null)
|
|||
|
subtitle.Paragraphs.Add(p);
|
|||
|
index += 128;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private Queue<Paragraph> _timeCodeQueue = new Queue<Paragraph>();
|
|||
|
|
|||
|
private Paragraph ReadParagraph(byte[] buffer, int index)
|
|||
|
{
|
|||
|
if (buffer[index] == 1 && _timeCodeQueue.Count > 0) // text
|
|||
|
{
|
|||
|
var sb = new StringBuilder();
|
|||
|
int skipCount = 0;
|
|||
|
int textLength = buffer[index + 2] - 11;
|
|||
|
int start = index + 13;
|
|||
|
|
|||
|
for (int i = 0; i <= textLength; i++)
|
|||
|
{
|
|||
|
if (skipCount > 0)
|
|||
|
{
|
|||
|
skipCount--;
|
|||
|
}
|
|||
|
else if (buffer[index + 13 + i] == 0xFE)
|
|||
|
{
|
|||
|
sb.Append(GetText(buffer, start, index + i + 13));
|
|||
|
start = index + 13 + i + 3;
|
|||
|
skipCount = 2;
|
|||
|
sb.AppendLine();
|
|||
|
}
|
|||
|
else if (buffer[index + 13 + i] == 0)
|
|||
|
{
|
|||
|
sb.Append(GetText(buffer, start, index + i + 13));
|
|||
|
break;
|
|||
|
}
|
|||
|
if (i == textLength)
|
|||
|
{
|
|||
|
sb.Append(GetText(buffer, start, index + i + 13 + 1));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Paragraph p;
|
|||
|
if (_timeCodeQueue.Count > 0)
|
|||
|
p = _timeCodeQueue.Dequeue();
|
|||
|
else
|
|||
|
p = new Paragraph();
|
|||
|
p.Number = buffer[index + 3] * 256 + buffer[index + 4]; // Subtitle number
|
|||
|
p.Text = sb.ToString();
|
|||
|
//if (p.Number == 0 && p.Text.StartsWith("LANG:", StringComparison.Ordinal) && p.Text.Length > 8)
|
|||
|
//{
|
|||
|
// _languageId = p.Text.Substring(5, 3);
|
|||
|
//}
|
|||
|
return p;
|
|||
|
}
|
|||
|
if (buffer[index] == 0x0a && _timeCodeQueue.Count > 0)
|
|||
|
{
|
|||
|
// ?
|
|||
|
}
|
|||
|
else if (buffer[index] == 0x09 && _timeCodeQueue.Count > 0)
|
|||
|
{
|
|||
|
// ?
|
|||
|
}
|
|||
|
else // time codes
|
|||
|
{
|
|||
|
_timeCodeQueue = new Queue<Paragraph>();
|
|||
|
for (int i = 0; i < 15; i++)
|
|||
|
{
|
|||
|
int start = index + 2 + (i * 8);
|
|||
|
int totalFrameNumber = (buffer[start + 3] << 16) + (buffer[start + 5] << 8) + buffer[start + 4];
|
|||
|
int durationInFrames = buffer[start + 6];
|
|||
|
var p = new Paragraph(string.Empty, FramesToMilliseconds(totalFrameNumber), FramesToMilliseconds(totalFrameNumber + durationInFrames));
|
|||
|
_timeCodeQueue.Enqueue(p);
|
|||
|
}
|
|||
|
}
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
private string GetText(byte[] buffer, int start, int end)
|
|||
|
{
|
|||
|
string text = string.Empty;
|
|||
|
if (buffer[start] == 0x1f && buffer[start + 1] == 0x57 && buffer[start + 2] == 0x31 && buffer[start + 3] == 0x36) // W16
|
|||
|
{
|
|||
|
if (end - start > 4)
|
|||
|
text = Encoding.GetEncoding(950).GetString(buffer, start + 4, end - start - 4);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (end - start > 0)
|
|||
|
text = _codePage.GetString(buffer, start, end - start);
|
|||
|
}
|
|||
|
if (text.Length > 4 && text[0] == 0x1f && text[1] == 'R' && text[4] == '.' && "0123456789".Contains(text[2]) && "0123456789".Contains(text[3]))
|
|||
|
{
|
|||
|
text = text.Remove(0, 5);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// special language codes...
|
|||
|
text = text.Replace("ÔA", "Á");
|
|||
|
text = text.Replace("ÔE", "É");
|
|||
|
text = text.Replace("ÔI", "Í");
|
|||
|
text = text.Replace("ÓN", "Ñ");
|
|||
|
text = text.Replace("ÔO", "Ó");
|
|||
|
text = text.Replace("ÔU", "Ú");
|
|||
|
text = text.Replace("Ôa", "á");
|
|||
|
text = text.Replace("Ôe", "é");
|
|||
|
text = text.Replace("Ôi", "í");
|
|||
|
text = text.Replace("Ón", "ñ");
|
|||
|
text = text.Replace("Ôo", "ó");
|
|||
|
text = text.Replace("Ôu", "ú");
|
|||
|
|
|||
|
text = text.Replace("ÒA", "À");
|
|||
|
text = text.Replace("ÒE", "È");
|
|||
|
text = text.Replace("ÒU", "Ù");
|
|||
|
text = text.Replace("Òa", "à");
|
|||
|
text = text.Replace("Òe", "è");
|
|||
|
text = text.Replace("Òu", "ù");
|
|||
|
|
|||
|
text = text.Replace("ÕU", "Ü");
|
|||
|
text = text.Replace("ÕA", "Ä");
|
|||
|
text = text.Replace("ÕO", "Ö");
|
|||
|
text = text.Replace("Õu", "ü");
|
|||
|
text = text.Replace("Õa", "ä");
|
|||
|
text = text.Replace("Õo", "ö");
|
|||
|
|
|||
|
text = text.Replace("õa", "â");
|
|||
|
text = text.Replace("õe", "ê");
|
|||
|
text = text.Replace("õi", "î");
|
|||
|
text = text.Replace("õu", "û");
|
|||
|
text = text.Replace("õA", "Â");
|
|||
|
text = text.Replace("õE", "Ê");
|
|||
|
text = text.Replace("õI", "Î");
|
|||
|
text = text.Replace("õU", "Û");
|
|||
|
|
|||
|
return ApplyFont(text);
|
|||
|
}
|
|||
|
|
|||
|
private static string ApplyFont(string text)
|
|||
|
{
|
|||
|
var sb = new StringBuilder();
|
|||
|
string post = string.Empty;
|
|||
|
int i = 0;
|
|||
|
while (i < text.Length)
|
|||
|
{
|
|||
|
if (text[i] == 01 && i < text.Length - 4 && text[i + 1] == 0x1D && text[i + 2] == 07)
|
|||
|
{
|
|||
|
if (post != string.Empty)
|
|||
|
sb.Append("</font>");
|
|||
|
sb.Append("<font color=\"Red\">");
|
|||
|
post = "<font>";
|
|||
|
i += 2;
|
|||
|
}
|
|||
|
else if (text[i] == 01 && i < text.Length - 4 && text[i + 1] == 06)
|
|||
|
{
|
|||
|
if (post != string.Empty)
|
|||
|
sb.Append("</font>");
|
|||
|
sb.Append("<font color=\"Cyan\">");
|
|||
|
post = "<font>";
|
|||
|
i++;
|
|||
|
}
|
|||
|
else if (text[i] == 2)
|
|||
|
{
|
|||
|
if (post != string.Empty)
|
|||
|
sb.Append("</font>");
|
|||
|
sb.Append("<font color=\"Green\">");
|
|||
|
post = "<font>";
|
|||
|
}
|
|||
|
else if (text[i] == 3)
|
|||
|
{
|
|||
|
if (post != string.Empty)
|
|||
|
sb.Append("</font>");
|
|||
|
sb.Append("<font color=\"Yellow\">");
|
|||
|
post = "<font>";
|
|||
|
}
|
|||
|
else if (text[i] == 6)
|
|||
|
{
|
|||
|
if (post != string.Empty)
|
|||
|
sb.Append("</font>");
|
|||
|
sb.Append("<font color=\"Cyan\">");
|
|||
|
post = "<font>";
|
|||
|
}
|
|||
|
else if (text[i] == 7)
|
|||
|
{
|
|||
|
if (post != string.Empty)
|
|||
|
sb.Append("</font>");
|
|||
|
sb.Append("<font color=\"Red\">");
|
|||
|
post = "<font>";
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
sb.Append(text[i]);
|
|||
|
}
|
|||
|
i++;
|
|||
|
}
|
|||
|
|
|||
|
text = sb + post;
|
|||
|
if (string.IsNullOrWhiteSpace(HtmlUtil.RemoveHtmlTags(text)))
|
|||
|
return string.Empty;
|
|||
|
return text;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|