FX_BOOL Encode(FX_BYTE* inPut, FX_INT32 width, FX_INT32 height, FX_BYTE*& outPut, FX_INT32& encodeLength)
{
AllocProxy<FX_BYTE> pResult((width * 2 + 4) * height);
AllocProxy<FX_INT16> pLength(height);
AllocProxy<FX_BYTE> pFirstSeed(width);
memset(pFirstSeed, 0, width);
FX_BYTE* pSeed = pFirstSeed;
for (int i = 0; i < height; i++)
{
FX_INT32 rowLength = 0;
FX_BYTE* pOut = pResult + (width * 2 + 4) * i;
if (i == 1)
{
pOut[rowLength++] = 0;
pOut[rowLength++] = 0;
}
rowLength += 2;
if (i >= 1)
{
pSeed = inPut + (i - 1) * width;
}
FX_BYTE* rowInput = inPut + (width * i);
CompressRow(pSeed, rowInput, width, pOut, rowLength);
if (i == 1)
{
pOut[2] = rowLength - 4;
pOut[3] = (rowLength - 4) >> 8;
}
else
{
pOut[0] = rowLength - 2;
pOut[1] = (rowLength - 2) >> 8;
}
if (rowLength >= 65535)
return FALSE;
pLength[i] = rowLength;
}
for (int i = 0; i < height; i++)
{
encodeLength += pLength[i];
}
outPut = FX_Alloc(FX_BYTE, encodeLength);
FX_INT32 copyOffSet = 0;
for (int i = 0; i < height; i++)
{
memcpy(outPut + copyOffSet, pResult + (width * 2 + 4) * i, pLength[i]);
copyOffSet += pLength[i];
}
return TRUE;
}
void SetCommand(FX_BYTE* inPut, FX_BYTE* outPut, FX_INT32& index, FX_INT32 offSet, FX_INT32 replaceNum)
{
if (offSet <= 30)
{
outPut[index++] = offSet | ((replaceNum - 1) << 5);
}
else
{
outPut[index++] = 0x1f | ((replaceNum - 1) << 5);
offSet -= 31;
while (offSet >= 255)
{
outPut[index++] = 0xff;
offSet -= 255;
}
outPut[index++] = offSet;
}
for (FX_INT32 i = 0; i < replaceNum; i++)
{
outPut[index++] = inPut[i];
}
}
void CompressRow(FX_BYTE* seed, FX_BYTE* inPut, FX_INT32 inLength, FX_BYTE* outPut, FX_INT32& outLength)
{
FX_INT32 offSet = 0;
FX_INT32 replaceNum = 0;
FX_BYTE replaceValue = 0;
for (FX_INT32 i = 0; i < inLength; i++)
{
if (inPut[i] == seed[i])
offSet++;
else
{
replaceNum = 0;
while ((i + replaceNum) < inLength
&& replaceNum < 9
&& inPut[i + replaceNum] != seed[i + replaceNum])
{
replaceNum++;
}
if (replaceNum >= 9)
replaceNum = 8;
SetCommand(inPut + i, outPut, outLength, offSet, replaceNum);
i += replaceNum - 1;
offSet = 0;
}
}
}