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