private List<CompressedFrame> GetCompressedFrames(HuffmanTree tree, bool reducedLines, List<Dictionary<FrameType, CompressedFrame>> framesChanges,
out List<int> frameDiffs)
{
var compressedFrames = new List<CompressedFrame>();
int currentFrame = 0;
frameDiffs = new List<int>();
for (int i = 0; i < Frames.Length; i++)
{
var frame = Frames[i];
var frameChanges = framesChanges[i];
int basisBitPos = 0;
byte[] basisBytes = null;
byte[] transBytes, transLeftBytes, transRightBytes, transTopBytes, transBottomBytes;
transBytes = transLeftBytes = transRightBytes = transTopBytes = transBottomBytes = null;
int frameTypeBit;
basisBytes = new byte[frame.Bytes.Length * 2];
Utils.AddInt(basisBytes, ref basisBitPos, frame.RepeatCount, 7);
frameTypeBit = basisBitPos;
Utils.AddInt(basisBytes, ref basisBitPos, (int)FrameType.Basic, 3);
Utils.AddInt(basisBytes, ref basisBitPos, frame.ReducedBytes.Length, BasicBytesLengthBits);
HuffmanRle.Encode(tree, reducedLines ? frame.ReducedBytes : frame.Bytes, ref basisBitPos, basisBytes, HuffmanRleRepeatedBits, HuffmanRleNotRepeatedBits);
basisBytes = basisBytes.Take((basisBitPos + 7) / 8).ToArray();
if (i != 0)
{
transBytes = GetCompressedFrameBytes(tree, frame, frameChanges[FrameType.Transitional]);
transLeftBytes = GetCompressedFrameBytes(tree, frame, frameChanges[FrameType.TransitionalLeft]);
transRightBytes = GetCompressedFrameBytes(tree, frame, frameChanges[FrameType.TransitionalRight]);
transTopBytes = GetCompressedFrameBytes(tree, frame, frameChanges[FrameType.TransitionalTop]);
transBottomBytes = GetCompressedFrameBytes(tree, frame, frameChanges[FrameType.TransitionalBottom]);
}
var typesBytes = new Dictionary<FrameType, byte[]>()
{
{ FrameType.Basic, basisBytes },
{ FrameType.Transitional, transBytes },
{ FrameType.TransitionalLeft, transLeftBytes },
{ FrameType.TransitionalRight, transRightBytes },
{ FrameType.TransitionalTop, transTopBytes },
{ FrameType.TransitionalBottom, transBottomBytes },
};
var minLengthBytesKey = typesBytes.Where(tb => tb.Value != null)
.Aggregate((a, b) => a.Value.Length < b.Value.Length ? a : b).Key;
Utils.AddInt(typesBytes[minLengthBytesKey], ref frameTypeBit, (int)minLengthBytesKey, 3);
compressedFrames.Add(new CompressedFrame
{
CompressedBytes = typesBytes[minLengthBytesKey],
FrameType = minLengthBytesKey,
FrameChanges = !frameChanges.ContainsKey(minLengthBytesKey) ? null : frameChanges[minLengthBytesKey].FrameChanges
});
currentFrame += typesBytes[minLengthBytesKey].Length;
frameDiffs.Add(typesBytes[minLengthBytesKey].Length);
}
return compressedFrames;
}