549 lines
16 KiB
C++
549 lines
16 KiB
C++
#pragma once
|
|
|
|
#include "Types.h"
|
|
#include "Utils.h"
|
|
|
|
namespace Jpeg2000
|
|
{
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
// Данный массив содержит все возможные состояния (см. Annex C Table C-2)
|
|
static MQCoderState aoMQCoderStates[47 * 2] =
|
|
{
|
|
{ 0x5601, 0, &aoMQCoderStates[2], &aoMQCoderStates[3] },
|
|
{ 0x5601, 1, &aoMQCoderStates[3], &aoMQCoderStates[2] },
|
|
{ 0x3401, 0, &aoMQCoderStates[4], &aoMQCoderStates[12] },
|
|
{ 0x3401, 1, &aoMQCoderStates[5], &aoMQCoderStates[13] },
|
|
{ 0x1801, 0, &aoMQCoderStates[6], &aoMQCoderStates[18] },
|
|
{ 0x1801, 1, &aoMQCoderStates[7], &aoMQCoderStates[19] },
|
|
{ 0x0ac1, 0, &aoMQCoderStates[8], &aoMQCoderStates[24] },
|
|
{ 0x0ac1, 1, &aoMQCoderStates[9], &aoMQCoderStates[25] },
|
|
{ 0x0521, 0, &aoMQCoderStates[10], &aoMQCoderStates[58] },
|
|
{ 0x0521, 1, &aoMQCoderStates[11], &aoMQCoderStates[59] },
|
|
{ 0x0221, 0, &aoMQCoderStates[76], &aoMQCoderStates[66] },
|
|
{ 0x0221, 1, &aoMQCoderStates[77], &aoMQCoderStates[67] },
|
|
{ 0x5601, 0, &aoMQCoderStates[14], &aoMQCoderStates[13] },
|
|
{ 0x5601, 1, &aoMQCoderStates[15], &aoMQCoderStates[12] },
|
|
{ 0x5401, 0, &aoMQCoderStates[16], &aoMQCoderStates[28] },
|
|
{ 0x5401, 1, &aoMQCoderStates[17], &aoMQCoderStates[29] },
|
|
{ 0x4801, 0, &aoMQCoderStates[18], &aoMQCoderStates[28] },
|
|
{ 0x4801, 1, &aoMQCoderStates[19], &aoMQCoderStates[29] },
|
|
{ 0x3801, 0, &aoMQCoderStates[20], &aoMQCoderStates[28] },
|
|
{ 0x3801, 1, &aoMQCoderStates[21], &aoMQCoderStates[29] },
|
|
{ 0x3001, 0, &aoMQCoderStates[22], &aoMQCoderStates[34] },
|
|
{ 0x3001, 1, &aoMQCoderStates[23], &aoMQCoderStates[35] },
|
|
{ 0x2401, 0, &aoMQCoderStates[24], &aoMQCoderStates[36] },
|
|
{ 0x2401, 1, &aoMQCoderStates[25], &aoMQCoderStates[37] },
|
|
{ 0x1c01, 0, &aoMQCoderStates[26], &aoMQCoderStates[40] },
|
|
{ 0x1c01, 1, &aoMQCoderStates[27], &aoMQCoderStates[41] },
|
|
{ 0x1601, 0, &aoMQCoderStates[58], &aoMQCoderStates[42] },
|
|
{ 0x1601, 1, &aoMQCoderStates[59], &aoMQCoderStates[43] },
|
|
{ 0x5601, 0, &aoMQCoderStates[30], &aoMQCoderStates[29] },
|
|
{ 0x5601, 1, &aoMQCoderStates[31], &aoMQCoderStates[28] },
|
|
{ 0x5401, 0, &aoMQCoderStates[32], &aoMQCoderStates[28] },
|
|
{ 0x5401, 1, &aoMQCoderStates[33], &aoMQCoderStates[29] },
|
|
{ 0x5101, 0, &aoMQCoderStates[34], &aoMQCoderStates[30] },
|
|
{ 0x5101, 1, &aoMQCoderStates[35], &aoMQCoderStates[31] },
|
|
{ 0x4801, 0, &aoMQCoderStates[36], &aoMQCoderStates[32] },
|
|
{ 0x4801, 1, &aoMQCoderStates[37], &aoMQCoderStates[33] },
|
|
{ 0x3801, 0, &aoMQCoderStates[38], &aoMQCoderStates[34] },
|
|
{ 0x3801, 1, &aoMQCoderStates[39], &aoMQCoderStates[35] },
|
|
{ 0x3401, 0, &aoMQCoderStates[40], &aoMQCoderStates[36] },
|
|
{ 0x3401, 1, &aoMQCoderStates[41], &aoMQCoderStates[37] },
|
|
{ 0x3001, 0, &aoMQCoderStates[42], &aoMQCoderStates[38] },
|
|
{ 0x3001, 1, &aoMQCoderStates[43], &aoMQCoderStates[39] },
|
|
{ 0x2801, 0, &aoMQCoderStates[44], &aoMQCoderStates[38] },
|
|
{ 0x2801, 1, &aoMQCoderStates[45], &aoMQCoderStates[39] },
|
|
{ 0x2401, 0, &aoMQCoderStates[46], &aoMQCoderStates[40] },
|
|
{ 0x2401, 1, &aoMQCoderStates[47], &aoMQCoderStates[41] },
|
|
{ 0x2201, 0, &aoMQCoderStates[48], &aoMQCoderStates[42] },
|
|
{ 0x2201, 1, &aoMQCoderStates[49], &aoMQCoderStates[43] },
|
|
{ 0x1c01, 0, &aoMQCoderStates[50], &aoMQCoderStates[44] },
|
|
{ 0x1c01, 1, &aoMQCoderStates[51], &aoMQCoderStates[45] },
|
|
{ 0x1801, 0, &aoMQCoderStates[52], &aoMQCoderStates[46] },
|
|
{ 0x1801, 1, &aoMQCoderStates[53], &aoMQCoderStates[47] },
|
|
{ 0x1601, 0, &aoMQCoderStates[54], &aoMQCoderStates[48] },
|
|
{ 0x1601, 1, &aoMQCoderStates[55], &aoMQCoderStates[49] },
|
|
{ 0x1401, 0, &aoMQCoderStates[56], &aoMQCoderStates[50] },
|
|
{ 0x1401, 1, &aoMQCoderStates[57], &aoMQCoderStates[51] },
|
|
{ 0x1201, 0, &aoMQCoderStates[58], &aoMQCoderStates[52] },
|
|
{ 0x1201, 1, &aoMQCoderStates[59], &aoMQCoderStates[53] },
|
|
{ 0x1101, 0, &aoMQCoderStates[60], &aoMQCoderStates[54] },
|
|
{ 0x1101, 1, &aoMQCoderStates[61], &aoMQCoderStates[55] },
|
|
{ 0x0ac1, 0, &aoMQCoderStates[62], &aoMQCoderStates[56] },
|
|
{ 0x0ac1, 1, &aoMQCoderStates[63], &aoMQCoderStates[57] },
|
|
{ 0x09c1, 0, &aoMQCoderStates[64], &aoMQCoderStates[58] },
|
|
{ 0x09c1, 1, &aoMQCoderStates[65], &aoMQCoderStates[59] },
|
|
{ 0x08a1, 0, &aoMQCoderStates[66], &aoMQCoderStates[60] },
|
|
{ 0x08a1, 1, &aoMQCoderStates[67], &aoMQCoderStates[61] },
|
|
{ 0x0521, 0, &aoMQCoderStates[68], &aoMQCoderStates[62] },
|
|
{ 0x0521, 1, &aoMQCoderStates[69], &aoMQCoderStates[63] },
|
|
{ 0x0441, 0, &aoMQCoderStates[70], &aoMQCoderStates[64] },
|
|
{ 0x0441, 1, &aoMQCoderStates[71], &aoMQCoderStates[65] },
|
|
{ 0x02a1, 0, &aoMQCoderStates[72], &aoMQCoderStates[66] },
|
|
{ 0x02a1, 1, &aoMQCoderStates[73], &aoMQCoderStates[67] },
|
|
{ 0x0221, 0, &aoMQCoderStates[74], &aoMQCoderStates[68] },
|
|
{ 0x0221, 1, &aoMQCoderStates[75], &aoMQCoderStates[69] },
|
|
{ 0x0141, 0, &aoMQCoderStates[76], &aoMQCoderStates[70] },
|
|
{ 0x0141, 1, &aoMQCoderStates[77], &aoMQCoderStates[71] },
|
|
{ 0x0111, 0, &aoMQCoderStates[78], &aoMQCoderStates[72] },
|
|
{ 0x0111, 1, &aoMQCoderStates[79], &aoMQCoderStates[73] },
|
|
{ 0x0085, 0, &aoMQCoderStates[80], &aoMQCoderStates[74] },
|
|
{ 0x0085, 1, &aoMQCoderStates[81], &aoMQCoderStates[75] },
|
|
{ 0x0049, 0, &aoMQCoderStates[82], &aoMQCoderStates[76] },
|
|
{ 0x0049, 1, &aoMQCoderStates[83], &aoMQCoderStates[77] },
|
|
{ 0x0025, 0, &aoMQCoderStates[84], &aoMQCoderStates[78] },
|
|
{ 0x0025, 1, &aoMQCoderStates[85], &aoMQCoderStates[79] },
|
|
{ 0x0015, 0, &aoMQCoderStates[86], &aoMQCoderStates[80] },
|
|
{ 0x0015, 1, &aoMQCoderStates[87], &aoMQCoderStates[81] },
|
|
{ 0x0009, 0, &aoMQCoderStates[88], &aoMQCoderStates[82] },
|
|
{ 0x0009, 1, &aoMQCoderStates[89], &aoMQCoderStates[83] },
|
|
{ 0x0005, 0, &aoMQCoderStates[90], &aoMQCoderStates[84] },
|
|
{ 0x0005, 1, &aoMQCoderStates[91], &aoMQCoderStates[85] },
|
|
{ 0x0001, 0, &aoMQCoderStates[90], &aoMQCoderStates[86] },
|
|
{ 0x0001, 1, &aoMQCoderStates[91], &aoMQCoderStates[87] },
|
|
{ 0x5601, 0, &aoMQCoderStates[92], &aoMQCoderStates[92] },
|
|
{ 0x5601, 1, &aoMQCoderStates[93], &aoMQCoderStates[93] },
|
|
};
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
// Вспомогательные функции
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
static void MQC_ByteOut(MQCoder *pMQCoder)
|
|
{
|
|
if (*pMQCoder->pBufferPointer == 0xff)
|
|
{
|
|
pMQCoder->pBufferPointer++;
|
|
*pMQCoder->pBufferPointer = pMQCoder->nCregister >> 20;
|
|
pMQCoder->nCregister &= 0xfffff;
|
|
pMQCoder->nCt = 7;
|
|
}
|
|
else
|
|
{
|
|
if ((pMQCoder->nCregister & 0x8000000) == 0) // CHANGE
|
|
{
|
|
pMQCoder->pBufferPointer++;
|
|
*pMQCoder->pBufferPointer = pMQCoder->nCregister >> 19;
|
|
pMQCoder->nCregister &= 0x7ffff;
|
|
pMQCoder->nCt = 8;
|
|
}
|
|
else
|
|
{
|
|
(*pMQCoder->pBufferPointer)++;
|
|
if (*pMQCoder->pBufferPointer == 0xff)
|
|
{
|
|
pMQCoder->nCregister &= 0x7ffffff;
|
|
pMQCoder->pBufferPointer++;
|
|
*pMQCoder->pBufferPointer = pMQCoder->nCregister >> 20;
|
|
pMQCoder->nCregister &= 0xfffff;
|
|
pMQCoder->nCt = 7;
|
|
}
|
|
else
|
|
{
|
|
pMQCoder->pBufferPointer++;
|
|
*pMQCoder->pBufferPointer = pMQCoder->nCregister >> 19;
|
|
pMQCoder->nCregister &= 0x7ffff;
|
|
pMQCoder->nCt = 8;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void MQC_RenormE(MQCoder *pMQCoder)
|
|
{
|
|
do
|
|
{
|
|
pMQCoder->nAregister <<= 1;
|
|
pMQCoder->nCregister <<= 1;
|
|
pMQCoder->nCt--;
|
|
|
|
if (0 == pMQCoder->nCt)
|
|
{
|
|
MQC_ByteOut(pMQCoder);
|
|
}
|
|
} while ((pMQCoder->nAregister & 0x8000) == 0);
|
|
}
|
|
|
|
static void MQC_CodeMPS(MQCoder *pMQCoder)
|
|
{
|
|
pMQCoder->nAregister -= (*pMQCoder->ppCurContext)->nLPSValue;
|
|
if ((pMQCoder->nAregister & 0x8000) == 0)
|
|
{
|
|
if (pMQCoder->nAregister < (*pMQCoder->ppCurContext)->nLPSValue)
|
|
{
|
|
pMQCoder->nAregister = (*pMQCoder->ppCurContext)->nLPSValue;
|
|
}
|
|
else
|
|
{
|
|
pMQCoder->nCregister += (*pMQCoder->ppCurContext)->nLPSValue;
|
|
}
|
|
*pMQCoder->ppCurContext = (*pMQCoder->ppCurContext)->pNextMPS;
|
|
MQC_RenormE(pMQCoder);
|
|
}
|
|
else
|
|
{
|
|
pMQCoder->nCregister += (*pMQCoder->ppCurContext)->nLPSValue;
|
|
}
|
|
}
|
|
|
|
static void MQC_CodeLPS(MQCoder *pMQCoder)
|
|
{
|
|
pMQCoder->nAregister -= (*pMQCoder->ppCurContext)->nLPSValue;
|
|
if (pMQCoder->nAregister < (*pMQCoder->ppCurContext)->nLPSValue)
|
|
{
|
|
pMQCoder->nCregister += (*pMQCoder->ppCurContext)->nLPSValue;
|
|
}
|
|
else
|
|
{
|
|
pMQCoder->nAregister = (*pMQCoder->ppCurContext)->nLPSValue;
|
|
}
|
|
*pMQCoder->ppCurContext = (*pMQCoder->ppCurContext)->pNextLPS;
|
|
MQC_RenormE(pMQCoder);
|
|
}
|
|
|
|
static void MQC_SetBits(MQCoder *pMQCoder)
|
|
{
|
|
unsigned int nTempCode = pMQCoder->nCregister + pMQCoder->nAregister;
|
|
pMQCoder->nCregister |= 0xffff;
|
|
if (pMQCoder->nCregister >= nTempCode)
|
|
{
|
|
pMQCoder->nCregister -= 0x8000;
|
|
}
|
|
}
|
|
|
|
static int MQC_MPSExchange(MQCoder *pMQCoder)
|
|
{
|
|
int nResult = 0;
|
|
if (pMQCoder->nAregister < (*pMQCoder->ppCurContext)->nLPSValue)
|
|
{
|
|
nResult = 1 - (*pMQCoder->ppCurContext)->nMPS;
|
|
*pMQCoder->ppCurContext = (*pMQCoder->ppCurContext)->pNextLPS;
|
|
}
|
|
else
|
|
{
|
|
nResult = (*pMQCoder->ppCurContext)->nMPS;
|
|
*pMQCoder->ppCurContext = (*pMQCoder->ppCurContext)->pNextMPS;
|
|
}
|
|
|
|
return nResult;
|
|
}
|
|
|
|
static int MQC_LPSExchange(MQCoder *pMQCoder)
|
|
{
|
|
int nResult = 0;
|
|
if (pMQCoder->nAregister < (*pMQCoder->ppCurContext)->nLPSValue)
|
|
{
|
|
pMQCoder->nAregister = (*pMQCoder->ppCurContext)->nLPSValue;
|
|
nResult = (*pMQCoder->ppCurContext)->nMPS;
|
|
*pMQCoder->ppCurContext = (*pMQCoder->ppCurContext)->pNextMPS;
|
|
}
|
|
else
|
|
{
|
|
pMQCoder->nAregister = (*pMQCoder->ppCurContext)->nLPSValue;
|
|
nResult = 1 - (*pMQCoder->ppCurContext)->nMPS;
|
|
*pMQCoder->ppCurContext = (*pMQCoder->ppCurContext)->pNextLPS;
|
|
}
|
|
|
|
return nResult;
|
|
}
|
|
|
|
static void MQC_ByteIn(MQCoder *pMQCoder)
|
|
{
|
|
if (pMQCoder->pBufferPointer != pMQCoder->pEnd)
|
|
{
|
|
unsigned int nCode = 0;
|
|
if (pMQCoder->pBufferPointer + 1 != pMQCoder->pEnd)
|
|
{
|
|
nCode = *(pMQCoder->pBufferPointer + 1);
|
|
}
|
|
else
|
|
{
|
|
nCode = 0xff;
|
|
}
|
|
if (*pMQCoder->pBufferPointer == 0xff)
|
|
{
|
|
if (nCode > 0x8f)
|
|
{
|
|
pMQCoder->nCregister += 0xff00;
|
|
pMQCoder->nCt = 8;
|
|
}
|
|
else
|
|
{
|
|
pMQCoder->pBufferPointer++;
|
|
pMQCoder->nCregister += nCode << 9;
|
|
pMQCoder->nCt = 7;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pMQCoder->pBufferPointer++;
|
|
pMQCoder->nCregister += nCode << 8;
|
|
pMQCoder->nCt = 8;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pMQCoder->nCregister += 0xff00;
|
|
pMQCoder->nCt = 8;
|
|
}
|
|
}
|
|
|
|
static void MQC_RenormD(MQCoder *pMQCoder)
|
|
{
|
|
do
|
|
{
|
|
if (pMQCoder->nCt == 0)
|
|
{
|
|
MQC_ByteIn(pMQCoder);
|
|
}
|
|
pMQCoder->nAregister <<= 1;
|
|
pMQCoder->nCregister <<= 1;
|
|
pMQCoder->nCt--;
|
|
} while (pMQCoder->nAregister < 0x8000);
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
// Основные функции
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
MQCoder* MQC_Create()
|
|
{
|
|
MQCoder *pCoder = (MQCoder*)Malloc(sizeof(MQCoder));
|
|
return pCoder;
|
|
}
|
|
void MQC_Destroy(MQCoder *pMQCoder)
|
|
{
|
|
Free(pMQCoder);
|
|
}
|
|
|
|
int MQC_BytesCount(MQCoder *pMQCoder)
|
|
{
|
|
return pMQCoder->pBufferPointer - pMQCoder->pStart;
|
|
}
|
|
|
|
void MQC_ResetStates(MQCoder *pMQCoder)
|
|
{
|
|
for (int nIndex = 0; nIndex < MQC_NUMCTXS; nIndex++)
|
|
{
|
|
pMQCoder->pContexts[nIndex] = aoMQCoderStates;
|
|
}
|
|
}
|
|
|
|
void MQC_SetState(MQCoder *pMQCoder, int nContextIndex, int nMSB, int nProb)
|
|
{
|
|
pMQCoder->pContexts[nContextIndex] = &aoMQCoderStates[nMSB + (nProb << 1)];
|
|
}
|
|
void MQC_SetCurContext(MQCoder *pMQCoder, int nContextIndex)
|
|
{
|
|
pMQCoder->ppCurContext = &pMQCoder->pContexts[nContextIndex];
|
|
}
|
|
|
|
void MQC_InitEncoder(MQCoder *pMQCoder, unsigned char *pBufferPointer)
|
|
{
|
|
MQC_SetCurContext(pMQCoder, 0);
|
|
|
|
pMQCoder->nAregister = 0x8000;
|
|
pMQCoder->nCregister = 0;
|
|
pMQCoder->pBufferPointer = pBufferPointer - 1;
|
|
pMQCoder->nCt = 12;
|
|
|
|
if (*pMQCoder->pBufferPointer == 0xff)
|
|
{
|
|
pMQCoder->nCt = 13;
|
|
}
|
|
pMQCoder->pStart = pBufferPointer;
|
|
}
|
|
void MQC_Encode(MQCoder *pMQCoder, int nValue)
|
|
{
|
|
if ((*pMQCoder->ppCurContext)->nMPS == nValue)
|
|
{
|
|
MQC_CodeMPS(pMQCoder);
|
|
}
|
|
else
|
|
{
|
|
MQC_CodeLPS(pMQCoder);
|
|
}
|
|
}
|
|
|
|
void MQC_Flush(MQCoder *pMQCoder)
|
|
{
|
|
MQC_SetBits(pMQCoder);
|
|
|
|
pMQCoder->nCregister <<= pMQCoder->nCt;
|
|
MQC_ByteOut(pMQCoder);
|
|
|
|
pMQCoder->nCregister <<= pMQCoder->nCt;
|
|
MQC_ByteOut(pMQCoder);
|
|
|
|
if (*pMQCoder->pBufferPointer != 0xff)
|
|
{
|
|
pMQCoder->pBufferPointer++;
|
|
}
|
|
}
|
|
void MQC_BypassInitEncoder(MQCoder *pMQCoder)
|
|
{
|
|
// TO DO: Данная функция не польностью протестирована
|
|
pMQCoder->nCregister = 0;
|
|
pMQCoder->nCt = 8;
|
|
|
|
//if (pMQCoder->pBufferPointer == 0xff)
|
|
//{
|
|
// pMQCoder->nCt = 7;
|
|
//}
|
|
}
|
|
void MQC_BypassEncoder(MQCoder *pMQCoder, int nValue)
|
|
{
|
|
// TO DO: Данная функция не польностью протестирована
|
|
pMQCoder->nCt--;
|
|
pMQCoder->nCregister = pMQCoder->nCregister + (nValue << pMQCoder->nCt);
|
|
|
|
if (pMQCoder->nCt == 0)
|
|
{
|
|
pMQCoder->pBufferPointer++;
|
|
*pMQCoder->pBufferPointer = pMQCoder->nCregister;
|
|
pMQCoder->nCt = 8;
|
|
|
|
if (*pMQCoder->pBufferPointer == 0xff)
|
|
{
|
|
pMQCoder->nCt = 7;
|
|
}
|
|
pMQCoder->nCregister = 0;
|
|
}
|
|
}
|
|
|
|
int MQC_BypassFlushEncoder(MQCoder *pMQCoder)
|
|
{
|
|
// TO DO: Данная функция не польностью протестирована
|
|
unsigned char nBitPadding = 0;
|
|
|
|
if (pMQCoder->nCt != 0)
|
|
{
|
|
while (pMQCoder->nCt > 0)
|
|
{
|
|
pMQCoder->nCt--;
|
|
pMQCoder->nCregister += nBitPadding << pMQCoder->nCt;
|
|
nBitPadding = (nBitPadding + 1) & 0x01;
|
|
}
|
|
pMQCoder->pBufferPointer++;
|
|
*pMQCoder->pBufferPointer = pMQCoder->nCregister;
|
|
pMQCoder->nCt = 8;
|
|
pMQCoder->nCregister = 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
void MQC_ResetEncoder(MQCoder *pMQCoder)
|
|
{
|
|
MQC_ResetStates(pMQCoder);
|
|
MQC_SetState(pMQCoder, 18, 0, 46);
|
|
MQC_SetState(pMQCoder, 0, 0, 3);
|
|
MQC_SetState(pMQCoder, 1, 0, 4);
|
|
}
|
|
|
|
int MQC_RestartEncoder(MQCoder *pMQCoder)
|
|
{
|
|
int nCorrection = 1;
|
|
|
|
int nLen = 27 - 15 - pMQCoder->nCt;
|
|
pMQCoder->nCregister <<= pMQCoder->nCt;
|
|
while (nLen > 0)
|
|
{
|
|
MQC_ByteOut(pMQCoder);
|
|
nLen -= pMQCoder->nCt;
|
|
pMQCoder->nCregister <<= pMQCoder->nCt;
|
|
}
|
|
MQC_ByteOut(pMQCoder);
|
|
|
|
return nCorrection;
|
|
}
|
|
|
|
void MQC_RestartInitEncoder(MQCoder *pMQCoder)
|
|
{
|
|
MQC_SetCurContext(pMQCoder, 0);
|
|
|
|
pMQCoder->nAregister = 0x8000;
|
|
pMQCoder->nCregister = 0;
|
|
pMQCoder->nCt = 12;
|
|
pMQCoder->pBufferPointer--;
|
|
|
|
if (*pMQCoder->pBufferPointer == 0xff)
|
|
{
|
|
pMQCoder->nCt = 13;
|
|
}
|
|
}
|
|
|
|
void MQC_ErtermEncoder(MQCoder *pMQCoder)
|
|
{
|
|
int nK = 11 - pMQCoder->nCt + 1;
|
|
|
|
while (nK > 0)
|
|
{
|
|
pMQCoder->nCregister <<= pMQCoder->nCt;
|
|
pMQCoder->nCt = 0;
|
|
MQC_ByteOut(pMQCoder);
|
|
nK -= pMQCoder->nCt;
|
|
}
|
|
|
|
if (*pMQCoder->pBufferPointer != 0xff)
|
|
{
|
|
MQC_ByteOut(pMQCoder);
|
|
}
|
|
}
|
|
void MQC_SegMarkEncoder(MQCoder *pMQCoder)
|
|
{
|
|
MQC_SetCurContext(pMQCoder, 18);
|
|
|
|
for (int nIndex = 1; nIndex < 5; nIndex++)
|
|
{
|
|
MQC_Encode(pMQCoder, nIndex % 2);
|
|
}
|
|
}
|
|
|
|
void MQC_InitDecoder(MQCoder *pMQCoder, unsigned char *nBufferPointer, int nLen)
|
|
{
|
|
MQC_SetCurContext(pMQCoder, 0);
|
|
|
|
pMQCoder->pStart = nBufferPointer;
|
|
pMQCoder->pEnd = nBufferPointer + nLen;
|
|
pMQCoder->pBufferPointer = nBufferPointer;
|
|
|
|
if (0 == nLen)
|
|
pMQCoder->nCregister = 0xff << 16;
|
|
else
|
|
pMQCoder->nCregister = *pMQCoder->pBufferPointer << 16;
|
|
|
|
MQC_ByteIn(pMQCoder);
|
|
|
|
pMQCoder->nCregister <<= 7;
|
|
pMQCoder->nCt -= 7;
|
|
pMQCoder->nAregister = 0x8000;
|
|
}
|
|
|
|
int MQC_Decode(MQCoder *pMQCoder)
|
|
{
|
|
int nResult = 0;
|
|
pMQCoder->nAregister -= (*pMQCoder->ppCurContext)->nLPSValue;
|
|
if ((pMQCoder->nCregister >> 16) < (*pMQCoder->ppCurContext)->nLPSValue)
|
|
{
|
|
nResult = MQC_LPSExchange(pMQCoder);
|
|
MQC_RenormD(pMQCoder);
|
|
}
|
|
else
|
|
{
|
|
pMQCoder->nCregister -= (*pMQCoder->ppCurContext)->nLPSValue << 16;
|
|
if ((pMQCoder->nAregister & 0x8000) == 0)
|
|
{
|
|
nResult = MQC_MPSExchange(pMQCoder);
|
|
MQC_RenormD(pMQCoder);
|
|
}
|
|
else
|
|
{
|
|
nResult = (*pMQCoder->ppCurContext)->nMPS;
|
|
}
|
|
}
|
|
|
|
return nResult;
|
|
}
|
|
} |