public static string Decompress_v_1_3(string str, int currentFrame)
{
byte[] bytes = Convert.FromBase64String(str);
int bitPos = 0;
byte tableLength = (byte)Utils.GetInt(bytes, ref bitPos, 8);
var bytesFreqs = new ByteCount[tableLength];
for (int i = 0; i < tableLength; i++)
{
bytesFreqs[i] = new ByteCount
{
Byte = (byte)Utils.GetInt(bytes, ref bitPos, 8),
Count = Utils.GetInt(bytes, ref bitPos, 24)
};
}
var tree = new HuffmanTree(bytesFreqs);
int frameDiffsCount = Utils.GetInt(bytes, ref bitPos, 24);
var frameNumbers = new List<int>();
int sum = 0;
frameNumbers.Add(sum);
for (int i = 0; i < frameDiffsCount; i++)
{
sum += Utils.GetInt(bytes, ref bitPos, 9);
frameNumbers.Add(sum);
}
int beginBitPos = bitPos;
bitPos = frameNumbers[currentFrame] * 8 + beginBitPos;
int repeatCount = Utils.GetInt(bytes, ref bitPos, 7);
var frameType = (FrameType)Utils.GetInt(bytes, ref bitPos, 3);
if (frameType == FrameType.Basic)
{
var frameLength = Utils.GetInt(bytes, ref bitPos, BasicBytesLengthBits);
var frameBytes = HuffmanRle2.Decode(tree, bytes, ref bitPos, frameLength, HuffmanRleRepeatedBits, HuffmanRleNotRepeatedBits);
return CharsToLine(BytesToFrame(frameBytes));
}
else
{
int prevFrame = currentFrame;
int prevRepeatCount;
FrameType prevFrameType;
do
{
prevFrame--;
bitPos = frameNumbers[prevFrame] * 8 + beginBitPos;
prevRepeatCount = Utils.GetInt(bytes, ref bitPos, 7);
prevFrameType = (FrameType)Utils.GetInt(bytes, ref bitPos, 3);
}
while (prevFrameType != FrameType.Basic);
var frameLength = Utils.GetInt(bytes, ref bitPos, BasicBytesLengthBits);
var frame = BytesToFrame(HuffmanRle2.Decode(tree, bytes, ref bitPos, frameLength, HuffmanRleRepeatedBits, HuffmanRleNotRepeatedBits));
do
{
prevFrame++;
bitPos = frameNumbers[prevFrame] * 8 + beginBitPos;
prevRepeatCount = Utils.GetInt(bytes, ref bitPos, 7);
prevFrameType = (FrameType)Utils.GetInt(bytes, ref bitPos, 3);
switch (prevFrameType)
{
case FrameType.Transitional:
break;
case FrameType.TransitionalLeft:
for (int y = 0; y < FrameHeight; y++)
for (int x = 0; x < FrameWidth - 1; x++)
frame[y, x] = frame[y, x + 1];
break;
case FrameType.TransitionalRight:
for (int y = 0; y < FrameHeight; y++)
for (int x = FrameWidth - 1; x >= 1; x--)
frame[y, x] = frame[y, x - 1];
break;
case FrameType.TransitionalTop:
for (int y = 0; y < FrameHeight - 1; y++)
for (int x = 0; x < FrameWidth; x++)
frame[y, x] = frame[y + 1, x];
break;
case FrameType.TransitionalBottom:
for (int y = FrameHeight - 1; y >= 1; y--)
for (int x = 0; x < FrameWidth; x++)
frame[y, x] = frame[y - 1, x];
break;
}
var frameChangesCount = Utils.GetInt(bytes, ref bitPos, 7);
for (int i = 0; i < frameChangesCount; i++)
{
var frameChangeType = (FrameChangeType)Utils.GetInt(bytes, ref bitPos, 2);
var position = Utils.GetInt(bytes, ref bitPos, 10);
int length;
if (frameChangeType == FrameChangeType.One)
length = 1;
else
length = Utils.GetInt(bytes, ref bitPos, frameChangeType == FrameChangeType.Horizontal ? 7 : 4);
for (int j = 0; j < length; j++)
{
frame[GetY(position), GetX(position)] = (char)Utils.GetValue(tree.Root, bytes, ref bitPos);
position += frameChangeType == FrameChangeType.Horizontal ? 1 : FrameWidth;
}
}
}
while (prevFrame != currentFrame);
return CharsToLine(frame).ToString();
}
}