EVOLUTION-MANAGER
Edit File: jp2luracallbacks.cpp
/****************************************************************************** * Project: GDAL * Author: Raul Alonso Reyes <raul dot alonsoreyes at satcen dot europa dot eu> * Author: Even Rouault, <even dot rouault at spatialys dot com> * Purpose: JPEG-2000 driver based on Lurawave library, driver developed by SatCen * ****************************************************************************** * Copyright (c) 2016, SatCen - European Union Satellite Centre * Copyright (c) 2016, Even Rouault * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "cpl_port.h" #include "lwf_jp2.h" #include "jp2luracallbacks.h" #ifdef ENABLE_MEMORY_REGISTRAR JP2LuraMemoryRegistrar::JP2LuraMemoryRegistrar() { } JP2LuraMemoryRegistrar::~JP2LuraMemoryRegistrar() { CPLDebug("JP2Lura", "JP2LuraMemoryRegistrar: %d block allocated leaked", static_cast<int>(oMap.size())); std::map<void*, size_t>::const_iterator oIter = oMap.begin(); for( ; oIter != oMap.end(); ++oIter ) { CPLDebug("JP2Lura", "force freeing %d bytes", static_cast<int>(oIter->second)); VSIFree(oIter->first); } } void JP2LuraMemoryRegistrar::Register(size_t nSize, void* ptr) { CPLAssert( oMap.find(ptr) == oMap.end() ); oMap[ptr] = nSize; } void JP2LuraMemoryRegistrar::Unregister(void* ptr) { CPLAssert( oMap.find(ptr) != oMap.end() ); oMap.erase(ptr); } #endif // ENABLE_MEMORY_REGISTRAR /************************************************************************/ /* GDALJP2Lura_Callback_Malloc() */ /************************************************************************/ void * JP2_Callback_Conv GDALJP2Lura_Callback_Malloc(size_t size, JP2_Callback_Param #ifdef ENABLE_MEMORY_REGISTRAR lParam #endif ) { void* ptr = VSIMalloc(size); #ifdef ENABLE_MEMORY_REGISTRAR if( lParam && ptr ) { ((JP2LuraMemoryRegistrar*)lParam)->Register(size, ptr); } #endif return ptr; } /************************************************************************/ /* GDALJP2Lura_Callback_Free() */ /************************************************************************/ JP2_Error JP2_Callback_Conv GDALJP2Lura_Callback_Free(void *ptr, JP2_Callback_Param #ifdef ENABLE_MEMORY_REGISTRAR lParam #endif ) { #ifdef ENABLE_MEMORY_REGISTRAR if( lParam && ptr ) { ((JP2LuraMemoryRegistrar*)lParam)->Unregister(ptr); } #endif VSIFree(ptr); return cJP2_Error_OK; } /************************************************************************/ /* GDALJP2Lura_Callback_Decompress_Read() */ /************************************************************************/ unsigned long JP2_Callback_Conv GDALJP2Lura_Callback_Decompress_Read( unsigned char *pucData, unsigned long ulPos, unsigned long ulSize, JP2_Callback_Param lParam) { VSILFILE* fp = reinterpret_cast<VSILFILE*>(lParam); if (VSIFSeekL(fp, ulPos, SEEK_SET) != 0) { return 0; } return static_cast<unsigned long>( VSIFReadL(pucData, 1, static_cast<size_t>(ulSize), fp)); } /************************************************************************/ /* splitIEEE754Float() */ /************************************************************************/ typedef union { float f; unsigned int ui; } float_uint_union; static void splitIEEE754Float(float f, unsigned int *mantissa, int *exponent, int *sign) { float_uint_union x; x.f = f; if (x.ui & 0x80000000) *sign = 1; else *sign = 0; *mantissa = x.ui & 0x07FFFFF; *exponent = (x.ui >> 23) & 0xFF; } /************************************************************************/ /* setIIIE754Sign() */ /************************************************************************/ static void setIIIE754Sign(float_uint_union* f, unsigned char sign) { if (!sign) f->ui = (f->ui & 0x7FFFFFFFU); else f->ui = (f->ui & 0x7FFFFFFFU) | 0x80000000U; } /************************************************************************/ /* setIIIE754Exponent() */ /************************************************************************/ static void setIIIE754Exponent(float_uint_union* f, unsigned char exponent) { f->ui = (f->ui & 0x807fffffU) | (exponent << 23); } /************************************************************************/ /* setIIIE754Mantissa() */ /************************************************************************/ static void setIIIE754Mantissa(float_uint_union* f, unsigned int mantissa) { f->ui = (f->ui & (0xFF800000U)) | mantissa; } /************************************************************************/ /* GDALJP2Lura_Callback_Decompress_Write() */ /************************************************************************/ JP2_Error JP2_Callback_Conv GDALJP2Lura_Callback_Decompress_Write( unsigned char* pucData, short sComponent, unsigned long ulRow, unsigned long ulStart, // starting pixel unsigned long ulNum, // number of pixels JP2_Callback_Param lParam) { #ifdef DEBUG_VERBOSE CPLDebug("JP2Lura", "Decompress(%d, %lu, %lu, %lu)", sComponent, ulRow, ulStart, ulNum); #endif GDALJP2Lura_Output_Data* pOutputData = reinterpret_cast<GDALJP2Lura_Output_Data*>(lParam); CPLAssert(ulRow < static_cast<unsigned long>(pOutputData->nBufYSize)); CPLAssert(ulStart + ulNum <= static_cast<unsigned long>(pOutputData->nBufXSize)); long lBps = 0; /****************************************************/ /* convert from component index to channel index */ /* i.e. index after expanding any palette samples */ /****************************************************/ if (pOutputData->lBps==0) //float { switch (sComponent) { case 0: case 1: case 2: { lBps = 32; break; } default: return cJP2_Error_Write_Callback_Undefined; } } else { lBps = pOutputData->lBps; } unsigned char* pucImageData; // buffer for decompressed image stripe if (pOutputData->lBps == 0) pucImageData = pOutputData->pimage; else { if( sComponent >= pOutputData->nBands ) { // Ignored component return cJP2_Error_OK; } if (sComponent != pOutputData->nBand - 1) { pucImageData = pOutputData->pDatacache[sComponent]; } else { pucImageData = pOutputData->pimage; } } /***********************************/ /* number of bytes for each sample */ /***********************************/ unsigned long ulBytesFromLura = ((lBps + 7) >> 3); unsigned long ulBytesrequest = GDALGetDataTypeSizeBytes(pOutputData->eBufType); /* distance between samples of the same channel */ unsigned long ulSkip = ulBytesrequest; unsigned long ulOffset = (pOutputData->nBufXSize * ulSkip) * ulRow + ulStart * ulSkip; unsigned char* pucStart = pucImageData + ulOffset; if (pOutputData->lBps == 0) { #ifdef DEBUG_VERBOSE CPLString osLineValues; #endif const unsigned int nSpaceMantissa = 4; for (unsigned long i = 0; i < ulNum; i++) { float_uint_union* f = (float_uint_union*)(&pucStart[i*4]); if (sComponent == 0) { #ifdef DEBUG_VERBOSE osLineValues += CPLSPrintf("%02X ", *pucData); #endif setIIIE754Sign(f, (*pucData == 0) ? 0 : 1); pucData++; } else if (sComponent == 1) { #ifdef DEBUG_VERBOSE osLineValues += CPLSPrintf("%02X ", *pucData); #endif setIIIE754Exponent(f, *pucData); pucData++; } else if (sComponent == 2) { unsigned int mantissa = *(unsigned int*)pucData; #ifdef DEBUG_VERBOSE osLineValues += CPLSPrintf("%02X ",mantissa); #endif setIIIE754Mantissa(f, mantissa); pucData += nSpaceMantissa; } } #ifdef DEBUG_VERBOSE CPLDebug("JP2Lura", "Component %d: %s", sComponent, osLineValues.c_str()); #endif } else { memcpy(pucStart, pucData, ulBytesFromLura * ulNum); } return cJP2_Error_OK; } /************************************************************************/ /* GDALJP2Lura_Callback_Compress_Write() */ /************************************************************************/ JP2_Error JP2_Callback_Conv GDALJP2Lura_Callback_Compress_Write( unsigned char *pucData, unsigned long ulPos, unsigned long ulSize, JP2_Callback_Param lParam) { JP2_Gdal_Stream_Data* data = reinterpret_cast<JP2_Gdal_Stream_Data*>(lParam); if (VSIFSeekL(data->fp, (vsi_l_offset)(ulPos + data->Position), SEEK_SET) != 0) { return cJP2_Error_Failure_Write; } if (VSIFWriteL(pucData, 1, (vsi_l_offset)ulSize, data->fp) != ulSize) { return cJP2_Error_Failure_Write; } return cJP2_Error_OK; } /************************************************************************/ /* GDALJP2Lura_Callback_Compress_Read() */ /************************************************************************/ JP2_Error JP2_Callback_Conv GDALJP2Lura_Callback_Compress_Read( unsigned char* pucData, short sComponent, unsigned long ulRow, unsigned long ulStart, unsigned long ulNum, JP2_Callback_Param lParam) { GDALJP2Lura_Input_Data* idata = reinterpret_cast<GDALJP2Lura_Input_Data*>(lParam); GDALDataset* poSrcDS = idata->poSrcDS; const int nBands = poSrcDS->GetRasterCount(); const int nYSize = poSrcDS->GetRasterYSize(); GDALProgressFunc pfnProgress = idata->pfnProgress; void * pProgressData = idata->pProgressData; if( ulStart == 0 && pfnProgress && !pfnProgress(static_cast<double>(ulRow+1)/nYSize, "", pProgressData) ) { return cJP2_Error_Read_Callback_Undefined; } GDALRasterBand *poBand; if (nBands == 1 && poSrcDS->GetRasterBand(1)->GetRasterDataType() == GDT_Float32) { poBand = poSrcDS->GetRasterBand(1); } else { poBand = poSrcDS->GetRasterBand(sComponent + 1); } GDALDataType eDataType = poBand->GetRasterDataType(); unsigned long ulBpsRead = 0; switch (eDataType) { case GDT_Byte: { ulBpsRead = 8; //Signed = 0; break; } case GDT_UInt16: { ulBpsRead = 16; //Signed = 0; break; } case GDT_Int16: { ulBpsRead = 16; //Signed = 1; break; } case GDT_UInt32: { ulBpsRead = 32; //Signed = 0; break; } case GDT_Int32: { ulBpsRead = 32; //Signed = 1; break; } case GDT_Float32: { ulBpsRead = 32; //Signed = 1; break; } default: break; } unsigned long ulBytes = (ulBpsRead <= 8) ? 1 : ((ulBpsRead > 16) ? 4 : 2); unsigned long ulRowBytes = ulBytes * ulNum; /* malloc of the row*/ unsigned char *pucPos = reinterpret_cast<unsigned char*>( VSIMalloc(ulRowBytes)); if (pucPos == NULL) { return cJP2_Error_Failure_Malloc; } /* check scanlines already read */ CPLErr err = poBand->RasterIO(GF_Read, static_cast<int>(ulStart), static_cast<int>(ulRow), static_cast<int>(ulNum), 1, pucPos, static_cast<int>(ulNum), 1, eDataType, 0, 0, NULL); if (err != CE_None) { VSIFree(pucPos); return cJP2_Error_Read_Callback_Undefined; } /* deliver the requested pixels to the library */ if (nBands == 1 && eDataType == GDT_Float32 ) { unsigned int mantissa; int exponent; int sign; const unsigned long nSpaceMantissa = 4; for (int i = 0; i < (int) ulNum; i++) { float *ptr = (float*)(&pucPos[i * 4]); splitIEEE754Float(*ptr, &mantissa, &exponent, &sign); switch (sComponent) { case 0: { pucData[i] = (sign) ? 255 : 0; break; } case 1: { pucData[i] = static_cast<unsigned char>(exponent); break; } case 2: { *reinterpret_cast<unsigned int*>( pucData + i * nSpaceMantissa) = mantissa; break; } } } } else { memcpy(pucData, pucPos, ulBytes * ulNum); } VSIFree(pucPos); return cJP2_Error_OK; }