add jpeg2000 support

This commit is contained in:
Kulikova Svetlana
2021-03-23 10:57:07 +03:00
parent 015a667484
commit 87631cdf58
8 changed files with 375 additions and 24 deletions

View File

@ -34,7 +34,7 @@
#define CXIMAGE_SUPPORT_WBMP 0
#define CXIMAGE_SUPPORT_WMF 0
#define CXIMAGE_SUPPORT_JP2 0
#define CXIMAGE_SUPPORT_JP2 1
#define CXIMAGE_SUPPORT_JPC 0
#define CXIMAGE_SUPPORT_PGX 0
#define CXIMAGE_SUPPORT_PNM 0
@ -83,11 +83,7 @@
#define CXIMAGE_ERR_NOFILE "null file handler"
#define CXIMAGE_ERR_NOIMAGE "null image!!!"
#if defined(BUILDING_WASM_MODULE)
#define CXIMAGE_SUPPORT_EXCEPTION_HANDLING 0
#else
#define CXIMAGE_SUPPORT_EXCEPTION_HANDLING 1
#endif // BUILDING_WASM_MODULE
/////////////////////////////////////////////////////////////////////////////
//color to grey mapping <H. Muelner> <jurgene>

View File

@ -22,7 +22,6 @@ if not base.is_dir("emsdk"):
# compile
compiler_flags = ["-o raster.js",
"-O3",
"-fno-exceptions",
"-fno-rtti",
"-s WASM=1",
"-s ALLOW_MEMORY_GROWTH=1",
@ -53,7 +52,7 @@ libCxImage_src_path = "./../../../cximage/CxImage"
input_cximage_sources = ["ximaenc.cpp", "ximaexif.cpp", "ximage.cpp", "ximainfo.cpp",
"ximajpg.cpp", "ximalpha.cpp", "ximapal.cpp", "ximasel.cpp",
"xmemfile.cpp", "ximapng.cpp", "ximabmp.cpp", "ximatran.cpp",
"ximatif.cpp", "tif_xfile.cpp"]
"ximatif.cpp", "tif_xfile.cpp", "ximajas.cpp"]
libJpeg_src_path = "./../../../cximage/jpeg"
input_jpeg_sources = ["jerror.c", "jdmarker.c", "jdapimin.c", "jdmaster.c", "jdapistd.c",
@ -79,6 +78,25 @@ input_tiff_sources = ["tif_close.c", "tif_dir.c", "tif_aux.c", "tif_getimage.c",
"tif_jpeg.c", "tif_next.c", "tif_thunder.c", "tif_packbits.c", "tif_lzw.c",
"tif_zip.c", "tif_fax3sm.c", "tif_predict.c"]
libJasper_src_path = "./../../../cximage/jasper"
input_jasper_sources = ["base/jas_init.c", "base/jas_stream.c", "base/jas_malloc.c",
"base/jas_image.c", "base/jas_cm.c", "base/jas_seq.c",
"base/jas_string.c", "base/jas_icc.c", "base/jas_debug.c",
"base/jas_iccdata.c", "base/jas_tvp.c", "base/jas_version.c",
"mif/mif_cod.c", "pnm/pnm_dec.c", "pnm/pnm_enc.c", "pnm/pnm_cod.c",
"bmp/bmp_dec.c", "bmp/bmp_enc.c", "bmp/bmp_cod.c", "ras/ras_dec.c",
"ras/ras_enc.c", "jp2/jp2_dec.c", "jp2/jp2_enc.c", "jp2/jp2_cod.c",
"jpc/jpc_cs.c", "jpc/jpc_enc.c", "jpc/jpc_dec.c", "jpc/jpc_t1cod.c",
"jpc/jpc_math.c", "jpc/jpc_util.c", "jpc/jpc_tsfb.c", "jpc/jpc_mct.c",
"jpc/jpc_t1enc.c", "jpc/jpc_t1dec.c", "jpc/jpc_bs.c", "jpc/jpc_t2cod.c",
"jpc/jpc_t2enc.c", "jpc/jpc_t2dec.c", "jpc/jpc_tagtree.c",
"jpc/jpc_mqenc.c", "jpc/jpc_mqdec.c", "jpc/jpc_mqcod.c",
"jpc/jpc_qmfb.c", "jpg/jpg_val.c", "jpg/jpg_dummy.c", "pgx/pgx_dec.c",
"pgx/pgx_enc.c"]
libJ2kFile_src_path = "./../../../raster/Jp2"
input_j2k_sources = ["J2kFile.cpp", "Reader.cpp"]
sources = []
for item in input_raster_sources:
sources.append(libRaster_src_path + '/' + item)
@ -92,12 +110,15 @@ for item in input_png_sources:
sources.append(libPng_src_path + '/' + item)
for item in input_tiff_sources:
sources.append(libTiff_src_path + '/' + item)
for item in input_jasper_sources:
sources.append(libJasper_src_path + '/' + item)
for item in input_j2k_sources:
sources.append(libJ2kFile_src_path + '/' + item)
sources.append("./wasm/src/base.cpp")
compiler_flags.append("-I./../../../../OfficeUtils/src/zlib-1.2.11")
#compiler_flags.append("-I" + libCxImage_src_path)
#compiler_flags.append("-I" + libJpeg_src_path)
compiler_flags.append("-DBUILDING_WASM_MODULE -D_tcsnicmp=strncmp")
compiler_flags.append("-I" + libJasper_src_path + "/include")
compiler_flags.append("-DBUILDING_WASM_MODULE -D_tcsnicmp=strncmp -D_lseek=lseek")
# arguments
arguments = ""

View File

@ -10,7 +10,7 @@ int main()
BYTE* pData = NULL;
DWORD nBytesCount;
NSFile::CFileBinary oFile;
if (!oFile.ReadAllBytes(NSFile::GetProcessDirectory() + L"/test.png", &pData, nBytesCount))
if (!oFile.ReadAllBytes(NSFile::GetProcessDirectory() + L"/test.jp2", &pData, nBytesCount))
return 1;
oFile.CloseFile();

View File

@ -418,21 +418,22 @@ void CBgraFrame::put_Palette(BYTE* pDataColors, const int& colors)
bool CBgraFrame::OpenFile(const std::wstring& strFileName, unsigned int nFileType)
{
m_nFileType = nFileType;
#if CXIMAGE_SUPPORT_JP2
if (CXIMAGE_FORMAT_JP2 == nFileType)
{
Jpeg2000::CJ2kFile oJ2;
return oJ2.Open(this, strFileName, std::wstring(L""));
}
#endif
m_nFileType = nFileType;
if (nFileType == 0)
{
CImageFileFormatChecker checker(strFileName);
m_nFileType = checker.eFileType;
}
#if CXIMAGE_SUPPORT_JP2
if (CXIMAGE_FORMAT_JP2 == m_nFileType)
{
Jpeg2000::CJ2kFile oJ2;
return oJ2.Open(this, strFileName, std::wstring(L""));
}
#endif
NSFile::CFileBinary oFile;
if (!oFile.OpenFile(strFileName))
return false;
@ -450,13 +451,20 @@ bool CBgraFrame::Decode(BYTE* pBuffer, int nSize, unsigned int nFileType)
{
m_nFileType = nFileType;
// добавить CXIMAGE_FORMAT_JP2 с буфером
if (nFileType == 0)
{
CImageFileFormatChecker checker(pBuffer, nSize);
m_nFileType = checker.eFileType;
}
#if CXIMAGE_SUPPORT_JP2
if (CXIMAGE_FORMAT_JP2 == m_nFileType)
{
Jpeg2000::CJ2kFile oJ2;
return oJ2.Open(this, pBuffer, nSize, std::wstring(L""));
}
#endif
CxImage img;
if (!img.Decode(pBuffer, nSize, m_nFileType))

View File

@ -77,6 +77,46 @@ namespace Jpeg2000
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)
@ -209,6 +249,128 @@ namespace Jpeg2000
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;

View File

@ -9,6 +9,7 @@ namespace Jpeg2000
{
public:
bool Open(CBgraFrame* pFrame, const std::wstring& wsSrcPath, const std::wstring& wsXmlOptions);
bool Open(CBgraFrame* pFrame, BYTE* pBuffer, int nSize, const std::wstring& wsXmlOptions);
bool Save(CBgraFrame* pFrame, const std::wstring& wsSrcPath, const std::wstring& wsXmlOptions);
bool Open(BYTE** ppData, int& nComponentsCount, int& nWidth, int& nHeight, const std::wstring& wsSrcPath, const std::wstring& wsXmlOptions);

View File

@ -188,6 +188,169 @@ namespace Jpeg2000
Free(pDInfo);
return pImage;
}
Image* Jp2ToImage(BYTE* pBuffer, int nSize, DecoderParams* pDecoderParams)
{
DInfo *pDInfo = (DInfo*)Malloc(sizeof(DInfo));
if (!pDInfo)
return NULL;
pDInfo->bIsDecompressor = true;
pDInfo->pJp2 = (void*)Jp2_CreateDecompress((PCommon)pDInfo);
if (!pDInfo->pJp2)
{
Free(pDInfo);
return NULL;
}
pDInfo->pJ2k = NULL;
pDInfo->eCodecFormat = codecJP2;
Jp2_SetupDecoder((Jp2Stream*)pDInfo->pJp2, pDecoderParams);
if (JP2_ERROR_NO_ERROR != pDInfo->nErrorCode)
{
Jp2_DestroyDecompress((Jp2Stream*)pDInfo->pJp2);
Free(pDInfo);
return NULL;
}
CReader *pStream = (CReader *)new CReaderStream(pBuffer, nSize);
if (!pStream)
{
Jp2_DestroyDecompress((Jp2Stream*)pDInfo->pJp2);
Free(pDInfo);
return NULL;
}
Image *pImage = Jp2_Decode((Jp2Stream*)pDInfo->pJp2, pStream); // в случае ошибки pImage = NULL
delete (pStream);
Jp2_DestroyDecompress((Jp2Stream*)pDInfo->pJp2);
Free(pDInfo);
return pImage;
}
Image* J2kToImage(BYTE* pBuffer, int nSize, DecoderParams* pDecoderParams)
{
DInfo *pDInfo = (DInfo*)Malloc(sizeof(DInfo));
if (!pDInfo)
return NULL;
pDInfo->bIsDecompressor = true;
pDInfo->pJ2k = (void*)J2k_CreateDecompress((PCommon)pDInfo);
if (!pDInfo->pJ2k)
{
Free(pDInfo);
return NULL;
}
pDInfo->pJp2 = NULL;
pDInfo->eCodecFormat = codecJ2K;
J2k_SetupDecoder((J2kCodestream*)pDInfo->pJ2k, pDecoderParams);
if (JP2_ERROR_NO_ERROR != pDInfo->nErrorCode)
{
J2k_DestroyDecompress((J2kCodestream*)pDInfo->pJ2k);
Free(pDInfo);
return NULL;
}
CReader *pStream = (CReader *)new CReaderStream(pBuffer, nSize);
if (!pStream)
{
J2k_DestroyDecompress((J2kCodestream*)pDInfo->pJ2k);
Free(pDInfo);
return NULL;
}
Image *pImage = J2k_Decode((J2kCodestream*)pDInfo->pJ2k, pStream); // в случае ошибки pImage = NULL
delete (pStream);
J2k_DestroyDecompress((J2kCodestream*)pDInfo->pJ2k);
Free(pDInfo);
return pImage;
}
Image* JptToImage(BYTE* pBuffer, int nSize, DecoderParams* pDecoderParams)
{
DInfo *pDInfo = (DInfo*)Malloc(sizeof(DInfo));
if (!pDInfo)
return NULL;
pDInfo->bIsDecompressor = true;
pDInfo->pJ2k = (void*)J2k_CreateDecompress((PCommon)pDInfo);
if (!pDInfo->pJ2k)
{
Free(pDInfo);
return NULL;
}
pDInfo->pJp2 = NULL;
pDInfo->eCodecFormat = codecJPT;
J2k_SetupDecoder((J2kCodestream*)pDInfo->pJ2k, pDecoderParams);
if (JP2_ERROR_NO_ERROR != pDInfo->nErrorCode)
{
J2k_DestroyDecompress((J2kCodestream*)pDInfo->pJ2k);
Free(pDInfo);
return NULL;
}
CReader *pStream = (CReader *)new CReaderStream(pBuffer, nSize);
if (!pStream)
{
J2k_DestroyDecompress((J2kCodestream*)pDInfo->pJ2k);
Free(pDInfo);
return NULL;
}
Image *pImage = J2k_DecodeJptStream((J2kCodestream*)pDInfo->pJ2k, pStream); // в случае ошибки pImage = NULL
delete (pStream);
J2k_DestroyDecompress((J2kCodestream*)pDInfo->pJ2k);
Free(pDInfo);
return NULL;
}
Image* Mj2ToImage(BYTE* pBuffer, int nSize, DecoderParams* pDecoderParams)
{
DInfo *pDInfo = (DInfo*)Malloc(sizeof(DInfo));
if (!pDInfo)
return NULL;
pDInfo->bIsDecompressor = true;
pDInfo->pMj2 = (void*)Mj2_CreateDecompress((PCommon)pDInfo);
if (!pDInfo->pMj2)
{
Free(pDInfo);
return NULL;
}
pDInfo->pJ2k = ((Mj2_Movie*)pDInfo->pMj2)->pJ2k;
pDInfo->eCodecFormat = codecMj2;
Mj2_SetupDecoder((Mj2_Movie*)pDInfo->pMj2, pDecoderParams);
if (JP2_ERROR_NO_ERROR != pDInfo->nErrorCode)
{
Mj2_DestroyDecompress((Mj2_Movie*)pDInfo->pMj2);
Free(pDInfo);
return NULL;
}
CReader *pStream = (CReader *)new CReaderStream(pBuffer, nSize);
if (!pStream)
{
Mj2_DestroyDecompress((Mj2_Movie*)pDInfo->pMj2);
Free(pDInfo);
return NULL;
}
Image *pImage = Mj2_Decode((Mj2_Movie*)pDInfo->pMj2, pStream); // в случае ошибки pImage = NULL
delete (pStream);
Mj2_DestroyDecompress((Mj2_Movie*)pDInfo->pMj2);
Free(pDInfo);
return pImage;
}
//-------------------------------------------------------------------------------------------------------------------------------
// Image -> Jpeg2000
//-------------------------------------------------------------------------------------------------------------------------------
@ -313,4 +476,4 @@ namespace Jpeg2000
return true;
}
}
}

View File

@ -51,7 +51,7 @@ namespace Jpeg2000
if (sIndexFile)
{
for (unsigned int nIndex = 0; nIndex < strlen(sIndexFile); nIndex)
for (unsigned int nIndex = 0; nIndex < strlen(sIndexFile); nIndex++)
{
pStream->Write(sIndexFile[nIndex], 1);
}
@ -759,4 +759,4 @@ namespace Jpeg2000
return true;
}
}
}