mirror of
https://github.com/SubtitleEdit/subtitleedit.git
synced 2024-11-22 11:12:36 +01:00
122 lines
3.9 KiB
C#
122 lines
3.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
|
|
namespace Nikse.SubtitleEdit.Core
|
|
{
|
|
public class XSub
|
|
{
|
|
public TimeCode Start { get; set; }
|
|
public TimeCode End { get; set; }
|
|
public int Width { get; private set; }
|
|
public int Height { get; private set; }
|
|
|
|
private byte[] colorBuffer;
|
|
private byte[] rleBuffer;
|
|
|
|
public XSub(string timeCode, int width, int height, byte[] colors, byte[] rle)
|
|
{
|
|
Start = DecodeTimeCode(timeCode.Substring(0, 13));
|
|
End = DecodeTimeCode(timeCode.Substring(13, 12));
|
|
Width = width;
|
|
Height = height;
|
|
colorBuffer = colors;
|
|
rleBuffer = rle;
|
|
}
|
|
|
|
private static TimeCode DecodeTimeCode(string timeCode)
|
|
{
|
|
var parts = timeCode.Split(new[] { ':', ';', '.', ',', '-' }, StringSplitOptions.RemoveEmptyEntries);
|
|
return new TimeCode(int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2]), int.Parse(parts[3]));
|
|
}
|
|
|
|
private static int GenerateBitmap(FastBitmap bmp, byte[] buf, List<Color> fourColors)
|
|
{
|
|
int w = bmp.Width;
|
|
int h = bmp.Height;
|
|
int nibbleOffset = 0;
|
|
var nibble_end = buf.Length * 2;
|
|
var x = 0;
|
|
var y = 0;
|
|
for (;;)
|
|
{
|
|
if (nibbleOffset >= nibble_end)
|
|
return -1;
|
|
var v = GetNibble(buf, nibbleOffset++);
|
|
if (v < 0x4)
|
|
{
|
|
v = (v << 4) | GetNibble(buf, nibbleOffset++);
|
|
if (v < 0x10)
|
|
{
|
|
v = (v << 4) | GetNibble(buf, nibbleOffset++);
|
|
if (v < 0x040)
|
|
{
|
|
v = (v << 4) | GetNibble(buf, nibbleOffset++);
|
|
if (v < 4)
|
|
{
|
|
v |= (w - x) << 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
var len = v >> 2;
|
|
if (len > (w - x))
|
|
len = (w - x);
|
|
|
|
var color = v & 0x03;
|
|
if (color > 0)
|
|
{
|
|
Color c = fourColors[color];
|
|
bmp.SetPixel(x, y, c, len);
|
|
}
|
|
|
|
x += len;
|
|
if (x >= w)
|
|
{
|
|
y++;
|
|
if (y >= h)
|
|
break;
|
|
x = 0;
|
|
nibbleOffset += (nibbleOffset & 1);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
private static int GetNibble(byte[] buf, int nibble_offset)
|
|
{
|
|
return (buf[nibble_offset >> 1] >> ((1 - (nibble_offset & 1)) << 2)) & 0xf;
|
|
}
|
|
|
|
public Bitmap GetImage(Color background, Color pattern, Color emphasis1, Color emphasis2)
|
|
{
|
|
var fourColors = new List<Color> { background, pattern, emphasis1, emphasis2 };
|
|
var bmp = new Bitmap(Width, Height);
|
|
if (fourColors[0] != Color.Transparent)
|
|
{
|
|
using (var gr = Graphics.FromImage(bmp))
|
|
{
|
|
gr.FillRectangle(new SolidBrush(fourColors[0]), new Rectangle(0, 0, bmp.Width, bmp.Height));
|
|
}
|
|
}
|
|
var fastBmp = new FastBitmap(bmp);
|
|
fastBmp.LockImage();
|
|
GenerateBitmap(fastBmp, rleBuffer, fourColors);
|
|
fastBmp.UnlockImage();
|
|
return bmp;
|
|
}
|
|
|
|
private Color GetColor(int start)
|
|
{
|
|
return Color.FromArgb(colorBuffer[start], colorBuffer[start + 1], colorBuffer[start + 2]);
|
|
}
|
|
|
|
public Bitmap GetImage()
|
|
{
|
|
return GetImage(Color.Transparent, GetColor(3), GetColor(6), GetColor(9));
|
|
}
|
|
|
|
}
|
|
}
|