mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-20 08:39:50 +08:00
2238 lines
74 KiB
C
2238 lines
74 KiB
C
#pragma once
|
|
// Ôóíêöèè â äàííîì ôàéëå ïðåäíàçíà÷åíû äëÿ ÷òåíèÿ/çàïèñè ðàçëè÷íûõ ÷àñòåé JPEG2000-codestream: ìàðêåðû è äàííûå
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
#include "math.h"
|
|
|
|
#include "Types.h"
|
|
#include "Reader.h"
|
|
#include "Tile.h"
|
|
#include "Image.h"
|
|
#include "Jpt.h"
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
static void J2k_DumpImage(FILE *pFile, Image *pImage)
|
|
{
|
|
fprintf( pFile, "Image\n");
|
|
fprintf( pFile, "{\n");
|
|
fprintf( pFile, " XOffset = %d, YOffset = %d, Xsiz = %d, Ysiz = %d\n", pImage->nXOsiz, pImage->nYOsiz, pImage->nXsiz, pImage->nYsiz );
|
|
fprintf( pFile, " ComponentsCount = %d\n", pImage->nCsiz );
|
|
for ( int nCurComponent = 0; nCurComponent < pImage->nCsiz; nCurComponent++ )
|
|
{
|
|
ImageComponent *pComponent = &pImage->pComponents[nCurComponent];
|
|
fprintf( pFile, " ComponentIndex %d\n", nCurComponent );
|
|
fprintf( pFile, " {\n" );
|
|
fprintf( pFile, " XRsiz = %d, YRsiz = %d\n", pComponent->nXRsiz, pComponent->nYRsiz );
|
|
fprintf( pFile, " Precision = %d\n", pComponent->nPrecision );
|
|
fprintf( pFile, " Signed = %d\n", pComponent->nSigned );
|
|
fprintf( pFile, " }\n" );
|
|
}
|
|
fprintf( pFile, "}\n");
|
|
}
|
|
|
|
static void J2k_DumpCodingParams(FILE *pFile, Image *pImage, CodingParams *pCodingParams)
|
|
{
|
|
fprintf( pFile, "<CodingParameters " );
|
|
fprintf( pFile, "tx0='%d' ty0='%d' ", pCodingParams->nXTOsiz, pCodingParams->nYTOsiz );
|
|
fprintf( pFile, "tdx='%d' tdy='%d' ", pCodingParams->nXTsiz, pCodingParams->nYTsiz );
|
|
fprintf( pFile, "tw='%d' th='%d'>\n", pCodingParams->nXTilesCount, pCodingParams->nYTilesCount );
|
|
|
|
for ( int nTileIndex = 0; nTileIndex < pCodingParams->nXTilesCount * pCodingParams->nYTilesCount; nTileIndex++ )
|
|
{
|
|
TileCodingParams *pTCP = &pCodingParams->pTCP[nTileIndex];
|
|
fprintf( pFile, "<Tile Index='%d' ", nTileIndex );
|
|
fprintf( pFile, "CodingStyle='%x' ", pTCP->nCodingStyle );
|
|
fprintf( pFile, "ProgressionOrder='%d' ", pTCP->eProgOrder );
|
|
fprintf( pFile, "LayersCount='%d' ", pTCP->nLayersCount );
|
|
fprintf( pFile, "MultiComponentTransform='%d' ", pTCP->nMCT );
|
|
fprintf( pFile, "Rates='");
|
|
for ( int nLayerIndex = 0; nLayerIndex < pTCP->nLayersCount; nLayerIndex++ )
|
|
{
|
|
fprintf( pFile, "%.1f ", pTCP->afRates[nLayerIndex] );
|
|
}
|
|
fprintf( pFile, "'>\n");
|
|
for ( int nCurComponent = 0; nCurComponent < pImage->nCsiz; nCurComponent++ )
|
|
{
|
|
TileCompCodingParams *pTCCP = &pTCP->pTCCP[nCurComponent];
|
|
fprintf( pFile, "<Component Index='%d'>\n", nCurComponent );
|
|
fprintf( pFile, "<CodingStyle Value='%x'/>\n", pTCCP->nCodingStyle );
|
|
fprintf( pFile, "<ResolutionsCount Value='%d'/>\n", pTCCP->nResolutionsCount );
|
|
fprintf( pFile, "<CodeBlockWidth Value='%d'/>\n", pTCCP->nCodeBlockWidth );
|
|
fprintf( pFile, "<CodeBlockHeight Value='%d'/>\n", pTCCP->nCodeBlockHeight );
|
|
fprintf( pFile, "<CodeBlockStyle Value='%x'/>\n", pTCCP->nCodeBlockStyle );
|
|
fprintf( pFile, "<TransformID Value='%d'/>\n", pTCCP->nTransformID );
|
|
fprintf( pFile, "<QuantStyle Value='%d'/>\n", pTCCP->nQuantStyle );
|
|
fprintf( pFile, "<GuardBitsCount Value='%d'/>\n", pTCCP->nGuardBitsCount );
|
|
fprintf( pFile, "<ROIShift Value='%d'/>\n", pTCCP->nROIShift );
|
|
fprintf( pFile, "<StepSizes Value='" );
|
|
|
|
int nBandsCount = pTCCP->nQuantStyle == J2K_CCP_QNTSTY_SIQNT ? 1 : pTCCP->nResolutionsCount * 3 - 2;
|
|
for ( int nBandIndex = 0; nBandIndex < nBandsCount; nBandIndex++ )
|
|
{
|
|
fprintf( pFile, "(%d,%d) ", pTCCP->aoStepSizes[nBandIndex].nMantissa, pTCCP->aoStepSizes[nBandIndex].nExponent );
|
|
}
|
|
fprintf( pFile, "'/>");
|
|
|
|
if ( pTCCP->nCodingStyle & J2K_CCP_CSTY_PRT )
|
|
{
|
|
fprintf( pFile, "<PartitionWidth Value='");
|
|
for ( int nResIndex = 0; nResIndex < pTCCP->nResolutionsCount; nResIndex++ )
|
|
{
|
|
fprintf( pFile, "(%d)", pTCCP->anPrecinctWidth[nResIndex] );
|
|
}
|
|
fprintf( pFile, "'/>");
|
|
fprintf( pFile, "<PartitionHeight Value='");
|
|
for ( int nResIndex = 0; nResIndex < pTCCP->nResolutionsCount; nResIndex++ )
|
|
{
|
|
fprintf( pFile, "(%d)", pTCCP->anPrecinctHeight[nResIndex] );
|
|
}
|
|
fprintf( pFile, "'/>");
|
|
}
|
|
fprintf( pFile, "</Component>\n" );
|
|
}
|
|
fprintf( pFile, "</Tile>\n");
|
|
}
|
|
fprintf( pFile, "</CodingParameters>\n");
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
// Âñïîìîãàòåëüíûå ôóíêöèè
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
static void J2k_WriteSOC(J2kCodestream *pJ2k)
|
|
{
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
pStream->Write( J2K_MS_SOC, 2 );
|
|
}
|
|
|
|
static void J2k_ReadSOC (J2kCodestream *pJ2k)
|
|
{
|
|
pJ2k->nState = j2kstateMHSIZ;
|
|
}
|
|
|
|
static void J2k_WriteSIZ(J2kCodestream *pJ2k)
|
|
{
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
Image *pImage = pJ2k->pImage;
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
|
|
pStream->Write( J2K_MS_SIZ, 2 ); // SIZ
|
|
|
|
int nLsizPos = pStream->Tell();
|
|
pStream->Skip( 2 );
|
|
|
|
pStream->Write( 0, 2); // Rsiz (capabilities)
|
|
pStream->Write( pImage->nXsiz, 4); // Xsiz
|
|
pStream->Write( pImage->nYsiz, 4); // Ysiz
|
|
pStream->Write( pImage->nXOsiz, 4); // X0siz
|
|
pStream->Write( pImage->nYOsiz, 4); // Y0siz
|
|
pStream->Write( pCodingParams->nXTsiz, 4); // XTsiz
|
|
pStream->Write( pCodingParams->nYTsiz, 4); // YTsiz
|
|
pStream->Write( pCodingParams->nXTOsiz, 4); // XT0siz
|
|
pStream->Write( pCodingParams->nYTOsiz, 4); // YT0siz
|
|
pStream->Write( pImage->nCsiz, 2); // Csiz
|
|
|
|
for ( int nIndex = 0; nIndex < pImage->nCsiz; nIndex++ )
|
|
{
|
|
pStream->Write( pImage->pComponents[nIndex].nPrecision - 1 + (pImage->pComponents[nIndex].nSigned << 7), 1); // Ssiz_i
|
|
pStream->Write( pImage->pComponents[nIndex].nXRsiz, 1); // XRsiz_i
|
|
pStream->Write( pImage->pComponents[nIndex].nYRsiz, 1); // YRsiz_i
|
|
}
|
|
int nLen = pStream->Tell() - nLsizPos;
|
|
pStream->Seek( nLsizPos );
|
|
pStream->Write( nLen, 2 ); // Lsiz
|
|
pStream->Seek( nLsizPos + nLen );
|
|
}
|
|
|
|
static void J2k_ReadSIZ (J2kCodestream *pJ2k)
|
|
{
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
Image *pImage = pJ2k->pImage;
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
|
|
int nLen = pStream->Read( 2 ); // Lsiz
|
|
|
|
pStream->Read( 2); // Rsiz (capabilities)
|
|
|
|
pImage->nXsiz = pStream->Read( 4 ); // Xsiz
|
|
pImage->nYsiz = pStream->Read( 4 ); // Ysiz
|
|
pImage->nXOsiz = pStream->Read( 4 ); // X0siz
|
|
pImage->nYOsiz = pStream->Read( 4 ); // Y0siz
|
|
|
|
pCodingParams->nXTsiz = pStream->Read( 4 ); // XTsiz
|
|
pCodingParams->nYTsiz = pStream->Read( 4 ); // YTsiz
|
|
pCodingParams->nXTOsiz = pStream->Read( 4 ); // XT0siz
|
|
pCodingParams->nYTOsiz = pStream->Read( 4 ); // YT0siz
|
|
|
|
pImage->nCsiz = pStream->Read( 2 ); // Csiz
|
|
pImage->pComponents = (ImageComponent *) Malloc(HEAP_ZERO_MEMORY, pImage->nCsiz * sizeof(ImageComponent) );
|
|
if ( !pImage->pComponents )
|
|
{
|
|
pJ2k->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
return;
|
|
}
|
|
|
|
for ( int nIndex = 0; nIndex < pImage->nCsiz; nIndex++ )
|
|
{
|
|
int nTemp = pStream->Read( 1 ); // Ssiz_i
|
|
pImage->pComponents[nIndex].nPrecision = (nTemp & 0x7f) + 1;
|
|
pImage->pComponents[nIndex].nSigned = nTemp >> 7;
|
|
pImage->pComponents[nIndex].nXRsiz = pStream->Read( 1 ); // XRsiz_i
|
|
pImage->pComponents[nIndex].nYRsiz = pStream->Read( 1 ); // YRsiz_i
|
|
|
|
int nWidth = CeilDiv( pImage->nXsiz - pImage->nXOsiz, pImage->pComponents[nIndex].nXRsiz );
|
|
int nHeight = CeilDiv( pImage->nYsiz - pImage->nYOsiz, pImage->pComponents[nIndex].nYRsiz );
|
|
|
|
pImage->pComponents[nIndex].nDecodedResCount = 0;
|
|
pImage->pComponents[nIndex].nFactorDiv2 = 0;
|
|
}
|
|
|
|
// Ñ÷èòàåì êîëè÷åñòâî òàéëîâ ïî Õ è Y
|
|
pCodingParams->nXTilesCount = CeilDiv( pImage->nXsiz - pCodingParams->nXTOsiz, pCodingParams->nXTsiz );
|
|
pCodingParams->nYTilesCount = CeilDiv( pImage->nYsiz - pCodingParams->nYTOsiz, pCodingParams->nYTsiz );
|
|
|
|
pCodingParams->pTCP = (TileCodingParams *) Malloc(HEAP_ZERO_MEMORY, pCodingParams->nXTilesCount * pCodingParams->nYTilesCount * sizeof( TileCodingParams ) );
|
|
if ( !pCodingParams->pTCP )
|
|
{
|
|
RELEASEHEAP( pImage->pComponents );
|
|
pJ2k->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
return;
|
|
}
|
|
|
|
pCodingParams->pTileIndex = (int *)Malloc(HEAP_ZERO_MEMORY, pCodingParams->nXTilesCount * pCodingParams->nYTilesCount * sizeof(int) );
|
|
if ( !pCodingParams->pTileIndex )
|
|
{
|
|
RELEASEHEAP( pImage->pComponents );
|
|
RELEASEHEAP( pCodingParams->pTCP );
|
|
pJ2k->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
return;
|
|
}
|
|
|
|
pCodingParams->nTileIndexSize = 0;
|
|
|
|
for ( int nIndex = 0; nIndex < pCodingParams->nXTilesCount * pCodingParams->nYTilesCount; nIndex++ )
|
|
{
|
|
pCodingParams->pTCP[nIndex].nUsePOC = 0;
|
|
pCodingParams->pTCP[nIndex].nPOCsCount = 0;
|
|
pCodingParams->pTCP[nIndex].nFirst = 1;
|
|
}
|
|
|
|
// Îáíóëÿåì äàííûå äëÿ PPM ìàðêåðà
|
|
pCodingParams->nPPM = 0;
|
|
pCodingParams->pPPMData = NULL;
|
|
pCodingParams->pPPMDataFirst = NULL;
|
|
pCodingParams->nPPMPrevious = 0;
|
|
pCodingParams->nPPMStore = 0;
|
|
|
|
pJ2k->pDefaultTCP->pTCCP = (TileCompCodingParams *) Malloc(HEAP_ZERO_MEMORY, sizeof(TileCompCodingParams) * pImage->nCsiz );
|
|
if ( !pJ2k->pDefaultTCP->pTCCP )
|
|
{
|
|
RELEASEHEAP( pImage->pComponents );
|
|
RELEASEHEAP( pCodingParams->pTCP );
|
|
RELEASEHEAP( pCodingParams->pTileIndex );
|
|
pJ2k->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
return;
|
|
}
|
|
|
|
for ( int nIndex = 0; nIndex < pCodingParams->nXTilesCount * pCodingParams->nYTilesCount; nIndex++ )
|
|
{
|
|
pCodingParams->pTCP[nIndex].pTCCP = (TileCompCodingParams *) Malloc(HEAP_ZERO_MEMORY, sizeof(TileCompCodingParams) * pImage->nCsiz );
|
|
if ( !pCodingParams->pTCP[nIndex].pTCCP )
|
|
{
|
|
for ( int nI = 0; nI < nIndex; nI++ )
|
|
{
|
|
RELEASEHEAP( pCodingParams->pTCP[nI].pTCCP );
|
|
RELEASEHEAP( pImage->pComponents );
|
|
RELEASEHEAP( pCodingParams->pTCP );
|
|
RELEASEHEAP( pCodingParams->pTileIndex );
|
|
RELEASEHEAP( pJ2k->pDefaultTCP->pTCCP );
|
|
pJ2k->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
pJ2k->ppTileData = (unsigned char **) Malloc(HEAP_ZERO_MEMORY, pCodingParams->nXTilesCount * pCodingParams->nYTilesCount * sizeof(unsigned char *) );
|
|
if ( !pJ2k->ppTileData )
|
|
{
|
|
for ( int nIndex = 0; nIndex < pCodingParams->nXTilesCount * pCodingParams->nYTilesCount; nIndex++ )
|
|
{
|
|
RELEASEHEAP( pCodingParams->pTCP[nIndex].pTCCP );
|
|
}
|
|
RELEASEHEAP( pImage->pComponents );
|
|
RELEASEHEAP( pCodingParams->pTCP );
|
|
RELEASEHEAP( pCodingParams->pTileIndex );
|
|
RELEASEHEAP( pJ2k->pDefaultTCP->pTCCP );
|
|
RELEASEHEAP( pJ2k->pDefaultTCP);
|
|
pJ2k->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
return;
|
|
}
|
|
|
|
pJ2k->pTileLen = (int *) Malloc(HEAP_ZERO_MEMORY, pCodingParams->nXTilesCount * pCodingParams->nYTilesCount * sizeof(int) );
|
|
if ( !pJ2k->pTileLen )
|
|
{
|
|
for ( int nIndex = 0; nIndex < pCodingParams->nXTilesCount * pCodingParams->nYTilesCount; nIndex++ )
|
|
{
|
|
RELEASEHEAP( pCodingParams->pTCP[nIndex].pTCCP );
|
|
}
|
|
RELEASEHEAP( pImage->pComponents );
|
|
RELEASEHEAP( pCodingParams->pTCP );
|
|
RELEASEHEAP( pCodingParams->pTileIndex );
|
|
RELEASEHEAP( pJ2k->pDefaultTCP->pTCCP );
|
|
RELEASEHEAP( pJ2k->pDefaultTCP);
|
|
RELEASEHEAP( pJ2k->ppTileData );
|
|
pJ2k->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
return;
|
|
}
|
|
pJ2k->nState = j2kstateMH;
|
|
}
|
|
|
|
static void J2k_WriteCOM(J2kCodestream *pJ2k)
|
|
{
|
|
if( pJ2k->pCodingParams->sComment )
|
|
{
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
char *sComment = pJ2k->pCodingParams->sComment;
|
|
|
|
pStream->Write( J2K_MS_COM, 2 );
|
|
int nLcomPos = pStream->Tell();
|
|
pStream->Skip( 2 );
|
|
pStream->Write( 0, 2 ); // Rcom
|
|
for ( unsigned int nIndex = 0; nIndex < strlen( sComment ); nIndex++ )
|
|
{
|
|
pStream->Write( sComment[nIndex], 1 ); // Ccom_i
|
|
}
|
|
int nLen = pStream->Tell() - nLcomPos;
|
|
pStream->Seek( nLcomPos );
|
|
pStream->Write( nLen, 2 ); // Lcom
|
|
pStream->Seek( nLcomPos + nLen );
|
|
}
|
|
}
|
|
|
|
static void J2k_ReadCOM (J2kCodestream *pJ2k)
|
|
{
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
int nLen = pStream->Read( 2 );
|
|
|
|
// TO DO: Ñäåëàòü íîðìàëüíîå ÷òåíèå
|
|
pStream->Skip( nLen - 2 );
|
|
}
|
|
|
|
static void J2k_WriteCOX(J2kCodestream *pJ2k, int nCurComponent)
|
|
{
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
TileCodingParams *pTCP = &pCodingParams->pTCP[pJ2k->nCurTileIndex];
|
|
TileCompCodingParams *pTCCP = &pTCP->pTCCP[nCurComponent];
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
pStream->Write( pTCCP->nResolutionsCount - 1, 1 ); // SPcox (D)
|
|
pStream->Write( pTCCP->nCodeBlockWidth - 2, 1 ); // SPcox (E)
|
|
pStream->Write( pTCCP->nCodeBlockHeight - 2, 1 ); // SPcox (F)
|
|
pStream->Write( pTCCP->nCodeBlockStyle, 1 ); // SPcox (G)
|
|
pStream->Write( pTCCP->nTransformID, 1 ); // SPcox (H)
|
|
|
|
if ( pTCCP->nCodingStyle & J2K_CCP_CSTY_PRT )
|
|
{
|
|
for ( int nIndex = 0; nIndex < pTCCP->nResolutionsCount; nIndex++ )
|
|
{
|
|
pStream->Write( pTCCP->anPrecinctWidth[nIndex] + ( pTCCP->anPrecinctHeight[nIndex] << 4 ), 1 ); // SPcox (I_i)
|
|
}
|
|
}
|
|
}
|
|
|
|
static void J2k_ReadCOX (J2kCodestream *pJ2k, int nCurComponent)
|
|
{
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
TileCodingParams *pTCP = pJ2k->nState == j2kstateTPH ? &pCodingParams->pTCP[pJ2k->nCurTileIndex] : pJ2k->pDefaultTCP;
|
|
TileCompCodingParams *pTCCP = &pTCP->pTCCP[nCurComponent];
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
pTCCP->nResolutionsCount = pStream->Read( 1 ) + 1; // SPcox (D)
|
|
|
|
/* check the reduce value */
|
|
pCodingParams->nReduceFactor = min( (pTCCP->nResolutionsCount) - 1, pCodingParams->nReduceFactor );
|
|
|
|
pTCCP->nCodeBlockWidth = pStream->Read( 1 ) + 2; // SPcox (E)
|
|
pTCCP->nCodeBlockHeight = pStream->Read( 1 ) + 2; // SPcox (F)
|
|
pTCCP->nCodeBlockStyle = pStream->Read( 1 ); // SPcox (G)
|
|
pTCCP->nTransformID = pStream->Read( 1 ); // SPcox (H)
|
|
|
|
if ( pTCCP->nCodingStyle & J2K_CP_CSTY_PRT )
|
|
{
|
|
for ( int nIndex = 0; nIndex < pTCCP->nResolutionsCount; nIndex++ )
|
|
{
|
|
int nTemp = pStream->Read( 1 ); // SPcox (I_i)
|
|
pTCCP->anPrecinctWidth[nIndex] = nTemp & 0xf;
|
|
pTCCP->anPrecinctHeight[nIndex] = nTemp >> 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void J2k_WriteCOD(J2kCodestream *pJ2k)
|
|
{
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
pStream->Write( J2K_MS_COD, 2 ); // COD
|
|
|
|
int nLcodPos = pStream->Tell();
|
|
pStream->Skip( 2 );
|
|
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
TileCodingParams *pTCP = &pCodingParams->pTCP[pJ2k->nCurTileIndex];
|
|
|
|
pStream->Write( pTCP->nCodingStyle, 1 ); // Scod
|
|
pStream->Write( pTCP->eProgOrder, 1 ); // SGcod (A)
|
|
pStream->Write( pTCP->nLayersCount, 2 ); // SGcod (B)
|
|
pStream->Write( pTCP->nMCT, 1 ); // SGcod (C)
|
|
|
|
J2k_WriteCOX( pJ2k, 0 );
|
|
int nLen = pStream->Tell() - nLcodPos;
|
|
pStream->Seek( nLcodPos );
|
|
pStream->Write( nLen, 2 ); // Lcod
|
|
pStream->Seek( nLcodPos + nLen );
|
|
}
|
|
|
|
//static void J2k_ReadEPC(J2kCodestream *pJ2k)
|
|
//{
|
|
// CReader *pStream = pJ2k->pStreamIO;
|
|
//
|
|
// unsigned long int DL, Lepcp, Pcrcp, l;
|
|
// unsigned short int Lepc, Pcrc = 0x0000;
|
|
// unsigned char Pepc;
|
|
//
|
|
// const char *ans1;
|
|
//
|
|
// /* Simply read the EPC parameters */
|
|
// Lepcp = pStream->Tell();// cio_tell(cio);
|
|
// Lepc = pStream->Read(2);//cio_read(cio, 2);
|
|
// Pcrcp = pStream->Tell();
|
|
// pStream->Skip(2); /* Pcrc */
|
|
// DL = cpStream->Read( 4);
|
|
// Pepc = pStream->Read( 1);
|
|
//
|
|
// /* compute Pcrc */
|
|
// pStream->Seek(Lepcp - 2);
|
|
//
|
|
// /* Marker */
|
|
// jpwl_updateCRC16(&Pcrc, (unsigned char) pStream->Read( 1));
|
|
// jpwl_updateCRC16(&Pcrc, (unsigned char) pStream->Read( 1));
|
|
//
|
|
// /* Length */
|
|
// jpwl_updateCRC16(&Pcrc, (unsigned char) pStream->Read( 1));
|
|
// jpwl_updateCRC16(&Pcrc, (unsigned char) pStream->Read( 1));
|
|
//
|
|
// /* skip Pcrc */
|
|
// pStream->Skip( 2);
|
|
//
|
|
// /* read all remaining */
|
|
// for (l = 4; l < Lepc; l++)
|
|
// jpwl_updateCRC16(&Pcrc, (unsigned char) pStream->Read( 1));
|
|
//
|
|
// /* check Pcrc with the result */
|
|
// pStream->Seek Pcrcp);
|
|
// ans1 = (Pcrc == (unsigned short int) pStream->Read( 2)) ? "crc-ok" : "crc-ko";
|
|
//
|
|
// pStream->Seek(Lepcp + Lepc);
|
|
//}
|
|
//static void J2k_ReadEPB(J2kCodestream *pJ2k)
|
|
//{
|
|
// CReader *pStream = pJ2k->pStreamIO;
|
|
//
|
|
// unsigned long int LDPepb, Pepb;
|
|
// unsigned short int Lepb;
|
|
// unsigned char Depb;
|
|
// char str1[25] = "";
|
|
// opj_bool status;
|
|
// static opj_bool first_in_tph = OPJ_TRUE;
|
|
// int type, pre_len, post_len;
|
|
// static unsigned char *redund = NULL;
|
|
//
|
|
// /* B/W = 45, RGB = 51 */
|
|
// /* SIZ SIZ_FIELDS SIZ_COMPS FOLLOWING_MARKER */
|
|
// int skipnum = 2 + 38 + 3 * pJ2k->cp->exp_comps + 2;
|
|
//
|
|
// if (j2k->cp->correct) {
|
|
//
|
|
// /* go back to EPB marker value */
|
|
// pStream->Seek(pStream->Tell() - 2);
|
|
//
|
|
// /* we need to understand where we are */
|
|
// if (pJ2k->state == J2K_STATE_MH) {
|
|
// /* we are in MH */
|
|
// type = 0; /* MH */
|
|
// pre_len = skipnum; /* SOC+SIZ */
|
|
// post_len = -1; /* auto */
|
|
//
|
|
// } else if ((pJ2k->state == J2K_STATE_TPH) && first_in_tph) {
|
|
// /* we are in TPH */
|
|
// type = 1; /* TPH */
|
|
// pre_len = 12; /* SOC+SIZ */
|
|
// first_in_tph = OPJ_FALSE;
|
|
// post_len = -1; /* auto */
|
|
//
|
|
// } else {
|
|
// /* we are elsewhere */
|
|
// type = 2; /* other */
|
|
// pre_len = 0; /* nada */
|
|
// post_len = -1; /* auto */
|
|
//
|
|
// }
|
|
//
|
|
// /* call EPB corrector */
|
|
// /*printf("before %x, ", redund);*/
|
|
// status = jpwl_epb_correct(j2k, /* J2K decompressor handle */
|
|
// cio->bp, /* pointer to EPB in codestream buffer */
|
|
// type, /* EPB type: MH */
|
|
// pre_len, /* length of pre-data */
|
|
// post_len, /* length of post-data: -1 means auto */
|
|
// NULL, /* do everything auto */
|
|
// &redund
|
|
// );
|
|
// /*printf("after %x\n", redund);*/
|
|
//
|
|
// /* Read the (possibly corrected) EPB parameters */
|
|
// cio_skip(cio, 2);
|
|
// Lepb = cio_read(cio, 2);
|
|
// Depb = cio_read(cio, 1);
|
|
// LDPepb = cio_read(cio, 4);
|
|
// Pepb = cio_read(cio, 4);
|
|
//
|
|
// if (!status) {
|
|
//
|
|
// opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL correction could not be performed\n");
|
|
//
|
|
// /* advance to EPB endpoint */
|
|
// cio_skip(cio, Lepb + 2);
|
|
//
|
|
// return;
|
|
// }
|
|
//
|
|
// /* last in current header? */
|
|
// if (Depb & 0x40) {
|
|
// redund = NULL; /* reset the pointer to L4 buffer */
|
|
// first_in_tph = OPJ_TRUE;
|
|
// }
|
|
//
|
|
// /* advance to EPB endpoint */
|
|
// cio_skip(cio, Lepb - 11);
|
|
//
|
|
// } else {
|
|
//
|
|
// /* Simply read the EPB parameters */
|
|
// Lepb = cio_read(cio, 2);
|
|
// Depb = cio_read(cio, 1);
|
|
// LDPepb = cio_read(cio, 4);
|
|
// Pepb = cio_read(cio, 4);
|
|
//
|
|
// /* What does Pepb tells us about the protection method? */
|
|
// if (((Pepb & 0xF0000000) >> 28) == 0)
|
|
// sprintf(str1, "pred"); /* predefined */
|
|
// else if (((Pepb & 0xF0000000) >> 28) == 1)
|
|
// sprintf(str1, "crc-%lu", 16 * ((Pepb & 0x00000001) + 1)); /* CRC mode */
|
|
// else if (((Pepb & 0xF0000000) >> 28) == 2)
|
|
// sprintf(str1, "rs(%lu,32)", (Pepb & 0x0000FF00) >> 8); /* RS mode */
|
|
// else if (Pepb == 0xFFFFFFFF)
|
|
// sprintf(str1, "nometh"); /* RS mode */
|
|
// else
|
|
// sprintf(str1, "unknown"); /* unknown */
|
|
//
|
|
// /* Now we write them to screen */
|
|
// opj_event_msg(j2k->cinfo, EVT_INFO,
|
|
// "EPB(%d): (%sl, %sp, %u), %lu, %s\n",
|
|
// cio_tell(cio) - 13,
|
|
// (Depb & 0x40) ? "" : "n", /* latest EPB or not? */
|
|
// (Depb & 0x80) ? "" : "n", /* packed or unpacked EPB? */
|
|
// (Depb & 0x3F), /* EPB index value */
|
|
// LDPepb, /*length of the data protected by the EPB */
|
|
// str1); /* protection method */
|
|
//
|
|
// cio_skip(cio, Lepb - 11);
|
|
// }
|
|
//}
|
|
|
|
static void J2k_ReadCOD (J2kCodestream *pJ2k)
|
|
{
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
TileCodingParams *pTCP = pJ2k->nState == j2kstateTPH ? &pCodingParams->pTCP[pJ2k->nCurTileIndex] : pJ2k->pDefaultTCP;
|
|
Image *pImage = pJ2k->pImage;
|
|
|
|
int nLen = pStream->Read( 2 ); // Lcod
|
|
pTCP->nCodingStyle = pStream->Read( 1 ); // Scod
|
|
pTCP->eProgOrder = (ProgressionOrder)pStream->Read( 1 ); // SGcod (A)
|
|
pTCP->nLayersCount = pStream->Read( 2 ); // SGcod (B)
|
|
pTCP->nMCT = pStream->Read( 1 ); // SGcod (C)
|
|
|
|
int nPos = pStream->Tell();
|
|
for ( int nIndex = 0; nIndex < pImage->nCsiz; nIndex++ )
|
|
{
|
|
pTCP->pTCCP[nIndex].nCodingStyle = pTCP->nCodingStyle & J2K_CP_CSTY_PRT;
|
|
pStream->Seek( nPos );
|
|
J2k_ReadCOX( pJ2k, nIndex );
|
|
}
|
|
}
|
|
|
|
static void J2k_WriteCOC(J2kCodestream *pJ2k, int nCurComponent)
|
|
{
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
TileCodingParams *pTCP = &pCodingParams->pTCP[pJ2k->nCurTileIndex];
|
|
Image *pImage = pJ2k->pImage;
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
pStream->Write( J2K_MS_COC, 2 ); // COC
|
|
|
|
int nLcocPos = pStream->Tell();
|
|
pStream->Skip( 2 );
|
|
|
|
pStream->Write( nCurComponent, pImage->nCsiz <= 256 ? 1 : 2 ); // Ccoc
|
|
pStream->Write( pTCP->pTCCP[nCurComponent].nCodingStyle, 1 ); // Scoc
|
|
J2k_WriteCOX( pJ2k, nCurComponent );
|
|
|
|
int nLen = pStream->Tell() - nLcocPos;
|
|
pStream->Seek( nLcocPos );
|
|
pStream->Write( nLen, 2 ); // Lcoc
|
|
pStream->Seek( nLcocPos + nLen );
|
|
}
|
|
|
|
static void J2k_ReadCOC (J2kCodestream *pJ2k)
|
|
{
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
TileCodingParams *pTCP = pJ2k->nState == j2kstateTPH ? &pCodingParams->pTCP[pJ2k->nCurTileIndex] : pJ2k->pDefaultTCP;
|
|
Image *pImage = pJ2k->pImage;
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
int nLen = pStream->Read( 2 ); // Lcoc
|
|
int nCurComponent = pStream->Read( pImage->nCsiz <= 256 ? 1 : 2 ); // Ccoc
|
|
pTCP->pTCCP[nCurComponent].nCodingStyle = pStream->Read( 1 ); // Scoc
|
|
J2k_ReadCOX( pJ2k, nCurComponent );
|
|
}
|
|
|
|
static void J2k_WriteQCX(J2kCodestream *pJ2k, int nCurComponent)
|
|
{
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
TileCodingParams *pTCP = &pCodingParams->pTCP[pJ2k->nCurTileIndex];
|
|
TileCompCodingParams *pTCCP = &pTCP->pTCCP[nCurComponent];
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
pStream->Write( pTCCP->nQuantStyle + (pTCCP->nGuardBitsCount << 5), 1 ); // Sqcx
|
|
int nBandsCount = pTCCP->nQuantStyle == J2K_CCP_QNTSTY_SIQNT ? 1 : pTCCP->nResolutionsCount * 3 - 2;
|
|
|
|
for ( int nCurBand = 0; nCurBand < nBandsCount; nCurBand++ )
|
|
{
|
|
int nExponent = pTCCP->aoStepSizes[nCurBand].nExponent;
|
|
int nMantissa = pTCCP->aoStepSizes[nCurBand].nMantissa;
|
|
|
|
if ( pTCCP->nQuantStyle == J2K_CCP_QNTSTY_NOQNT )
|
|
{
|
|
pStream->Write( nExponent << 3, 1 );// SPqcx_i
|
|
}
|
|
else
|
|
{
|
|
pStream->Write( (nExponent << 11) + nMantissa, 2 ); // SPqcx_i
|
|
}
|
|
}
|
|
}
|
|
|
|
static void J2k_ReadQCX (J2kCodestream *pJ2k, int nCurComponent, int nLen)
|
|
{
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
TileCodingParams *pTCP = pJ2k->nState == j2kstateTPH ? &pCodingParams->pTCP[pJ2k->nCurTileIndex] : pJ2k->pDefaultTCP;
|
|
TileCompCodingParams *pTCCP = &pTCP->pTCCP[nCurComponent];
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
int nTemp = pStream->Read( 1 ); // Sqcx
|
|
pTCCP->nQuantStyle = nTemp & 0x1f;
|
|
pTCCP->nGuardBitsCount = nTemp >> 5;
|
|
|
|
int nBandsCount = ( pTCCP->nQuantStyle == J2K_CCP_QNTSTY_SIQNT ) ? 1 : ( ( pTCCP->nQuantStyle == J2K_CCP_QNTSTY_NOQNT ) ? nLen - 1 : (nLen - 1) / 2 );
|
|
|
|
for ( int nCurBand = 0; nCurBand < nBandsCount; nCurBand++ )
|
|
{
|
|
int nExponent = 0, nMantissa = 0;
|
|
if ( pTCCP->nQuantStyle == J2K_CCP_QNTSTY_NOQNT )
|
|
{
|
|
nExponent = pStream->Read( 1 ) >> 3; // SPqcx_i
|
|
nMantissa = 0;
|
|
}
|
|
else
|
|
{
|
|
nTemp = pStream->Read( 2 ); // SPqcx_i
|
|
nExponent = nTemp >> 11;
|
|
nMantissa = nTemp & 0x7ff;
|
|
}
|
|
pTCCP->aoStepSizes[nCurBand].nExponent = nExponent;
|
|
pTCCP->aoStepSizes[nCurBand].nMantissa = nMantissa;
|
|
}
|
|
|
|
// Add : Åñëè òèï êâàíòîâàíèÿ ScalarImplicit, òîãäà âû÷èñëèì êîýôôèöèåíòû êâàíòîâàíèÿ äëÿ îñòàëüíûõ Subbands
|
|
if ( pTCCP->nQuantStyle == J2K_CCP_QNTSTY_SIQNT )
|
|
{
|
|
for ( int nCurBand = 1; nCurBand < J2K_MAXBANDS; nCurBand++ )
|
|
{
|
|
pTCCP->aoStepSizes[nCurBand].nExponent = ( (pTCCP->aoStepSizes[0].nExponent) - ((nCurBand - 1) / 3) > 0 ) ? (pTCCP->aoStepSizes[0].nExponent) - ((nCurBand - 1) / 3) : 0;
|
|
pTCCP->aoStepSizes[nCurBand].nMantissa = pTCCP->aoStepSizes[0].nMantissa;
|
|
}
|
|
}
|
|
// ddA
|
|
}
|
|
|
|
static void J2k_WriteQCD(J2kCodestream *pJ2k)
|
|
{
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
pStream->Write( J2K_MS_QCD, 2 ); // QCD
|
|
int nLqcdPos = pStream->Tell();
|
|
pStream->Skip( 2 );
|
|
|
|
J2k_WriteQCX( pJ2k, 0 );
|
|
|
|
int nLen = pStream->Tell() - nLqcdPos;
|
|
pStream->Seek( nLqcdPos );
|
|
pStream->Write( nLen, 2 ); // Lqcd
|
|
pStream->Seek( nLqcdPos + nLen );
|
|
}
|
|
|
|
static void J2k_ReadQCD (J2kCodestream *pJ2k)
|
|
{
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
Image *pImage = pJ2k->pImage;
|
|
|
|
int nLen = pStream->Read( 2 ); // Lqcd
|
|
int nPos = pStream->Tell();
|
|
for ( int nIndex = 0; nIndex < pImage->nCsiz; nIndex++ )
|
|
{
|
|
pStream->Seek( nPos );
|
|
J2k_ReadQCX( pJ2k, nIndex, nLen - 2 );
|
|
}
|
|
}
|
|
|
|
static void J2k_WriteQCC(J2kCodestream *pJ2k, int nCurComponent)
|
|
{
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
pStream->Write( J2K_MS_QCC, 2 ); // QCC
|
|
|
|
int nLqccPos = pStream->Tell();
|
|
pStream->Skip( 2 );
|
|
|
|
pStream->Write( nCurComponent, pJ2k->pImage->nCsiz <= 256 ? 1 : 2 ); // Cqcc
|
|
J2k_WriteQCX( pJ2k, nCurComponent );
|
|
|
|
int nLen = pStream->Tell() - nLqccPos;
|
|
pStream->Seek( nLqccPos );
|
|
pStream->Write( nLen, 2 ); // Lqcc
|
|
pStream->Seek( nLqccPos + nLen );
|
|
}
|
|
|
|
static void J2k_ReadQCC (J2kCodestream *pJ2k)
|
|
{
|
|
int nComponentsCount = pJ2k->pImage->nCsiz;
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
int nLen = pStream->Read( 2 ); // Lqcc
|
|
int nCurComponent = pStream->Read( nComponentsCount <= 256 ? 1 : 2 ); // Cqcc
|
|
J2k_ReadQCX( pJ2k, nCurComponent, nLen - 2 - (nComponentsCount <= 256 ? 1 : 2) );
|
|
}
|
|
|
|
static void J2k_WritePOC(J2kCodestream *pJ2k)
|
|
{
|
|
int nComponentsCount = pJ2k->pImage->nCsiz;
|
|
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
TileCodingParams *pTCP = &pCodingParams->pTCP[pJ2k->nCurTileIndex];
|
|
TileCompCodingParams *pTCCP = &pTCP->pTCCP[0];
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
int nChangesCount = pTCP->nPOCsCount;
|
|
pStream->Write( J2K_MS_POC, 2 ); // POC
|
|
|
|
int nLen = 2 + (5 + 2 * (nComponentsCount <= 256 ? 1 : 2)) * nChangesCount;
|
|
pStream->Write( nLen, 2 ); // Lpoc
|
|
|
|
for ( int nIndex = 0; nIndex < nChangesCount; nIndex++ )
|
|
{
|
|
POC *pPOC = &pTCP->aoPOC[nIndex];
|
|
pStream->Write( pPOC->nRSpoc, 1 ); // RSpoc_i
|
|
pStream->Write( pPOC->nCSpoc, (nComponentsCount <= 256 ? 1 : 2) ); // CSpoc_i
|
|
|
|
pStream->Write( pPOC->nLYEpoc, 2 ); // LYEpoc_i
|
|
pPOC->nLYEpoc = min( pPOC->nLYEpoc, pTCP->nLayersCount);
|
|
|
|
pStream->Write( pPOC->nREpoc, 1 ); // REpoc_i
|
|
pPOC->nREpoc = min( pPOC->nREpoc, pTCCP->nResolutionsCount);
|
|
|
|
pStream->Write( pPOC->nCEpoc, (nComponentsCount <= 256 ? 1 : 2)); // CEpoc_i
|
|
pPOC->nCEpoc = min( pPOC->nCEpoc, nComponentsCount);
|
|
|
|
pStream->Write( pPOC->ePpoc, 1 ); // Ppoc_i
|
|
}
|
|
}
|
|
|
|
static void J2k_ReadPOC (J2kCodestream *pJ2k)
|
|
{
|
|
int nComponentsCount = pJ2k->pImage->nCsiz;
|
|
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
TileCodingParams *pTCP = pJ2k->nState == j2kstateTPH ? &pCodingParams->pTCP[pJ2k->nCurTileIndex] : pJ2k->pDefaultTCP;
|
|
TileCompCodingParams *pTCCP = &pTCP->pTCCP[0];
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
int nOldPOC = pTCP->nUsePOC ? pTCP->nPOCsCount + 1 : 0;
|
|
pTCP->nUsePOC = 1;
|
|
|
|
int nLen = pStream->Read( 2 ); // Lpoc
|
|
int nChangesCount = (nLen - 2) / (5 + 2 * (nComponentsCount <= 256 ? 1 : 2));
|
|
|
|
for ( int nIndex = nOldPOC; nIndex < nChangesCount + nOldPOC; nIndex++ )
|
|
{
|
|
POC *pPOC = &pTCP->aoPOC[nIndex];
|
|
pPOC->nRSpoc = pStream->Read( 1 ); // RSpoc_i
|
|
pPOC->nCSpoc = pStream->Read( nComponentsCount <= 256 ? 1 : 2 ); // CSpoc_i
|
|
pPOC->nLYEpoc = min( pStream->Read( 2 ), (unsigned int) pTCP->nLayersCount ); // LYEpoc_i
|
|
pPOC->nREpoc = min( pStream->Read( 1 ), (unsigned int) pTCCP->nResolutionsCount ); // REpoc_i
|
|
pPOC->nCEpoc = min( pStream->Read( nComponentsCount <= 256 ? 1 : 2 ), (unsigned int) nComponentsCount ); // CEpoc_i
|
|
pPOC->ePpoc = (ProgressionOrder)pStream->Read( 1 ); // Ppoc_i
|
|
}
|
|
|
|
pTCP->nPOCsCount = nChangesCount + nOldPOC - 1;
|
|
}
|
|
|
|
static void J2k_ReadCRG (J2kCodestream *pJ2k)
|
|
{
|
|
int nXcrg_i, nYcrg_i;
|
|
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
int nComponentsCount = pJ2k->pImage->nCsiz;
|
|
|
|
int nLen = pStream->Read( 2 ); // Lcrg
|
|
for ( int nIndex = 0; nIndex < nComponentsCount; nIndex++ )
|
|
{
|
|
nXcrg_i = pStream->Read( 2 ); // Xcrg_i
|
|
nYcrg_i = pStream->Read( 2 ); // Ycrg_i
|
|
}
|
|
}
|
|
|
|
static void J2k_ReadTLM (J2kCodestream *pJ2k)
|
|
{
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
int nLen = pStream->Read( 2 ); // Ltlm
|
|
int nZtlm = pStream->Read( 1 ); // Ztlm
|
|
int nStlm = pStream->Read( 1 ); // Stlm
|
|
|
|
int nTlmSize = ( ( nStlm >> 4 ) & 0x01 ) + ( ( nStlm >> 4 ) & 0x02 );
|
|
int nPlmSize = ( nStlm >> 6 ) & 0x01;
|
|
|
|
int nTileTlm = ( nLen - 4 ) / ( ( nPlmSize + 1 ) * 2 + nTlmSize );
|
|
for ( int nIndex = 0; nIndex < nTileTlm; nIndex++ )
|
|
{
|
|
long int nTtlm_i = pStream->Read( nTlmSize ); // Ttlm_i
|
|
long int nPtlm_i = pStream->Read( nPlmSize ? 4 : 2 ); // Ptlm_i
|
|
}
|
|
}
|
|
|
|
static void J2k_ReadPLM (J2kCodestream *pJ2k)
|
|
{
|
|
int nPacketLen = 0;
|
|
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
int nLen = pStream->Read( 2 ); // Lplm
|
|
int nZplm = pStream->Read( 1 ); // Zplm
|
|
nLen -= 3;
|
|
while ( nLen > 0 )
|
|
{
|
|
int nNplm = pStream->Read( 4 ); // Nplm
|
|
nLen -= 4;
|
|
for ( int nIndex = nNplm; nIndex > 0; nIndex-- )
|
|
{
|
|
int nAdd = pStream->Read( 1 );
|
|
nLen--;
|
|
|
|
nPacketLen = (nPacketLen << 7) + nAdd; // Iplm_ij
|
|
if ( (nAdd & 0x80) == 0 )
|
|
{
|
|
// íîâûé packet
|
|
nPacketLen = 0;
|
|
}
|
|
if ( nLen <= 0 )
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void J2k_ReadPLT (J2kCodestream *pJ2k)
|
|
{
|
|
int nPacketLen = 0;
|
|
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
int nLen = pStream->Read( 2 ); // Lplt
|
|
int nZplt = pStream->Read( 1 ); // Zplt
|
|
|
|
for ( int nIndex = nLen - 3; nIndex > 0; nIndex-- )
|
|
{
|
|
int nAdd = pStream->Read( 1 );
|
|
nPacketLen = (nPacketLen << 7) + nAdd; // Iplt_i
|
|
if ( (nAdd & 0x80) == 0 )
|
|
{
|
|
// íîâûé packet
|
|
nPacketLen = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void J2k_ReadPPM (J2kCodestream *pJ2k)
|
|
{
|
|
int nNppm;
|
|
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
int nLen = pStream->Read( 2 ); // Lppm
|
|
pCodingParams->nPPM = 1;
|
|
|
|
int nZppm = pStream->Read( 1 ); // Zppm
|
|
nLen -= 3;
|
|
|
|
while ( nLen > 0 )
|
|
{
|
|
if ( pCodingParams->nPPMPrevious == 0 )
|
|
{
|
|
nNppm = pStream->Read( 4 ); // Nppm
|
|
nLen -= 4;
|
|
}
|
|
else
|
|
{
|
|
nNppm = pCodingParams->nPPMPrevious;
|
|
}
|
|
|
|
int nStore = pCodingParams->nPPMStore;
|
|
if ( nZppm == 0 ) // Ïåðâûé PPM ìàðêåð
|
|
{
|
|
pCodingParams->pPPMData = (unsigned char *) Malloc(HEAP_ZERO_MEMORY, nNppm * sizeof(unsigned char) );
|
|
if ( !pCodingParams->pPPMData )
|
|
{
|
|
pJ2k->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
return;
|
|
}
|
|
pCodingParams->pPPMDataFirst = pCodingParams->pPPMData;
|
|
pCodingParams->nPPMLength = nNppm;
|
|
}
|
|
else // Íå ïåðâûé PPM ìàðêåð
|
|
{
|
|
BYTE *pPPMData_new = (BYTE *)Malloc(0, ( nNppm + pCodingParams->nPPMStore ) * sizeof(unsigned char));
|
|
if (!pPPMData_new)
|
|
{
|
|
pJ2k->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
return;
|
|
}
|
|
memcpy(pPPMData_new,pCodingParams->pPPMData,nNppm * sizeof(unsigned char));
|
|
RELEASEHEAP(pCodingParams->pPPMData);
|
|
pCodingParams->pPPMData = pPPMData_new;
|
|
|
|
pCodingParams->pPPMDataFirst = pCodingParams->pPPMData;
|
|
pCodingParams->nPPMLength = nNppm + pCodingParams->nPPMStore;
|
|
}
|
|
|
|
// Ñ÷èòûâàåì îñòàëüíûå äàííûå
|
|
int nIndex;
|
|
for ( nIndex = nNppm; nIndex > 0; nIndex-- )
|
|
{
|
|
pCodingParams->pPPMData[nStore] = pStream->Read( 1 );
|
|
nStore++;
|
|
nLen--;
|
|
if ( nLen == 0 ) // Ñëó÷àé, êîãäà packet header íå çàêîí÷èëñÿ â òåêóùåì ìàðêåðå, íî çàêîí÷èòñÿ â ñëåäóþùåì
|
|
break;
|
|
}
|
|
pCodingParams->nPPMPrevious = nIndex - 1;
|
|
pCodingParams->nPPMStore = nStore;
|
|
}
|
|
}
|
|
|
|
static void J2k_ReadPPT (J2kCodestream *pJ2k)
|
|
{
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
TileCodingParams *pTCP = pCodingParams->pTCP + pJ2k->nCurTileIndex;
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
int nLen = pStream->Read( 2 ); // Lppt
|
|
int nZppt = pStream->Read( 1 ); // Zppt
|
|
pTCP->nPPT = 1;
|
|
|
|
if ( nZppt == 0 ) // Ïåðâûé PPT ìàðêåð
|
|
{
|
|
pTCP->pPPTData = (unsigned char *) Malloc(HEAP_ZERO_MEMORY, (nLen - 3) * sizeof(unsigned char) );
|
|
if (!pTCP->pPPTData)
|
|
{
|
|
pJ2k->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
return;
|
|
}
|
|
pTCP->pPPTDataFirst = pTCP->pPPTData;
|
|
pTCP->nPPTStore = 0;
|
|
pTCP->nPPTLength = nLen - 3;
|
|
}
|
|
else // Íå ïåðâûé PPT ìàðêåð
|
|
{
|
|
BYTE *pPPTData_new = (unsigned char *) Malloc(HEAP_ZERO_MEMORY, (nLen - 3 + pTCP->nPPTStore) * sizeof(unsigned char));
|
|
if (!pPPTData_new)
|
|
{
|
|
pJ2k->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
return;
|
|
}
|
|
memcpy(pPPTData_new,pTCP->pPPTData,(nLen - 3) * sizeof(unsigned char) );
|
|
RELEASEHEAP(pTCP->pPPTData);
|
|
pTCP->pPPTData =pPPTData_new;
|
|
|
|
pTCP->pPPTDataFirst = pTCP->pPPTData;
|
|
pTCP->nPPTLength = nLen - 3 + pTCP->nPPTStore;
|
|
}
|
|
|
|
int nStore = pTCP->nPPTStore;
|
|
for ( int nIndex = nLen - 3; nIndex > 0; nIndex-- )
|
|
{
|
|
pTCP->pPPTData[nStore] = pStream->Read( 1 );
|
|
nStore++;
|
|
}
|
|
pTCP->nPPTStore = nStore;
|
|
}
|
|
|
|
static void J2k_WriteSOT(J2kCodestream *pJ2k)
|
|
{
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
pJ2k->nSOTStartPos = pStream->Tell();
|
|
|
|
pStream->Write( J2K_MS_SOT, 2 ); // SOT
|
|
|
|
int nLsotPos = pStream->Tell();
|
|
pStream->Skip( 2 );
|
|
|
|
pStream->Write( pJ2k->nCurTileIndex, 2 ); // Isot
|
|
pStream->Skip( 4 ); // Psot (ïîêà îñòàâëÿåì ìåñòî, ñþäà ïèøåì â ôóíêöèè J2k_WriteSOD)
|
|
pStream->Write( 0, 1 ); // TPsot
|
|
pStream->Write( 1, 1 ); // TNsot
|
|
|
|
int nLen = pStream->Tell() - nLsotPos;
|
|
pStream->Seek( nLsotPos );
|
|
pStream->Write( nLen, 2 ); // Lsot
|
|
pStream->Seek( nLsotPos + nLen);
|
|
}
|
|
|
|
static void J2k_ReadSOT (J2kCodestream *pJ2k)
|
|
{
|
|
char nStatus = 0;
|
|
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
int nLen = pStream->Read( 2 ); // Lsot
|
|
int nTileIndex = pStream->Read( 2 ); // Isot
|
|
|
|
if ( pCodingParams->nTileIndexSize == 0 )
|
|
{
|
|
pCodingParams->pTileIndex[pCodingParams->nTileIndexSize] = nTileIndex;
|
|
pCodingParams->nTileIndexSize++;
|
|
}
|
|
else
|
|
{
|
|
int nIndex = 0;
|
|
while ( nIndex < pCodingParams->nTileIndexSize && nStatus == 0 )
|
|
{
|
|
nStatus = pCodingParams->pTileIndex[nIndex] == nTileIndex ? 1 : 0;
|
|
nIndex++;
|
|
}
|
|
if ( 0 == nStatus )
|
|
{
|
|
pCodingParams->pTileIndex[pCodingParams->nTileIndexSize] = nTileIndex;
|
|
pCodingParams->nTileIndexSize++;
|
|
}
|
|
}
|
|
|
|
int nTotalLen = pStream->Read( 4 ); // Psot
|
|
|
|
if ( !nTotalLen )
|
|
nTotalLen = pStream->GetLeftSize() + 8;
|
|
|
|
int nTilePartIndex = pStream->Read( 1 ); // TPsot
|
|
int nTilePartsCount = pStream->Read( 1 ); // TNsot
|
|
|
|
pJ2k->nCurTileIndex = nTileIndex;
|
|
// pJ2k->pEndOfTile = ByteIO_GetCurPos( pStream ) - 12 + nTotalLen;
|
|
|
|
pJ2k->nSizeOfTile = pStream->Tell()- 12 + nTotalLen;
|
|
pJ2k->nState = j2kstateTPH;
|
|
|
|
TileCodingParams *pTCP = &pCodingParams->pTCP[pJ2k->nCurTileIndex];
|
|
|
|
if ( pTCP->nFirst == 1 ) // Èíèöèàëèçèðóåì PPT
|
|
{
|
|
TileCompCodingParams *pTemp = pTCP->pTCCP;
|
|
memcpy( pTCP, pJ2k->pDefaultTCP, sizeof(TileCodingParams) );
|
|
pTCP->nPPT = 0;
|
|
pTCP->pPPTData = NULL;
|
|
pTCP->pPPTDataFirst = NULL;
|
|
pTCP->pTCCP = pTemp;
|
|
|
|
for ( int nIndex = 0; nIndex < pJ2k->pImage->nCsiz; nIndex++ )
|
|
{
|
|
pTCP->pTCCP[nIndex] = pJ2k->pDefaultTCP->pTCCP[nIndex];
|
|
}
|
|
pCodingParams->pTCP[pJ2k->nCurTileIndex].nFirst = 0;
|
|
}
|
|
}
|
|
|
|
static void J2k_WriteSOD(J2kCodestream *pJ2k, void *pTileCoder)
|
|
{
|
|
TCD *pTCD = (TCD*)pTileCoder;
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
pStream->Write( J2K_MS_SOD, 2 ); // SOD
|
|
|
|
if ( pJ2k->nCurTileIndex == 0 )
|
|
{
|
|
pJ2k->nSODStartPos = pStream->Tell() + pJ2k->nPosCorrection;
|
|
}
|
|
|
|
// INDEX
|
|
ImageInfo *pImageInfo = pJ2k->pImageInfo;
|
|
if ( pImageInfo && pImageInfo->nIndexOn )
|
|
{
|
|
pImageInfo->pTile[pJ2k->nCurTileIndex].nEndHeader = pStream->Tell() + pJ2k->nPosCorrection - 1;
|
|
}
|
|
// INDEX
|
|
|
|
TileCodingParams *pTCP = &pCodingParams->pTCP[pJ2k->nCurTileIndex];
|
|
for ( int nCurLayer = 0; nCurLayer < pTCP->nLayersCount; nCurLayer++ )
|
|
{
|
|
pTCP->afRates[nCurLayer] -= pTCP->afRates[nCurLayer] ? (pJ2k->nSODStartPos / (pCodingParams->nYTilesCount * pCodingParams->nXTilesCount)) : 0;
|
|
}
|
|
if( pImageInfo )
|
|
{
|
|
pImageInfo->nPacketCount = 0;
|
|
}
|
|
|
|
int nTileDataLen = TCD_EncodeTile( pTCD, pJ2k->nCurTileIndex,(BYTE*)pStream->GetOwner()+pStream->Tell(), pStream->GetLeftSize() - 2, pImageInfo );
|
|
|
|
// Çàïèñûâàåì ïîëå Psot â ìàðêåðå SOT
|
|
int nTotalLen = pStream->Tell() + nTileDataLen - pJ2k->nSOTStartPos;
|
|
pStream->Seek( pJ2k->nSOTStartPos + 6);
|
|
pStream->Write( nTotalLen, 4 ); // Psot
|
|
pStream->Seek( pJ2k->nSOTStartPos + nTotalLen );
|
|
}
|
|
|
|
static void J2k_ReadSOD (J2kCodestream *pJ2k)
|
|
{
|
|
int nTruncate = 0;
|
|
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
int nCurTileIndex = pJ2k->nCurTileIndex;
|
|
|
|
int nLen = min( pJ2k->nSizeOfTile - pStream->Tell(), pStream->GetLeftSize() + 1 );
|
|
|
|
if ( nLen == pStream->GetLeftSize() + 1 )
|
|
{
|
|
nTruncate = 1; // Îáðåçàííûé codestream
|
|
}
|
|
|
|
unsigned char *pData = (unsigned char *) Malloc(HEAP_ZERO_MEMORY, ( pJ2k->pTileLen[nCurTileIndex] + nLen ) * sizeof(unsigned char));
|
|
if ( !pData )
|
|
{
|
|
pJ2k->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
return;
|
|
}
|
|
|
|
for ( int nIndex = 0; nIndex < pJ2k->pTileLen[nCurTileIndex]; nIndex++ )
|
|
{
|
|
pData[nIndex] = pJ2k->ppTileData[nCurTileIndex][nIndex];
|
|
}
|
|
|
|
unsigned char *pDataPointer = pData + pJ2k->pTileLen[nCurTileIndex];
|
|
//for ( int nIndex = 0; nIndex < nLen; nIndex++ )
|
|
//{
|
|
// pDataPointer[nIndex] = pStream->Read( 1 ); // Ñ÷èòûâàåì çàêîäèðîâàííûå äàííûå òåêóùåãî òàéëà
|
|
//}
|
|
|
|
pStream->Read(pDataPointer,nLen);
|
|
|
|
pJ2k->pTileLen[nCurTileIndex] += nLen;
|
|
RELEASEHEAP( pJ2k->ppTileData[nCurTileIndex] );
|
|
pJ2k->ppTileData[nCurTileIndex] = pData;
|
|
|
|
if ( !nTruncate )
|
|
{
|
|
pJ2k->nState = j2kstateTPHSOT;
|
|
}
|
|
else
|
|
{
|
|
pJ2k->nState = j2kstateNEOC;
|
|
}
|
|
}
|
|
|
|
static void J2k_WriteRGN(J2kCodestream *pJ2k, int nCurComponent, int nTileIndex)
|
|
{
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
TileCodingParams *pTCP = &pCodingParams->pTCP[nTileIndex];
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
int nComponentsCount = pJ2k->pImage->nCsiz;
|
|
|
|
pStream->Write( J2K_MS_RGN, 2 ); // RGN
|
|
pStream->Write( nComponentsCount <= 256 ? 5 : 6, 2 ); // Lrgn
|
|
pStream->Write( nCurComponent, nComponentsCount <= 256 ? 1 : 2 ); // Crgn
|
|
pStream->Write( 0, 1 ); // Srgn
|
|
pStream->Write( pTCP->pTCCP[nCurComponent].nROIShift, 1 ); // SPrgn
|
|
}
|
|
|
|
static void J2k_ReadRGN (J2kCodestream *pJ2k)
|
|
{
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
TileCodingParams *pTCP = pJ2k->nState == j2kstateTPH ? &pCodingParams->pTCP[pJ2k->nCurTileIndex] : pJ2k->pDefaultTCP;
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
|
|
int nComponentsCount = pJ2k->pImage->nCsiz;
|
|
|
|
int nLen = pStream->Read( 2 ); // Lrgn
|
|
int nCurComponent = pStream->Read( nComponentsCount <= 256 ? 1 : 2 ); // Crgn
|
|
int nROIStyle = pStream->Read( 1 ); // Srgn
|
|
// TO DO: Âñòàâèòü ïðîâåðêó nROIStyle == 0
|
|
pTCP->pTCCP[nCurComponent].nROIShift = pStream->Read( 1 ); // SPrgn
|
|
}
|
|
|
|
static void J2k_WriteEOC(J2kCodestream *pJ2k)
|
|
{
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
pStream->Write( J2K_MS_EOC, 2 ); // EOC
|
|
}
|
|
|
|
static void J2k_ReadEOC (J2kCodestream *pJ2k)
|
|
{
|
|
#ifndef NO_PACKETS_DECODING
|
|
TCD *pTCD = TCD_Create( pJ2k->pCodecInfo );
|
|
TCD_MallocDecode( pTCD, pJ2k->pImage, pJ2k->pCodingParams );
|
|
|
|
if ( pTCD->pCodecInfo->nErrorCode == JP2_ERROR_NO_ERROR )
|
|
{
|
|
for ( int nIndex = 0; nIndex < pJ2k->pCodingParams->nTileIndexSize; nIndex++ )
|
|
{
|
|
int nTileIndex = pJ2k->pCodingParams->pTileIndex[nIndex];
|
|
TCD_DecodeTile( pTCD, pJ2k->ppTileData[nTileIndex], pJ2k->pTileLen[nTileIndex], nTileIndex );
|
|
RELEASEHEAP( pJ2k->ppTileData[nTileIndex] );
|
|
pJ2k->ppTileData[nTileIndex] = NULL;
|
|
}
|
|
TCD_FreeDecode( pTCD );
|
|
}
|
|
else
|
|
{
|
|
for ( int nIndex = 0; nIndex < pJ2k->pCodingParams->nTileIndexSize; nIndex++ )
|
|
{
|
|
int nTileIndex = pJ2k->pCodingParams->pTileIndex[nIndex];
|
|
RELEASEHEAP( pJ2k->ppTileData[nTileIndex] );
|
|
pJ2k->ppTileData[nTileIndex] = NULL;
|
|
}
|
|
}
|
|
TCD_Destroy( pTCD );
|
|
#else
|
|
for ( int nIndex = 0; nIndex < j2k->cp->tileno_size; nIndex++ )
|
|
{
|
|
int nTileIndex = pJ2k->pCodingParams->pTileIndex[nIndex];
|
|
RELEASEHEAP( pJ2k->ppTileData[nTileIndex] );
|
|
pJ2k->ppTileData[nTileIndex] = NULL;
|
|
}
|
|
#endif
|
|
|
|
pJ2k->nState = j2kstateMT;
|
|
}
|
|
static void J2k_ReadUNK (J2kCodestream *pJ2k)
|
|
{
|
|
// Ïðåäïîëàãàåì, ÷òî íåèçâåñòíûé ìàðêåð íå ïóñòîé, à, çíà÷èò,
|
|
// ó íåãî ñëåäóþùèå äâà áàéòà - äëèíà ìàðêåðà.
|
|
CReader *pStream = pJ2k->pStreamIO;
|
|
int nLen = pStream->Read( 2 );
|
|
|
|
if ( nLen > 0 )
|
|
pStream->Read( nLen - 2 );
|
|
|
|
Event_Message(EVT_WARNING, "Unknown marker\n" );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
// Òàáëèöà ñâÿçûâàþùàÿ ïðî÷òåííûé ìàðêåð - ñîñòîÿíèå äåêîäåðà - äåéñòâèå(ôóíêöèÿ) äåêîäåðà ïðè ïðî÷òåíèè äàííîãî ìàðêåðà
|
|
typedef struct TDecoderMSTableEntry
|
|
{
|
|
int nID; // Çíà÷åíèå ìàðêåðà
|
|
int nStates; // Ñîñòîÿíèå äåêîäåðà, êîãäà ïîÿâëÿåòñÿ äàííûé ìàðêåð
|
|
void (*pHandler) (J2kCodestream *pJ2k); // Äåéñòâèå ñâÿçàííîå ñ äàííûì ìàðêåðîì
|
|
} DecoderMSTableEntry;
|
|
|
|
DecoderMSTableEntry c_aoJ2k_DecoderMSTable[] =
|
|
{
|
|
{ J2K_MS_SOC, j2kstateMHSOC, J2k_ReadSOC },
|
|
{ J2K_MS_SOT, j2kstateMH | j2kstateTPHSOT, J2k_ReadSOT },
|
|
{ J2K_MS_SOD, j2kstateTPH, J2k_ReadSOD },
|
|
{ J2K_MS_EOC, j2kstateTPHSOT, J2k_ReadEOC },
|
|
{ J2K_MS_SIZ, j2kstateMHSIZ, J2k_ReadSIZ },
|
|
{ J2K_MS_COD, j2kstateMH | j2kstateTPH, J2k_ReadCOD },
|
|
{ J2K_MS_COC, j2kstateMH | j2kstateTPH, J2k_ReadCOC },
|
|
{ J2K_MS_RGN, j2kstateMH | j2kstateTPH, J2k_ReadRGN },
|
|
{ J2K_MS_QCD, j2kstateMH | j2kstateTPH, J2k_ReadQCD },
|
|
{ J2K_MS_QCC, j2kstateMH | j2kstateTPH, J2k_ReadQCC },
|
|
{ J2K_MS_POC, j2kstateMH | j2kstateMH, J2k_ReadPOC },
|
|
{ J2K_MS_TLM, j2kstateMH, J2k_ReadTLM },
|
|
{ J2K_MS_PLM, j2kstateMH, J2k_ReadPLM },
|
|
{ J2K_MS_PLT, j2kstateTPH, J2k_ReadPLT },
|
|
{ J2K_MS_PPM, j2kstateMH, J2k_ReadPPM },
|
|
{ J2K_MS_PPT, j2kstateTPH, J2k_ReadPPT },
|
|
{ J2K_MS_SOP, 0, 0 },
|
|
{ J2K_MS_CRG, j2kstateMH, J2k_ReadCRG },
|
|
{ J2K_MS_COM, j2kstateMH | j2kstateTPH, J2k_ReadCOM },
|
|
{ 0, j2kstateMH | j2kstateTPH, J2k_ReadUNK }
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
//,{J2K_MS_EPC, j2kstateMH | j2kstateMH, J2k_ReadEPC},
|
|
//{J2K_MS_EPB, j2kstateMH | j2kstateMH, j2k_read_epb},
|
|
//{J2K_MS_ESD, j2kstateMH | j2kstateMH, j2k_read_esd},
|
|
//{J2K_MS_RED, j2kstateMH | j2kstateMH, j2k_read_red},
|
|
//{J2K_MS_SEC, j2kstateMH/*J2K_DEC_STATE_MH*/,j2k_read_sec},
|
|
//{J2K_MS_INSEC, 0, j2k_read_insec},
|
|
//{J2K_MS_UNK, j2kstateMH | J2K_STATE_TPH, 0}
|
|
|
|
};
|
|
|
|
static DecoderMSTableEntry *J2k_DeocderMSTableLookup(int nID)
|
|
{
|
|
DecoderMSTableEntry *pEntry = NULL;
|
|
for ( pEntry = c_aoJ2k_DecoderMSTable; pEntry->nID != 0; pEntry++ )
|
|
{
|
|
if ( pEntry->nID == nID )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
return pEntry;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
// Äåêîäèðîâàíèå ïîòîêîâ J2K / JPT
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
J2kCodestream* J2k_CreateDecompress(PCommon pCodecInfo)
|
|
{
|
|
J2kCodestream *pJ2k = (J2kCodestream*)Malloc(HEAP_ZERO_MEMORY, sizeof(J2kCodestream) );
|
|
if( pJ2k )
|
|
{
|
|
pJ2k->pCodecInfo = pCodecInfo;
|
|
pJ2k->pDefaultTCP = (TileCodingParams*)Malloc(HEAP_ZERO_MEMORY, sizeof(TileCodingParams));
|
|
if( !pJ2k->pDefaultTCP )
|
|
{
|
|
pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
RELEASEHEAP( pJ2k );
|
|
return NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
return pJ2k;
|
|
}
|
|
|
|
void J2k_DestroyDecompress(J2kCodestream *pJ2k)
|
|
{
|
|
if (!pJ2k)return;
|
|
|
|
RELEASEHEAP( pJ2k->pTileLen );
|
|
RELEASEHEAP( pJ2k->ppTileData );
|
|
|
|
if( pJ2k->pDefaultTCP != NULL )
|
|
{
|
|
TileCodingParams *pDefaultTCP = pJ2k->pDefaultTCP;
|
|
|
|
RELEASEHEAP( pDefaultTCP->pPPTDataFirst );
|
|
|
|
RELEASEHEAP( pJ2k->pDefaultTCP->pTCCP );
|
|
|
|
RELEASEHEAP( pJ2k->pDefaultTCP );
|
|
}
|
|
if( pJ2k->pCodingParams != NULL )
|
|
{
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
if( pCodingParams->pTCP != NULL )
|
|
{
|
|
for( int nIndex = 0; nIndex < pCodingParams->nXTilesCount * pCodingParams->nYTilesCount; nIndex++ )
|
|
{
|
|
RELEASEHEAP( pCodingParams->pTCP[nIndex].pPPTDataFirst );
|
|
RELEASEHEAP( pCodingParams->pTCP[nIndex].pTCCP );
|
|
}
|
|
RELEASEHEAP( pCodingParams->pTCP );
|
|
}
|
|
RELEASEHEAP( pCodingParams->pPPMDataFirst );
|
|
RELEASEHEAP( pCodingParams->pTileIndex );
|
|
RELEASEHEAP( pCodingParams->sComment );
|
|
|
|
RELEASEHEAP( pCodingParams );
|
|
}
|
|
|
|
RELEASEHEAP( pJ2k );
|
|
}
|
|
|
|
void J2k_SetupDecoder(J2kCodestream *pJ2k, DecoderParams *pParameters)
|
|
{
|
|
if( pJ2k && pParameters )
|
|
{
|
|
// Ñîçäàåì è èíèöèàëèçèðóåì ñòðóêòóðó CodingParams
|
|
CodingParams *pCodingParams = (CodingParams*)Malloc(HEAP_ZERO_MEMORY, sizeof(CodingParams));
|
|
if ( !pCodingParams )
|
|
{
|
|
pJ2k->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
return;
|
|
}
|
|
pCodingParams->nReduceFactor = pParameters->nReduce;
|
|
pCodingParams->nLayerFactor = pParameters->nLayer;
|
|
pCodingParams->eLimitDecoding = pParameters->eLimitDecoding;
|
|
pJ2k->pCodingParams = pCodingParams;
|
|
}
|
|
}
|
|
|
|
Image* J2k_Decode(J2kCodestream *pJ2k, CReader *pStream)
|
|
{
|
|
PCommon pCodecInfo = pJ2k->pCodecInfo;
|
|
|
|
pJ2k->pStreamIO = pStream;
|
|
|
|
// Ñîçäàåì ïóñòóþ êàðòèíêó
|
|
Image *pImage = Image_CreateEmpty();
|
|
if ( !pImage )
|
|
{
|
|
pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
return NULL;
|
|
}
|
|
pJ2k->pImage = pImage;
|
|
|
|
pJ2k->nState = j2kstateMHSOC;
|
|
|
|
for (;;)
|
|
{
|
|
int nID = pStream->Read( 2 );
|
|
|
|
if ( nID >> 8 != 0xff )
|
|
{
|
|
Image_Destroy( pImage );
|
|
pImage = NULL;
|
|
Event_Message( EVT_ERROR, "%.8x: expected a marker instead of %x\n", pStream->Tell() - 2, nID );
|
|
return 0;
|
|
}
|
|
DecoderMSTableEntry *pEntry = J2k_DeocderMSTableLookup( nID );
|
|
|
|
if ( !(pJ2k->nState & pEntry->nStates) )
|
|
{
|
|
Image_Destroy( pImage );
|
|
pImage = NULL;
|
|
Event_Message( EVT_ERROR, "%.8x: unexpected marker %x\n", pStream->Tell() - 2, nID );
|
|
return 0;
|
|
}
|
|
|
|
// Ïðîâåðÿåì îãðàíè÷åíèå íà äåêîäèðîâàíèå
|
|
if ( pEntry->nID == J2K_MS_SOT && pJ2k->pCodingParams->eLimitDecoding == declimLimitToMainHeader )
|
|
{
|
|
Event_Message( EVT_INFO, "Main Header decoded.\n");
|
|
return pImage;
|
|
}
|
|
|
|
if ( pEntry->pHandler )
|
|
{
|
|
(*pEntry->pHandler)(pJ2k);
|
|
}
|
|
else
|
|
{
|
|
Image_Destroy( pImage );
|
|
pImage = NULL;
|
|
Event_Message( EVT_ERROR, "Error handler occure" );
|
|
break;
|
|
}
|
|
if ( pJ2k->nState == j2kstateMT )
|
|
{
|
|
pCodecInfo->nErrorCode = JP2_ERROR_NO_ERROR;
|
|
break;
|
|
}
|
|
if ( pJ2k->nState == j2kstateNEOC )
|
|
{
|
|
pCodecInfo->nErrorCode = JP2_ERROR_NO_ERROR;
|
|
break;
|
|
}
|
|
// Ïðîâåðÿåì íå ïîÿâèëàñü ëè îøèáêà
|
|
if ( JP2_ERROR_NO_ERROR != pCodecInfo->nErrorCode )
|
|
{
|
|
Image_Destroy( pImage );
|
|
pImage = NULL;
|
|
Event_Message( EVT_ERROR, "Error occure" );
|
|
return 0;
|
|
}
|
|
}
|
|
if ( pJ2k->nState == j2kstateNEOC )
|
|
{
|
|
J2k_ReadEOC( pJ2k );
|
|
}
|
|
|
|
if ( pJ2k->nState != j2kstateMT )
|
|
{
|
|
Event_Message( EVT_WARNING, "Incomplete bitstream\n");
|
|
}
|
|
|
|
return pImage;
|
|
}
|
|
|
|
Image* J2k_DecodeJptStream(J2kCodestream *pJ2k, CReader *pStream)
|
|
{
|
|
PCommon pCodecInfo = pJ2k->pCodecInfo;
|
|
|
|
pJ2k->pStreamIO = pStream;
|
|
|
|
// Ñîçäåì ïóñòóþ êàðòèíêó
|
|
Image *pImage = Image_CreateEmpty();
|
|
if ( !pImage )
|
|
{
|
|
pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
return NULL;
|
|
}
|
|
|
|
pJ2k->nState = j2kstateMHSOC;
|
|
|
|
// Èíèöèàëèçèðóåì çàãîëîâîê
|
|
JPTMessageHeader oHeader;
|
|
JPT_InitMessageHeader( &oHeader );
|
|
// ×èòàåì ïåðâûé çàãîëîâîê ñîîáùåíèÿ
|
|
JPT_ReadMessageHeader( pCodecInfo, pStream, &oHeader );
|
|
|
|
int nPosition = pStream->Tell();
|
|
if ( oHeader.nClassId != 6 ) // 6 : Main header data-bin message
|
|
{
|
|
Image_Destroy( pImage );
|
|
Event_Message( EVT_ERROR, "[JPT-stream] : Expecting Main header first [class_Id %d] !\n", oHeader.nClassId );
|
|
return 0;
|
|
}
|
|
|
|
for (;;)
|
|
{
|
|
if ( !pStream->GetLeftSize() )
|
|
{
|
|
J2k_ReadEOC( pJ2k );
|
|
return pImage;
|
|
}
|
|
|
|
if ( (unsigned int) ( pStream->Tell() - nPosition) == oHeader.nMessageLength )
|
|
{
|
|
JPT_ReadMessageHeader( pCodecInfo, pStream, &oHeader );
|
|
nPosition = pStream->Tell();
|
|
if ( oHeader.nClassId != 4 ) // 4 : Tile data-bin message
|
|
{
|
|
Image_Destroy( pImage );
|
|
Event_Message( EVT_ERROR, "[JPT-stream] : Expecting Tile info !\n");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int nId = pStream->Read( 2);
|
|
if ( nId >> 8 != 0xff )
|
|
{
|
|
Image_Destroy( pImage );
|
|
Event_Message( EVT_ERROR, "%.8x: expected a marker instead of %x\n", pStream->Tell() - 2, nId );
|
|
return 0;
|
|
}
|
|
DecoderMSTableEntry *pEntry = J2k_DeocderMSTableLookup( nId );
|
|
if ( !( pJ2k->nState & pEntry->nStates ) )
|
|
{
|
|
Image_Destroy( pImage );
|
|
Event_Message( EVT_ERROR, "%.8x: unexpected marker %x\n", pStream->Tell() - 2, nId );
|
|
return 0;
|
|
}
|
|
if ( pEntry->pHandler )
|
|
{
|
|
(*pEntry->pHandler)( pJ2k );
|
|
}
|
|
if ( pJ2k->nState == j2kstateMT )
|
|
{
|
|
break;
|
|
}
|
|
if ( pJ2k->nState == j2kstateNEOC )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if ( pJ2k->nState == j2kstateNEOC )
|
|
{
|
|
J2k_ReadEOC( pJ2k );
|
|
}
|
|
|
|
if ( pJ2k->nState != j2kstateMT )
|
|
{
|
|
Event_Message( EVT_WARNING, "Incomplete bitstream\n");
|
|
}
|
|
|
|
return pImage;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
// Êîäèðîâàíèå â ïîòîê J2K
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
J2kCodestream* J2k_CreateCompress(PCommon pCodecInfo)
|
|
{
|
|
J2kCodestream *pJ2k = (J2kCodestream*)Malloc(HEAP_ZERO_MEMORY, sizeof(J2kCodestream) );
|
|
if( pJ2k )
|
|
{
|
|
pJ2k->pCodecInfo = pCodecInfo;
|
|
}
|
|
else
|
|
{
|
|
pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
return pJ2k;
|
|
}
|
|
|
|
void J2k_DestroyCompress(J2kCodestream *pJ2k)
|
|
{
|
|
if( !pJ2k )
|
|
return;
|
|
|
|
if( pJ2k->pImageInfo != NULL )
|
|
{
|
|
ImageInfo *pImageInfo = pJ2k->pImageInfo;
|
|
if ( pImageInfo->nIndexOn && pJ2k->pCodingParams )
|
|
{
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
for ( int nTileIndex = 0; nTileIndex < pCodingParams->nXTilesCount * pCodingParams->nYTilesCount; nTileIndex++ )
|
|
{
|
|
TileInfo *pTileInfo = &pImageInfo->pTile[nTileIndex];
|
|
RELEASEHEAP( pTileInfo->pdThreshold );
|
|
RELEASEHEAP( pTileInfo->pPacket );
|
|
}
|
|
RELEASEHEAP( pImageInfo->pTile );
|
|
}
|
|
RELEASEHEAP( pImageInfo );
|
|
}
|
|
if( pJ2k->pCodingParams != NULL )
|
|
{
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
|
|
RELEASEHEAP( pCodingParams->sComment );
|
|
RELEASEHEAP( pCodingParams->pMatrix );
|
|
|
|
for ( int nTileIndex = 0; nTileIndex < pCodingParams->nXTilesCount * pCodingParams->nYTilesCount; nTileIndex++ )
|
|
{
|
|
RELEASEHEAP( pCodingParams->pTCP[nTileIndex].pTCCP );
|
|
}
|
|
RELEASEHEAP( pCodingParams->pTCP );
|
|
RELEASEHEAP( pCodingParams );
|
|
}
|
|
|
|
RELEASEHEAP( pJ2k );
|
|
}
|
|
|
|
void J2k_SetupEncoder(J2kCodestream *pJ2k, EncoderParams *pParameters, Image *pImage)
|
|
{
|
|
if( !pJ2k || !pParameters || ! pImage )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Ñîçäàåì è èíèöèàëèçèðóåì ñòðóêòóðó Coding parameters
|
|
CodingParams *pCodingParams = (CodingParams*)Malloc(HEAP_ZERO_MEMORY, sizeof(CodingParams));
|
|
if ( !pCodingParams )
|
|
{
|
|
pJ2k->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
return;
|
|
}
|
|
pJ2k->pCodingParams = pCodingParams;
|
|
|
|
pCodingParams->nXTilesCount = 1;
|
|
pCodingParams->nYTilesCount = 1;
|
|
|
|
// Êîïèðóåì çàäàííûå ïàðàìåòðû
|
|
|
|
pCodingParams->nDistoAlloc = pParameters->nDistoAlloc;
|
|
pCodingParams->nFixedAlloc = pParameters->nFixedAlloc;
|
|
pCodingParams->nFixedQuality = pParameters->nFixedQuality;
|
|
|
|
// Fixed_quality
|
|
if( pParameters->pMatrix )
|
|
{
|
|
size_t array_size = pParameters->nLayersCount * pParameters->nResolutionsCount * 3 * sizeof(int);
|
|
pCodingParams->pMatrix = (int *) Malloc(HEAP_ZERO_MEMORY, array_size);
|
|
if ( !pCodingParams->pMatrix )
|
|
{
|
|
RELEASEHEAP( pCodingParams );
|
|
pJ2k->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
return;
|
|
}
|
|
memcpy( pCodingParams->pMatrix, pParameters->pMatrix, array_size );
|
|
}
|
|
|
|
// Ñîçäàåì ëè ôàéë èíäåêñàöèè?
|
|
pCodingParams->nIndexOn = pParameters->nIndexOn;
|
|
if( pCodingParams->nIndexOn )
|
|
{
|
|
pJ2k->pImageInfo = (ImageInfo*)Malloc(HEAP_ZERO_MEMORY, sizeof(ImageInfo));
|
|
if ( !pJ2k->pImageInfo )
|
|
{
|
|
if ( pCodingParams->pMatrix )
|
|
RELEASEHEAP( pCodingParams->pMatrix );
|
|
RELEASEHEAP( pCodingParams );
|
|
pJ2k->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Tiles
|
|
pCodingParams->nXTsiz = pParameters->nXTsiz;
|
|
pCodingParams->nYTsiz = pParameters->nYTsiz;
|
|
|
|
// Tile offset
|
|
pCodingParams->nXTOsiz = pParameters->nXTOsiz;
|
|
pCodingParams->nYTOsiz = pParameters->nYTOsiz;
|
|
|
|
// Comment
|
|
if( pParameters->sComment )
|
|
{
|
|
pCodingParams->sComment = (char*)Malloc(HEAP_ZERO_MEMORY, strlen(pParameters->sComment) + 1 );
|
|
if( pCodingParams->sComment )
|
|
{
|
|
strcpy( pCodingParams->sComment, pParameters->sComment );
|
|
}
|
|
}
|
|
|
|
// Âû÷èñëÿåì äðóãèå ïàðàìåòðû êîäèðîâàíèÿ
|
|
|
|
if ( pParameters->bTileSizeOn )
|
|
{
|
|
pCodingParams->nXTilesCount = CeilDiv( pImage->nXsiz - pCodingParams->nXTOsiz, pCodingParams->nXTsiz );
|
|
pCodingParams->nYTilesCount = CeilDiv( pImage->nYsiz - pCodingParams->nYTOsiz, pCodingParams->nYTsiz );
|
|
}
|
|
else
|
|
{
|
|
pCodingParams->nXTsiz = pImage->nXsiz - pCodingParams->nXTOsiz;
|
|
pCodingParams->nYTsiz = pImage->nYsiz - pCodingParams->nYTOsiz;
|
|
}
|
|
|
|
|
|
pCodingParams->pTCP = (TileCodingParams *) Malloc(HEAP_ZERO_MEMORY, pCodingParams->nXTilesCount * pCodingParams->nYTilesCount * sizeof(TileCodingParams) );
|
|
if ( !pCodingParams->pTCP )
|
|
{
|
|
RELEASEHEAP( pCodingParams->pMatrix );
|
|
RELEASEHEAP( pJ2k->pImageInfo );
|
|
RELEASEHEAP( pCodingParams );
|
|
|
|
pJ2k->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
return;
|
|
}
|
|
|
|
for ( int nTileIndex = 0; nTileIndex < pCodingParams->nXTilesCount * pCodingParams->nYTilesCount; nTileIndex++ )
|
|
{
|
|
TileCodingParams *pTCP = &pCodingParams->pTCP[nTileIndex];
|
|
pTCP->nLayersCount = pParameters->nLayersCount;
|
|
for ( int nLayerIndex = 0; nLayerIndex < pTCP->nLayersCount; nLayerIndex++ )
|
|
{
|
|
if ( pCodingParams->nFixedQuality ) // Add fixed quality
|
|
{
|
|
pTCP->afDistoRatio[nLayerIndex] = pParameters->afDistoratio[nLayerIndex];
|
|
}
|
|
else
|
|
{
|
|
pTCP->afRates[nLayerIndex] = pParameters->afRates[nLayerIndex];
|
|
}
|
|
}
|
|
pTCP->nCodingStyle = pParameters->nCodingStyle;
|
|
pTCP->eProgOrder = pParameters->eProgOrder;
|
|
pTCP->nMCT = pImage->nCsiz == 3 ? 1 : 0;
|
|
|
|
int nPOCsCountTile = 0;
|
|
pTCP->nUsePOC = 0;
|
|
|
|
if ( pParameters->nPOCsCount )
|
|
{
|
|
pTCP->nUsePOC = 1;
|
|
for ( int nPOCIndex = 0; nPOCIndex < pParameters->nPOCsCount; nPOCIndex++ )
|
|
{
|
|
if( ( nTileIndex == pParameters->aoPOC[nPOCIndex].nTile - 1 ) || ( pParameters->aoPOC[nPOCIndex].nTile == -1 ) )
|
|
{
|
|
POC *pTCP_POC = &pTCP->aoPOC[nPOCsCountTile];
|
|
pTCP_POC->nRSpoc = pParameters->aoPOC[nPOCsCountTile].nRSpoc;
|
|
pTCP_POC->nCSpoc = pParameters->aoPOC[nPOCsCountTile].nCSpoc;
|
|
pTCP_POC->nLYEpoc = pParameters->aoPOC[nPOCsCountTile].nLYEpoc;
|
|
pTCP_POC->nREpoc = pParameters->aoPOC[nPOCsCountTile].nREpoc;
|
|
pTCP_POC->nCEpoc = pParameters->aoPOC[nPOCsCountTile].nCEpoc;
|
|
pTCP_POC->ePpoc = pParameters->aoPOC[nPOCsCountTile].ePpoc;
|
|
pTCP_POC->nTile = pParameters->aoPOC[nPOCsCountTile].nTile;
|
|
nPOCsCountTile++;
|
|
}
|
|
}
|
|
}
|
|
pTCP->nPOCsCount = nPOCsCountTile;
|
|
|
|
pTCP->pTCCP = (TileCompCodingParams *) Malloc(HEAP_ZERO_MEMORY, pImage->nCsiz * sizeof(TileCompCodingParams) );
|
|
if ( !pTCP->pTCCP )
|
|
{
|
|
for ( int nI = 0; nI < nTileIndex; nI++ )
|
|
{
|
|
TileCodingParams *pDeleteTCP = &pCodingParams->pTCP[nI];
|
|
RELEASEHEAP( pDeleteTCP->pTCCP );
|
|
}
|
|
RELEASEHEAP( pCodingParams->pMatrix );
|
|
RELEASEHEAP( pJ2k->pImageInfo );
|
|
|
|
RELEASEHEAP( pCodingParams->pTCP );
|
|
RELEASEHEAP( pCodingParams );
|
|
pJ2k->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
|
return;
|
|
}
|
|
|
|
for ( int nComponentIndex = 0; nComponentIndex < pImage->nCsiz; nComponentIndex++ )
|
|
{
|
|
TileCompCodingParams *pTCCP = &pTCP->pTCCP[nComponentIndex];
|
|
pTCCP->nCodingStyle = pParameters->nCodingStyle & 0x01; // 0 => îäíà îáëàñòü || 1 => ïðèçâîëüíîå êîëè÷åñòâî îáëàñòåé
|
|
pTCCP->nResolutionsCount = pParameters->nResolutionsCount;
|
|
pTCCP->nCodeBlockWidth = FloorLog2( pParameters->nCodeBlockWidthInit );
|
|
pTCCP->nCodeBlockHeight = FloorLog2( pParameters->nCodeBlockHeightInit );
|
|
pTCCP->nCodeBlockStyle = pParameters->nCodeBlockStyle;
|
|
pTCCP->nTransformID = pParameters->nTransformId ? 0 : 1;
|
|
pTCCP->nQuantStyle = pParameters->nTransformId ? J2K_CCP_QNTSTY_SEQNT : J2K_CCP_QNTSTY_NOQNT;
|
|
pTCCP->nGuardBitsCount = 2;
|
|
|
|
if ( nComponentIndex == pParameters->nROIComponentIndex )
|
|
{
|
|
pTCCP->nROIShift = pParameters->nROIShift;
|
|
}
|
|
else
|
|
{
|
|
pTCCP->nROIShift = 0;
|
|
}
|
|
|
|
if ( pParameters->nCodingStyle & J2K_CCP_CSTY_PRT )
|
|
{
|
|
int nPrecinctIndex = 0;
|
|
for ( int nLevelIndex = pTCCP->nResolutionsCount - 1; nLevelIndex >= 0; nLevelIndex-- )
|
|
{
|
|
if ( nPrecinctIndex < pParameters->nPrecinctCount )
|
|
{
|
|
if ( pParameters->anPrecinctWidthInit[nPrecinctIndex] < 1 )
|
|
{
|
|
pTCCP->anPrecinctWidth[nLevelIndex] = 1;
|
|
}
|
|
else
|
|
{
|
|
pTCCP->anPrecinctWidth[nLevelIndex] = FloorLog2( pParameters->anPrecinctWidthInit[nPrecinctIndex] );
|
|
}
|
|
if ( pParameters->anPrecinctHeightInit[nPrecinctIndex] < 1 )
|
|
{
|
|
pTCCP->anPrecinctHeight[nLevelIndex] = 1;
|
|
}
|
|
else
|
|
{
|
|
pTCCP->anPrecinctHeight[nLevelIndex] = FloorLog2( pParameters->anPrecinctHeightInit[nPrecinctIndex] );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int nPrecinctCount = pParameters->nPrecinctCount;
|
|
int nPrecinctWidth = pParameters->anPrecinctWidthInit[nPrecinctCount - 1] >> ( nPrecinctIndex - ( nPrecinctCount - 1 ) );
|
|
int nPrecinctHeight = pParameters->anPrecinctHeightInit[nPrecinctCount - 1] >> ( nPrecinctIndex - ( nPrecinctCount - 1 ) );
|
|
if ( nPrecinctWidth < 1 )
|
|
{
|
|
pTCCP->anPrecinctWidth[nLevelIndex] = 1;
|
|
}
|
|
else
|
|
{
|
|
pTCCP->anPrecinctWidth[nLevelIndex] = FloorLog2( nPrecinctWidth );
|
|
}
|
|
if ( nPrecinctHeight < 1 )
|
|
{
|
|
pTCCP->anPrecinctHeight[nLevelIndex] = 1;
|
|
}
|
|
else
|
|
{
|
|
pTCCP->anPrecinctHeight[nLevelIndex] = FloorLog2( nPrecinctHeight );
|
|
}
|
|
}
|
|
nPrecinctIndex++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for ( int nLevelIndex = 0; nLevelIndex < pTCCP->nResolutionsCount; nLevelIndex++ )
|
|
{
|
|
pTCCP->anPrecinctWidth[nLevelIndex] = 15;
|
|
pTCCP->anPrecinctHeight[nLevelIndex] = 15;
|
|
}
|
|
}
|
|
|
|
DWT_CalcExplicitStepsizes( pTCCP, pImage->pComponents[nComponentIndex].nPrecision );
|
|
}
|
|
}
|
|
}
|
|
|
|
static int J2k_CreateIndex(J2kCodestream *pJ2k, CReader *pStream, ImageInfo *pImageInfo, char *sIndex)
|
|
{
|
|
double dTotalDisto = 0;
|
|
|
|
pImageInfo->nCodestreamSize = pStream->Tell() + pJ2k->nPosCorrection;
|
|
|
|
FILE* pFile = fopen( sIndex, "w" );
|
|
if ( !pFile )
|
|
{
|
|
Event_Message(EVT_ERROR, "failed to open %s for writing\n", sIndex );
|
|
return 0;
|
|
}
|
|
|
|
fprintf( pFile, "%d %d\n", pImageInfo->nImageWidth, pImageInfo->nImageHeight );
|
|
fprintf( pFile, "%d\n", pImageInfo->eProgOrder );
|
|
fprintf( pFile, "%d %d\n", pImageInfo->nXTsiz, pImageInfo->nYTsiz );
|
|
fprintf( pFile, "%d %d\n", pImageInfo->nXTilesCount, pImageInfo->nYTilesCount );
|
|
fprintf( pFile, "%d\n", pImageInfo->nCompCount );
|
|
fprintf( pFile, "%d\n", pImageInfo->nLayersCount );
|
|
fprintf( pFile, "%d\n", pImageInfo->nDecompCount );
|
|
|
|
for ( int nResolutionIndex = pImageInfo->nDecompCount; nResolutionIndex >= 0; nResolutionIndex-- )
|
|
{
|
|
fprintf( pFile, "[%d,%d] ", (1 << pImageInfo->pTile[0].anPrecinctWidth[nResolutionIndex]), (1 << pImageInfo->pTile[0].anPrecinctWidth[nResolutionIndex]) );
|
|
}
|
|
fprintf( pFile, "\n" );
|
|
fprintf( pFile, "%d\n", pImageInfo->nMainHeadEnd );
|
|
fprintf( pFile, "%d\n", pImageInfo->nCodestreamSize );
|
|
|
|
for ( int nTileIndex = 0; nTileIndex < pImageInfo->nXTilesCount * pImageInfo->nYTilesCount; nTileIndex++ )
|
|
{
|
|
fprintf( pFile, "%4d %9d %9d %9d %9e %9d %9e\n", pImageInfo->pTile[nTileIndex].nTileCount, pImageInfo->pTile[nTileIndex].nStartPos, pImageInfo->pTile[nTileIndex].nEndHeader, pImageInfo->pTile[nTileIndex].nEndPos, pImageInfo->pTile[nTileIndex].dDistoTile, pImageInfo->pTile[nTileIndex].nNBPix, pImageInfo->pTile[nTileIndex].dDistoTile / pImageInfo->pTile[nTileIndex].nNBPix );
|
|
}
|
|
|
|
for ( int nTileIndex = 0; nTileIndex < pImageInfo->nXTilesCount * pImageInfo->nYTilesCount; nTileIndex++ )
|
|
{
|
|
int nStartPos = 0, nEndPos = 0;
|
|
double dDisto = 0;
|
|
int nPackNB = 0;
|
|
|
|
if ( pImageInfo->eProgOrder == poLRCP )
|
|
{
|
|
for ( int nLayerIndex = 0; nLayerIndex < pImageInfo->nLayersCount; nLayerIndex++ )
|
|
{
|
|
for ( int nResolutionIndex = 0; nResolutionIndex < pImageInfo->nDecompCount + 1; nResolutionIndex++ )
|
|
{
|
|
for ( int nComponentIndex = 0; nComponentIndex < pImageInfo->nCompCount; nComponentIndex++ )
|
|
{
|
|
int nPrecinctMax = pImageInfo->pTile[nTileIndex].anXPrecinctCount[nResolutionIndex] * pImageInfo->pTile[nTileIndex].anYPrecinctCount[nResolutionIndex];
|
|
for ( int nPrecinctIndex = 0; nPrecinctIndex < nPrecinctMax; nPrecinctIndex++ )
|
|
{
|
|
nStartPos = pImageInfo->pTile[nTileIndex].pPacket[nPackNB].nStartPos;
|
|
nEndPos = pImageInfo->pTile[nTileIndex].pPacket[nPackNB].nEndPos;
|
|
dDisto = pImageInfo->pTile[nTileIndex].pPacket[nPackNB].dDisto;
|
|
fprintf( pFile, "%4d %6d %7d %5d %6d %6d %9d %9d %8e\n", nPackNB, nTileIndex, nLayerIndex, nResolutionIndex, nComponentIndex, nPrecinctIndex, nStartPos, nEndPos, dDisto );
|
|
dTotalDisto += dDisto;
|
|
nPackNB++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ( pImageInfo->eProgOrder == poRLCP )
|
|
{
|
|
for ( int nResolutionIndex = 0; nResolutionIndex < pImageInfo->nDecompCount + 1; nResolutionIndex++ )
|
|
{
|
|
for ( int nLayerIndex = 0; nLayerIndex < pImageInfo->nLayersCount; nLayerIndex++ )
|
|
{
|
|
for ( int nComponentIndex = 0; nComponentIndex < pImageInfo->nCompCount; nComponentIndex++ )
|
|
{
|
|
int nPrecinctMax = pImageInfo->pTile[nTileIndex].anXPrecinctCount[nResolutionIndex] * pImageInfo->pTile[nTileIndex].anYPrecinctCount[nResolutionIndex];
|
|
for ( int nPrecinctIndex = 0; nPrecinctIndex < nPrecinctMax; nPrecinctIndex++ )
|
|
{
|
|
nStartPos = pImageInfo->pTile[nTileIndex].pPacket[nPackNB].nStartPos;
|
|
nEndPos = pImageInfo->pTile[nTileIndex].pPacket[nPackNB].nEndPos;
|
|
dDisto = pImageInfo->pTile[nTileIndex].pPacket[nPackNB].dDisto;
|
|
fprintf( pFile, "%4d %6d %5d %7d %6d %6d %9d %9d %8e\n", nPackNB, nTileIndex, nResolutionIndex, nLayerIndex, nComponentIndex, nPrecinctIndex, nStartPos, nEndPos, dDisto );
|
|
dTotalDisto += dDisto;
|
|
nPackNB++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ( pImageInfo->eProgOrder == poRPCL )
|
|
{
|
|
for ( int nResolutionIndex = 0; nResolutionIndex < pImageInfo->nDecompCount + 1; nResolutionIndex++ )
|
|
{
|
|
// Ïðåäïîëàãàåì, ÷òî çíà÷åíèÿ XRsiz, YRsiz îäèíàêîâûå äëÿ âñåõ êîìïîíåíò
|
|
int nX0 = pImageInfo->nXTOsiz + nTileIndex - (int)floor( (float)nTileIndex/(float)pImageInfo->nXTilesCount ) * pImageInfo->nXTilesCount * pImageInfo->nXTsiz;
|
|
int nY0 = pImageInfo->nXTOsiz + (int)floor( (float)nTileIndex/(float)pImageInfo->nXTilesCount ) * pImageInfo->nYTsiz;
|
|
int nX1 = nX0 + pImageInfo->nXTsiz;
|
|
int nY1 = nY0 + pImageInfo->nYTsiz;
|
|
for( int nY = nY0; nY < nY1; nY++ )
|
|
{
|
|
for( int nX = nX0; nX < nX1; nX++ )
|
|
{
|
|
for ( int nComponentIndex = 0; nComponentIndex < pImageInfo->nCompCount; nComponentIndex++ )
|
|
{
|
|
int nPrecinctMax = pImageInfo->pTile[nTileIndex].anXPrecinctCount[nResolutionIndex] * pImageInfo->pTile[nTileIndex].anYPrecinctCount[nResolutionIndex];
|
|
for ( int nPrecinctIndex = 0; nPrecinctIndex < nPrecinctMax; nPrecinctIndex++ )
|
|
{
|
|
int nXPrecinctCount = pImageInfo->pTile[nTileIndex].anXPrecinctCount[nResolutionIndex];
|
|
int nPrecinctX = (int) pow( double(2), pImageInfo->pTile[nTileIndex].anPrecinctWidth[nResolutionIndex] + pImageInfo->nDecompCount - nResolutionIndex );
|
|
int nPrecinctY = (int) pow( double(2), pImageInfo->pTile[nTileIndex].anPrecinctHeight[nResolutionIndex] + pImageInfo->nDecompCount - nResolutionIndex );
|
|
int nPrecinctXIndex = nPrecinctIndex - (int) floor( (float)nPrecinctIndex/(float)nXPrecinctCount ) * nXPrecinctCount;
|
|
int nPrecinctYIndex = (int) floor( (float)nPrecinctIndex/(float)nXPrecinctCount );
|
|
if ( nPrecinctYIndex * nPrecinctY == nY )
|
|
{
|
|
if ( nPrecinctXIndex * nPrecinctX == nX )
|
|
{
|
|
for ( int nLayerIndex = 0; nLayerIndex < pImageInfo->nLayersCount; nLayerIndex++ )
|
|
{
|
|
nStartPos = pImageInfo->pTile[nTileIndex].pPacket[nPackNB].nStartPos;
|
|
nEndPos = pImageInfo->pTile[nTileIndex].pPacket[nPackNB].nEndPos;
|
|
dDisto = pImageInfo->pTile[nTileIndex].pPacket[nPackNB].dDisto;
|
|
fprintf( pFile, "%4d %6d %5d %6d %6d %7d %9d %9d %8e\n", nPackNB, nTileIndex, nResolutionIndex, nPrecinctIndex, nComponentIndex, nLayerIndex, nStartPos, nEndPos, dDisto );
|
|
dTotalDisto += dDisto;
|
|
nPackNB++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ( pImageInfo->eProgOrder == poPCRL )
|
|
{
|
|
// Ïðåäïîëàãàåì, ÷òî çíà÷åíèÿ XRsiz, YRsiz îäèíàêîâûå äëÿ âñåõ êîìïîíåíò
|
|
int nX0 = pImageInfo->nXTOsiz + nTileIndex - (int)floor( (float)nTileIndex/(float)pImageInfo->nXTilesCount ) * pImageInfo->nXTilesCount * pImageInfo->nXTsiz;
|
|
int nY0 = pImageInfo->nXTOsiz + (int)floor( (float)nTileIndex/(float)pImageInfo->nXTilesCount ) * pImageInfo->nYTsiz;
|
|
int nX1 = nX0 + pImageInfo->nXTsiz;
|
|
int nY1 = nY0 + pImageInfo->nYTsiz;
|
|
for( int nY = nY0; nY < nY1; nY++ )
|
|
{
|
|
for( int nX = nX0; nX < nX1; nX++ )
|
|
{
|
|
for ( int nComponentIndex = 0; nComponentIndex < pImageInfo->nCompCount; nComponentIndex++ )
|
|
{
|
|
for ( int nResolutionIndex = 0; nResolutionIndex < pImageInfo->nDecompCount + 1; nResolutionIndex++ )
|
|
{
|
|
int nPrecinctMax = pImageInfo->pTile[nTileIndex].anXPrecinctCount[nResolutionIndex] * pImageInfo->pTile[nTileIndex].anYPrecinctCount[nResolutionIndex];
|
|
for ( int nPrecinctIndex = 0; nPrecinctIndex < nPrecinctMax; nPrecinctIndex++ )
|
|
{
|
|
int nXPrecinctCount = pImageInfo->pTile[nTileIndex].anXPrecinctCount[nResolutionIndex];
|
|
int nPrecinctX = (int) pow( double(2), pImageInfo->pTile[nTileIndex].anPrecinctWidth[nResolutionIndex] + pImageInfo->nDecompCount - nResolutionIndex );
|
|
int nPrecinctY = (int) pow( double(2), pImageInfo->pTile[nTileIndex].anPrecinctHeight[nResolutionIndex] + pImageInfo->nDecompCount - nResolutionIndex );
|
|
int nPrecinctXIndex = nPrecinctIndex - (int) floor( (float)nPrecinctIndex/(float)nXPrecinctCount ) * nXPrecinctCount;
|
|
int nPrecinctYIndex = (int) floor( (float)nPrecinctIndex/(float)nXPrecinctCount );
|
|
if ( nPrecinctYIndex * nPrecinctY == nY )
|
|
{
|
|
if ( nPrecinctXIndex * nPrecinctX == nX )
|
|
{
|
|
for ( int nLayerIndex = 0; nLayerIndex < pImageInfo->nLayersCount; nLayerIndex++ )
|
|
{
|
|
nStartPos = pImageInfo->pTile[nTileIndex].pPacket[nPackNB].nStartPos;
|
|
nEndPos = pImageInfo->pTile[nTileIndex].pPacket[nPackNB].nEndPos;
|
|
dDisto = pImageInfo->pTile[nTileIndex].pPacket[nPackNB].dDisto;
|
|
fprintf( pFile, "%4d %6d %6d %6d %5d %7d %9d %9d %8e\n", nPackNB, nTileIndex, nPrecinctIndex, nComponentIndex, nResolutionIndex, nLayerIndex, nStartPos, nEndPos, dDisto );
|
|
dTotalDisto += dDisto;
|
|
nPackNB++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for ( int nComponentIndex = 0; nComponentIndex < pImageInfo->nCompCount; nComponentIndex++ )
|
|
{
|
|
// Ïðåäïîëàãàåì, ÷òî çíà÷åíèÿ XRsiz, YRsiz îäèíàêîâûå äëÿ âñåõ êîìïîíåíò
|
|
int nX0 = pImageInfo->nXTOsiz + nTileIndex - (int)floor( (float)nTileIndex/(float)pImageInfo->nXTilesCount ) * pImageInfo->nXTilesCount * pImageInfo->nXTsiz;
|
|
int nY0 = pImageInfo->nXTOsiz + (int)floor( (float)nTileIndex/(float)pImageInfo->nXTilesCount ) * pImageInfo->nYTsiz;
|
|
int nX1 = nX0 + pImageInfo->nXTsiz;
|
|
int nY1 = nY0 + pImageInfo->nYTsiz;
|
|
for( int nY = nY0; nY < nY1; nY++ )
|
|
{
|
|
for( int nX = nX0; nX < nX1; nX++ )
|
|
{
|
|
for ( int nResolutionIndex = 0; nResolutionIndex < pImageInfo->nDecompCount + 1; nResolutionIndex++ )
|
|
{
|
|
int nPrecinctMax = pImageInfo->pTile[nTileIndex].anXPrecinctCount[nResolutionIndex] * pImageInfo->pTile[nTileIndex].anYPrecinctCount[nResolutionIndex];
|
|
for ( int nPrecinctIndex = 0; nPrecinctIndex < nPrecinctMax; nPrecinctIndex++ )
|
|
{
|
|
int nXPrecinctCount = pImageInfo->pTile[nTileIndex].anXPrecinctCount[nResolutionIndex];
|
|
int nPrecinctX = (int) pow( double(2), pImageInfo->pTile[nTileIndex].anPrecinctWidth[nResolutionIndex] + pImageInfo->nDecompCount - nResolutionIndex );
|
|
int nPrecinctY = (int) pow( double(2), pImageInfo->pTile[nTileIndex].anPrecinctHeight[nResolutionIndex] + pImageInfo->nDecompCount - nResolutionIndex );
|
|
int nPrecinctXIndex = nPrecinctIndex - (int) floor( (float)nPrecinctIndex/(float)nXPrecinctCount ) * nXPrecinctCount;
|
|
int nPrecinctYIndex = (int) floor( (float)nPrecinctIndex/(float)nXPrecinctCount );
|
|
if ( nPrecinctYIndex * nPrecinctY == nY )
|
|
{
|
|
if ( nPrecinctXIndex * nPrecinctX == nX )
|
|
{
|
|
for ( int nLayerIndex = 0; nLayerIndex < pImageInfo->nLayersCount; nLayerIndex++ )
|
|
{
|
|
nStartPos = pImageInfo->pTile[nTileIndex].pPacket[nPackNB].nStartPos;
|
|
nEndPos = pImageInfo->pTile[nTileIndex].pPacket[nPackNB].nEndPos;
|
|
dDisto = pImageInfo->pTile[nTileIndex].pPacket[nPackNB].dDisto;
|
|
fprintf( pFile, "%4d %6d %6d %6d %5d %7d %9d %9d %8e\n", nPackNB, nTileIndex, nComponentIndex, nPrecinctIndex, nResolutionIndex, nLayerIndex, nStartPos, nEndPos, dDisto );
|
|
dTotalDisto += dDisto;
|
|
nPackNB++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fprintf( pFile, "%8e\n", pImageInfo->dDistoMax );
|
|
fprintf( pFile, "%.8e\n", dTotalDisto );
|
|
fclose( pFile );
|
|
|
|
return 1;
|
|
}
|
|
|
|
bool J2k_Encode(J2kCodestream *pJ2k, CReader *pStream, Image *pImage, char *sIndex)
|
|
{
|
|
pJ2k->pStreamIO = pStream;
|
|
pJ2k->pImage = pImage;
|
|
|
|
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
|
|
|
#ifdef _DEBUG
|
|
FILE *pFile;
|
|
pFile = fopen( "E:\\Jpeg2000CodingParams.xml", "wb" );
|
|
if ( pFile )
|
|
{
|
|
J2k_DumpCodingParams( pFile, pImage, pCodingParams );
|
|
fclose( pFile );
|
|
}
|
|
#endif
|
|
|
|
// Èíäåêñàöèÿ
|
|
ImageInfo *pImageInfo = pJ2k->pImageInfo;
|
|
if ( pImageInfo && pCodingParams->nIndexOn )
|
|
{
|
|
pImageInfo->nIndexOn = pCodingParams->nIndexOn;
|
|
pImageInfo->pTile = (TileInfo *) Malloc(HEAP_ZERO_MEMORY, pCodingParams->nXTilesCount * pCodingParams->nYTilesCount * sizeof(TileInfo) );
|
|
pImageInfo->nImageWidth = pImage->nXsiz - pImage->nXOsiz;
|
|
pImageInfo->nImageHeight = pImage->nYsiz - pImage->nYOsiz;
|
|
pImageInfo->eProgOrder = (&pCodingParams->pTCP[0])->eProgOrder;
|
|
pImageInfo->nXTilesCount = pCodingParams->nXTilesCount;
|
|
pImageInfo->nYTilesCount = pCodingParams->nYTilesCount;
|
|
pImageInfo->nXTsiz = pCodingParams->nXTsiz;
|
|
pImageInfo->nYTsiz = pCodingParams->nYTsiz;
|
|
pImageInfo->nXTOsiz = pCodingParams->nXTOsiz;
|
|
pImageInfo->nYTOsiz = pCodingParams->nYTOsiz;
|
|
pImageInfo->nCompCount = pImage->nCsiz;
|
|
pImageInfo->nLayersCount = (&pCodingParams->pTCP[0])->nLayersCount;
|
|
pImageInfo->nDecompCount = (&pCodingParams->pTCP[0])->pTCCP->nResolutionsCount - 1;
|
|
pImageInfo->dDistoMax = 0;
|
|
}
|
|
//-------------
|
|
|
|
J2k_WriteSOC( pJ2k );
|
|
J2k_WriteSIZ( pJ2k );
|
|
J2k_WriteCOD( pJ2k );
|
|
J2k_WriteQCD( pJ2k );
|
|
|
|
for ( int nComponentIndex = 0; nComponentIndex < pImage->nCsiz; nComponentIndex++ )
|
|
{
|
|
TileCodingParams *pTCP = &pCodingParams->pTCP[0];
|
|
if ( pTCP->pTCCP[nComponentIndex].nROIShift )
|
|
J2k_WriteRGN( pJ2k, nComponentIndex, 0);
|
|
}
|
|
if ( pCodingParams->sComment != NULL )
|
|
{
|
|
J2k_WriteCOM( pJ2k );
|
|
}
|
|
|
|
// Èíäåêñàöèÿ
|
|
if( pImageInfo && pImageInfo->nIndexOn )
|
|
{
|
|
pImageInfo->nMainHeadEnd = pStream->Tell() - 1;
|
|
}
|
|
//-------------
|
|
|
|
// Ñîçäàåì ñòðóêðòóðó äëÿ êîäèðîâàíèÿ òàéëîâ
|
|
TCD *pTCD = TCD_Create( pJ2k->pCodecInfo );
|
|
|
|
// Êîäèðóåì êàæäûé òàéë
|
|
for ( int nTileIndex = 0; nTileIndex < pCodingParams->nXTilesCount * pCodingParams->nYTilesCount; nTileIndex++ )
|
|
{
|
|
Event_Message(EVT_INFO, "tile number %d / %d\n", nTileIndex + 1, pCodingParams->nXTilesCount * pCodingParams->nYTilesCount );
|
|
|
|
pJ2k->nCurTileIndex = nTileIndex;
|
|
|
|
// Èíèöèàëèçèðóåì ïåðåä êîäèðîâàíèåì
|
|
if ( 0 == nTileIndex )
|
|
{
|
|
TCD_MallocEncode( pTCD, pImage, pCodingParams, pJ2k->nCurTileIndex);
|
|
}
|
|
else
|
|
{
|
|
TCD_InitEncode( pTCD, pImage, pCodingParams, pJ2k->nCurTileIndex);
|
|
}
|
|
// Ïðîâåðÿåì îøèáêó
|
|
if ( JP2_ERROR_NO_ERROR != pTCD->pCodecInfo->nErrorCode )
|
|
{
|
|
TCD_Destroy( pTCD );
|
|
return false;
|
|
}
|
|
|
|
// Èíäåêñàöèÿ
|
|
if( pImageInfo && pImageInfo->nIndexOn )
|
|
{
|
|
pImageInfo->pTile[pJ2k->nCurTileIndex].nTileCount = pJ2k->nCurTileIndex;
|
|
pImageInfo->pTile[pJ2k->nCurTileIndex].nStartPos = pStream->Tell() + pJ2k->nPosCorrection;
|
|
}
|
|
//-------------
|
|
|
|
J2k_WriteSOT( pJ2k );
|
|
|
|
for ( int nComponentIndex = 1; nComponentIndex < pImage->nCsiz; nComponentIndex++ )
|
|
{
|
|
J2k_WriteCOC( pJ2k, nComponentIndex );
|
|
J2k_WriteQCC( pJ2k, nComponentIndex );
|
|
}
|
|
if ( pCodingParams->pTCP[nTileIndex].nPOCsCount )
|
|
{
|
|
J2k_WritePOC( pJ2k );
|
|
}
|
|
|
|
J2k_WriteSOD( pJ2k, pTCD );
|
|
|
|
// Èíäåêñàöèÿ
|
|
if( pImageInfo && pImageInfo->nIndexOn )
|
|
{
|
|
pImageInfo->pTile[pJ2k->nCurTileIndex].nEndPos = pStream->Tell() + pJ2k->nPosCorrection - 1;
|
|
}
|
|
//-------------
|
|
|
|
}
|
|
|
|
// Óäàëÿåì ñòðóêòóðó êîäèðóþùóþ òàéëû
|
|
TCD_FreeEncode( pTCD );
|
|
TCD_Destroy( pTCD );
|
|
|
|
J2k_WriteEOC( pJ2k );
|
|
|
|
// Ñîçäàåì ôàéë ñ èíäåêñàöèåé
|
|
if( pImageInfo && pImageInfo->nIndexOn )
|
|
{
|
|
if( !J2k_CreateIndex( pJ2k, pStream, pImageInfo, sIndex ) )
|
|
{
|
|
Event_Message(EVT_ERROR, "failed to create index file %s\n", sIndex );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
return true;
|
|
}
|