Files
core/ASCImageStudio3/ASCImageJpeg2000/J2k.h

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