private CompressedFrame CalculateFrameChanges(Frame[] frames, FrameType type, int frameNumber)
{
int x_inc = 0;
int y_inc = 0;
switch (type)
{
case FrameType.TransitionalLeft:
x_inc = -1;
break;
case FrameType.TransitionalRight:
x_inc = 1;
break;
case FrameType.TransitionalTop:
y_inc = -1;
break;
case FrameType.TransitionalBottom:
y_inc = 1;
break;
}
var currentFrame = frames[frameNumber];
var prevFrame = frames[frameNumber - 1];
var changesPos = new List<Tuple<int, int>>();
for (int y = 0; y < FrameHeight; y++)
{
if (y + y_inc >= 0 && y + y_inc < FrameHeight)
{
var line = currentFrame.Lines[y + y_inc];
var prevLine = prevFrame.Lines[y];
for (int x = 0; x < FrameWidth; x++)
{
if (x + x_inc >= 0 && x + x_inc < FrameWidth)
{
if (line[x + x_inc] != prevLine[x])
changesPos.Add(new Tuple<int, int>(x + x_inc, y + y_inc));
}
}
}
}
var frameChanges = new List<FrameChange>();
var markedChanges = new bool[FrameHeight, FrameWidth];
if (type == FrameType.TransitionalLeft || type == FrameType.TransitionalRight)
{
int x = type == FrameType.TransitionalLeft ? FrameWidth - 1 : 0;
var chars = new List<char>();
for (int y = 0; y < FrameHeight; y++)
{
markedChanges[y, x] = true;
chars.Add(currentFrame.Lines[y][x]);
}
frameChanges.Add(new FrameChange { Type = FrameChangeType.Vertical, X = x, Y = 0, Chars = chars, Length = FrameHeight });
}
else if (type == FrameType.TransitionalTop || type == FrameType.TransitionalBottom)
{
int y = type == FrameType.TransitionalTop ? FrameHeight - 1 : 0;
var chars = new List<char>();
for (int x = 0; x < FrameWidth; x++)
{
markedChanges[y, x] = true;
chars.Add(currentFrame.Lines[y][x]);
}
frameChanges.Add(new FrameChange { Type = FrameChangeType.Horizontal, X = 0, Y = y, Chars = chars, Length = FrameWidth });
}
foreach (var changePos in changesPos)
{
if (!markedChanges[changePos.Item2, changePos.Item1])
{
int lineXInd = FrameWidth;
for (int x = changePos.Item1 + 1; x < FrameWidth; x++)
if (changesPos.FirstOrDefault(pos => pos.Item1 == x && pos.Item2 == changePos.Item2) == null)
{
lineXInd = x;
break;
}
int lineYInd = FrameHeight;
for (int y = changePos.Item2 + 1; y < FrameHeight; y++)
if (changesPos.FirstOrDefault(pos => pos.Item1 == changePos.Item1 && pos.Item2 == y) == null)
{
lineYInd = y;
break;
}
var frameChange = new FrameChange
{
X = changePos.Item1,
Y = changePos.Item2
};
if (lineXInd - changePos.Item1 >= lineYInd - changePos.Item2)
{
if (lineXInd - changePos.Item1 == 1)
{
frameChange.Type = FrameChangeType.One;
frameChange.Length = 1;
frameChange.Chars = new List<char>()
{
currentFrame.Lines[changePos.Item2][changePos.Item1],
};
markedChanges[changePos.Item2, changePos.Item1] = true;
}
else
{
frameChange.Type = FrameChangeType.Horizontal;
frameChange.Length = lineXInd - changePos.Item1;
frameChange.Chars = new List<char>();
for (int x = 0; x < frameChange.Length; x++)
{
frameChange.Chars.Add(currentFrame.Lines[changePos.Item2][changePos.Item1 + x]);
markedChanges[changePos.Item2, changePos.Item1 + x] = true;
}
}
}
else
{
frameChange.Type = FrameChangeType.Vertical;
frameChange.Length = lineYInd - changePos.Item2;
frameChange.Chars = new List<char>();
for (int y = 0; y < frameChange.Length; y++)
{
frameChange.Chars.Add(currentFrame.Lines[changePos.Item2 + y][changePos.Item1]);
markedChanges[changePos.Item2 + y, changePos.Item1] = true;
}
}
frameChanges.Add(frameChange);
}
}
return new CompressedFrame { FrameChanges = frameChanges, FrameType = type };
}