Files
Yajbir Singh f1b860b25c
Some checks failed
check / markdownlint (push) Has been cancelled
check / spellchecker (push) Has been cancelled
updated
2025-12-11 19:03:17 +05:30

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;
}
}