2238 lines
75 KiB
C++
2238 lines
75 KiB
C++
#pragma once
|
||
// Функции в данном файле предназначены для чтения/записи различных частей JPEG2000-codestream: маркеры и данные
|
||
//-------------------------------------------------------------------------------------------------------------------------------
|
||
|
||
#include "math.h"
|
||
|
||
#include "Types.h"
|
||
#include "Reader.h"
|
||
#include "Tile.h"
|
||
#include "Image.h"
|
||
#include "Jpt.h"
|
||
|
||
namespace Jpeg2000
|
||
{
|
||
//-------------------------------------------------------------------------------------------------------------------------------
|
||
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(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(pCodingParams->nXTilesCount * pCodingParams->nYTilesCount * sizeof(TileCodingParams));
|
||
if (!pCodingParams->pTCP)
|
||
{
|
||
Free(pImage->pComponents);
|
||
pJ2k->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
||
return;
|
||
}
|
||
|
||
pCodingParams->pTileIndex = (int *)Malloc(pCodingParams->nXTilesCount * pCodingParams->nYTilesCount * sizeof(int));
|
||
if (!pCodingParams->pTileIndex)
|
||
{
|
||
Free(pImage->pComponents);
|
||
Free(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(sizeof(TileCompCodingParams) * pImage->nCsiz);
|
||
if (!pJ2k->pDefaultTCP->pTCCP)
|
||
{
|
||
Free(pImage->pComponents);
|
||
Free(pCodingParams->pTCP);
|
||
Free(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(sizeof(TileCompCodingParams) * pImage->nCsiz);
|
||
if (!pCodingParams->pTCP[nIndex].pTCCP)
|
||
{
|
||
for (int nI = 0; nI < nIndex; nI++)
|
||
{
|
||
Free(pCodingParams->pTCP[nI].pTCCP);
|
||
Free(pImage->pComponents);
|
||
Free(pCodingParams->pTCP);
|
||
Free(pCodingParams->pTileIndex);
|
||
Free(pJ2k->pDefaultTCP->pTCCP);
|
||
pJ2k->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
pJ2k->ppTileData = (unsigned char **)Malloc(pCodingParams->nXTilesCount * pCodingParams->nYTilesCount * sizeof(unsigned char *));
|
||
if (!pJ2k->ppTileData)
|
||
{
|
||
for (int nIndex = 0; nIndex < pCodingParams->nXTilesCount * pCodingParams->nYTilesCount; nIndex++)
|
||
{
|
||
Free(pCodingParams->pTCP[nIndex].pTCCP);
|
||
}
|
||
Free(pImage->pComponents);
|
||
Free(pCodingParams->pTCP);
|
||
Free(pCodingParams->pTileIndex);
|
||
Free(pJ2k->pDefaultTCP->pTCCP);
|
||
Free(pJ2k->pDefaultTCP);
|
||
pJ2k->pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
||
return;
|
||
}
|
||
|
||
pJ2k->pTileLen = (int *)Malloc(pCodingParams->nXTilesCount * pCodingParams->nYTilesCount * sizeof(int));
|
||
if (!pJ2k->pTileLen)
|
||
{
|
||
for (int nIndex = 0; nIndex < pCodingParams->nXTilesCount * pCodingParams->nYTilesCount; nIndex++)
|
||
{
|
||
Free(pCodingParams->pTCP[nIndex].pTCCP);
|
||
}
|
||
Free(pImage->pComponents);
|
||
Free(pCodingParams->pTCP);
|
||
Free(pCodingParams->pTileIndex);
|
||
Free(pJ2k->pDefaultTCP->pTCCP);
|
||
Free(pJ2k->pDefaultTCP);
|
||
Free(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 = (std::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 = (std::min)(pPOC->nLYEpoc, pTCP->nLayersCount);
|
||
|
||
pStream->Write(pPOC->nREpoc, 1); // REpoc_i
|
||
pPOC->nREpoc = (std::min)(pPOC->nREpoc, pTCCP->nResolutionsCount);
|
||
|
||
pStream->Write(pPOC->nCEpoc, (nComponentsCount <= 256 ? 1 : 2)); // CEpoc_i
|
||
pPOC->nCEpoc = (std::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 = (std::min)(pStream->Read(2), (unsigned int)pTCP->nLayersCount); // LYEpoc_i
|
||
pPOC->nREpoc = (std::min)(pStream->Read(1), (unsigned int)pTCCP->nResolutionsCount); // REpoc_i
|
||
pPOC->nCEpoc = (std::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(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((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));
|
||
Free(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((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((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));
|
||
Free(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 = (std::min)(pJ2k->nSizeOfTile - pStream->Tell(), pStream->GetLeftSize() + 1);
|
||
|
||
if (nLen == pStream->GetLeftSize() + 1)
|
||
{
|
||
nTruncate = 1; // Обрезанный codestream
|
||
}
|
||
|
||
unsigned char *pData = (unsigned char *)Malloc((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;
|
||
Free(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);
|
||
Free(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];
|
||
Free(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];
|
||
Free( 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(sizeof(J2kCodestream));
|
||
if (pJ2k)
|
||
{
|
||
pJ2k->pCodecInfo = pCodecInfo;
|
||
pJ2k->pDefaultTCP = (TileCodingParams*)Malloc(sizeof(TileCodingParams));
|
||
if (!pJ2k->pDefaultTCP)
|
||
{
|
||
pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
||
Free(pJ2k);
|
||
return NULL;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
|
||
}
|
||
return pJ2k;
|
||
}
|
||
|
||
void J2k_DestroyDecompress(J2kCodestream *pJ2k)
|
||
{
|
||
if (!pJ2k)return;
|
||
|
||
Free(pJ2k->pTileLen);
|
||
Free(pJ2k->ppTileData);
|
||
|
||
if (pJ2k->pDefaultTCP != NULL)
|
||
{
|
||
TileCodingParams *pDefaultTCP = pJ2k->pDefaultTCP;
|
||
|
||
Free(pDefaultTCP->pPPTDataFirst);
|
||
Free(pJ2k->pDefaultTCP->pTCCP);
|
||
Free(pJ2k->pDefaultTCP);
|
||
}
|
||
if (pJ2k->pCodingParams != NULL)
|
||
{
|
||
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
||
if (pCodingParams->pTCP != NULL)
|
||
{
|
||
for (int nIndex = 0; nIndex < pCodingParams->nXTilesCount * pCodingParams->nYTilesCount; nIndex++)
|
||
{
|
||
Free(pCodingParams->pTCP[nIndex].pPPTDataFirst);
|
||
Free(pCodingParams->pTCP[nIndex].pTCCP);
|
||
}
|
||
Free(pCodingParams->pTCP);
|
||
}
|
||
Free(pCodingParams->pPPMDataFirst);
|
||
Free(pCodingParams->pTileIndex);
|
||
Free(pCodingParams->sComment);
|
||
Free(pCodingParams);
|
||
}
|
||
|
||
Free(pJ2k);
|
||
}
|
||
|
||
void J2k_SetupDecoder(J2kCodestream *pJ2k, DecoderParams *pParameters)
|
||
{
|
||
if (pJ2k && pParameters)
|
||
{
|
||
// Создаем и инициализируем структуру CodingParams
|
||
CodingParams *pCodingParams = (CodingParams*)Malloc(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(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];
|
||
Free(pTileInfo->pdThreshold);
|
||
Free(pTileInfo->pPacket);
|
||
}
|
||
Free(pImageInfo->pTile);
|
||
}
|
||
Free(pImageInfo);
|
||
}
|
||
if (pJ2k->pCodingParams != NULL)
|
||
{
|
||
CodingParams *pCodingParams = pJ2k->pCodingParams;
|
||
|
||
Free(pCodingParams->sComment);
|
||
Free(pCodingParams->pMatrix);
|
||
|
||
for (int nTileIndex = 0; nTileIndex < pCodingParams->nXTilesCount * pCodingParams->nYTilesCount; nTileIndex++)
|
||
{
|
||
Free(pCodingParams->pTCP[nTileIndex].pTCCP);
|
||
}
|
||
Free(pCodingParams->pTCP);
|
||
Free(pCodingParams);
|
||
}
|
||
|
||
Free(pJ2k);
|
||
}
|
||
|
||
void J2k_SetupEncoder(J2kCodestream *pJ2k, EncoderParams *pParameters, Image *pImage)
|
||
{
|
||
if (!pJ2k || !pParameters || !pImage)
|
||
{
|
||
return;
|
||
}
|
||
|
||
// Создаем и инициализируем структуру Coding parameters
|
||
CodingParams *pCodingParams = (CodingParams*)Malloc(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(array_size);
|
||
if (!pCodingParams->pMatrix)
|
||
{
|
||
Free(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(sizeof(ImageInfo));
|
||
if (!pJ2k->pImageInfo)
|
||
{
|
||
if (pCodingParams->pMatrix)
|
||
Free(pCodingParams->pMatrix);
|
||
Free(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(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(pCodingParams->nXTilesCount * pCodingParams->nYTilesCount * sizeof(TileCodingParams));
|
||
if (!pCodingParams->pTCP)
|
||
{
|
||
Free(pCodingParams->pMatrix);
|
||
Free(pJ2k->pImageInfo);
|
||
Free(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(pImage->nCsiz * sizeof(TileCompCodingParams));
|
||
if (!pTCP->pTCCP)
|
||
{
|
||
for (int nI = 0; nI < nTileIndex; nI++)
|
||
{
|
||
TileCodingParams *pDeleteTCP = &pCodingParams->pTCP[nI];
|
||
Free(pDeleteTCP->pTCCP);
|
||
}
|
||
Free(pCodingParams->pMatrix);
|
||
Free(pJ2k->pImageInfo);
|
||
|
||
Free(pCodingParams->pTCP);
|
||
Free(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(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;
|
||
}
|
||
}
|