Files
core/ASCImageStudio3/ASCImageJpeg2000/Tile.h

1602 lines
61 KiB
C

#pragma once
#include "DWT.h"
#include "Tier1.h"
#include "Tier2.h"
#include "float.h"
//-------------------------------------------------------------------------------------------------------------------------------
// Îñíîâíûå ôóíêöèè
//-------------------------------------------------------------------------------------------------------------------------------
void TCD_Dump(FILE *pFile, TCD *pTCD, TCDImage *pTCDImage)
{
fprintf( pFile, "<Image ");
fprintf( pFile, "TilesCountW='%d' TilesCountH='%d' X0='%d' X1='%d' Y0='%d' Y1='%d'>", pTCDImage->nTilesCountW, pTCDImage->nTilesCountH, pTCD->pImage->nXOsiz, pTCD->pImage->nXsiz, pTCD->pImage->nYOsiz, pTCD->pImage->nYsiz );
for ( int nTileIndex = 0; nTileIndex < 1; nTileIndex++ )
{
Tile *pTile = &pTCD->pTCDImage->pTiles[nTileIndex];
fprintf( pFile, "<Tile Index ");
fprintf( pFile, "X0='%d' Y0='%d' X1='%d' Y1='%d' ComponentsCount='%d'>\n", pTile->nX0, pTile->nY0, pTile->nX1, pTile->nY1, pTile->nComponentsCount );
for ( int nComponentIndex = 0; nComponentIndex < pTile->nComponentsCount; nComponentIndex++ )
{
TileComp *pTileComp = &pTile->pComponents[nComponentIndex];
fprintf( pFile, "<TileComp Index='%d' ", nComponentIndex );
fprintf( pFile, "X0='%d' Y0='%d' X1='%d' Y1='%d' ResolutionsCount='%d'>\n", pTileComp->nX0, pTileComp->nY0, pTileComp->nX1, pTileComp->nY1, pTileComp->nResolutionsCount );
for ( int nResolutionIndex = 0; nResolutionIndex < pTileComp->nResolutionsCount; nResolutionIndex++ )
{
Resolution *pResolution = &pTileComp->pResolutions[nResolutionIndex];
fprintf( pFile, "<Resolution Index='%d' ", nResolutionIndex );
fprintf( pFile, "X0='%d' Y0='%d' X1='%d' Y1='%d' PrecCountW='%d' PrecCountH='%d' BandsCount='%d'>\n", pResolution->nX0, pResolution->nY0, pResolution->nX1, pResolution->nY1, pResolution->nPrecCountW, pResolution->nPrecCountH, pResolution->nBandsCount );
for ( int nBandIndex = 0; nBandIndex < pResolution->nBandsCount; nBandIndex++ )
{
Band *pBand = &pResolution->aBands[nBandIndex];
fprintf( pFile, "<Band Index='%d' ", nBandIndex );
fprintf( pFile, "X0='%d' Y0='%d' X1='%d' Y1='%d' StepSize='%f' BPSCount='%d'>\n", pBand->nX0, pBand->nY0, pBand->nX1, pBand->nY1, pBand->fStepSize, pBand->nBPSCount );
for ( int nPrecinctIndex = 0; nPrecinctIndex < pResolution->nPrecCountW * pResolution->nPrecCountH; nPrecinctIndex++ )
{
Precinct *pPrecinct = &pBand->pPrecincts[nPrecinctIndex];
fprintf( pFile, "<Precinct Index='%d' ", nPrecinctIndex );
fprintf( pFile, "X0='%d' Y0='%d' X1='%d' Y1='%d' CodeBlockCountW='%d' CodeBlockCountH='%d'>\n", pPrecinct->nX0, pPrecinct->nY0, pPrecinct->nX1, pPrecinct->nY1, pPrecinct->nCountInWidth, pPrecinct->nCountInHeight );
for ( int nCodeBlockIndex = 0; nCodeBlockIndex < pPrecinct->nCountInWidth * pPrecinct->nCountInHeight; nCodeBlockIndex++ )
{
CodeBlock *pCodeBlock = &pPrecinct->pCodeBlocks[nCodeBlockIndex];
fprintf( pFile, "<CodeBlock Index='%d' ", nCodeBlockIndex );
fprintf( pFile, "X0='%d' Y0='%d' X1='%d' Y1='%d'/>\n", pCodeBlock->nX0, pCodeBlock->nY0, pCodeBlock->nX1, pCodeBlock->nY1 );
}
fprintf( pFile, "</Precinct>\n");
}
fprintf( pFile, "</Band>\n");
}
fprintf( pFile, "</Resolution>\n");
}
fprintf( pFile, "</TileComp>\n");
}
fprintf( pFile, "</Tile>\n");
}
fprintf( pFile, "</Image>\n");
}
TCD* TCD_Create(PCommon pCodecInfo)
{
TCD *pTCD = (TCD*)Malloc(HEAP_ZERO_MEMORY, sizeof(TCD) );
if( !pTCD )
return NULL;
pTCD->pCodecInfo = pCodecInfo;
pTCD->pTCDImage = (TCDImage*)Malloc(HEAP_ZERO_MEMORY, sizeof(TCDImage));
if( !pTCD->pTCDImage )
{
RELEASEHEAP(pTCD );
return NULL;
}
return pTCD;
}
void TCD_Destroy(TCD *pTCD)
{
if( pTCD )
{
RELEASEHEAP(pTCD->pTCDImage );
RELEASEHEAP(pTCD );
}
}
void TCD_FreeEncode(TCD *pTCD)
{
for ( int nTileIndex = 0; nTileIndex < 1; nTileIndex++ )
{
Tile *pTile = pTCD->pTCDImage->pTiles;
if ( pTile )
{
for ( int nComponentIndex = 0; nComponentIndex < pTile->nComponentsCount; nComponentIndex++ )
{
TileComp *pTileComp = &pTile->pComponents[nComponentIndex];
if ( pTileComp )
{
for ( int nResolutionIndex = 0; nResolutionIndex < pTileComp->nResolutionsCount; nResolutionIndex++ )
{
Resolution *pResolution = &pTileComp->pResolutions[nResolutionIndex];
if ( pResolution )
{
for ( int nBandIndex = 0; nBandIndex < pResolution->nBandsCount; nBandIndex++ )
{
Band *pBand = &pResolution->aBands[nBandIndex];
if ( pBand )
{
for ( int nPrecinctIndex = 0; nPrecinctIndex < pResolution->nPrecCountW * pResolution->nPrecCountH; nPrecinctIndex++ )
{
Precinct *pPrecinct = &pBand->pPrecincts[nPrecinctIndex];
if ( pPrecinct )
{
TGT_Destroy( pPrecinct->pInclTree );
TGT_Destroy( pPrecinct->pIMSBTree );
RELEASEHEAP(pPrecinct->pCodeBlocks );
}
}
RELEASEHEAP(pBand->pPrecincts );
}
}
}
}
RELEASEHEAP(pTileComp->pResolutions );
}
}
if ( pTile->pComponents != NULL )
RELEASEHEAP(pTile->pComponents );
pTile->pComponents = NULL;
}
}
if ( pTCD->pTCDImage->pTiles != NULL )
RELEASEHEAP(pTCD->pTCDImage->pTiles );
pTCD->pTCDImage->pTiles = NULL;
}
void TCD_MallocEncode(TCD *pTCD, Image *pImage, CodingParams *pCodingParams, int nCurTileIndex)
{
pTCD->pImage = pImage;
pTCD->pCodingParams = pCodingParams;
pTCD->pTCDImage->nTilesCountW = pCodingParams->nXTilesCount;
pTCD->pTCDImage->nTilesCountH = pCodingParams->nYTilesCount;
pTCD->pTCDImage->pTiles = (Tile *) Malloc(HEAP_ZERO_MEMORY, sizeof(Tile));
if ( !pTCD->pTCDImage->pTiles )
{
TCD_FreeEncode( pTCD );
pTCD->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
return;
}
for ( int nTileIndex = 0; nTileIndex < 1; nTileIndex++ )
{
TileCodingParams *pTCP = &pCodingParams->pTCP[nCurTileIndex];
// Ñì. ñòð 59 ISO/IEC FDIS15444-1
int nP = nCurTileIndex % pCodingParams->nXTilesCount;
int nQ = nCurTileIndex / pCodingParams->nXTilesCount;
Tile *pTile = pTCD->pTCDImage->pTiles;
// Ãðàíèöû òàéëà (ìàøòàáèðîâàííûå îòíîñèòåëüíî ðàçìåðîâ èçîáðàæåíèÿ, åñëè íåîáõîäèìî)
pTile->nX0 = max( pCodingParams->nXTOsiz + nP * pCodingParams->nXTsiz, pImage->nXOsiz );
pTile->nY0 = max( pCodingParams->nYTOsiz + nQ * pCodingParams->nYTsiz, pImage->nYOsiz );
pTile->nX1 = min( pCodingParams->nXTOsiz + (nP + 1) * pCodingParams->nXTsiz, pImage->nXsiz );
pTile->nY1 = min( pCodingParams->nYTOsiz + (nQ + 1) * pCodingParams->nYTsiz, pImage->nYsiz );
pTile->nComponentsCount = pImage->nCsiz;
// RATE >>
for ( int nIndex = 0; nIndex < pTCP->nLayersCount; nIndex++ )
{
pTCP->afRates[nIndex] = pTCP->afRates[nIndex] ? ( (float)( pTile->nComponentsCount * (pTile->nX1 - pTile->nX0) * (pTile->nY1 - pTile->nY0) * pImage->pComponents[0].nPrecision ) ) / ( pTCP->afRates[nIndex] * 8 * pImage->pComponents[0].nXRsiz * pImage->pComponents[0].nYRsiz ) : 0;
if ( pTCP->afRates[nIndex] )
{
if ( nIndex && pTCP->afRates[nIndex] < pTCP->afRates[nIndex - 1] + 10 )
{
pTCP->afRates[nIndex] = pTCP->afRates[nIndex - 1] + 20;
}
else
{
if ( !nIndex && pTCP->afRates[nIndex] < 30 )
pTCP->afRates[nIndex] = 30;
}
}
}
// << RATE
pTile->pComponents = (TileComp *) Malloc(HEAP_ZERO_MEMORY, pImage->nCsiz * sizeof(TileComp) );
if ( !pTile->pComponents )
{
TCD_FreeEncode( pTCD );
pTCD->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
return;
}
for ( int nComponentIndex = 0; nComponentIndex < pTile->nComponentsCount; nComponentIndex++ )
{
TileCompCodingParams *pTCCP = &pTCP->pTCCP[nComponentIndex];
TileComp *pTileComp = &pTile->pComponents[nComponentIndex];
// Ãðàíèöû êàæäîé òàéë-êîìïîíåíòû (ãëîáàëüíûå)
pTileComp->nX0 = CeilDiv( pTile->nX0, pImage->pComponents[nComponentIndex].nXRsiz );
pTileComp->nY0 = CeilDiv( pTile->nY0, pImage->pComponents[nComponentIndex].nYRsiz );
pTileComp->nX1 = CeilDiv( pTile->nX1, pImage->pComponents[nComponentIndex].nXRsiz );
pTileComp->nY1 = CeilDiv( pTile->nY1, pImage->pComponents[nComponentIndex].nYRsiz );
pTileComp->pData = (int *) Malloc(HEAP_ZERO_MEMORY, (pTileComp->nX1 - pTileComp->nX0) * (pTileComp->nY1 - pTileComp->nY0) * sizeof(int) );
if ( !pTileComp->pData )
{
TCD_FreeEncode( pTCD );
pTCD->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
return;
}
pTileComp->nResolutionsCount = pTCCP->nResolutionsCount;
pTileComp->pResolutions = (Resolution *) Malloc(HEAP_ZERO_MEMORY, pTileComp->nResolutionsCount * sizeof(Resolution) );
if ( !pTileComp->pResolutions )
{
TCD_FreeEncode( pTCD );
pTCD->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
return;
}
for ( int nResolutionIndex = 0; nResolutionIndex < pTileComp->nResolutionsCount; nResolutionIndex++ )
{
int nLevel = pTileComp->nResolutionsCount - 1 - nResolutionIndex;
Resolution *pResolution = &pTileComp->pResolutions[nResolutionIndex];
// Ãðàíèöû äëÿ êàæäîãî óðîâíÿ (ãëîáàëüíûå)
pResolution->nX0 = CeilDivPow2( pTileComp->nX0, nLevel );
pResolution->nY0 = CeilDivPow2( pTileComp->nY0, nLevel );
pResolution->nX1 = CeilDivPow2( pTileComp->nX1, nLevel );
pResolution->nY1 = CeilDivPow2( pTileComp->nY1, nLevel );
pResolution->nBandsCount = ( nResolutionIndex == 0 ? 1 : 3 );
// Ñì. ñòð. 35, òàáëèöà A-23 ISO/IEC FDIS154444-1
int nPPx, nPPy;
if ( pTCCP->nCodingStyle & J2K_CCP_CSTY_PRT )
{
nPPx = pTCCP->anPrecinctWidth[nResolutionIndex];
nPPy = pTCCP->anPrecinctHeight[nResolutionIndex];
}
else
{
nPPx = 15;
nPPy = 15;
}
// Ñì. ñòð. 64, Annex-B.6, ISO/IEC FDIS15444-1
int nFloorTRX0 = FloorDivPow2( pResolution->nX0, nPPx ) << nPPx;
int nFloorTRY0 = FloorDivPow2( pResolution->nY0, nPPy ) << nPPy;
int nCeilTRX1 = CeilDivPow2( pResolution->nX1, nPPx ) << nPPx;
int nCeilTRY1 = CeilDivPow2( pResolution->nY1, nPPy ) << nPPy;
pResolution->nPrecCountW = (nCeilTRX1 - nFloorTRX0) >> nPPx;
pResolution->nPrecCountH = (nCeilTRY1 - nFloorTRY0) >> nPPy;
int nCBWidthExpn, nCBHeightExpn;
int nTLCodeBlockGlobalStartX, nTLCodeBlockGlobalStartY, nBRCodeBlockGlobalEndX, nBRCodeBlockGlobalEndY;
if ( 0 == nResolutionIndex )
{
nTLCodeBlockGlobalStartX = nFloorTRX0;
nTLCodeBlockGlobalStartY = nFloorTRY0;
nBRCodeBlockGlobalEndX = nCeilTRX1;
nBRCodeBlockGlobalEndY = nCeilTRY1;
nCBWidthExpn = nPPx;
nCBHeightExpn = nPPy;
}
else
{
nTLCodeBlockGlobalStartX = CeilDivPow2( nFloorTRX0, 1 );
nTLCodeBlockGlobalStartY = CeilDivPow2( nFloorTRY0, 1 );
nBRCodeBlockGlobalEndX = CeilDivPow2( nCeilTRX1, 1 );
nBRCodeBlockGlobalEndY = CeilDivPow2( nCeilTRY1, 1 );
nCBWidthExpn = nPPx - 1;
nCBHeightExpn = nPPy - 1;
}
int nXCBa = min( pTCCP->nCodeBlockWidth, nCBWidthExpn );
int nYCBa = min( pTCCP->nCodeBlockHeight, nCBHeightExpn );
for ( int nBandIndex = 0; nBandIndex < pResolution->nBandsCount; nBandIndex++ )
{
Band *pBand = &pResolution->aBands[nBandIndex];
pBand->nBandIndex = ( nResolutionIndex == 0 ? 0 : nBandIndex + 1 );
int nBandX0 = (pBand->nBandIndex == 1) || (pBand->nBandIndex == 3) ? 1 : 0;
int nBandY0 = (pBand->nBandIndex == 2) || (pBand->nBandIndex == 3) ? 1 : 0;
if ( pBand->nBandIndex == 0 )
{
pBand->nX0 = CeilDivPow2( pTileComp->nX0, nLevel );
pBand->nY0 = CeilDivPow2( pTileComp->nY0, nLevel );
pBand->nX1 = CeilDivPow2( pTileComp->nX1, nLevel );
pBand->nY1 = CeilDivPow2( pTileComp->nY1, nLevel );
}
else
{
pBand->nX0 = CeilDivPow2( pTileComp->nX0 - (1 << nLevel) * nBandX0, nLevel + 1 );
pBand->nY0 = CeilDivPow2( pTileComp->nY0 - (1 << nLevel) * nBandY0, nLevel + 1 );
pBand->nX1 = CeilDivPow2( pTileComp->nX1 - (1 << nLevel) * nBandX0, nLevel + 1 );
pBand->nY1 = CeilDivPow2( pTileComp->nY1 - (1 << nLevel) * nBandY0, nLevel + 1 );
}
QuantStepSize *pStepSize = &pTCCP->aoStepSizes[ nResolutionIndex == 0 ? 0 : 3 * (nResolutionIndex - 1) + nBandIndex + 1 ];
int nGain = pTCCP->nTransformID == 0 ? DWT_GetGainIrr( pBand->nBandIndex ) : DWT_GetGainRev( pBand->nBandIndex );
int nBPSCount = pImage->pComponents[nComponentIndex].nPrecision + nGain;
pBand->fStepSize = (float)( ( 1.0 + pStepSize->nMantissa / 2048.0 ) * pow( 2.0, nBPSCount - pStepSize->nExponent ) );
pBand->nBPSCount = pStepSize->nExponent + pTCCP->nGuardBitsCount - 1;
pBand->pPrecincts = (Precinct *) Malloc(HEAP_ZERO_MEMORY, 3 * pResolution->nPrecCountW * pResolution->nPrecCountH * sizeof(Precinct));
if ( !pBand->pPrecincts )
{
pTCD->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
return;
}
for ( int nIndex = 0; nIndex < pResolution->nPrecCountW * pResolution->nPrecCountH * 3; nIndex++ )
{
pBand->pPrecincts[nIndex].pIMSBTree = NULL;
pBand->pPrecincts[nIndex].pInclTree = NULL;
}
for ( int nPrecinctIndex = 0; nPrecinctIndex < pResolution->nPrecCountW * pResolution->nPrecCountH; nPrecinctIndex++ )
{
int nGlobalCodeBlockStartX = nTLCodeBlockGlobalStartX + (nPrecinctIndex % pResolution->nPrecCountW) * ( 1 << nCBWidthExpn );
int nGlobalCodeBlockStartY = nTLCodeBlockGlobalStartY + (nPrecinctIndex / pResolution->nPrecCountW) * ( 1 << nCBHeightExpn );
int nGlobalCodeBlockEndX = nGlobalCodeBlockStartX + (1 << nCBWidthExpn);
int nGlobalCodeBlockEndY = nGlobalCodeBlockStartY + (1 << nCBHeightExpn);
Precinct *pPrecinct = &pBand->pPrecincts[nPrecinctIndex];
// Ðàçìåðû îáëàñòè (Precinct)
pPrecinct->nX0 = max( nGlobalCodeBlockStartX, pBand->nX0 );
pPrecinct->nY0 = max( nGlobalCodeBlockStartY, pBand->nY0 );
pPrecinct->nX1 = min( nGlobalCodeBlockEndX, pBand->nX1 );
pPrecinct->nY1 = min( nGlobalCodeBlockEndY, pBand->nY1 );
int nTLCodeBlockStartX = FloorDivPow2( pPrecinct->nX0, nXCBa ) << nXCBa;
int nTLCodeBlockStartY = FloorDivPow2( pPrecinct->nY0, nYCBa ) << nYCBa;
int nBRCodeBlockEndX = CeilDivPow2( pPrecinct->nX1, nXCBa ) << nXCBa;
int nBRCodeBlockEndY = CeilDivPow2( pPrecinct->nY1, nYCBa ) << nYCBa;
pPrecinct->nCountInWidth = (nBRCodeBlockEndX - nTLCodeBlockStartX) >> nXCBa;
pPrecinct->nCountInHeight = (nBRCodeBlockEndY - nTLCodeBlockStartY) >> nYCBa;
pPrecinct->pCodeBlocks = (CodeBlock *) Malloc(HEAP_ZERO_MEMORY, (pPrecinct->nCountInWidth * pPrecinct->nCountInHeight) * sizeof(CodeBlock) );
if ( !pPrecinct->pCodeBlocks )
{
TCD_FreeEncode( pTCD );
pTCD->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
return;
}
pPrecinct->pInclTree = TGT_Create( pPrecinct->nCountInWidth, pPrecinct->nCountInHeight );
pPrecinct->pIMSBTree = TGT_Create( pPrecinct->nCountInWidth, pPrecinct->nCountInHeight );
for ( int nCodeBlockIndex = 0; nCodeBlockIndex < pPrecinct->nCountInWidth * pPrecinct->nCountInHeight; nCodeBlockIndex++ )
{
int nCodeBlockStartX = nTLCodeBlockStartX + (nCodeBlockIndex % pPrecinct->nCountInWidth) * (1 << nXCBa);
int nCodeBlockStartY = nTLCodeBlockStartY + (nCodeBlockIndex / pPrecinct->nCountInWidth) * (1 << nYCBa);
int nCodeBlockEndX = nCodeBlockStartX + (1 << nXCBa);
int nCodeBlockEndY = nCodeBlockStartY + (1 << nYCBa);
CodeBlock *pCodeBlock = &pPrecinct->pCodeBlocks[nCodeBlockIndex];
// Ãðàíèöû CodeBlock (ãëîáàëüíûå)
pCodeBlock->nX0 = max( nCodeBlockStartX, pPrecinct->nX0 );
pCodeBlock->nY0 = max( nCodeBlockStartY, pPrecinct->nY0 );
pCodeBlock->nX1 = min( nCodeBlockEndX, pPrecinct->nX1 );
pCodeBlock->nY1 = min( nCodeBlockEndY, pPrecinct->nY1 );
}
}
}
}
}
}
//#ifdef _DEBUG
// FILE *pFile;
// pFile = fopen( "E:\\Jpeg2000DumpFile.xml", "wb" );
// if ( pFile )
// {
// TCD_Dump( pFile, pTCD, pTCD->pTCDImage );
// fclose( pFile );
// }
//#endif
}
void TCD_InitEncode(TCD *pTCD, Image *pImage, CodingParams *pCodingParams, int nCurTileIndex)
{
for ( int nTileIndex = 0; nTileIndex < 1; nTileIndex++ )
{
TileCodingParams *pTCP = &pCodingParams->pTCP[nCurTileIndex];
// Ñì. ñòð 59 ISO/IEC FDIS15444-1
int nP = nCurTileIndex % pCodingParams->nXTilesCount;
int nQ = nCurTileIndex / pCodingParams->nXTilesCount;
Tile *pTile = pTCD->pTCDImage->pTiles;
// Ãðàíèöû òàéëà (ìàøòàáèðîâàííûå îòíîñèòåëüíî ðàçìåðîâ èçîáðàæåíèÿ, åñëè íåîáõîäèìî)
pTile->nX0 = max( pCodingParams->nXTOsiz + nP * pCodingParams->nXTsiz, pImage->nXOsiz );
pTile->nY0 = max( pCodingParams->nYTOsiz + nQ * pCodingParams->nYTsiz, pImage->nYOsiz );
pTile->nX1 = min( pCodingParams->nXTOsiz + (nP + 1) * pCodingParams->nXTsiz, pImage->nXsiz );
pTile->nY1 = min( pCodingParams->nYTOsiz + (nQ + 1) * pCodingParams->nYTsiz, pImage->nYsiz );
pTile->nComponentsCount = pImage->nCsiz;
// RATE >>
for ( int nIndex = 0; nIndex < pTCP->nLayersCount; nIndex++ )
{
pTCP->afRates[nIndex] = pTCP->afRates[nIndex] ? ( (float)( pTile->nComponentsCount * (pTile->nX1 - pTile->nX0) * (pTile->nY1 - pTile->nY0) * pImage->pComponents[0].nPrecision ) ) / ( pTCP->afRates[nIndex] * 8 * pImage->pComponents[0].nXRsiz * pImage->pComponents[0].nYRsiz ) : 0;
if ( pTCP->afRates[nIndex] )
{
if ( nIndex && pTCP->afRates[nIndex] < pTCP->afRates[nIndex - 1] + 10 )
{
pTCP->afRates[nIndex] = pTCP->afRates[nIndex - 1] + 20;
}
else
{
if ( !nIndex && pTCP->afRates[nIndex] < 30 )
pTCP->afRates[nIndex] = 30;
}
}
}
// << RATE
for ( int nComponentIndex = 0; nComponentIndex < pTile->nComponentsCount; nComponentIndex++ )
{
TileCompCodingParams *pTCCP = &pTCP->pTCCP[nComponentIndex];
TileComp *pTileComp = &pTile->pComponents[nComponentIndex];
// Ãðàíèöû êàæäîé òàéë-êîìïîíåíòû (ãëîáàëüíûå)
pTileComp->nX0 = CeilDiv( pTile->nX0, pImage->pComponents[nComponentIndex].nXRsiz );
pTileComp->nY0 = CeilDiv( pTile->nY0, pImage->pComponents[nComponentIndex].nYRsiz );
pTileComp->nX1 = CeilDiv( pTile->nX1, pImage->pComponents[nComponentIndex].nXRsiz );
pTileComp->nY1 = CeilDiv( pTile->nY1, pImage->pComponents[nComponentIndex].nYRsiz );
pTileComp->pData = (int *) Malloc(HEAP_ZERO_MEMORY, (pTileComp->nX1 - pTileComp->nX0) * (pTileComp->nY1 - pTileComp->nY0) * sizeof(int) );
if ( !pTileComp->pData )
{
TCD_FreeEncode( pTCD );
pTCD->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
return;
}
pTileComp->nResolutionsCount = pTCCP->nResolutionsCount;
for ( int nResolutionIndex = 0; nResolutionIndex < pTileComp->nResolutionsCount; nResolutionIndex++ )
{
int nLevel = pTileComp->nResolutionsCount - 1 - nResolutionIndex;
Resolution *pResolution = &pTileComp->pResolutions[nResolutionIndex];
// Ãðàíèöû äëÿ êàæäîãî óðîâíÿ (ãëîáàëüíûå)
pResolution->nX0 = CeilDivPow2( pTileComp->nX0, nLevel );
pResolution->nY0 = CeilDivPow2( pTileComp->nY0, nLevel );
pResolution->nX1 = CeilDivPow2( pTileComp->nX1, nLevel );
pResolution->nY1 = CeilDivPow2( pTileComp->nY1, nLevel );
pResolution->nBandsCount = ( nResolutionIndex == 0 ? 1 : 3 );
// Ñì. ñòð. 35, òàáëèöà A-23 ISO/IEC FDIS154444-1
int nPPx, nPPy;
if ( pTCCP->nCodingStyle & J2K_CCP_CSTY_PRT )
{
nPPx = pTCCP->anPrecinctWidth[nResolutionIndex];
nPPy = pTCCP->anPrecinctHeight[nResolutionIndex];
}
else
{
nPPx = 15;
nPPy = 15;
}
// Ñì. ñòð. 64, Annex-B.6, ISO/IEC FDIS15444-1
int nFloorTRX0 = FloorDivPow2( pResolution->nX0, nPPx ) << nPPx;
int nFloorTRY0 = FloorDivPow2( pResolution->nY0, nPPy ) << nPPy;
int nCeilTRX1 = CeilDivPow2( pResolution->nX1, nPPx ) << nPPx;
int nCeilTRY1 = CeilDivPow2( pResolution->nY1, nPPy ) << nPPy;
pResolution->nPrecCountW = (nCeilTRX1 - nFloorTRX0) >> nPPx;
pResolution->nPrecCountH = (nCeilTRY1 - nFloorTRY0) >> nPPy;
int nCBWidthExpn, nCBHeightExpn;
int nTLCodeBlockGlobalStartX, nTLCodeBlockGlobalStartY, nBRCodeBlockGlobalEndX, nBRCodeBlockGlobalEndY;
if ( 0 == nResolutionIndex )
{
nTLCodeBlockGlobalStartX = nFloorTRX0;
nTLCodeBlockGlobalStartY = nFloorTRY0;
nBRCodeBlockGlobalEndX = nCeilTRX1;
nBRCodeBlockGlobalEndY = nCeilTRY1;
nCBWidthExpn = nPPx;
nCBHeightExpn = nPPy;
}
else
{
nTLCodeBlockGlobalStartX = CeilDivPow2( nFloorTRX0, 1 );
nTLCodeBlockGlobalStartY = CeilDivPow2( nFloorTRY0, 1 );
nBRCodeBlockGlobalEndX = CeilDivPow2( nCeilTRX1, 1 );
nBRCodeBlockGlobalEndY = CeilDivPow2( nCeilTRY1, 1 );
nCBWidthExpn = nPPx - 1;
nCBHeightExpn = nPPy - 1;
}
int nXCBa = min( pTCCP->nCodeBlockWidth, nCBWidthExpn );
int nYCBa = min( pTCCP->nCodeBlockHeight, nCBHeightExpn );
for ( int nBandIndex = 0; nBandIndex < pResolution->nBandsCount; nBandIndex++ )
{
Band *pBand = &pResolution->aBands[nBandIndex];
pBand->nBandIndex = ( nResolutionIndex == 0 ? 0 : nBandIndex + 1 );
int nBandX0 = (pBand->nBandIndex == 1) || (pBand->nBandIndex == 3) ? 1 : 0;
int nBandY0 = (pBand->nBandIndex == 2) || (pBand->nBandIndex == 3) ? 1 : 0;
if ( 0 == pBand->nBandIndex )
{
pBand->nX0 = CeilDivPow2( pTileComp->nX0, nLevel );
pBand->nY0 = CeilDivPow2( pTileComp->nY0, nLevel );
pBand->nX1 = CeilDivPow2( pTileComp->nX1, nLevel );
pBand->nY1 = CeilDivPow2( pTileComp->nY1, nLevel );
}
else
{
pBand->nX0 = CeilDivPow2( pTileComp->nX0 - ( 1 << nLevel ) * nBandX0, nLevel + 1 );
pBand->nY0 = CeilDivPow2( pTileComp->nY0 - ( 1 << nLevel ) * nBandY0, nLevel + 1 );
pBand->nX1 = CeilDivPow2( pTileComp->nX1 - ( 1 << nLevel ) * nBandX0, nLevel + 1 );
pBand->nY1 = CeilDivPow2( pTileComp->nY1 - ( 1 << nLevel ) * nBandY0, nLevel + 1 );
}
QuantStepSize *pStepSize = &pTCCP->aoStepSizes[nResolutionIndex == 0 ? 0 : 3 * (nResolutionIndex - 1) + nBandIndex + 1];
int nGain = pTCCP->nTransformID == 0 ? DWT_GetGainIrr( pBand->nBandIndex ) : DWT_GetGainRev( pBand->nBandIndex );
int nBPSCount = pImage->pComponents[nComponentIndex].nPrecision + nGain;
pBand->fStepSize = (float)( ( 1.0 + pStepSize->nMantissa / 2048.0 ) * pow( 2.0, nBPSCount - pStepSize->nExponent ) );
pBand->nBPSCount = pStepSize->nExponent + pTCCP->nGuardBitsCount - 1;
for ( int nPrecinctIndex = 0; nPrecinctIndex < pResolution->nPrecCountW * pResolution->nPrecCountH; nPrecinctIndex++ )
{
int nGlobalCodeBlockStartX = nTLCodeBlockGlobalStartX + (nPrecinctIndex % pResolution->nPrecCountW) * (1 << nCBWidthExpn);
int nGlobalCodeBlockStartY = nTLCodeBlockGlobalStartY + (nPrecinctIndex / pResolution->nPrecCountW) * (1 << nCBHeightExpn);
int nGlobalCodeBlockEndX = nGlobalCodeBlockStartX + (1 << nCBWidthExpn);
int nGlobalCodeBlockEndY = nGlobalCodeBlockStartY + (1 << nCBHeightExpn);
Precinct *pPrecinct = &pBand->pPrecincts[nPrecinctIndex];
// Ðàçìåðû îáëàñòè (Precinct)
pPrecinct->nX0 = max( nGlobalCodeBlockStartX, pBand->nX0 );
pPrecinct->nY0 = max( nGlobalCodeBlockStartY, pBand->nY0 );
pPrecinct->nX1 = min( nGlobalCodeBlockEndX, pBand->nX1 );
pPrecinct->nY1 = min( nGlobalCodeBlockEndY, pBand->nY1 );
int nTLCodeBlockStartX = FloorDivPow2( pPrecinct->nX0, nXCBa ) << nXCBa;
int nTLCodeBlockStartY = FloorDivPow2( pPrecinct->nY0, nYCBa ) << nYCBa;
int nBRCodeBlockEndX = CeilDivPow2( pPrecinct->nX1, nXCBa ) << nXCBa;
int nBRCodeBlockEndY = CeilDivPow2( pPrecinct->nY1, nYCBa ) << nYCBa;
pPrecinct->nCountInWidth = (nBRCodeBlockEndX - nTLCodeBlockStartX) >> nXCBa;
pPrecinct->nCountInHeight = (nBRCodeBlockEndY - nTLCodeBlockStartY) >> nYCBa;
RELEASEHEAP(pPrecinct->pCodeBlocks );
pPrecinct->pCodeBlocks = (CodeBlock *) Malloc(HEAP_ZERO_MEMORY, pPrecinct->nCountInWidth * pPrecinct->nCountInHeight * sizeof(CodeBlock) );
if ( !pPrecinct->pCodeBlocks )
{
TCD_FreeEncode( pTCD );
pTCD->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
return;
}
if ( pPrecinct->pInclTree != NULL )
{
TGT_Destroy( pPrecinct->pInclTree );
}
if ( pPrecinct->pIMSBTree != NULL )
{
TGT_Destroy( pPrecinct->pIMSBTree );
}
pPrecinct->pInclTree = TGT_Create( pPrecinct->nCountInWidth, pPrecinct->nCountInHeight );
pPrecinct->pIMSBTree = TGT_Create( pPrecinct->nCountInWidth, pPrecinct->nCountInHeight );
for ( int nCodeBlockIndex = 0; nCodeBlockIndex < pPrecinct->nCountInWidth * pPrecinct->nCountInHeight; nCodeBlockIndex++ )
{
int nCodeBlockStartX = nTLCodeBlockStartX + (nCodeBlockIndex % pPrecinct->nCountInWidth) * (1 << nXCBa);
int nCodeBlockStartY = nTLCodeBlockStartY + (nCodeBlockIndex / pPrecinct->nCountInWidth) * (1 << nYCBa);
int nCodeBlockEndX = nCodeBlockStartX + (1 << nXCBa);
int nCodeBlockEndY = nCodeBlockStartY + (1 << nYCBa);
CodeBlock *pCodeBlock = &pPrecinct->pCodeBlocks[nCodeBlockIndex];
// Ãðàíèöû CodeBlock (ãëîáàëüíûå)
pCodeBlock->nX0 = max( nCodeBlockStartX, pPrecinct->nX0 );
pCodeBlock->nY0 = max( nCodeBlockStartY, pPrecinct->nY0 );
pCodeBlock->nX1 = min( nCodeBlockEndX, pPrecinct->nX1 );
pCodeBlock->nY1 = min( nCodeBlockEndY, pPrecinct->nY1 );
}
}
}
}
}
}
//#ifdef _DEBUG
// FILE *pFile;
// pFile = fopen( "E:\\Jpeg2000DumpFile.xml", "wb" );
// if ( pFile )
// {
// TCD_Dump( pFile, pTCD, pTCD->pTCDImage );
// fclose( pFile );
// }
//#endif
}
void TCD_FreeDecode(TCD *pTCD)
{
TCDImage *pTCDImage = pTCD->pTCDImage;
if ( pTCDImage != NULL )
{
for ( int nTileIndex = 0; nTileIndex < pTCDImage->nTilesCountW * pTCDImage->nTilesCountH; nTileIndex++ )
{
Tile *pTile = &pTCDImage->pTiles[nTileIndex];
if ( pTile != NULL )
{
for ( int nComponentIndex = 0; nComponentIndex < pTile->nComponentsCount; nComponentIndex++ )
{
TileComp *pTileComp = &pTile->pComponents[nComponentIndex];
if ( pTileComp != NULL )
{
for ( int nResolutionIndex = 0; nResolutionIndex < pTileComp->nResolutionsCount; nResolutionIndex++ )
{
Resolution *pResolution = &pTileComp->pResolutions[nResolutionIndex];
if ( pResolution != NULL )
{
for ( int nBandIndex = 0; nBandIndex < pResolution->nBandsCount; nBandIndex++ )
{
Band *pBand = &pResolution->aBands[nBandIndex];
if ( pBand != NULL )
{
for ( int nPrecinctIndex = 0; nPrecinctIndex < pResolution->nPrecCountH * pResolution->nPrecCountW; nPrecinctIndex++ )
{
if (pBand->pPrecincts == NULL)continue;
Precinct *pPrecinct = &pBand->pPrecincts[nPrecinctIndex];
if ( pPrecinct != NULL )
{
RELEASEHEAP(pPrecinct->pCodeBlocks );
if ( pPrecinct->pIMSBTree != NULL )
TGT_Destroy( pPrecinct->pIMSBTree );
if ( pPrecinct->pInclTree != NULL )
TGT_Destroy( pPrecinct->pInclTree );
}
}
RELEASEHEAP(pBand->pPrecincts );
}
}
}
}
RELEASEHEAP(pTileComp->pResolutions );
RELEASEHEAP(pTileComp->pData );
}
}
RELEASEHEAP(pTile->pComponents );
}
}
if ( pTCDImage->pTiles != NULL )
RELEASEHEAP(pTCDImage->pTiles );
}
}
void TCD_MallocDecode(TCD *pTCD, Image *pImage, CodingParams *pCodingParams)
{
pTCD->pImage = pImage;
pTCD->pCodingParams = pCodingParams;
pTCD->pTCDImage->nTilesCountW = pCodingParams->nXTilesCount;
pTCD->pTCDImage->nTilesCountH = pCodingParams->nYTilesCount;
pTCD->pTCDImage->pTiles = (Tile *)Malloc(HEAP_ZERO_MEMORY, pCodingParams->nXTilesCount * pCodingParams->nYTilesCount * sizeof(Tile) );
if ( !pTCD->pTCDImage->pTiles )
{
pTCD->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
return;
}
for ( int nIndex = 0; nIndex < pCodingParams->nTileIndexSize; nIndex++ )
{
TileCodingParams *pTCP = &(pCodingParams->pTCP[pCodingParams->pTileIndex[nIndex]]);
Tile *pTile = &(pTCD->pTCDImage->pTiles[pCodingParams->pTileIndex[nIndex]]);
// Ñì. ñòð 59 ISO/IEC FDIS15444-1
int nTileIndex = pCodingParams->pTileIndex[nIndex];
int nP = nTileIndex % pCodingParams->nXTilesCount;
int nQ = nTileIndex / pCodingParams->nXTilesCount;
// Ãðàíèöû òàéëà (ìàøòàáèðîâàííûå îòíîñèòåëüíî ðàçìåðîâ èçîáðàæåíèÿ, åñëè íåîáõîäèìî)
pTile->nX0 = max( pCodingParams->nXTOsiz + nP * pCodingParams->nXTsiz, pImage->nXOsiz );
pTile->nY0 = max( pCodingParams->nYTOsiz + nQ * pCodingParams->nYTsiz, pImage->nYOsiz );
pTile->nX1 = min( pCodingParams->nXTOsiz + (nP + 1) * pCodingParams->nXTsiz, pImage->nXsiz );
pTile->nY1 = min( pCodingParams->nYTOsiz + (nQ + 1) * pCodingParams->nYTsiz, pImage->nYsiz );
pTile->nComponentsCount = pImage->nCsiz;
pTile->pComponents = (TileComp *) Malloc(HEAP_ZERO_MEMORY, pImage->nCsiz * sizeof(TileComp) );
if ( !pTile->pComponents )
{
TCD_FreeDecode( pTCD );
pTCD->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
return;
}
for ( int nComponentIndex = 0; nComponentIndex < pTile->nComponentsCount; nComponentIndex++ )
{
TileCompCodingParams *pTCCP = &pTCP->pTCCP[nComponentIndex];
TileComp *pTileComp = &pTile->pComponents[nComponentIndex];
// Ãðàíèöû êàæäîé òàéë-êîìïîíåíòû (ãëîáàëüíûå)
pTileComp->nX0 = CeilDiv( pTile->nX0, pImage->pComponents[nComponentIndex].nXRsiz );
pTileComp->nY0 = CeilDiv( pTile->nY0, pImage->pComponents[nComponentIndex].nYRsiz );
pTileComp->nX1 = CeilDiv( pTile->nX1, pImage->pComponents[nComponentIndex].nXRsiz );
pTileComp->nY1 = CeilDiv( pTile->nY1, pImage->pComponents[nComponentIndex].nYRsiz );
long sz_alloc = (pTileComp->nX1 - pTileComp->nX0) * (pTileComp->nY1 - pTileComp->nY0) * sizeof(int);
pTileComp->pData = (int *) Malloc(HEAP_ZERO_MEMORY, sz_alloc );
if ( !pTileComp->pData )
{
TCD_FreeDecode( pTCD );
pTCD->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
return;
}
pTileComp->nResolutionsCount = pTCCP->nResolutionsCount;
pTileComp->pResolutions = (Resolution *) Malloc(HEAP_ZERO_MEMORY, pTileComp->nResolutionsCount * sizeof(Resolution) );
if ( !pTileComp->pResolutions )
{
TCD_FreeDecode( pTCD );
pTCD->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
return;
}
for ( int nResolutionIndex = 0; nResolutionIndex < pTileComp->nResolutionsCount; nResolutionIndex++ )
{
int nLevel = pTileComp->nResolutionsCount - 1 - nResolutionIndex;
Resolution *pResolution = &pTileComp->pResolutions[nResolutionIndex];
// Ãðàíèöû äëÿ êàæäîãî óðîâíÿ (ãëîáàëüíûå)
pResolution->nX0 = CeilDivPow2( pTileComp->nX0, nLevel );
pResolution->nY0 = CeilDivPow2( pTileComp->nY0, nLevel );
pResolution->nX1 = CeilDivPow2( pTileComp->nX1, nLevel );
pResolution->nY1 = CeilDivPow2( pTileComp->nY1, nLevel );
pResolution->nBandsCount = ( nResolutionIndex == 0 ? 1 : 3 );
// Ñì. ñòð. 35, òàáëèöà A-23 ISO/IEC FDIS154444-1
int nPPx, nPPy;
if ( pTCCP->nCodingStyle & J2K_CCP_CSTY_PRT )
{
nPPx = pTCCP->anPrecinctWidth[nResolutionIndex];
nPPy = pTCCP->anPrecinctHeight[nResolutionIndex];
}
else
{
nPPx = 15;
nPPy = 15;
}
// Ñì. ñòð. 64, Annex-B.6, ISO/IEC FDIS15444-1
int nFlootTRX0 = FloorDivPow2( pResolution->nX0, nPPx ) << nPPx;
int nFloorTRY0 = FloorDivPow2( pResolution->nY0, nPPy ) << nPPy;
int nCeilTRX1 = CeilDivPow2( pResolution->nX1, nPPx ) << nPPx;
int nCeilTRY1 = CeilDivPow2( pResolution->nY1, nPPy ) << nPPy;
pResolution->nPrecCountW = (pResolution->nX0 == pResolution->nX1) ? 0 : ((nCeilTRX1 - nFlootTRX0) >> nPPx);
pResolution->nPrecCountH = (pResolution->nY0 == pResolution->nY1) ? 0 : ((nCeilTRY1 - nFloorTRY0) >> nPPy);
int nCBWidthExpn, nCBHeightExpn;
int nTLCodeBlockGlobalStartX, nTLCodeBlockGlobalStartY, nBRCodeBlockGlobalEndX, nBRCodeBlockGlobalEndY;
if ( 0 == nResolutionIndex )
{
nTLCodeBlockGlobalStartX = nFlootTRX0;
nTLCodeBlockGlobalStartY = nFloorTRY0;
nBRCodeBlockGlobalEndX = nCeilTRX1;
nBRCodeBlockGlobalEndY = nCeilTRY1;
nCBWidthExpn = nPPx;
nCBHeightExpn = nPPy;
}
else
{
nTLCodeBlockGlobalStartX = CeilDivPow2( nFlootTRX0, 1 );
nTLCodeBlockGlobalStartY = CeilDivPow2( nFloorTRY0, 1 );
nBRCodeBlockGlobalEndX = CeilDivPow2( nCeilTRX1, 1 );
nBRCodeBlockGlobalEndY = CeilDivPow2( nCeilTRY1, 1 );
nCBWidthExpn = nPPx - 1;
nCBHeightExpn = nPPy - 1;
}
int nXCBa = min( pTCCP->nCodeBlockWidth, nCBWidthExpn );
int nYCBa = min( pTCCP->nCodeBlockHeight, nCBHeightExpn );
for ( int nBandIndex = 0; nBandIndex < pResolution->nBandsCount; nBandIndex++ )
{
Band *pBand = &pResolution->aBands[nBandIndex];
pBand->nBandIndex = ( nResolutionIndex == 0 ? 0 : nBandIndex + 1 );
int nBandX0 = (pBand->nBandIndex == 1) || (pBand->nBandIndex == 3) ? 1 : 0;
int nBandY0 = (pBand->nBandIndex == 2) || (pBand->nBandIndex == 3) ? 1 : 0;
if ( 0 == pBand->nBandIndex )
{
pBand->nX0 = CeilDivPow2( pTileComp->nX0, nLevel );
pBand->nY0 = CeilDivPow2( pTileComp->nY0, nLevel );
pBand->nX1 = CeilDivPow2( pTileComp->nX1, nLevel );
pBand->nY1 = CeilDivPow2( pTileComp->nY1, nLevel );
}
else
{
pBand->nX0 = CeilDivPow2( pTileComp->nX0 - (1 << nLevel) * nBandX0, nLevel + 1 );
pBand->nY0 = CeilDivPow2( pTileComp->nY0 - (1 << nLevel) * nBandY0, nLevel + 1 );
pBand->nX1 = CeilDivPow2( pTileComp->nX1 - (1 << nLevel) * nBandX0, nLevel + 1 );
pBand->nY1 = CeilDivPow2( pTileComp->nY1 - (1 << nLevel) * nBandY0, nLevel + 1 );
}
QuantStepSize *pStepSize = &pTCCP->aoStepSizes[nResolutionIndex == 0 ? 0 : 3 * (nResolutionIndex - 1) + nBandIndex + 1];
int nGain = pTCCP->nTransformID == 0 ? DWT_GetGainIrr( pBand->nBandIndex ) : DWT_GetGainRev( pBand->nBandIndex );
int nBPSCount = pImage->pComponents[nComponentIndex].nPrecision + nGain;
pBand->fStepSize = (float)( ( 1.0 + pStepSize->nMantissa / 2048.0 ) * pow( 2.0, nBPSCount - pStepSize->nExponent ) );
pBand->nBPSCount = pStepSize->nExponent + pTCCP->nGuardBitsCount - 1;
pBand->pPrecincts = (Precinct *) Malloc(HEAP_ZERO_MEMORY, pResolution->nPrecCountW * pResolution->nPrecCountH * sizeof(Precinct) );
if ( !pBand->pPrecincts )
{
TCD_FreeDecode( pTCD );
pTCD->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
return;
}
for ( int nPrecinctIndex = 0; nPrecinctIndex < pResolution->nPrecCountW * pResolution->nPrecCountH; nPrecinctIndex++ )
{
int nGlobalCodeBlockStartX = nTLCodeBlockGlobalStartX + (nPrecinctIndex % pResolution->nPrecCountW) * (1 << nCBWidthExpn);
int nGlobalCodeBlockStartY = nTLCodeBlockGlobalStartY + (nPrecinctIndex / pResolution->nPrecCountW) * (1 << nCBHeightExpn);
int nGlobalCodeBlockEndX = nGlobalCodeBlockStartX + (1 << nCBWidthExpn);
int nGlobalCodeBlockEndY = nGlobalCodeBlockStartY + (1 << nCBHeightExpn);
Precinct *pPrecinct = &pBand->pPrecincts[nPrecinctIndex];
// Ðàçìåðû îáëàñòè (Precinct)
pPrecinct->nX0 = max( nGlobalCodeBlockStartX, pBand->nX0 );
pPrecinct->nY0 = max( nGlobalCodeBlockStartY, pBand->nY0 );
pPrecinct->nX1 = min( nGlobalCodeBlockEndX, pBand->nX1 );
pPrecinct->nY1 = min( nGlobalCodeBlockEndY, pBand->nY1 );
int nTLCodeBlockStartX = FloorDivPow2( pPrecinct->nX0, nXCBa ) << nXCBa;
int nTLCodeBlockStartY = FloorDivPow2( pPrecinct->nY0, nYCBa ) << nYCBa;
int nBRCodeBlockEndX = CeilDivPow2( pPrecinct->nX1, nXCBa ) << nXCBa;
int nBRCodeBlockEndY = CeilDivPow2( pPrecinct->nY1, nYCBa ) << nYCBa;
pPrecinct->nCountInWidth = (nBRCodeBlockEndX - nTLCodeBlockStartX) >> nXCBa;
pPrecinct->nCountInHeight = (nBRCodeBlockEndY - nTLCodeBlockStartY) >> nYCBa;
pPrecinct->pCodeBlocks = (CodeBlock *) Malloc(HEAP_ZERO_MEMORY, pPrecinct->nCountInWidth * pPrecinct->nCountInHeight * sizeof(CodeBlock) );
if ( !pPrecinct->pCodeBlocks )
{
TCD_FreeDecode( pTCD );
pTCD->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
return;
}
pPrecinct->pInclTree = TGT_Create( pPrecinct->nCountInWidth, pPrecinct->nCountInHeight );
pPrecinct->pIMSBTree = TGT_Create( pPrecinct->nCountInWidth, pPrecinct->nCountInHeight );
for ( int nCodeBlockIndex = 0; nCodeBlockIndex < pPrecinct->nCountInWidth * pPrecinct->nCountInHeight; nCodeBlockIndex++ )
{
int nCodeBlockStartX = nTLCodeBlockStartX + (nCodeBlockIndex % pPrecinct->nCountInWidth) * (1 << nXCBa);
int nCodeBlockStartY = nTLCodeBlockStartY + (nCodeBlockIndex / pPrecinct->nCountInWidth) * (1 << nYCBa);
int nCodeBlockEndX = nCodeBlockStartX + (1 << nXCBa);
int nCodeBlockEndY = nCodeBlockStartY + (1 << nYCBa);
// Ãðàíèöû CodeBlock (ãëîáàëüíûå)
CodeBlock *pCodeBlock = &pPrecinct->pCodeBlocks[nCodeBlockIndex];
pCodeBlock->nX0 = max( nCodeBlockStartX, pPrecinct->nX0 );
pCodeBlock->nY0 = max( nCodeBlockStartY, pPrecinct->nY0 );
pCodeBlock->nX1 = min( nCodeBlockEndX, pPrecinct->nX1 );
pCodeBlock->nY1 = min( nCodeBlockEndY, pPrecinct->nY1 );
}
}
}
}
}
}
//
//#ifdef _DEBUG
// FILE *pFile;
// pFile = fopen( "E:\\Jpeg2000DumpFile.xml", "wb" );
// if ( pFile )
// {
// TCD_Dump( pFile, pTCD, pTCD->pTCDImage );
// fclose( pFile );
// }
//#endif
// Âûäåëÿåì ìåñòî äëÿ õðàíåíèÿ çàêîäèðîâàííûõ äàííûõ ( = îêîí÷àòåëüíîå èçîáðàæåíèå ).
unsigned int nX0 = 0, nY0 = 0, nX1 = 0, nY1 = 0, nWidth, nHeight;
for ( int nComponentIndex = 0; nComponentIndex < pImage->nCsiz; nComponentIndex++ )
{
for ( int nIndex = 0; nIndex < pCodingParams->nTileIndexSize; nIndex++ )
{
int nTileIndex = pCodingParams->pTileIndex[nIndex];
nX0 = ( nIndex == 0 ? pTCD->pTCDImage->pTiles[nTileIndex].pComponents[nComponentIndex].nX0 : min( nX0, (unsigned int) pTCD->pTCDImage->pTiles[nTileIndex].pComponents[nComponentIndex].nX0 ) );
nY0 = ( nIndex == 0 ? pTCD->pTCDImage->pTiles[nTileIndex].pComponents[nComponentIndex].nY0 : min( nY0, (unsigned int) pTCD->pTCDImage->pTiles[nTileIndex].pComponents[nComponentIndex].nY0 ) );
nX1 = ( nIndex == 0 ? pTCD->pTCDImage->pTiles[nTileIndex].pComponents[nComponentIndex].nX1 : max( nX1, (unsigned int) pTCD->pTCDImage->pTiles[nTileIndex].pComponents[nComponentIndex].nX1 ) );
nY1 = ( nIndex == 0 ? pTCD->pTCDImage->pTiles[nTileIndex].pComponents[nComponentIndex].nY1 : max( nY1, (unsigned int) pTCD->pTCDImage->pTiles[nTileIndex].pComponents[nComponentIndex].nY1 ) );
}
nWidth = nX1 - nX0;
nHeight = nY1 - nY0;
pImage->pComponents[nComponentIndex].pData = (int *) Malloc(HEAP_ZERO_MEMORY, nWidth * nHeight * sizeof(int) );
if ( !pImage->pComponents[nComponentIndex].pData )
{
TCD_FreeDecode( pTCD );
for ( int nI = 0; nI < nComponentIndex; nI++ )
RELEASEHEAP(pImage->pComponents[nI].pData );
pTCD->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
return;
}
pImage->pComponents[nComponentIndex].nWidth = nWidth;
pImage->pComponents[nComponentIndex].nHeight = nHeight;
pImage->pComponents[nComponentIndex].nXOsiz = nX0;
pImage->pComponents[nComponentIndex].nYOsiz = nY0;
}
}
void TCD_MakeLayerFixed(TCD *pTCD, int nLayerIndex, int nFinal)
{
CodingParams *pCodingParams = pTCD->pCodingParams;
Tile *pTile = pTCD->pTCDTile;
TileCodingParams *pTCP = pTCD->pTCP;
int aMatrix[10][10][3];
int nValue = 0; // aMatrix[pTCP->nLayersCount][pTile->pComponents[0].nResolutionsCount][3]
for ( int nComponentIndex = 0; nComponentIndex < pTile->nComponentsCount; nComponentIndex++ )
{
TileComp *pTileComp = &pTile->pComponents[nComponentIndex];
for ( int nI = 0; nI < pTCP->nLayersCount; nI++ )
{
for ( int nJ = 0; nJ < pTileComp->nResolutionsCount; nJ++ )
{
for ( int nK = 0; nK < 3; nK++ )
{
aMatrix[nI][nJ][nK] = (int) ( pCodingParams->pMatrix[nI * pTileComp->nResolutionsCount * 3 + nJ * 3 + nK] * (float) (pTCD->pImage->pComponents[nComponentIndex].nPrecision / 16.0) );
}
}
}
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];
Layer *pLayer = &pCodeBlock->aLayers[nLayerIndex];
int nIMSB = pTCD->pImage->pComponents[nComponentIndex].nPrecision - pCodeBlock->nBPSCount; // Êîëè÷åñòâî bit-plan ðàâíûõ 0
if ( 0 == nLayerIndex )
{
nValue = aMatrix[nLayerIndex][nResolutionIndex][nBandIndex];
if ( nIMSB >= nValue )
{
nValue = 0;
}
else
{
nValue -= nIMSB;
}
}
else
{
nValue = aMatrix[nLayerIndex][nResolutionIndex][nBandIndex] - aMatrix[nLayerIndex - 1][nResolutionIndex][nBandIndex];
if ( nIMSB >= aMatrix[nLayerIndex - 1][nResolutionIndex][nBandIndex] )
{
nValue -= ( nIMSB - aMatrix[nLayerIndex - 1][nResolutionIndex][nBandIndex] );
if ( nValue < 0 )
{
nValue = 0;
}
}
}
if ( 0 == nLayerIndex )
{
pCodeBlock->nPassesCountInLayers = 0;
}
int nLayersPasses = pCodeBlock->nPassesCountInLayers;
if ( 0 == pCodeBlock->nPassesCountInLayers )
{
if ( nValue != 0 )
{
nLayersPasses = 3 * nValue - 2 + pCodeBlock->nPassesCountInLayers;
}
else
{
nLayersPasses = pCodeBlock->nPassesCountInLayers;
}
}
else
{
nLayersPasses = 3 * nValue + pCodeBlock->nPassesCountInLayers;
}
pLayer->nPassesCount = nLayersPasses - pCodeBlock->nPassesCountInLayers;
if ( !pLayer->nPassesCount )
continue;
if ( 0 == pCodeBlock->nPassesCountInLayers )
{
pLayer->nLen = pCodeBlock->aPasses[nLayersPasses - 1].nRate;
pLayer->pData = pCodeBlock->aData;
}
else
{
pLayer->nLen = pCodeBlock->aPasses[nLayersPasses - 1].nRate - pCodeBlock->aPasses[pCodeBlock->nPassesCountInLayers - 1].nRate;
pLayer->pData = pCodeBlock->aData + pCodeBlock->aPasses[pCodeBlock->nPassesCountInLayers - 1].nRate;
}
if ( nFinal )
pCodeBlock->nPassesCountInLayers = nLayersPasses;
}
}
}
}
}
}
void TCD_RateAllocateFixed(TCD *pTCD)
{
for ( int nLayerIndex = 0; nLayerIndex < pTCD->pTCP->nLayersCount; nLayerIndex++ )
{
TCD_MakeLayerFixed( pTCD, nLayerIndex, 1 );
}
}
void TCD_MakeLayer(TCD *pTCD, int nLayerIndex, double dTreshold, int nFinal)
{
Tile *pTile = pTCD->pTCDTile;
pTile->adDistoLayer[nLayerIndex] = 0;
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];
Layer *pLayer = &pCodeBlock->aLayers[nLayerIndex];
if ( 0 == nLayerIndex )
{
pCodeBlock->nPassesCountInLayers = 0;
}
int nLayersPasses = pCodeBlock->nPassesCountInLayers;
for ( int nPassIndex = pCodeBlock->nPassesCountInLayers; nPassIndex < pCodeBlock->nTotalPassesCount; nPassIndex++ )
{
TCDPass *pPass = &pCodeBlock->aPasses[nPassIndex];
int nRate = 0;
double dDisto = 0;
if ( 0 == nLayersPasses )
{
nRate = pPass->nRate;
dDisto = pPass->dDistortionDec;
}
else
{
nRate = pPass->nRate - pCodeBlock->aPasses[nLayersPasses - 1].nRate;
dDisto = pPass->dDistortionDec - pCodeBlock->aPasses[nLayersPasses - 1].dDistortionDec;
}
if ( !nRate )
{
if ( dDisto != 0 )
nLayersPasses = nPassIndex + 1;
continue;
}
if ( dDisto / nRate >= dTreshold )
nLayersPasses = nPassIndex + 1;
}
pLayer->nPassesCount = nLayersPasses - pCodeBlock->nPassesCountInLayers;
if ( !pLayer->nPassesCount )
{
pLayer->dDisto = 0;
continue;
}
if ( 0 == pCodeBlock->nPassesCountInLayers )
{
pLayer->nLen = pCodeBlock->aPasses[nLayersPasses - 1].nRate;
pLayer->pData = pCodeBlock->aData;
pLayer->dDisto = pCodeBlock->aPasses[nLayersPasses - 1].dDistortionDec;
}
else
{
pLayer->nLen = pCodeBlock->aPasses[nLayersPasses - 1].nRate - pCodeBlock->aPasses[pCodeBlock->nPassesCountInLayers - 1].nRate;
pLayer->pData = pCodeBlock->aData + pCodeBlock->aPasses[pCodeBlock->nPassesCountInLayers - 1].nRate;
pLayer->dDisto = pCodeBlock->aPasses[nLayersPasses - 1].dDistortionDec - pCodeBlock->aPasses[pCodeBlock->nPassesCountInLayers - 1].dDistortionDec;
}
pTile->adDistoLayer[nLayerIndex] += pLayer->dDisto;
if ( nFinal )
pCodeBlock->nPassesCountInLayers = nLayersPasses;
}
}
}
}
}
}
bool TCD_RateAllocate(TCD *pTCD, unsigned char *pDst, int nLen, ImageInfo *pImageInfo)
{
CodingParams *pCodingParams = pTCD->pCodingParams;
Tile *pTile = pTCD->pTCDTile;
TileCodingParams *pTCP = pTCD->pTCP;
double dMin = DBL_MAX;
double dMax = 0;
double dMaxSE = 0;
pTile->nNBPix = 0;
for ( int nComponentIndex = 0; nComponentIndex < pTile->nComponentsCount; nComponentIndex++ )
{
TileComp *pTileComp = &pTile->pComponents[nComponentIndex];
pTileComp->nNBPix = 0;
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];
for ( int nPassIndex = 0; nPassIndex < pCodeBlock->nTotalPassesCount; nPassIndex++ )
{
TCDPass *pPass = &pCodeBlock->aPasses[nPassIndex];
int nRate = 1;
double dDisto = 0;
if ( 0 == nPassIndex )
{
nRate = pPass->nRate;
dDisto = pPass->dDistortionDec;
}
else
{
nRate = pPass->nRate - pCodeBlock->aPasses[nPassIndex - 1].nRate;
dDisto = pPass->dDistortionDec - pCodeBlock->aPasses[nPassIndex - 1].dDistortionDec;
}
if ( 0 == nRate )
{
continue;
}
int dRateDistoSlope = dDisto / nRate;
if ( dRateDistoSlope < dMin )
{
dMin = dRateDistoSlope;
}
if ( dRateDistoSlope > dMax )
{
dMax = dRateDistoSlope;
}
}
pTile->nNBPix += ( (pCodeBlock->nX1 - pCodeBlock->nX0) * (pCodeBlock->nY1 - pCodeBlock->nY0) );
pTileComp->nNBPix += ( (pCodeBlock->nX1 - pCodeBlock->nX0) * (pCodeBlock->nY1 - pCodeBlock->nY0) );
}
}
}
}
dMaxSE += ( ( (double)(1 << pTCD->pImage->pComponents[nComponentIndex].nPrecision) - 1.0 ) * ( (double)(1 << pTCD->pImage->pComponents[nComponentIndex].nPrecision) -1.0 ) ) * ( (double)(pTileComp->nNBPix) );
}
// INDEX >>
if( pImageInfo && pImageInfo->nIndexOn )
{
TileInfo *pTileInfo = &pImageInfo->pTile[pTCD->nTCDTileIndex];
pTileInfo->nNBPix = pTile->nNBPix;
pTileInfo->dDistoTile = pTile->dDistoTile;
pTileInfo->pdThreshold = (double *) Malloc(HEAP_ZERO_MEMORY, pTCP->nLayersCount * sizeof(double) );
}
// << INDEX
double adCumDisto[100]; // Fixed quality
const double c_dK = 1; // Fixed quality
for ( int nLayerIndex = 0; nLayerIndex < pTCP->nLayersCount; nLayerIndex++ )
{
double dLow = dMin;
double dHigh = dMax;
int nSuccess = 0;
// TO DO: Óáðàòü nMaxLen
int nMaxLen = pTCP->afRates[nLayerIndex] ? min(((int) ceil(pTCP->afRates[nLayerIndex])), nLen) : nLen;
double dGoodThreshold = 0;
double dDistoTarget = pTile->dDistoTile - ( (c_dK * dMaxSE) / pow( (float)10, pTCP->afDistoRatio[nLayerIndex] / 10 ) );
if ( ( pTCP->afRates[nLayerIndex] ) || ( pCodingParams->nDistoAlloc == 0 ) )
{
Tier2 *pTier2 = Tier2_Create( pTCD->pCodecInfo, pTCD->pImage, pCodingParams );
for ( int nIndex = 0; nIndex < 32; nIndex++ )
{
double dThreshold = (dLow + dHigh) / 2;
double dDistoAchieved = 0;
TCD_MakeLayer( pTCD, nLayerIndex, dThreshold, 0 );
if ( pCodingParams->nFixedQuality )
{
dDistoAchieved = (nLayerIndex == 0) ? pTile->adDistoLayer[0] : ( adCumDisto[nLayerIndex - 1] + pTile->adDistoLayer[nLayerIndex] );
if ( dDistoAchieved < dDistoTarget )
{
dHigh = dThreshold;
continue;
}
dLow = dThreshold;
}
else
{
int nL = Tier2_EncodePackets( pTier2, pTCD->nTCDTileIndex, pTile, nLayerIndex + 1, pDst, nMaxLen, pImageInfo );
if ( -999 == nL )
{
dLow = dThreshold;
continue;
}
dHigh = dThreshold;
}
nSuccess = 1;
dGoodThreshold = dThreshold;
}
Tier2_Destroy( pTier2 );
}
else
{
nSuccess = 1;
dGoodThreshold = dMin;
}
if ( !nSuccess )
{
return false;
}
if( pImageInfo && pImageInfo->nIndexOn )
{
pImageInfo->pTile[pTCD->nTCDTileIndex].pdThreshold[nLayerIndex] = dGoodThreshold;
}
TCD_MakeLayer( pTCD, nLayerIndex, dGoodThreshold, 1 );
adCumDisto[nLayerIndex] = (nLayerIndex == 0) ? pTile->adDistoLayer[0] : ( adCumDisto[nLayerIndex - 1] + pTile->adDistoLayer[nLayerIndex] );
}
return true;
}
int TCD_EncodeTile(TCD *pTCD, int nTileIndex, unsigned char *pDst, int nLen, ImageInfo *pImageInfo)
{
TileCodingParams *pTCP = &pTCD->pCodingParams->pTCP[0];
TileCompCodingParams *pTCCP = &pTCP->pTCCP[0];
Image *pImage = pTCD->pImage;
pTCD->nTCDTileIndex = nTileIndex;
pTCD->pTCDTile = pTCD->pTCDImage->pTiles;
pTCD->pTCP = &pTCD->pCodingParams->pTCP[nTileIndex];
Tile *pTile = pTCD->pTCDTile;
TileCodingParams *pTCD_TCP = pTCD->pTCP;
CodingParams *pCodingParams = pTCD->pCodingParams;
// INDEX >>
if( pImageInfo && pImageInfo->nIndexOn )
{
int nPrecCount = 0;
TileComp *pTileCompIndex = &pTile->pComponents[0]; /* based on component 0 */
for ( int nIndex = 0; nIndex < pTileCompIndex->nResolutionsCount; nIndex++ )
{
Resolution *pResolutionIndex = &pTileCompIndex->pResolutions[nIndex];
pImageInfo->pTile[nTileIndex].anXPrecinctCount[nIndex] = pResolutionIndex->nPrecCountW;
pImageInfo->pTile[nTileIndex].anYPrecinctCount[nIndex] = pResolutionIndex->nPrecCountH;
nPrecCount += pResolutionIndex->nPrecCountW * pResolutionIndex->nPrecCountH;
pImageInfo->pTile[nTileIndex].anPrecinctWidth[nIndex] = pTCCP->anPrecinctWidth[nIndex];
pImageInfo->pTile[nTileIndex].anPrecinctHeight[nIndex] = pTCCP->anPrecinctHeight[nIndex];
}
pImageInfo->pTile[nTileIndex].pPacket = (PacketInfo *) Malloc(HEAP_ZERO_MEMORY, pImageInfo->nCompCount * pImageInfo->nLayersCount * nPrecCount * sizeof(PacketInfo) );
}
// << INDEX
//---------------TILE-DATA--------------
double dEncodingTime = Clock(); // Çàñåêàåì ñêîëüêî ïîòðåáîâàëîñü âðåìåíè äëÿ êîäèðîâàíèÿ òàéëà
for ( int nComponentIndex = 0; nComponentIndex < pTile->nComponentsCount; nComponentIndex++ )
{
int nAdjust = pImage->pComponents[nComponentIndex].nSigned ? 0 : 1 << (pImage->pComponents[nComponentIndex].nPrecision - 1);
int nOffsetX = CeilDiv( pImage->nXOsiz, pImage->pComponents[nComponentIndex].nXRsiz );
int nOffsety = CeilDiv( pImage->nYOsiz, pImage->pComponents[nComponentIndex].nYRsiz );
TileComp *pTileComp = &pTile->pComponents[nComponentIndex];
int nTileWidth = pTileComp->nX1 - pTileComp->nX0;
int nWidth = CeilDiv( pImage->nXsiz - pImage->nXOsiz, pImage->pComponents[nComponentIndex].nXRsiz );
// Èçâëåêàåì äàííûå òàéëà
if ( pTCD_TCP->pTCCP[nComponentIndex].nTransformID == 1 )
{
for ( int nY = pTileComp->nY0; nY < pTileComp->nY1; nY++ )
{
// Èõîäíûå äàííûå
int *pData = &pImage->pComponents[nComponentIndex].pData[(pTileComp->nX0 - nOffsetX) + (nY - nOffsety) * nWidth];
// Ðåçóëüòàò
int *pTileData = &pTileComp->pData[(nY - pTileComp->nY0) * nTileWidth];
for ( int nX = pTileComp->nX0; nX < pTileComp->nX1; nX++ )
{
*pTileData++ = *pData++ - nAdjust;
}
}
}
else if ( pTCD_TCP->pTCCP[nComponentIndex].nTransformID == 0 )
{
for ( int nY = pTileComp->nY0; nY < pTileComp->nY1; nY++ )
{
// Èõîäíûå äàííûå
int *pData = &pImage->pComponents[nComponentIndex].pData[(pTileComp->nX0 - nOffsetX) + (nY - nOffsety) * nWidth];
// Ðåçóëüòàò
int *pTileData = &pTileComp->pData[(nY - pTileComp->nY0) * nTileWidth];
for ( int nX = pTileComp->nX0; nX < pTileComp->nX1; nX++ )
{
*pTileData++ = (*pData++ - nAdjust) << 13;
}
}
}
}
//----------------MCT-------------------
if ( pTCD_TCP->nMCT )
{
int nSamplesCount = ( pTile->pComponents[0].nX1 - pTile->pComponents[0].nX0 ) * ( pTile->pComponents[0].nY1 - pTile->pComponents[0].nY0 );
if ( pTCD_TCP->pTCCP[0].nTransformID == 0 )
{
ForwardICT( pTile->pComponents[0].pData, pTile->pComponents[1].pData, pTile->pComponents[2].pData, nSamplesCount );
}
else
{
ForwardRCT( pTile->pComponents[0].pData, pTile->pComponents[1].pData, pTile->pComponents[2].pData, nSamplesCount );
}
}
//----------------DWT---------------------
for ( int nComponentIndex = 0; nComponentIndex < pTile->nComponentsCount; nComponentIndex++ )
{
TileComp *pTileComp = &pTile->pComponents[nComponentIndex];
if ( pTCD_TCP->pTCCP[nComponentIndex].nTransformID == 1 )
{
DWT_EncodeRev( pTileComp );
}
else if ( pTCD_TCP->pTCCP[nComponentIndex].nTransformID == 0 )
{
DWT_EncodeIrr( pTileComp );
}
}
//------------------TIER1-----------------
Tier1 *pTier1 = Tier1_Create( pTCD->pCodecInfo );
Tier1_EncodeCodeBlocks( pTier1, pTile, pTCD_TCP );
Tier1_Destroy( pTier1 );
//-----------RATE-ALLOCATE----------------
// INDEX
if( pImageInfo )
{
pImageInfo->nIndexWrite = 0;
}
if ( pCodingParams->nDistoAlloc || pCodingParams->nFixedQuality )
{
// Normal Rate/Distortion allocation
TCD_RateAllocate( pTCD, pDst, nLen, pImageInfo );
}
else
{
// Fixed layer allocation
TCD_RateAllocateFixed( pTCD );
}
//--------------TIER2---------------------
// INDEX
if( pImageInfo )
{
pImageInfo->nIndexWrite = 1;
}
Tier2 *pTier2 = Tier2_Create( pTCD->pCodecInfo, pImage, pCodingParams );
int nRes = Tier2_EncodePackets( pTier2, nTileIndex, pTile, pTCD_TCP->nLayersCount, pDst, nLen, pImageInfo );
Tier2_Destroy( pTier2 );
//---------------CLEAN--------------------
dEncodingTime = Clock() - dEncodingTime;
Event_Message(EVT_INFO, "- tile encoded in %f s\n", dEncodingTime );
// Îñâîáîæäàåì ïàìÿòü
for ( int nComponentIndex = 0; nComponentIndex < pTile->nComponentsCount; nComponentIndex++ )
{
TileComp *pTileComp = &pTile->pComponents[nComponentIndex];
RELEASEHEAP(pTileComp->pData );
}
return nRes;
}
bool TCD_DecodeTile(TCD *pTCD, unsigned char *pSrc, int nLen, int nTileIndex)
{
int nEOF = 0;
pTCD->nTCDTileIndex = nTileIndex;
pTCD->pTCDTile = &(pTCD->pTCDImage->pTiles[nTileIndex]);
pTCD->pTCP = &(pTCD->pCodingParams->pTCP[nTileIndex]);
Tile *pTile = pTCD->pTCDTile;
double dDecodeTime = Clock(); // Âðåìÿ, çàòðà÷åííîå íà äåêîäèðîâàíèå òàéëà
Event_Message(EVT_INFO, "tile %d of %d\n", nTileIndex + 1, pTCD->pCodingParams->nXTilesCount * pTCD->pCodingParams->nYTilesCount );
//--------------TIER2---------------------
Tier2 *pTier2 = Tier2_Create( pTCD->pCodecInfo, pTCD->pImage, pTCD->pCodingParams );
int nRes = Tier2_DecodePackets( pTier2, pSrc, nLen, nTileIndex, pTile );
Tier2_Destroy( pTier2 );
if ( nRes == -999 )
{
nEOF = 1;
Event_Message(EVT_ERROR, "tcd_decode: incomplete bistream\n" );
}
//------------------TIER1-----------------
double dTier1Time = Clock();
Tier1 *pTier1 = Tier1_Create( pTCD->pCodecInfo );
Tier1_DecodeCodeBlocks( pTier1, pTile, pTCD->pTCP );
Tier1_Destroy( pTier1 );
dTier1Time = Clock() - dTier1Time;
Event_Message(EVT_INFO, "- tiers-1 took %f s\n", dTier1Time );
//----------------DWT---------------------
double dDWTTime = Clock();
for ( int nComponentIndex = 0; nComponentIndex < pTile->nComponentsCount; nComponentIndex++ )
{
TileComp *pTileComp = &pTile->pComponents[nComponentIndex];
if ( pTCD->pCodingParams->nReduceFactor != 0 )
{
pTCD->pImage->pComponents[nComponentIndex].nDecodedResCount = pTile->pComponents[nComponentIndex].nResolutionsCount - pTCD->pCodingParams->nReduceFactor - 1;
}
if ( pTCD->pTCP->pTCCP[nComponentIndex].nTransformID == 1 )
{
DWT_DecodeRev( pTileComp, pTileComp->nResolutionsCount - 1 - pTCD->pImage->pComponents[nComponentIndex].nDecodedResCount );
}
else
{
DWT_DecodeIrr( pTileComp, pTileComp->nResolutionsCount - 1 - pTCD->pImage->pComponents[nComponentIndex].nDecodedResCount );
}
if ( pTile->pComponents[nComponentIndex].nResolutionsCount > 0 )
{
pTCD->pImage->pComponents[nComponentIndex].nFactorDiv2 = pTile->pComponents[nComponentIndex].nResolutionsCount - (pTCD->pImage->pComponents[nComponentIndex].nDecodedResCount + 1);
}
}
dDWTTime = Clock() - dDWTTime;
Event_Message(EVT_INFO, "- dwt took %f s\n", dDWTTime );
//----------------MCT-------------------
if ( pTCD->pTCP->nMCT )
{
if ( pTCD->pTCP->pTCCP[0].nTransformID == 1 )
{
InverseRCT( pTile->pComponents[0].pData, pTile->pComponents[1].pData, pTile->pComponents[2].pData, (pTile->pComponents[0].nX1 - pTile->pComponents[0].nX0) * (pTile->pComponents[0].nY1 - pTile->pComponents[0].nY0) );
}
else
{
InverseICT( pTile->pComponents[0].pData, pTile->pComponents[1].pData, pTile->pComponents[2].pData, (pTile->pComponents[0].nX1 - pTile->pComponents[0].nX0) * (pTile->pComponents[0].nY1 - pTile->pComponents[0].nY0) );
}
}
//---------------TILE-DATA--------------
for ( int nComponentIndex = 0; nComponentIndex < pTile->nComponentsCount; nComponentIndex++ )
{
TileComp *pTileComp = &pTile->pComponents[nComponentIndex];
Resolution *pResolution = &pTileComp->pResolutions[pTCD->pImage->pComponents[nComponentIndex].nDecodedResCount];
int nAdjust = pTCD->pImage->pComponents[nComponentIndex].nSigned ? 0 : 1 << (pTCD->pImage->pComponents[nComponentIndex].nPrecision - 1);
int nMin = pTCD->pImage->pComponents[nComponentIndex].nSigned ? -(1 << (pTCD->pImage->pComponents[nComponentIndex].nPrecision - 1)) : 0;
int nMax = pTCD->pImage->pComponents[nComponentIndex].nSigned ? (1 << (pTCD->pImage->pComponents[nComponentIndex].nPrecision - 1)) - 1 : (1 << pTCD->pImage->pComponents[nComponentIndex].nPrecision) - 1;
int nTileWidth = pTileComp->nX1 - pTileComp->nX0;
int nWidth = pTCD->pImage->pComponents[nComponentIndex].nWidth;
int offset_x = CeilDivPow2( pTCD->pImage->pComponents[nComponentIndex].nXOsiz, pTCD->pImage->pComponents[nComponentIndex].nFactorDiv2 );
int offset_y = CeilDivPow2( pTCD->pImage->pComponents[nComponentIndex].nYOsiz, pTCD->pImage->pComponents[nComponentIndex].nFactorDiv2 );
for ( int nY = pResolution->nY0; nY < pResolution->nY1; nY++ )
{
for ( int nX = pResolution->nX0; nX < pResolution->nX1; nX++ )
{
int nValue = 0;
float fTemp = (float)( ( pTileComp->pData[nX - pResolution->nX0 + (nY - pResolution->nY0) * nTileWidth] ) / 8192.0 );
if ( pTCD->pTCP->pTCCP[nComponentIndex].nTransformID == 1 )
{
nValue = pTileComp->pData[nX - pResolution->nX0 + (nY - pResolution->nY0) * nTileWidth];
}
else
{
int nTemp2 = ( (int) (floor( fabs( fTemp ) )) ) + ( (int) floor( fabs( fTemp * 2 ) ) % 2 );
nValue = ( ( fTemp < 0 ) ? -nTemp2 : nTemp2 );
}
nValue += nAdjust;
pTCD->pImage->pComponents[nComponentIndex].pData[(nX - offset_x) + (nY - offset_y) * nWidth] = Clamp( nValue, nMin, nMax );
}
}
}
dDecodeTime = Clock() - dDecodeTime;
Event_Message(EVT_INFO, "- tile decoded in %f s\n", dDecodeTime );
for ( int nComponentIndex = 0; nComponentIndex < pTile->nComponentsCount; nComponentIndex++ )
{
RELEASEHEAP(pTCD->pTCDImage->pTiles[nTileIndex].pComponents[nComponentIndex].pData );
pTCD->pTCDImage->pTiles[nTileIndex].pComponents[nComponentIndex].pData = NULL;
}
if ( nEOF )
{
return false;
}
return true;
}