Files
core/DesktopEditor/raster/Jp2/J2kFile.cpp
Kulikova Svetlana 87631cdf58 add jpeg2000 support
2021-03-23 10:57:07 +03:00

886 lines
32 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.

#include "J2kFile.h"
#include "J2kIncludes.h"
#include "Utils.h"
namespace Jpeg2000
{
//extern Image* Jp2ToImage(const std::wstring& wsFileName, DecoderParams* pDecoderParams);
//extern Image* J2kToImage(const std::wstring& wsFileName, DecoderParams* pDecoderParams);
//extern Image* JptToImage(const std::wstring& wsFileName, DecoderParams* pDecoderParams);
//extern Image* Mj2ToImage(const std::wstring& wsFileName, DecoderParams* pDecoderParams);
//extern bool ImageToJ2k(Image *pImage, const std::wstring& wsFilePath, EncoderParams* pEncoderParams);
//extern bool ImageToJ2p(Image *pImage, const std::wstring& wsFilePath, EncoderParams* pEncoderParams);
//extern void Image_Destroy(Image *pImage);
//extern Image* Image_Create(int nComponentsCount, ImageComponentParams *pCompParams, ColorSpace eColorSpace);
void* Malloc(size_t nSize)
{
void *pMemBlock = malloc(nSize);
if (!pMemBlock)
{
// TODO: print error "Memory !!\n")
}
else
{
memset(pMemBlock, 0x00, nSize);
}
return pMemBlock;
}
int check_j2000_type(FILE* pFile)
{
if (!pFile)
return 0;
BYTE *pBuffer = new BYTE[1024];
if (!pBuffer)
return 0;
size_t nBytesRead = fread(pBuffer, 1, 1024, pFile);
int type =0;
if ((32 <= nBytesRead) && (0x00 == pBuffer[0] && 0x00 == pBuffer[1] && 0x00 == pBuffer[2] && 0x0c == pBuffer[3]
&& 0x6a == pBuffer[4] && 0x50 == pBuffer[5] && 0x20 == pBuffer[6] && 0x20 == pBuffer[7]
&& 0x0d == pBuffer[8] && 0x0a == pBuffer[9] && 0x87 == pBuffer[10] && 0x0a == pBuffer[11]
&& 0x00 == pBuffer[12] && 0x00 == pBuffer[13] && 0x00 == pBuffer[14] /*&& (0x14 == pBuffer[15] || 0x18 == pBuffer[15] )*/
&& 0x66 == pBuffer[16] && 0x74 == pBuffer[17] && 0x79 == pBuffer[18] && 0x70 == pBuffer[19]
&& 0x6a == pBuffer[20] && 0x70 == pBuffer[21] && 0x32 == pBuffer[22] && 0x20 == pBuffer[23]
&& 0x00 == pBuffer[24] && 0x00 == pBuffer[25] && 0x00 == pBuffer[26] && 0x00 == pBuffer[27]
/*&& 0x6a == pBuffer[28] && 0x70 == pBuffer[29] && 0x32 == pBuffer[30] && 0x20 == pBuffer[31]*/))
{
type = 1;
}
if ((4 <= nBytesRead) && (0xff == pBuffer[0] && 0x4f == pBuffer[1] && 0xff == pBuffer[2] && 0x51 == pBuffer[3]))
{
type = 2;
}
if ((32 <= nBytesRead) && (0x00 == pBuffer[0] && 0x00 == pBuffer[1] && 0x00 == pBuffer[2] && 0x0c == pBuffer[3]
&& 0x6a == pBuffer[4] && 0x50 == pBuffer[5] && 0x20 == pBuffer[6] && 0x20 == pBuffer[7]
&& 0x0d == pBuffer[8] && 0x0a == pBuffer[9] && 0x87 == pBuffer[10] && 0x0a == pBuffer[11]
&& 0x00 == pBuffer[12] && 0x00 == pBuffer[13] && 0x00 == pBuffer[14] && 0x18 == pBuffer[15]
&& 0x66 == pBuffer[16] && 0x74 == pBuffer[17] && 0x79 == pBuffer[18] && 0x70 == pBuffer[19]
&& 0x6d == pBuffer[20] && 0x6a == pBuffer[21] && 0x70 == pBuffer[22] && 0x32 == pBuffer[23]
&& 0x00 == pBuffer[24] && 0x00 == pBuffer[25] && 0x00 == pBuffer[26] && 0x00 == pBuffer[27]
&& 0x6d == pBuffer[28] && 0x6a == pBuffer[29] && 0x70 == pBuffer[30] && 0x32 == pBuffer[31]))
{
type = 3;
}
delete[] pBuffer;
fseek(pFile, 0, SEEK_SET);
return type;
}
int check_j2000_type(BYTE* pBuffer, int nSize)
{
if (!pBuffer)
return 0;
int type = 0;
if ((32 <= nSize) && (0x00 == pBuffer[0] && 0x00 == pBuffer[1] && 0x00 == pBuffer[2] && 0x0c == pBuffer[3]
&& 0x6a == pBuffer[4] && 0x50 == pBuffer[5] && 0x20 == pBuffer[6] && 0x20 == pBuffer[7]
&& 0x0d == pBuffer[8] && 0x0a == pBuffer[9] && 0x87 == pBuffer[10] && 0x0a == pBuffer[11]
&& 0x00 == pBuffer[12] && 0x00 == pBuffer[13] && 0x00 == pBuffer[14] /*&& (0x14 == pBuffer[15] || 0x18 == pBuffer[15] )*/
&& 0x66 == pBuffer[16] && 0x74 == pBuffer[17] && 0x79 == pBuffer[18] && 0x70 == pBuffer[19]
&& 0x6a == pBuffer[20] && 0x70 == pBuffer[21] && 0x32 == pBuffer[22] && 0x20 == pBuffer[23]
&& 0x00 == pBuffer[24] && 0x00 == pBuffer[25] && 0x00 == pBuffer[26] && 0x00 == pBuffer[27]
/*&& 0x6a == pBuffer[28] && 0x70 == pBuffer[29] && 0x32 == pBuffer[30] && 0x20 == pBuffer[31]*/))
{
type = 1;
}
if ((4 <= nSize) && (0xff == pBuffer[0] && 0x4f == pBuffer[1] && 0xff == pBuffer[2] && 0x51 == pBuffer[3]))
{
type = 2;
}
if ((32 <= nSize) && (0x00 == pBuffer[0] && 0x00 == pBuffer[1] && 0x00 == pBuffer[2] && 0x0c == pBuffer[3]
&& 0x6a == pBuffer[4] && 0x50 == pBuffer[5] && 0x20 == pBuffer[6] && 0x20 == pBuffer[7]
&& 0x0d == pBuffer[8] && 0x0a == pBuffer[9] && 0x87 == pBuffer[10] && 0x0a == pBuffer[11]
&& 0x00 == pBuffer[12] && 0x00 == pBuffer[13] && 0x00 == pBuffer[14] && 0x18 == pBuffer[15]
&& 0x66 == pBuffer[16] && 0x74 == pBuffer[17] && 0x79 == pBuffer[18] && 0x70 == pBuffer[19]
&& 0x6d == pBuffer[20] && 0x6a == pBuffer[21] && 0x70 == pBuffer[22] && 0x32 == pBuffer[23]
&& 0x00 == pBuffer[24] && 0x00 == pBuffer[25] && 0x00 == pBuffer[26] && 0x00 == pBuffer[27]
&& 0x6d == pBuffer[28] && 0x6a == pBuffer[29] && 0x70 == pBuffer[30] && 0x32 == pBuffer[31]))
{
type = 3;
}
return type;
}
// CJ2kFile
bool CJ2kFile::Open(CBgraFrame* pFrame, const std::wstring& wsSrcPath, const std::wstring& wsXmlOptions)
{
Image *pImage = NULL;
DecoderParams oParameters;
// Установим стандартные значения параметров
ApplyDecoderOptions(&oParameters, wsXmlOptions);
///////////////////////////////////////////////////////////////////////////////////
NSFile::CFileBinary oFile;
if (!oFile.OpenFile(wsSrcPath))
return false;
DWORD nFileSize = oFile.GetFileSize();
int type = check_j2000_type(oFile.GetFileNative());
oFile.CloseFile();
bool bOpenResult = false;
if (!bOpenResult && type == 1)
bOpenResult = (NULL != (pImage = Jp2ToImage(wsSrcPath, &oParameters)));
if (!bOpenResult && type == 2)
bOpenResult = (NULL != (pImage = J2kToImage(wsSrcPath, &oParameters)));
if (!bOpenResult && type == 3)
bOpenResult = (NULL != (pImage = Mj2ToImage(wsSrcPath, &oParameters)));
if (!bOpenResult && type == 4)
bOpenResult = (NULL != (pImage = JptToImage(wsSrcPath, &oParameters)));
if (!bOpenResult)
{
Image_Destroy(pImage);
return false;
}
int nWidth = pImage->pComponents[0].nWidth;
int nHeight = pImage->pComponents[0].nHeight;
int nBufferSize = 4 /*pImage->nCsiz*/ * nWidth * nHeight;
if (nBufferSize < 1)
{
Image_Destroy(pImage);
return false;
}
pFrame->put_Width(nWidth);
pFrame->put_Height(nHeight);
pFrame->put_Stride(4 * nWidth);
BYTE* pData = new BYTE[nBufferSize];
if (!pData)
{
Image_Destroy(pImage);
return false;
}
pFrame->put_Data(pData);
unsigned char* pBufferPtr = (unsigned char*)pData;
long nCreatedBufferSize = nBufferSize;
// Пишем данные в pBufferPtr
if (pImage->nCsiz == 3 && pImage->pComponents[0].nXRsiz == pImage->pComponents[1].nXRsiz && pImage->pComponents[1].nXRsiz == pImage->pComponents[2].nXRsiz
&& pImage->pComponents[0].nYRsiz == pImage->pComponents[1].nYRsiz && pImage->pComponents[1].nYRsiz == pImage->pComponents[2].nYRsiz
&& pImage->pComponents[0].nPrecision == pImage->pComponents[1].nPrecision && pImage->pComponents[1].nPrecision == pImage->pComponents[2].nPrecision)
{
int nResW = CeilDivPow2(pImage->pComponents[0].nWidth, pImage->pComponents[0].nFactorDiv2);
int nResH = CeilDivPow2(pImage->pComponents[0].nHeight, pImage->pComponents[0].nFactorDiv2);
for (int nIndex = 0; nIndex < nResW * nResH; nIndex++)
{
unsigned char nR = pImage->pComponents[0].pData[nWidth * nResH - ((nIndex) / (nResW)+1) * nWidth + (nIndex) % (nResW)];
unsigned char nG = pImage->pComponents[1].pData[nWidth * nResH - ((nIndex) / (nResW)+1) * nWidth + (nIndex) % (nResW)];
unsigned char nB = pImage->pComponents[2].pData[nWidth * nResH - ((nIndex) / (nResW)+1) * nWidth + (nIndex) % (nResW)];
pBufferPtr[0] = nB;
pBufferPtr[1] = nG;
pBufferPtr[2] = nR;
pBufferPtr[3] = 255;
pBufferPtr += 4;
}
}
else if (pImage->nCsiz >= 4 && pImage->pComponents[0].nXRsiz == pImage->pComponents[1].nXRsiz && pImage->pComponents[1].nXRsiz == pImage->pComponents[2].nXRsiz && pImage->pComponents[2].nXRsiz == pImage->pComponents[3].nXRsiz
&& pImage->pComponents[0].nYRsiz == pImage->pComponents[1].nYRsiz && pImage->pComponents[1].nYRsiz == pImage->pComponents[2].nYRsiz && pImage->pComponents[2].nYRsiz == pImage->pComponents[3].nYRsiz
&& pImage->pComponents[0].nPrecision == pImage->pComponents[1].nPrecision && pImage->pComponents[1].nPrecision == pImage->pComponents[2].nPrecision && pImage->pComponents[2].nPrecision == pImage->pComponents[3].nPrecision)
{
int nResW = CeilDivPow2(pImage->pComponents[0].nWidth, pImage->pComponents[0].nFactorDiv2);
int nResH = CeilDivPow2(pImage->pComponents[0].nHeight, pImage->pComponents[0].nFactorDiv2);
for (int nIndex = 0; nIndex < nResW * nResH; nIndex++)
{
unsigned char nR = pImage->pComponents[0].pData[nWidth * nResH - ((nIndex) / (nResW)+1) * nWidth + (nIndex) % (nResW)];
unsigned char nG = pImage->pComponents[1].pData[nWidth * nResH - ((nIndex) / (nResW)+1) * nWidth + (nIndex) % (nResW)];
unsigned char nB = pImage->pComponents[2].pData[nWidth * nResH - ((nIndex) / (nResW)+1) * nWidth + (nIndex) % (nResW)];
unsigned char nA = pImage->pComponents[3].pData[nWidth * nResH - ((nIndex) / (nResW)+1) * nWidth + (nIndex) % (nResW)];
pBufferPtr[0] = nB;
pBufferPtr[1] = nG;
pBufferPtr[2] = nR;
pBufferPtr[3] = nA;
pBufferPtr += 4;
}
}
else // Grayscale
{
int nResW = CeilDivPow2(pImage->pComponents[0].nWidth, pImage->pComponents[0].nFactorDiv2);
int nResH = CeilDivPow2(pImage->pComponents[0].nHeight, pImage->pComponents[0].nFactorDiv2);
for (int nIndex = 0; nIndex < nResW * nResH; nIndex++)
{
unsigned char nG = pImage->pComponents[0].pData[nWidth * nResH - ((nIndex) / (nResW)+1) * nWidth + (nIndex) % (nResW)];
pBufferPtr[0] = nG;
pBufferPtr[1] = nG;
pBufferPtr[2] = nG;
pBufferPtr[3] = 255;
pBufferPtr += 4;
}
}
Image_Destroy(pImage);
return true;
}
bool CJ2kFile::Open(CBgraFrame* pFrame, BYTE* pBuffer, int nSize, const std::wstring& wsXmlOptions)
{
Image *pImage = NULL;
DecoderParams oParameters;
// Установим стандартные значения параметров
ApplyDecoderOptions(&oParameters, wsXmlOptions);
///////////////////////////////////////////////////////////////////////////////////
int type = check_j2000_type(pBuffer, nSize);
bool bOpenResult = false;
if (!bOpenResult && type == 1)
bOpenResult = (NULL != (pImage = Jp2ToImage(pBuffer, nSize, &oParameters)));
if (!bOpenResult && type == 2)
bOpenResult = (NULL != (pImage = J2kToImage(pBuffer, nSize, &oParameters)));
if (!bOpenResult && type == 3)
bOpenResult = (NULL != (pImage = Mj2ToImage(pBuffer, nSize, &oParameters)));
if (!bOpenResult && type == 4)
bOpenResult = (NULL != (pImage = JptToImage(pBuffer, nSize, &oParameters)));
if (!bOpenResult)
{
Image_Destroy(pImage);
return false;
}
int nWidth = pImage->pComponents[0].nWidth;
int nHeight = pImage->pComponents[0].nHeight;
int nBufferSize = 4 /*pImage->nCsiz*/ * nWidth * nHeight;
if (nBufferSize < 1)
{
Image_Destroy(pImage);
return false;
}
pFrame->put_Width(nWidth);
pFrame->put_Height(nHeight);
pFrame->put_Stride(4 * nWidth);
BYTE* pData = new BYTE[nBufferSize];
if (!pData)
{
Image_Destroy(pImage);
return false;
}
pFrame->put_Data(pData);
unsigned char* pBufferPtr = (unsigned char*)pData;
long nCreatedBufferSize = nBufferSize;
// Пишем данные в pBufferPtr
if (pImage->nCsiz == 3 && pImage->pComponents[0].nXRsiz == pImage->pComponents[1].nXRsiz && pImage->pComponents[1].nXRsiz == pImage->pComponents[2].nXRsiz
&& pImage->pComponents[0].nYRsiz == pImage->pComponents[1].nYRsiz && pImage->pComponents[1].nYRsiz == pImage->pComponents[2].nYRsiz
&& pImage->pComponents[0].nPrecision == pImage->pComponents[1].nPrecision && pImage->pComponents[1].nPrecision == pImage->pComponents[2].nPrecision)
{
int nResW = CeilDivPow2(pImage->pComponents[0].nWidth, pImage->pComponents[0].nFactorDiv2);
int nResH = CeilDivPow2(pImage->pComponents[0].nHeight, pImage->pComponents[0].nFactorDiv2);
for (int nIndex = 0; nIndex < nResW * nResH; nIndex++)
{
unsigned char nR = pImage->pComponents[0].pData[nWidth * nResH - ((nIndex) / (nResW)+1) * nWidth + (nIndex) % (nResW)];
unsigned char nG = pImage->pComponents[1].pData[nWidth * nResH - ((nIndex) / (nResW)+1) * nWidth + (nIndex) % (nResW)];
unsigned char nB = pImage->pComponents[2].pData[nWidth * nResH - ((nIndex) / (nResW)+1) * nWidth + (nIndex) % (nResW)];
pBufferPtr[0] = nB;
pBufferPtr[1] = nG;
pBufferPtr[2] = nR;
pBufferPtr[3] = 255;
pBufferPtr += 4;
}
}
else if (pImage->nCsiz >= 4 && pImage->pComponents[0].nXRsiz == pImage->pComponents[1].nXRsiz && pImage->pComponents[1].nXRsiz == pImage->pComponents[2].nXRsiz && pImage->pComponents[2].nXRsiz == pImage->pComponents[3].nXRsiz
&& pImage->pComponents[0].nYRsiz == pImage->pComponents[1].nYRsiz && pImage->pComponents[1].nYRsiz == pImage->pComponents[2].nYRsiz && pImage->pComponents[2].nYRsiz == pImage->pComponents[3].nYRsiz
&& pImage->pComponents[0].nPrecision == pImage->pComponents[1].nPrecision && pImage->pComponents[1].nPrecision == pImage->pComponents[2].nPrecision && pImage->pComponents[2].nPrecision == pImage->pComponents[3].nPrecision)
{
int nResW = CeilDivPow2(pImage->pComponents[0].nWidth, pImage->pComponents[0].nFactorDiv2);
int nResH = CeilDivPow2(pImage->pComponents[0].nHeight, pImage->pComponents[0].nFactorDiv2);
for (int nIndex = 0; nIndex < nResW * nResH; nIndex++)
{
unsigned char nR = pImage->pComponents[0].pData[nWidth * nResH - ((nIndex) / (nResW)+1) * nWidth + (nIndex) % (nResW)];
unsigned char nG = pImage->pComponents[1].pData[nWidth * nResH - ((nIndex) / (nResW)+1) * nWidth + (nIndex) % (nResW)];
unsigned char nB = pImage->pComponents[2].pData[nWidth * nResH - ((nIndex) / (nResW)+1) * nWidth + (nIndex) % (nResW)];
unsigned char nA = pImage->pComponents[3].pData[nWidth * nResH - ((nIndex) / (nResW)+1) * nWidth + (nIndex) % (nResW)];
pBufferPtr[0] = nB;
pBufferPtr[1] = nG;
pBufferPtr[2] = nR;
pBufferPtr[3] = nA;
pBufferPtr += 4;
}
}
else // Grayscale
{
int nResW = CeilDivPow2(pImage->pComponents[0].nWidth, pImage->pComponents[0].nFactorDiv2);
int nResH = CeilDivPow2(pImage->pComponents[0].nHeight, pImage->pComponents[0].nFactorDiv2);
for (int nIndex = 0; nIndex < nResW * nResH; nIndex++)
{
unsigned char nG = pImage->pComponents[0].pData[nWidth * nResH - ((nIndex) / (nResW)+1) * nWidth + (nIndex) % (nResW)];
pBufferPtr[0] = nG;
pBufferPtr[1] = nG;
pBufferPtr[2] = nG;
pBufferPtr[3] = 255;
pBufferPtr += 4;
}
}
Image_Destroy(pImage);
return true;
}
bool CJ2kFile::Open(BYTE** ppData, int& nComponentsCount, int& nWidth, int& nHeight, const std::wstring& wsSrcPath, const std::wstring& wsXmlOptions)
{
Image *pImage = NULL;
DecoderParams oParameters;
// Установим стандартные значения параметров
ApplyDecoderOptions(&oParameters, wsXmlOptions);
///////////////////////////////////////////////////////////////////////////////////
NSFile::CFileBinary oFile;
if (!oFile.OpenFile(wsSrcPath))
return false;
DWORD nFileSize = oFile.GetFileSize();
int type = check_j2000_type(oFile.GetFileNative());
oFile.CloseFile();
bool bOpenResult = false;
if (!bOpenResult && type == 1)
bOpenResult = (NULL != (pImage = Jp2ToImage(wsSrcPath, &oParameters)));
if (!bOpenResult && type == 2)
bOpenResult = (NULL != (pImage = J2kToImage(wsSrcPath, &oParameters)));
if (!bOpenResult && type == 3)
bOpenResult = (NULL != (pImage = Mj2ToImage(wsSrcPath, &oParameters)));
if (!bOpenResult && type == 4)
bOpenResult = (NULL != (pImage = JptToImage(wsSrcPath, &oParameters)));
if (!bOpenResult)
{
Image_Destroy(pImage);
return false;
}
nWidth = pImage->pComponents[0].nWidth;
nHeight = pImage->pComponents[0].nHeight;
int nBufferSize = pImage->nCsiz * nWidth * nHeight;
if (nBufferSize < 1 || pImage->nCsiz <= 0)
{
Image_Destroy(pImage);
return false;
}
*ppData = new BYTE[nBufferSize];
if (!(*ppData))
{
Image_Destroy(pImage);
return false;
}
unsigned char* pBufferPtr = (unsigned char*)(*ppData);
long nCreatedBufferSize = nBufferSize;
nComponentsCount = pImage->nCsiz;
// Пишем данные в pBufferPtr
for (int nComponent = 1; nComponent < nComponentsCount; nComponent++)
{
if (pImage->pComponents[0].nXRsiz != pImage->pComponents[nComponent].nXRsiz
|| pImage->pComponents[0].nYRsiz != pImage->pComponents[nComponent].nYRsiz
|| pImage->pComponents[0].nPrecision != pImage->pComponents[nComponent].nPrecision)
{
delete[](*ppData);
Image_Destroy(pImage);
return false;
}
}
int nResW = CeilDivPow2(pImage->pComponents[0].nWidth, pImage->pComponents[0].nFactorDiv2);
int nResH = CeilDivPow2(pImage->pComponents[0].nHeight, pImage->pComponents[0].nFactorDiv2);
for (int nIndex = 0; nIndex < nResW * nResH; nIndex++)
{
for (int nComponent = 0; nComponent < nComponentsCount; nComponent++)
{
pBufferPtr[nComponent] = pImage->pComponents[nComponent].pData[nWidth * nResH - ((nIndex) / (nResW)+1) * nWidth + (nIndex) % (nResW)];
}
pBufferPtr += nComponentsCount;
}
Image_Destroy(pImage);
return true;
}
bool CJ2kFile::Save(CBgraFrame* pFrame, const std::wstring& wsDstPath, const std::wstring& wsXmlOptions)
{
// TODO: Запись не реализована, надо доделать.
return false;
if (!pFrame)
return false;
LONG lWidth = pFrame->get_Width();
LONG lHeight = pFrame->get_Height();
BYTE* pSourceBuffer = pFrame->get_Data();
LONG lBufferSize = 4 * lWidth * lHeight;
// Далее обрабатываем Xml с параметрами компрессии
EncoderParams oParameters;
int nFormat = ApplyEncoderOptions(&oParameters, wsXmlOptions);
// TODO: Добавить возможность записи альфа-канала
ImageComponentParams aComponentParams[3]; // Пока пусть будет максимально три компоненты (RGB)
Image *pImage = NULL;
int nComponentsCount = oParameters.nComponentsCount;
memset(&aComponentParams[0], 0, sizeof(ImageComponentParams));
for (int nIndex = 0; nIndex < nComponentsCount; nIndex++)
{
aComponentParams[nIndex].nPrecision = 8;
aComponentParams[nIndex].nBPP = 8;
aComponentParams[nIndex].nSigned = 0;
aComponentParams[nIndex].nXRsiz = oParameters.nSubSamplingDx;
aComponentParams[nIndex].nYRsiz = oParameters.nSubSamplingDy;
aComponentParams[nIndex].nWidth = (int)lWidth;
aComponentParams[nIndex].nHeight = (int)lHeight;
}
// Создаем структуру Image
pImage = Image_Create(nComponentsCount, &aComponentParams[0], csRGB);
if (!pImage)
return false;
pImage->nXOsiz = oParameters.nImageOffsetX0;
pImage->nYOsiz = oParameters.nImageOffsetY0;
pImage->nXsiz = (!pImage->nXOsiz) ? (lWidth - 1) * oParameters.nSubSamplingDx + 1 : pImage->nXOsiz + (lWidth - 1) * oParameters.nSubSamplingDy + 1;
pImage->nYsiz = (!pImage->nYOsiz) ? (lHeight - 1) * oParameters.nSubSamplingDy + 1 : pImage->nYOsiz + (lHeight - 1) * oParameters.nSubSamplingDy + 1;
if (3 == nComponentsCount)
{
int nIndex = 0;
for (int nY = 0; nY < (int)lHeight; nY++)
{
for (int nX = 0; nX < (int)lWidth; nX++, pSourceBuffer += 4)
{
pImage->pComponents[0].pData[nIndex] = pSourceBuffer[2];
pImage->pComponents[1].pData[nIndex] = pSourceBuffer[1];
pImage->pComponents[2].pData[nIndex] = pSourceBuffer[0];
nIndex++;
}
}
}
else if (1 == nComponentsCount)
{
int nIndex = 0;
for (int nY = 0; nY < (int)lHeight; nY++)
{
for (int nX = 0; nX < (int)lWidth; nX++, pSourceBuffer += 4)
{
pImage->pComponents[0].pData[nIndex] = pSourceBuffer[0];
nIndex++;
}
}
}
else
{
Image_Destroy(pImage);
return false;
}
bool bRes = false;
switch (nFormat)
{
case 0: bRes = ImageToJ2k(pImage, wsDstPath, &oParameters); break;
case 1: bRes = ImageToJ2p(pImage, wsDstPath, &oParameters); break;
case -1:
default: bRes = false;
}
Image_Destroy(pImage);
return bRes;
}
void CJ2kFile::ApplyDecoderOptions(void *pParametersV, const std::wstring& sXml)
{
DecoderParams* pParameters = (DecoderParams*)pParametersV;
memset(pParameters, 0, sizeof(DecoderParams));
pParameters->eLimitDecoding = declimNoLimitation;
pParameters->nReduce = 0;
pParameters->nLayer = 0;
// TODO: Сделать чтение параметров декодирования
//if (sXml.GetLength() > 0)
//{
// XmlUtils::CXmlNode oMainNode;
// oMainNode.FromXmlString(sXml);
// if (-1 != oMainNode.GetName().Find(_T("Jpeg2000-Options")))
// {
// XmlUtils::CXmlNode oOpenNode;
// if (oMainNode.GetNode(_T("OpenOptions"), oOpenNode))
// {
// XmlUtils::CXmlNode oCurNode;
// CString sValue;
// // ReduceFactor
// if (oOpenNode.GetNode(_T("ConvertToRGBA"), oCurNode))
// {
// sValue = oCurNode.GetAttribute(_T("value"), _T("0"));
// pParameters->bConvertToRGBA = (_wtoi(sValue.GetBuffer()) ? true : false);
// }
// // ReduceFactor
// if (oOpenNode.GetNode(_T("ReduceFactor"), oCurNode))
// {
// sValue = oCurNode.GetAttribute(_T("value"), _T("0"));
// pParameters->nReduce = _wtoi(sValue.GetBuffer());
// }
// // LayersCount
// if (oOpenNode.GetNode(_T("LayersCount"), oCurNode))
// {
// sValue = oCurNode.GetAttribute(_T("value"), _T("0"));
// pParameters->nLayer = _wtoi(sValue.GetBuffer());
// }
// }
// }
//}
}
long CJ2kFile::ApplyEncoderOptions(void *pParametersV, const std::wstring& sXml)
{
EncoderParams* pParameters = (EncoderParams*)pParameters;
int nFormat = 0; // J2k
// Сначала выставляем стандартные значения параметров
memset(pParameters, 0, sizeof(EncoderParams));
pParameters->nComponentsCount = 3;
pParameters->nResolutionsCount = 6;
pParameters->nCodeBlockHeightInit = 64;
pParameters->nCodeBlockWidthInit = 64;
pParameters->eProgOrder = poLRCP;
pParameters->nROIComponentIndex = -1; // Нет ROI
pParameters->nSubSamplingDx = 1;
pParameters->nSubSamplingDy = 1;
pParameters->bTileSizeOn = false;
pParameters->sComment = (char*)"Manufactured by Online Media Technologies Ltd.";
// TODO: Сделать чтение параметров кодирования
//if (sXml.GetLength() > 0)
//{
// XmlUtils::CXmlNode oMainNode;
// oMainNode.FromXmlString(sXml);
// if (-1 != oMainNode.GetName().Find(_T("Jpeg2000-Options")))
// {
// XmlUtils::CXmlNode oSaveNode;
// if (oMainNode.GetNode(_T("SaveOptions"), oSaveNode))
// {
// XmlUtils::CXmlNode oCurNode;
// CString sValue;
// // ComponentsCount
// if (oSaveNode.GetNode(_T("ComponentsCount"), oCurNode))
// {
// pParameters->nComponentsCount = XmlUtils::GetInteger(oCurNode.GetAttribute(_T("value"), _T("3")));
// }
// // Format
// if (oSaveNode.GetNode(_T("Format"), oCurNode))
// {
// sValue = oCurNode.GetAttribute(_T("value"), _T("0"));
// nFormat = _wtoi(sValue.GetBuffer());
// }
// // Tile
// if (oSaveNode.GetNode(_T("Tile"), oCurNode))
// {
// sValue = oCurNode.GetAttribute(_T("width"), _T("32"));
// pParameters->nXTsiz = max(32, _wtoi(sValue.GetBuffer()));
// sValue = oCurNode.GetAttribute(_T("height"), _T("32"));
// pParameters->nYTsiz = max(32, _wtoi(sValue.GetBuffer()));
// pParameters->bTileSizeOn = true;
// sValue = oCurNode.GetAttribute(_T("offsetx"), _T("0"));
// pParameters->nXTOsiz = _wtoi(sValue.GetBuffer());
// sValue = oCurNode.GetAttribute(_T("offsety"), _T("0"));
// pParameters->nYTOsiz = _wtoi(sValue.GetBuffer());
// }
// // Resolution
// if (oSaveNode.GetNode(_T("Resolution"), oCurNode))
// {
// sValue = oCurNode.GetAttribute(_T("levelscount"), _T("6"));
// pParameters->nResolutionsCount = max(1, min(J2K_MAXRLVLS, _wtoi(sValue.GetBuffer())));
// }
// // PrecinctDimension
// if (oSaveNode.GetNode(_T("PrecinctDimension"), oCurNode))
// {
// sValue = oCurNode.GetText();
// wchar_t *wsTemp = sValue.GetBuffer();
// char nSeparateChar = 0;
// int nPrecinctsCount = 0;
// do
// {
// nSeparateChar = 0;
// swscanf(wsTemp, _T("[%d,%d]%c"), &pParameters->anPrecinctWidthInit[nPrecinctsCount], &pParameters->anPrecinctHeightInit[nPrecinctsCount], &nSeparateChar);
// pParameters->nCodingStyle |= 0x01;
// nPrecinctsCount++;
// if (J2K_MAXRLVLS == nPrecinctsCount)
// break;
// wsTemp = wcspbrk(wsTemp, _T("]")) + 2;
// } while (',' == nSeparateChar);
// pParameters->nPrecinctCount = nPrecinctsCount;
// }
// // CodeBlockDimension
// if (oSaveNode.GetNode(_T("CodeBlockDimension"), oCurNode))
// {
// sValue = oCurNode.GetAttribute(_T("width"), _T("64"));
// pParameters->nCodeBlockWidthInit = max(4, min(4096, _wtoi(sValue.GetBuffer())));
// sValue = oCurNode.GetAttribute(_T("height"), _T("64"));
// pParameters->nCodeBlockHeightInit = max(4, min(4096, _wtoi(sValue.GetBuffer())));
// }
// // ProgressionOrder
// if (oSaveNode.GetNode(_T("ProgressionOrder"), oCurNode))
// {
// sValue = oCurNode.GetAttribute(_T("value"), _T("0"));
// int nProgOrder = max(0, min(4, _wtoi(sValue.GetBuffer())));
// switch (nProgOrder)
// {
// case 0: pParameters->eProgOrder = poLRCP; break;
// case 1: pParameters->eProgOrder = poRLCP; break;
// case 2: pParameters->eProgOrder = poRPCL; break;
// case 3: pParameters->eProgOrder = poPCRL; break;
// case 4: pParameters->eProgOrder = poCPRL; break;
// }
// }
// // Subsampling
// if (oSaveNode.GetNode(_T("Subsampling"), oCurNode))
// {
// sValue = oCurNode.GetAttribute(_T("dx"), _T("1"));
// pParameters->nSubSamplingDx = max(1, min(J2K_MAXSSFTR, _wtoi(sValue.GetBuffer())));
// sValue = oCurNode.GetAttribute(_T("dy"), _T("1"));
// pParameters->nSubSamplingDy = max(1, min(J2K_MAXSSFTR, _wtoi(sValue.GetBuffer())));
// }
// // SOPmarker
// if (oSaveNode.GetNode(_T("SOPmarker"), oCurNode))
// {
// // Пока отключим, потом надо будет добавить - для этого нужно выделять память для стрктуры ImageInfo
// //pParameters->nCodingStyle |= 0x02;
// }
// // EPHmarker
// if (oSaveNode.GetNode(_T("EPHmarker"), oCurNode))
// {
// pParameters->nCodingStyle |= 0x04;
// }
// // ROI
// if (oSaveNode.GetNode(_T("ROI"), oCurNode))
// {
// sValue = oCurNode.GetAttribute(_T("componentindex"), _T("-1"));
// pParameters->nROIComponentIndex = max(-1, _wtoi(sValue.GetBuffer()));
// sValue = oCurNode.GetAttribute(_T("shift"), _T("0"));
// pParameters->nROIShift = max(0, min(37, _wtoi(sValue.GetBuffer())));
// }
// // Comment
// if (oSaveNode.GetNode(_T("Comment"), oCurNode))
// {
// sValue = oCurNode.GetAttribute(_T("value"));
// // TO DO: Неправильное копирование строки
// USES_CONVERSION;
// pParameters->sComment = W2A(sValue.GetBuffer());
// }
// // Compression
// if (oSaveNode.GetNode(_T("Compression"), oCurNode))
// {
// sValue = oCurNode.GetAttribute(_T("lossless"), _T("1"));
// pParameters->nTransformId = _wtoi(sValue.GetBuffer()) ? 0 : 1;
// }
// // Rate-Disto
// if (oSaveNode.GetNode(_T("Rate-Disto"), oCurNode))
// {
// sValue = oCurNode.GetText();
// wchar_t *wsTemp = sValue.GetBuffer();
// while (swscanf(wsTemp, _T("%f"), &pParameters->afRates[pParameters->nLayersCount]) == 1)
// {
// pParameters->nLayersCount++;
// while (*wsTemp && *wsTemp != _T(','))
// {
// wsTemp++;
// }
// if (!*wsTemp)
// break;
// wsTemp++;
// }
// pParameters->nDistoAlloc = 1;
// }
// // Fixed-Quality
// if (oSaveNode.GetNode(_T("Fixed-Quality"), oCurNode))
// {
// sValue = oCurNode.GetText();
// wchar_t *wsTemp = sValue.GetBuffer();
// while (swscanf(wsTemp, _T("%f"), &pParameters->afDistoratio[pParameters->nLayersCount]) == 1)
// {
// pParameters->nLayersCount++;
// while (*wsTemp && *wsTemp != ',')
// {
// wsTemp++;
// }
// if (!*wsTemp)
// break;
// wsTemp++;
// }
// pParameters->nFixedQuality = 1;
// }
// // Fixed-Layer
// if (oSaveNode.GetNode(_T("Fixed-Layer"), oCurNode))
// {
// sValue = oCurNode.GetAttribute(_T("layerscount"), _T("1"));
// int nLayersCount = max(1, _wtoi(sValue.GetBuffer()));
// pParameters->nLayersCount = nLayersCount;
// int nResolutionsCount = pParameters->nResolutionsCount;
// int nMatrixWidth = nResolutionsCount * 3;
// pParameters->pMatrix = (int*)Malloc(0, nLayersCount * nMatrixWidth * sizeof(int));
// sValue = oCurNode.GetText();
// wchar_t *wsTemp = sValue.GetBuffer();
// for (int nLayerIndex = 0; nLayerIndex < nLayersCount; nLayerIndex++)
// {
// int *pRow = &pParameters->pMatrix[nLayerIndex * nMatrixWidth];
// int *pCol = pRow;
// pParameters->afRates[nLayerIndex] = 1;
// swscanf(wsTemp, _T("%d,"), &pCol[0]);
// wsTemp += 2;
// if (pCol[0] > 9)
// wsTemp++;
// pCol[1] = 0;
// pCol[2] = 0;
// for (int nResolutionIndex = 1; nResolutionIndex < nResolutionsCount; nResolutionIndex++)
// {
// pCol += 3;
// swscanf(wsTemp, _T("%d,%d,%d"), &pCol[0], &pCol[1], &pCol[2]);
// wsTemp += 6;
// if (pCol[0] > 9)
// wsTemp++;
// if (pCol[1] > 9)
// wsTemp++;
// if (pCol[2] > 9)
// wsTemp++;
// }
// if (nLayerIndex < nLayersCount - 1)
// wsTemp++;
// }
// pParameters->nFixedAlloc = 1;
// }
// }
// }
//}
// Проверим кооректность введенных параметров
// Параметры nDistoAlloc, nFixedQuality, nFixedAlloc нельзя использовать вместе
if ((pParameters->nDistoAlloc || pParameters->nFixedAlloc || pParameters->nFixedQuality) && (!(pParameters->nDistoAlloc ^ pParameters->nFixedAlloc ^ pParameters->nFixedQuality)))
return -1;
// Если параметры не заданы, тогда по умолчанию ставим компрессию без потерь
if (0 == pParameters->nLayersCount)
{
pParameters->afRates[0] = 0;
pParameters->nLayersCount = 1;
pParameters->nDistoAlloc = 1;
}
if (pParameters->nXTOsiz > pParameters->nImageOffsetX0 || pParameters->nYTOsiz > pParameters->nImageOffsetY0)
return -1;
for (int nIndex = 0; nIndex < pParameters->nPOCsCount; nIndex++)
{
if (-1 == pParameters->aoPOC[nIndex].ePpoc)
{
// TO DO: Выдать ошибку, что порядок не задан
}
}
return nFormat;
}
}