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

1140 lines
34 KiB
C++

#pragma once
#include "DWT.h"
#include "ArithmeticCoder.h"
#include "Raw.h"
namespace Jpeg2000
{
//-------------------------------------------------------------------------------------------------------------------------------
// Вспомогательные функции
//-------------------------------------------------------------------------------------------------------------------------------
static int Tier1_GetContextIndexZC(Tier1 *pTier1, int nF, int nOrient)
{
return pTier1->lut_ctxno_zc[(nOrient << 8) | (nF & T1_SIG_OTH)];
}
static int Tier1_GetContextIndexSC(Tier1 *pTier1, int nF)
{
return pTier1->lut_ctxno_sc[(nF & (T1_SIG_PRIM | T1_SGN)) >> 4];
}
static int Tier1_GetContextIndexMag(Tier1 *pTier1, int nF)
{
return pTier1->lut_ctxno_mag[(nF & T1_SIG_OTH) | (((nF & T1_REFINE) != 0) << 11)];
}
static int Tier1_GetSPB(Tier1 *pTier1, int nF)
{
return pTier1->lut_spb[(nF & (T1_SIG_PRIM | T1_SGN)) >> 4];
}
static int Tier1_GetNMSEDecSig(Tier1 *pTier1, int nValue, int nBitPos)
{
if (nBitPos > T1_NMSEDEC_FRACBITS)
{
return pTier1->lut_nmsedec_sig[(nValue >> (nBitPos - T1_NMSEDEC_FRACBITS)) & ((1 << T1_NMSEDEC_BITS) - 1)];
}
return pTier1->lut_nmsedec_sig0[nValue & ((1 << T1_NMSEDEC_BITS) - 1)];
}
static int Tier1_GetNMSEDecRef(Tier1 *pTier1, int nValue, int nBitPos)
{
if (nBitPos > T1_NMSEDEC_FRACBITS)
{
return pTier1->lut_nmsedec_ref[(nValue >> (nBitPos - T1_NMSEDEC_FRACBITS)) & ((1 << T1_NMSEDEC_BITS) - 1)];
}
return pTier1->lut_nmsedec_ref0[nValue & ((1 << T1_NMSEDEC_BITS) - 1)];
}
static void Tier1_UpdateFlags(int *pFlags, int nSign)
{
int *pSouth = pFlags - (T1_MAXCBLKW + 2);
int *pNorth = pFlags + (T1_MAXCBLKW + 2);
pSouth[-1] |= T1_SIG_SE;
pSouth[1] |= T1_SIG_SW;
pNorth[-1] |= T1_SIG_NE;
pNorth[1] |= T1_SIG_NW;
*pSouth |= T1_SIG_S;
*pNorth |= T1_SIG_N;
pFlags[-1] |= T1_SIG_E;
pFlags[1] |= T1_SIG_W;
if (nSign)
{
*pSouth |= T1_SGN_S;
*pNorth |= T1_SGN_N;
pFlags[-1] |= T1_SGN_E;
pFlags[1] |= T1_SGN_W;
}
}
static void Tier1_EncoderSigPassStep(Tier1 *pTier1, int *pFlags, int *pData, int nOrient, int nBufferPos, int nOne, int *pNMSEDec, char nType, int nVSC)
{
MQCoder *pMQCoder = pTier1->pMQCoder;
int nFlag = nVSC ? ((*pFlags) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*pFlags);
if ((nFlag & T1_SIG_OTH) && !(nFlag & (T1_SIG | T1_VISIT)))
{
int nValue = abs(*pData) & nOne ? 1 : 0;
if (nType == T1_TYPE_RAW) // BYPASS/LAZY MODE
{
MQC_SetCurContext(pMQCoder, Tier1_GetContextIndexZC(pTier1, nFlag, nOrient)); // ESSAI
MQC_BypassEncoder(pMQCoder, nValue);
}
else
{
MQC_SetCurContext(pMQCoder, Tier1_GetContextIndexZC(pTier1, nFlag, nOrient));
MQC_Encode(pMQCoder, nValue);
}
if (nValue)
{
nValue = *pData < 0 ? 1 : 0;
*pNMSEDec += Tier1_GetNMSEDecSig(pTier1, abs(*pData), nBufferPos + T1_NMSEDEC_FRACBITS);
if (nType == T1_TYPE_RAW) // BYPASS/LAZY MODE
{
MQC_SetCurContext(pMQCoder, Tier1_GetContextIndexSC(pTier1, nFlag)); // ESSAI
MQC_BypassEncoder(pMQCoder, nValue);
}
else
{
MQC_SetCurContext(pMQCoder, Tier1_GetContextIndexSC(pTier1, nFlag));
MQC_Encode(pMQCoder, nValue ^ Tier1_GetSPB(pTier1, nFlag));
}
Tier1_UpdateFlags(pFlags, nValue);
*pFlags |= T1_SIG;
}
*pFlags |= T1_VISIT;
}
}
static void Tier1_DecoderSigPassStep(Tier1 *pTier1, int *pFlags, int *pData, int nOrient, int nOnePlusHalf, char nType, int nVSC)
{
Raw *pRaw = pTier1->pRaw;
MQCoder *pMQCoder = pTier1->pMQCoder;
int nValue = 0;
int nFlag = nVSC ? ((*pFlags) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*pFlags);
if ((nFlag & T1_SIG_OTH) && !(nFlag & (T1_SIG | T1_VISIT)))
{
if (nType == T1_TYPE_RAW)
{
if (Raw_Decode(pRaw))
{
nValue = Raw_Decode(pRaw); // ESSAI
*pData = nValue ? -nOnePlusHalf : nOnePlusHalf;
Tier1_UpdateFlags(pFlags, nValue);
*pFlags |= T1_SIG;
}
}
else
{
MQC_SetCurContext(pMQCoder, Tier1_GetContextIndexZC(pTier1, nFlag, nOrient));
if (MQC_Decode(pMQCoder))
{
MQC_SetCurContext(pMQCoder, Tier1_GetContextIndexSC(pTier1, nFlag));
nValue = MQC_Decode(pMQCoder) ^ Tier1_GetSPB(pTier1, nFlag);
*pData = nValue ? -nOnePlusHalf : nOnePlusHalf;
Tier1_UpdateFlags(pFlags, nValue);
*pFlags |= T1_SIG;
}
}
*pFlags |= T1_VISIT;
}
}
static void Tier1_EncoderSigPass(Tier1 *pTier1, int nWidth, int nHeight, int nBufferPos, int nOrient, int *pNMSEDec, char nType, int nCodeBlockStyle)
{
*pNMSEDec = 0;
int nOne = 1 << (nBufferPos + T1_NMSEDEC_FRACBITS);
for (int nY = 0; nY < nHeight; nY += 4)
{
for (int nX = 0; nX < nWidth; nX++)
{
for (int nYY = nY; nYY < nY + 4 && nYY < nHeight; nYY++)
{
int nVSC = ((nCodeBlockStyle & J2K_CCP_CBLKSTY_VSC) && (nYY == nY + 3 || nYY == nHeight - 1)) ? 1 : 0;
Tier1_EncoderSigPassStep(pTier1, &pTier1->aFlags[1 + nYY][1 + nX], &pTier1->aData[nYY][nX], nOrient, nBufferPos, nOne, pNMSEDec, nType, nVSC);
}
}
}
}
static void Tier1_DecoderSigPass(Tier1 *pTier1, int nWidth, int nHeight, int nBufferPos, int nOrient, char nType, int nCodeBlockStyle)
{
int nOne = 1 << nBufferPos;
int nHalf = nOne >> 1;
int nOnePlusHalf = nOne | nHalf;
for (int nY = 0; nY < nHeight; nY += 4)
{
for (int nX = 0; nX < nWidth; nX++)
{
for (int nYY = nY; nYY < nY + 4 && nYY < nHeight; nYY++)
{
int nVSC = ((nCodeBlockStyle & J2K_CCP_CBLKSTY_VSC) && (nYY == nY + 3 || nYY == nHeight - 1)) ? 1 : 0;
Tier1_DecoderSigPassStep(pTier1, &pTier1->aFlags[1 + nYY][1 + nX], &pTier1->aData[nYY][nX], nOrient, nOnePlusHalf, nType, nVSC);
}
}
}
}
static void Tier1_EnocderRefPassStep(Tier1 *pTier1, int *pFlags, int *pData, int nBufferPos, int nOne, int *pNMSEDec, char nType, int nVSC)
{
MQCoder *pMQCoder = pTier1->pMQCoder;
int nFlag = nVSC ? ((*pFlags) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*pFlags);
if ((nFlag & (T1_SIG | T1_VISIT)) == T1_SIG)
{
*pNMSEDec += Tier1_GetNMSEDecRef(pTier1, abs(*pData), nBufferPos + T1_NMSEDEC_FRACBITS);
int nValue = abs(*pData) & nOne ? 1 : 0;
if (nType == T1_TYPE_RAW)
{
MQC_SetCurContext(pMQCoder, Tier1_GetContextIndexMag(pTier1, nFlag)); // ESSAI
MQC_BypassEncoder(pMQCoder, nValue);
}
else
{
MQC_SetCurContext(pMQCoder, Tier1_GetContextIndexMag(pTier1, nFlag));
MQC_Encode(pMQCoder, nValue);
}
*pFlags |= T1_REFINE;
}
}
static void Tier1_DecoderRefPassStep(Tier1 *pTier1, int *pFlags, int *pData, int nPosHalf, int nNegHalf, char nType, int nVSC)
{
MQCoder *pMQCoder = pTier1->pMQCoder;
Raw *pRaw = pTier1->pRaw;
int nFlag = nVSC ? ((*pFlags) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*pFlags);
if ((nFlag & (T1_SIG | T1_VISIT)) == T1_SIG)
{
int nValue = 0;
if (nType == T1_TYPE_RAW)
{
MQC_SetCurContext(pMQCoder, Tier1_GetContextIndexMag(pTier1, nFlag)); // ESSAI
nValue = Raw_Decode(pRaw);
}
else
{
MQC_SetCurContext(pMQCoder, Tier1_GetContextIndexMag(pTier1, nFlag));
nValue = MQC_Decode(pMQCoder);
}
int nTemp = nValue ? nPosHalf : nNegHalf;
*pData += *pData < 0 ? -nTemp : nTemp;
*pFlags |= T1_REFINE;
}
}
static void Tier1_EncoderRefPass(Tier1 *pTier1, int nWidth, int nHeight, int nBufferPos, int *pNMSEDec, char nType, int nCodeBlockStyle)
{
*pNMSEDec = 0;
int nOne = 1 << (nBufferPos + T1_NMSEDEC_FRACBITS);
for (int nY = 0; nY < nHeight; nY += 4)
{
for (int nX = 0; nX < nWidth; nX++)
{
for (int nYY = nY; nYY < nY + 4 && nYY < nHeight; nYY++)
{
int nVSC = ((nCodeBlockStyle & J2K_CCP_CBLKSTY_VSC) && (nYY == nY + 3 || nYY == nHeight - 1)) ? 1 : 0;
Tier1_EnocderRefPassStep(pTier1, &pTier1->aFlags[1 + nYY][1 + nX], &pTier1->aData[nYY][nX], nBufferPos, nOne, pNMSEDec, nType, nVSC);
}
}
}
}
static void Tier1_DecoderRefPass(Tier1 *pTier1, int nWidth, int nHeight, int nBufferPos, char nType, int nCodeBlockStyle)
{
int nOne = 1 << nBufferPos;
int nPosHalf = nOne >> 1;
int nNegHalf = nBufferPos > 0 ? -nPosHalf : -1;
for (int nY = 0; nY < nHeight; nY += 4)
{
for (int nX = 0; nX < nWidth; nX++)
{
for (int nYY = nY; nYY < nY + 4 && nYY < nHeight; nYY++)
{
int nVSC = ((nCodeBlockStyle & J2K_CCP_CBLKSTY_VSC) && (nYY == nY + 3 || nYY == nHeight - 1)) ? 1 : 0;
Tier1_DecoderRefPassStep(pTier1, &pTier1->aFlags[1 + nYY][1 + nX], &pTier1->aData[nYY][nX], nPosHalf, nNegHalf, nType, nVSC);
}
}
}
}
static void Tier1_EncoderClnPassStep(Tier1 *pTier1, int *pFlags, int *pData, int nOrient, int nBufferPos, int nOne, int *pNMSEDec, int nPartial, int nVSC)
{
MQCoder *pMQCoder = pTier1->pMQCoder;
int nFlag = nVSC ? ((*pFlags) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*pFlags);
int nValue = 0;
if (nPartial)
{
goto LABEL_PARTIAL;
}
if (!(*pFlags & (T1_SIG | T1_VISIT)))
{
MQC_SetCurContext(pMQCoder, Tier1_GetContextIndexZC(pTier1, nFlag, nOrient));
nValue = abs(*pData) & nOne ? 1 : 0;
MQC_Encode(pMQCoder, nValue);
if (nValue)
{
LABEL_PARTIAL:
*pNMSEDec += Tier1_GetNMSEDecSig(pTier1, abs(*pData), nBufferPos + T1_NMSEDEC_FRACBITS);
MQC_SetCurContext(pMQCoder, Tier1_GetContextIndexSC(pTier1, nFlag));
nValue = *pData < 0 ? 1 : 0;
MQC_Encode(pMQCoder, nValue ^ Tier1_GetSPB(pTier1, nFlag));
Tier1_UpdateFlags(pFlags, nValue);
*pFlags |= T1_SIG;
}
}
*pFlags &= ~T1_VISIT;
}
static void Tier1_DecoderClnPassStep(Tier1 *pTier1, int *pFlags, int *pData, int nOrient, int nOnePlusHalf, int nPartial, int nVSC)
{
MQCoder *pMQCoder = pTier1->pMQCoder;
int nFlag = nVSC ? ((*pFlags) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*pFlags);
int nValue = 0;
if (nPartial)
{
goto LABEL_PARTIAL;
}
if (!(nFlag & (T1_SIG | T1_VISIT)))
{
MQC_SetCurContext(pMQCoder, Tier1_GetContextIndexZC(pTier1, nFlag, nOrient));
if (MQC_Decode(pMQCoder))
{
LABEL_PARTIAL:
MQC_SetCurContext(pMQCoder, Tier1_GetContextIndexSC(pTier1, nFlag));
nValue = MQC_Decode(pMQCoder) ^ Tier1_GetSPB(pTier1, nFlag);
*pData = nValue ? -nOnePlusHalf : nOnePlusHalf;
Tier1_UpdateFlags(pFlags, nValue);
*pFlags |= T1_SIG;
}
}
*pFlags &= ~T1_VISIT;
}
static void Tier1_EncoderClnPass(Tier1 *pTier1, int nWidth, int nHeight, int nBufferPos, int nOrient, int *pNMSEDec, int nCodeBlockStyle)
{
MQCoder *pMQCoder = pTier1->pMQCoder;
*pNMSEDec = 0;
int nOne = 1 << (nBufferPos + T1_NMSEDEC_FRACBITS);
for (int nY = 0; nY < nHeight; nY += 4)
{
for (int nX = 0; nX < nWidth; nX++)
{
int nAgg = 0, nRunLen = 0;
if (nY + 3 < nHeight)
{
if (nCodeBlockStyle & J2K_CCP_CBLKSTY_VSC)
{
nAgg = !(pTier1->aFlags[1 + nY][1 + nX] & (T1_SIG | T1_VISIT | T1_SIG_OTH) || pTier1->aFlags[1 + nY + 1][1 + nX] & (T1_SIG | T1_VISIT | T1_SIG_OTH)
|| pTier1->aFlags[1 + nY + 2][1 + nX] & (T1_SIG | T1_VISIT | T1_SIG_OTH) || (pTier1->aFlags[1 + nY + 3][1 + nX] & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) & (T1_SIG | T1_VISIT | T1_SIG_OTH));
}
else
{
nAgg = !(pTier1->aFlags[1 + nY][1 + nX] & (T1_SIG | T1_VISIT | T1_SIG_OTH) || pTier1->aFlags[1 + nY + 1][1 + nX] & (T1_SIG | T1_VISIT | T1_SIG_OTH)
|| pTier1->aFlags[1 + nY + 2][1 + nX] & (T1_SIG | T1_VISIT | T1_SIG_OTH) || pTier1->aFlags[1 + nY + 3][1 + nX] & (T1_SIG | T1_VISIT | T1_SIG_OTH));
}
}
else
{
nAgg = 0;
}
if (nAgg)
{
for (nRunLen = 0; nRunLen < 4; nRunLen++)
{
if (abs(pTier1->aData[nY + nRunLen][nX]) & nOne)
break;
}
MQC_SetCurContext(pMQCoder, T1_CTXNO_AGG);
MQC_Encode(pMQCoder, nRunLen != 4);
if (nRunLen == 4)
{
continue;
}
MQC_SetCurContext(pMQCoder, T1_CTXNO_UNI);
MQC_Encode(pMQCoder, nRunLen >> 1);
MQC_Encode(pMQCoder, nRunLen & 1);
}
else
{
nRunLen = 0;
}
for (int nYY = nY + nRunLen; nYY < nY + 4 && nYY < nHeight; nYY++)
{
int nVSC = ((nCodeBlockStyle & J2K_CCP_CBLKSTY_VSC) && (nYY == nY + 3 || nYY == nHeight - 1)) ? 1 : 0;
Tier1_EncoderClnPassStep(pTier1, &pTier1->aFlags[1 + nYY][1 + nX], &pTier1->aData[nYY][nX], nOrient, nBufferPos, nOne, pNMSEDec, nAgg && (nYY == nY + nRunLen), nVSC);
}
}
}
}
static void Tier1_DecoderClnPass(Tier1 *pTier1, int nWidth, int nHeight, int nBufferPos, int nOrient, int nCodeBlockStyle)
{
int nSegSym = nCodeBlockStyle & J2K_CCP_CBLKSTY_SEGSYM;
MQCoder *pMQCoder = pTier1->pMQCoder;
int nOne = 1 << nBufferPos;
int nHalf = nOne >> 1;
int nOnePlusHalf = nOne | nHalf;
for (int nY = 0; nY < nHeight; nY += 4)
{
for (int nX = 0; nX < nWidth; nX++)
{
int nAgg = 0, nRunLen = 0;
if (nY + 3 < nHeight)
{
if (nCodeBlockStyle & J2K_CCP_CBLKSTY_VSC)
{
nAgg = !(pTier1->aFlags[1 + nY][1 + nX] & (T1_SIG | T1_VISIT | T1_SIG_OTH) || pTier1->aFlags[1 + nY + 1][1 + nX] & (T1_SIG | T1_VISIT | T1_SIG_OTH)
|| pTier1->aFlags[1 + nY + 2][1 + nX] & (T1_SIG | T1_VISIT | T1_SIG_OTH) || (pTier1->aFlags[1 + nY + 3][1 + nX] & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) & (T1_SIG | T1_VISIT | T1_SIG_OTH));
}
else
{
nAgg = !(pTier1->aFlags[1 + nY][1 + nX] & (T1_SIG | T1_VISIT | T1_SIG_OTH) || pTier1->aFlags[1 + nY + 1][1 + nX] & (T1_SIG | T1_VISIT | T1_SIG_OTH)
|| pTier1->aFlags[1 + nY + 2][1 + nX] & (T1_SIG | T1_VISIT | T1_SIG_OTH) || pTier1->aFlags[1 + nY + 3][1 + nX] & (T1_SIG | T1_VISIT | T1_SIG_OTH));
}
}
else
{
nAgg = 0;
}
if (nAgg)
{
MQC_SetCurContext(pMQCoder, T1_CTXNO_AGG);
if (!MQC_Decode(pMQCoder))
{
continue;
}
MQC_SetCurContext(pMQCoder, T1_CTXNO_UNI);
nRunLen = MQC_Decode(pMQCoder);
nRunLen = (nRunLen << 1) | MQC_Decode(pMQCoder);
}
else
{
nRunLen = 0;
}
for (int nYY = nY + nRunLen; nYY < nY + 4 && nYY < nHeight; nYY++)
{
int nVSC = ((nCodeBlockStyle & J2K_CCP_CBLKSTY_VSC) && (nYY == nY + 3 || nYY == nHeight - 1)) ? 1 : 0;
Tier1_DecoderClnPassStep(pTier1, &pTier1->aFlags[1 + nYY][1 + nX], &pTier1->aData[nYY][nX], nOrient, nOnePlusHalf, nAgg && (nYY == nY + nRunLen), nVSC);
}
}
}
if (nSegSym)
{
MQC_SetCurContext(pMQCoder, T1_CTXNO_UNI);
int nValue = MQC_Decode(pMQCoder);
nValue = (nValue << 1) | MQC_Decode(pMQCoder);
nValue = (nValue << 1) | MQC_Decode(pMQCoder);
nValue = (nValue << 1) | MQC_Decode(pMQCoder);
// if ( 0xa != nValue )
//{
// Event_Message( pTier1->pCodecInfo, EVT_WARNING, "Bad segmentation symbol %x\n", nValue );
//}
}
}
// Mode fixed_quality
static double Tier1_GetWMSEDec(int nNMSEDec, int nComponentIndex, int nLevel, int nOrient, int nBufferPos, int nQFMBID, double dStepSize, int nComponentsCount)
{
double dWidth1, dWidth2;
if (1 == nQFMBID)
{
dWidth1 = (nComponentsCount > 1) ? GetNormRCT(nComponentIndex) : 1;
dWidth2 = DWT_GetNormRev(nLevel, nOrient);
}
else
{
dWidth1 = (nComponentsCount > 1) ? GetNormICT(nComponentIndex) : 1;
dWidth2 = DWT_GetNormIrr(nLevel, nOrient);
}
double dWMSEDec = dWidth1 * dWidth2 * dStepSize * (1 << nBufferPos);
dWMSEDec *= dWMSEDec * nNMSEDec / 8192.0;
return dWMSEDec;
}
static void Tier1_EncodeCodeBlock(Tier1 *pTier1, CodeBlock *pCodeBlock, int nOrient, int nComponentIndex, int nLevel, int nQFMBID, double dStepSize, int nCodeBlockStyle, int nComponentsCount, Tile *pTile)
{
int nNMSEDec = 0;
double dCumWMSEDec = 0;
char nType = T1_TYPE_MQ;
MQCoder *pMQCoder = pTier1->pMQCoder;
int nWidth = pCodeBlock->nX1 - pCodeBlock->nX0;
int nHeight = pCodeBlock->nY1 - pCodeBlock->nY0;
int nMax = 0;
for (int nY = 0; nY < nHeight; nY++)
{
for (int nX = 0; nX < nWidth; nX++)
{
nMax = (std::max)(nMax, abs(pTier1->aData[nY][nX]));
}
}
pCodeBlock->nBPSCount = nMax ? (FloorLog2(nMax) + 1) - T1_NMSEDEC_FRACBITS : 0;
for (int nX = 0; nX <= nWidth; nX++)
{
for (int nY = 0; nY <= nHeight; nY++)
{
pTier1->aFlags[nY][nX] = 0;
}
}
int nBufferPos = pCodeBlock->nBPSCount - 1;
int nPassType = 2;
MQC_ResetStates(pMQCoder);
MQC_SetState(pMQCoder, T1_CTXNO_UNI, 0, 46);
MQC_SetState(pMQCoder, T1_CTXNO_AGG, 0, 3);
MQC_SetState(pMQCoder, T1_CTXNO_ZC, 0, 4);
MQC_InitEncoder(pMQCoder, pCodeBlock->aData);
int nPassIndex;
for (nPassIndex = 0; nBufferPos >= 0; nPassIndex++)
{
TCDPass *pPass = &pCodeBlock->aPasses[nPassIndex];
int nCorrection = 3;
nType = ((nBufferPos < (pCodeBlock->nBPSCount - 4)) && (nPassType < 2) && (nCodeBlockStyle & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ;
switch (nPassType)
{
case 0:
Tier1_EncoderSigPass(pTier1, nWidth, nHeight, nBufferPos, nOrient, &nNMSEDec, nType, nCodeBlockStyle);
break;
case 1:
Tier1_EncoderRefPass(pTier1, nWidth, nHeight, nBufferPos, &nNMSEDec, nType, nCodeBlockStyle);
break;
case 2:
Tier1_EncoderClnPass(pTier1, nWidth, nHeight, nBufferPos, nOrient, &nNMSEDec, nCodeBlockStyle);
// Code switch SEGMARK (SEGSYM)
if (nCodeBlockStyle & J2K_CCP_CBLKSTY_SEGSYM)
MQC_SegMarkEncoder(pMQCoder);
break;
}
// fixed_quality
dCumWMSEDec += Tier1_GetWMSEDec(nNMSEDec, nComponentIndex, nLevel, nOrient, nBufferPos, nQFMBID, dStepSize, nComponentsCount);
pTile->dDistoTile += Tier1_GetWMSEDec(nNMSEDec, nComponentIndex, nLevel, nOrient, nBufferPos, nQFMBID, dStepSize, nComponentsCount);
// Code switch "RESTART" (TERMALL)
if ((nCodeBlockStyle & J2K_CCP_CBLKSTY_TERMALL) && !((nPassType == 2) && (nBufferPos - 1 < 0)))
{
if (nType == T1_TYPE_RAW)
{
MQC_Flush(pMQCoder);
nCorrection = 1;
//nCorrection = MQC_BypassFlushEncoder();
}
else
{
//nCorrection = MQC_RestartEncoder();
MQC_Flush(pMQCoder);
nCorrection = 1;
}
pPass->nTerm = 1;
}
else
{
if (((nBufferPos < (pCodeBlock->nBPSCount - 4) && (nPassType > 0)) || ((nBufferPos == (pCodeBlock->nBPSCount - 4)) && (nPassType == 2))) && (nCodeBlockStyle & J2K_CCP_CBLKSTY_LAZY))
{
if (nType == T1_TYPE_RAW)
{
MQC_Flush(pMQCoder);
nCorrection = 1;
//nCorrection = MQC_BypassFlushEncoder();
}
else
{
//nCorrection = MQC_RestartEncoder();
MQC_Flush(pMQCoder);
nCorrection = 1;
}
pPass->nTerm = 1;
}
else
{
pPass->nTerm = 0;
}
}
if (++nPassType == 3)
{
nPassType = 0;
nBufferPos--;
}
if (pPass->nTerm && nBufferPos > 0)
{
nType = ((nBufferPos < (pCodeBlock->nBPSCount - 4)) && (nPassType < 2) && (nCodeBlockStyle & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ;
if (nType == T1_TYPE_RAW)
MQC_BypassInitEncoder(pMQCoder);
else
MQC_RestartInitEncoder(pMQCoder);
}
pPass->dDistortionDec = dCumWMSEDec;
pPass->nRate = MQC_BytesCount(pMQCoder) + nCorrection;
pPass->nLen = pPass->nRate - (nPassIndex == 0 ? 0 : pCodeBlock->aPasses[nPassIndex - 1].nRate);
// Code-switch "RESET"
if (nCodeBlockStyle & J2K_CCP_CBLKSTY_RESET)
MQC_ResetEncoder(pMQCoder);
}
// Code switch "ERTERM" (PTERM)
if (nCodeBlockStyle & J2K_CCP_CBLKSTY_PTERM)
MQC_ErtermEncoder(pMQCoder);
else // Default coding
if (!(nCodeBlockStyle & J2K_CCP_CBLKSTY_LAZY))
MQC_Flush(pMQCoder);
pCodeBlock->nTotalPassesCount = nPassIndex;
}
static void Tier1_DecodeCodeBlock(Tier1 *pTier1, CodeBlock *pCodeBlock, int nOrient, int nROIShift, int nCodeBlockStyle)
{
char nType = T1_TYPE_MQ;
Raw *pRaw = pTier1->pRaw;
MQCoder *pMQCoder = pTier1->pMQCoder;
int nWidth = pCodeBlock->nX1 - pCodeBlock->nX0;
int nHeight = pCodeBlock->nY1 - pCodeBlock->nY0;
for (int nY = 0; nY <= nHeight; nY++)
{
for (int nX = 0; nX <= nWidth; nX++)
{
pTier1->aFlags[nY][nX] = 0;
}
}
for (int nX = 0; nX < nWidth; nX++)
{
for (int nY = 0; nY < nHeight; nY++)
{
pTier1->aData[nY][nX] = 0;
}
}
int nBufferPos = nROIShift + pCodeBlock->nBPSCount - 1;
int nPassType = 2;
MQC_ResetStates(pMQCoder);
MQC_SetState(pMQCoder, T1_CTXNO_UNI, 0, 46);
MQC_SetState(pMQCoder, T1_CTXNO_AGG, 0, 3);
MQC_SetState(pMQCoder, T1_CTXNO_ZC, 0, 4);
for (int nSegIndex = 0; nSegIndex < pCodeBlock->nSegmentsCount; nSegIndex++)
{
TCDSegment *pSegment = &pCodeBlock->aSegments[nSegIndex];
nType = ((nBufferPos <= (pCodeBlock->nBPSCount - 1) - 4) && (nPassType < 2) && (nCodeBlockStyle & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ;
if (nType == T1_TYPE_RAW)
{
Raw_InitDecoder(pRaw, pSegment->pData, pSegment->nLength);
}
else
{
MQC_InitDecoder(pMQCoder, pSegment->pData, pSegment->nLength);
}
for (int nPassIndex = 0; nPassIndex < pSegment->nPassesCount; nPassIndex++)
{
switch (nPassType)
{
case 0:
Tier1_DecoderSigPass(pTier1, nWidth, nHeight, nBufferPos + 1, nOrient, nType, nCodeBlockStyle);
break;
case 1:
Tier1_DecoderRefPass(pTier1, nWidth, nHeight, nBufferPos + 1, nType, nCodeBlockStyle);
break;
case 2:
Tier1_DecoderClnPass(pTier1, nWidth, nHeight, nBufferPos + 1, nOrient, nCodeBlockStyle);
break;
}
if ((nCodeBlockStyle & J2K_CCP_CBLKSTY_RESET) && nType == T1_TYPE_MQ)
{
MQC_ResetStates(pMQCoder);
MQC_SetState(pMQCoder, T1_CTXNO_UNI, 0, 46);
MQC_SetState(pMQCoder, T1_CTXNO_AGG, 0, 3);
MQC_SetState(pMQCoder, T1_CTXNO_ZC, 0, 4);
}
if (++nPassType == 3)
{
nPassType = 0;
nBufferPos--;
}
}
}
}
static int Tier1_InitContextIndexZC(int nF, int nOrient)
{
int nHor = ((nF & T1_SIG_W) != 0) + ((nF & T1_SIG_E) != 0);
int nVer = ((nF & T1_SIG_N) != 0) + ((nF & T1_SIG_S) != 0);
int nDia = ((nF & T1_SIG_NW) != 0) + ((nF & T1_SIG_NE) != 0) + ((nF & T1_SIG_SE) != 0) + ((nF & T1_SIG_SW) != 0);
int nHorVer, nTemp;
int nLen = 0;
switch (nOrient)
{
case 2:
nTemp = nHor;
nHor = nVer;
nVer = nTemp;
case 0:
case 1:
if (!nHor)
{
if (!nVer)
{
if (!nDia)
nLen = 0;
else if (1 == nDia)
nLen = 1;
else
nLen = 2;
}
else if (1 == nVer)
{
nLen = 3;
}
else
{
nLen = 4;
}
}
else if (1 == nHor)
{
if (!nVer)
{
if (!nDia)
nLen = 5;
else
nLen = 6;
}
else
{
nLen = 7;
}
}
else
nLen = 8;
break;
case 3:
nHorVer = nHor + nVer;
if (!nDia)
{
if (!nHorVer)
{
nLen = 0;
}
else if (1 == nHorVer)
{
nLen = 1;
}
else
{
nLen = 2;
}
}
else if (1 == nDia)
{
if (!nHorVer)
{
nLen = 3;
}
else if (1 == nHorVer)
{
nLen = 4;
}
else
{
nLen = 5;
}
}
else if (2 == nDia)
{
if (!nHorVer)
{
nLen = 6;
}
else
{
nLen = 7;
}
}
else
{
nLen = 8;
}
break;
}
return (T1_CTXNO_ZC + nLen);
}
static int Tier1_InitContextIndexSC(int nF)
{
int nLen = 0;
int nHorC = (std::min)(((nF & (T1_SIG_E | T1_SGN_E)) == T1_SIG_E) + ((nF & (T1_SIG_W | T1_SGN_W)) == T1_SIG_W), 1) - (std::min)(((nF & (T1_SIG_E | T1_SGN_E)) == (T1_SIG_E | T1_SGN_E)) + ((nF & (T1_SIG_W | T1_SGN_W)) == (T1_SIG_W | T1_SGN_W)), 1);
int nVerC = (std::min)(((nF & (T1_SIG_N | T1_SGN_N)) == T1_SIG_N) + ((nF & (T1_SIG_S | T1_SGN_S)) == T1_SIG_S), 1) - (std::min)(((nF & (T1_SIG_N | T1_SGN_N)) == (T1_SIG_N | T1_SGN_N)) + ((nF & (T1_SIG_S | T1_SGN_S)) == (T1_SIG_S | T1_SGN_S)), 1);
if (nHorC < 0)
{
nHorC = -nHorC;
nVerC = -nVerC;
}
if (!nHorC)
{
if (1 == nVerC)
nLen = 1;
else if (!nVerC)
nLen = 0;
else
nLen = 1;
}
else if (1 == nHorC)
{
if (-1 == nVerC)
nLen = 2;
else if (!nVerC)
nLen = 3;
else
nLen = 4;
}
return (T1_CTXNO_SC + nLen);
}
static int Tier1_InitContextIndexMag(int nF)
{
int nLen = 0;
if (!(nF & T1_REFINE))
nLen = (nF & (T1_SIG_OTH)) ? 1 : 0;
else
nLen = 2;
return (T1_CTXNO_MAG + nLen);
}
static int Tier1_InitSPB(int nF)
{
int nLen = 0;
int nHorC = (std::min)(((nF & (T1_SIG_E | T1_SGN_E)) == T1_SIG_E) + ((nF & (T1_SIG_W | T1_SGN_W)) == T1_SIG_W), 1) - (std::min)(((nF & (T1_SIG_E | T1_SGN_E)) == (T1_SIG_E | T1_SGN_E)) + ((nF & (T1_SIG_W | T1_SGN_W)) == (T1_SIG_W | T1_SGN_W)), 1);
int nVerC = (std::min)(((nF & (T1_SIG_N | T1_SGN_N)) == T1_SIG_N) + ((nF & (T1_SIG_S | T1_SGN_S)) == T1_SIG_S), 1) - (std::min)(((nF & (T1_SIG_N | T1_SGN_N)) == (T1_SIG_N | T1_SGN_N)) + ((nF & (T1_SIG_S | T1_SGN_S)) == (T1_SIG_S | T1_SGN_S)), 1);
if (!nHorC && !nVerC)
nLen = 0;
else
nLen = (!(nHorC > 0 || (!nHorC && nVerC > 0)));
return nLen;
}
static void Tier1_InitLuts(Tier1 *pTier1)
{
for (int nJ = 0; nJ < 4; nJ++)
{
for (int nI = 0; nI < 256; ++nI)
{
pTier1->lut_ctxno_zc[(nJ << 8) | nI] = Tier1_InitContextIndexZC(nI, nJ);
}
}
for (int nI = 0; nI < 256; nI++)
{
pTier1->lut_ctxno_sc[nI] = Tier1_InitContextIndexSC(nI << 4);
}
for (int nJ = 0; nJ < 2; nJ++)
{
for (int nI = 0; nI < 2048; ++nI)
{
pTier1->lut_ctxno_mag[(nJ << 11) + nI] = Tier1_InitContextIndexMag((nJ ? T1_REFINE : 0) | nI);
}
}
for (int nI = 0; nI < 256; ++nI)
{
pTier1->lut_spb[nI] = Tier1_InitSPB(nI << 4);
}
for (int nI = 0; nI < (1 << T1_NMSEDEC_BITS); nI++)
{
double dT = nI / pow(double(2), T1_NMSEDEC_FRACBITS);
double dU = dT;
double dV = dT - 1.5;
pTier1->lut_nmsedec_sig[nI] = (std::max)(0, (int)(floor((dU * dU - dV * dV) * pow(double(2), T1_NMSEDEC_FRACBITS) + 0.5) / pow(double(2), T1_NMSEDEC_FRACBITS) * 8192.0));
pTier1->lut_nmsedec_sig0[nI] = (std::max)(0, (int)(floor((dU * dU) * pow(double(2), T1_NMSEDEC_FRACBITS) + 0.5) / pow(double(2), T1_NMSEDEC_FRACBITS) * 8192.0));
dU = dT - 1.0;
if (nI & (1 << (T1_NMSEDEC_BITS - 1)))
{
dV = dT - 1.5;
}
else
{
dV = dT - 0.5;
}
pTier1->lut_nmsedec_ref[nI] = (std::max)(0, (int)(floor((dU * dU - dV * dV) * pow(double(2), T1_NMSEDEC_FRACBITS) + 0.5) / pow(double(2), T1_NMSEDEC_FRACBITS) * 8192.0));
pTier1->lut_nmsedec_ref0[nI] = (std::max)(0, (int)(floor((dU * dU) * pow(double(2), T1_NMSEDEC_FRACBITS) + 0.5) / pow(double(2), T1_NMSEDEC_FRACBITS) * 8192.0));
}
}
//-------------------------------------------------------------------------------------------------------------------------------
// Основные функции
//-------------------------------------------------------------------------------------------------------------------------------
Tier1* Tier1_Create(PCommon pCodecInfo)
{
Tier1 *pTier1 = (Tier1*)Malloc(sizeof(Tier1));
if (!pTier1)
{
pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
return NULL;
}
else
{
pTier1->pCodecInfo = pCodecInfo;
pTier1->pMQCoder = MQC_Create();
if (!pTier1->pMQCoder)
{
pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
Free(pTier1);
return NULL;
}
pTier1->pRaw = Raw_Create();
if (!pTier1->pRaw)
{
pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
Free(pTier1->pMQCoder);
Free(pTier1);
return NULL;
}
// Инициализируем таблицы
Tier1_InitLuts(pTier1);
}
return pTier1;
}
void Tier1_Destroy(Tier1 *pTier1)
{
if (pTier1)
{
MQC_Destroy(pTier1->pMQCoder);
Raw_Destroy(pTier1->pRaw);
Free(pTier1);
}
}
void Tier1_EncodeCodeBlocks(Tier1 *pTier1, Tile *pTile, TileCodingParams *pTCP)
{
pTile->dDistoTile = 0; // Fixed quality
for (int nComponentIndex = 0; nComponentIndex < pTile->nComponentsCount; nComponentIndex++)
{
TileComp *pTileComp = &pTile->pComponents[nComponentIndex];
for (int nResolutionIndex = 0; nResolutionIndex < pTileComp->nResolutionsCount; nResolutionIndex++)
{
Resolution *pResolution = &pTileComp->pResolutions[nResolutionIndex];
for (int nBandIndex = 0; nBandIndex < pResolution->nBandsCount; nBandIndex++)
{
Band *pBand = &pResolution->aBands[nBandIndex];
for (int nPrecinctIndex = 0; nPrecinctIndex < pResolution->nPrecCountW * pResolution->nPrecCountH; nPrecinctIndex++)
{
Precinct *pPrecinct = &pBand->pPrecincts[nPrecinctIndex];
for (int nCodeBlockIndex = 0; nCodeBlockIndex < pPrecinct->nCountInWidth * pPrecinct->nCountInHeight; nCodeBlockIndex++)
{
CodeBlock *pCodeBlock = &pPrecinct->pCodeBlocks[nCodeBlockIndex];
int nX = pCodeBlock->nX0 - pBand->nX0;
int nY = pCodeBlock->nY0 - pBand->nY0;
if (pBand->nBandIndex & 1)
{
Resolution *pResolution = &pTileComp->pResolutions[nResolutionIndex - 1];
nX += pResolution->nX1 - pResolution->nX0;
}
if (pBand->nBandIndex & 2)
{
Resolution *pResolution = &pTileComp->pResolutions[nResolutionIndex - 1];
nY += pResolution->nY1 - pResolution->nY0;
}
int nWidth = pTileComp->nX1 - pTileComp->nX0;
if (pTCP->pTCCP[nComponentIndex].nTransformID == 1)
{
for (int nYIndex = 0; nYIndex < pCodeBlock->nY1 - pCodeBlock->nY0; nYIndex++)
{
for (int nXIndex = 0; nXIndex < pCodeBlock->nX1 - pCodeBlock->nX0; nXIndex++)
{
pTier1->aData[nYIndex][nXIndex] = pTileComp->pData[(nX + nXIndex) + (nY + nYIndex) * nWidth] << T1_NMSEDEC_FRACBITS;
}
}
}
else
{
// if ( pTCP->pTCCPs[nComponentIndex].qmfbid == 0 )
for (int nYIndex = 0; nYIndex < pCodeBlock->nY1 - pCodeBlock->nY0; nYIndex++)
{
for (int nXIndex = 0; nXIndex < pCodeBlock->nX1 - pCodeBlock->nX0; nXIndex++)
{
pTier1->aData[nYIndex][nXIndex] = FixedMult(pTileComp->pData[nX + nXIndex + (nY + nYIndex) * nWidth], 8192 * 8192 / ((int)floor(pBand->fStepSize * 8192))) >> (13 - T1_NMSEDEC_FRACBITS);
}
}
}
int nOrient = pBand->nBandIndex;
if (2 == nOrient)
{
nOrient = 1;
}
else if (1 == nOrient)
{
nOrient = 2;
}
Tier1_EncodeCodeBlock(pTier1, pCodeBlock, nOrient, nComponentIndex, pTileComp->nResolutionsCount - 1 - nResolutionIndex, pTCP->pTCCP[nComponentIndex].nTransformID, pBand->fStepSize, pTCP->pTCCP[nComponentIndex].nCodeBlockStyle, pTile->nComponentsCount, pTile);
}
}
}
}
}
}
void Tier1_DecodeCodeBlocks(Tier1 *pTier1, Tile *pTile, TileCodingParams *pTCP)
{
for (int nComponentIndex = 0; nComponentIndex < pTile->nComponentsCount; nComponentIndex++)
{
TileComp *pTileComp = &pTile->pComponents[nComponentIndex];
for (int nResolutionIndex = 0; nResolutionIndex < pTileComp->nResolutionsCount; nResolutionIndex++)
{
Resolution *pResolution = &pTileComp->pResolutions[nResolutionIndex];
for (int nBandIndex = 0; nBandIndex < pResolution->nBandsCount; nBandIndex++)
{
Band *pBand = &pResolution->aBands[nBandIndex];
for (int nPrecinctIndex = 0; nPrecinctIndex < pResolution->nPrecCountW * pResolution->nPrecCountH; nPrecinctIndex++)
{
Precinct *pPrecinct = &pBand->pPrecincts[nPrecinctIndex];
for (int nCodeBlockIndex = 0; nCodeBlockIndex < pPrecinct->nCountInWidth * pPrecinct->nCountInHeight; nCodeBlockIndex++)
{
CodeBlock *pCodeBlock = &pPrecinct->pCodeBlocks[nCodeBlockIndex];
int nOrient = pBand->nBandIndex;
if (2 == nOrient)
{
nOrient = 1;
}
else if (1 == nOrient)
{
nOrient = 2;
}
try
{
Tier1_DecodeCodeBlock(pTier1, pCodeBlock, nOrient, pTCP->pTCCP[nComponentIndex].nROIShift, pTCP->pTCCP[nComponentIndex].nCodeBlockStyle);
}
catch (...)
{
break;
}
int nX = pCodeBlock->nX0 - pBand->nX0;
int nY = pCodeBlock->nY0 - pBand->nY0;
if (pBand->nBandIndex & 1)
{
Resolution *pResolution = &pTileComp->pResolutions[nResolutionIndex - 1];
nX += pResolution->nX1 - pResolution->nX0;
}
if (pBand->nBandIndex & 2)
{
Resolution *pResolution = &pTileComp->pResolutions[nResolutionIndex - 1];
nY += pResolution->nY1 - pResolution->nY0;
}
if (pTCP->pTCCP[nComponentIndex].nROIShift)
{
int nTreshold = 1 << pTCP->pTCCP[nComponentIndex].nROIShift;
for (int nYIndex = 0; nYIndex < pCodeBlock->nY1 - pCodeBlock->nY0; nYIndex++)
{
for (int nXIndex = 0; nXIndex < pCodeBlock->nX1 - pCodeBlock->nX0; nXIndex++)
{
int nValue = pTier1->aData[nYIndex][nXIndex];
int nMagnitude = abs(nValue);
if (nMagnitude >= nTreshold)
{
nMagnitude >>= pTCP->pTCCP[nComponentIndex].nROIShift;
pTier1->aData[nYIndex][nXIndex] = nValue < 0 ? -nMagnitude : nMagnitude;
}
}
}
}
int nWidth = pTileComp->nX1 - pTileComp->nX0;
if (pTCP->pTCCP[nComponentIndex].nTransformID == 1)
{
for (int nYIndex = 0; nYIndex < pCodeBlock->nY1 - pCodeBlock->nY0; nYIndex++)
{
for (int nXIndex = 0; nXIndex < pCodeBlock->nX1 - pCodeBlock->nX0; nXIndex++)
{
pTileComp->pData[nX + nXIndex + (nY + nYIndex) * nWidth] = pTier1->aData[nYIndex][nXIndex] / 2;
}
}
}
else
{
// if ( pTCP->pTCCPs[nComponentIndex].qmfbid == 0 )
for (int nYIndex = 0; nYIndex < pCodeBlock->nY1 - pCodeBlock->nY0; nYIndex++)
{
for (int nXIndex = 0; nXIndex < pCodeBlock->nX1 - pCodeBlock->nX0; nXIndex++)
{
if (pTier1->aData[nYIndex][nXIndex] >> 1 == 0)
{
pTileComp->pData[nX + nXIndex + (nY + nYIndex) * nWidth] = 0;
}
else
{
double dTemp = (double)((pTier1->aData[nYIndex][nXIndex] << 12) * pBand->fStepSize);
int nTemp2 = ((int)(floor(fabs(dTemp)))) + ((int)floor(fabs(dTemp * 2)) % 2);
pTileComp->pData[nX + nXIndex + (nY + nYIndex) * nWidth] = ((dTemp < 0) ? -nTemp2 : nTemp2);
}
}
}
}
}
}
}
}
}
}
}