Files
DocumentServer-v-9.2.0/core/DesktopEditor/raster/Jp2/J2k.h
Yajbir Singh f1b860b25c
Some checks failed
check / markdownlint (push) Has been cancelled
check / spellchecker (push) Has been cancelled
updated
2025-12-11 19:03:17 +05:30

2238 lines
75 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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