diff options
Diffstat (limited to 'conversion/ecw.cc')
-rw-r--r-- | conversion/ecw.cc | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/conversion/ecw.cc b/conversion/ecw.cc new file mode 100644 index 0000000..3035e28 --- /dev/null +++ b/conversion/ecw.cc @@ -0,0 +1,339 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +#include "raslib/rminit.hh" +#include "raslib/rmdebug.hh" +#include "raslib/parseparams.hh" +#include "raslib/mitera.hh" +#include "raslib/minterval.hh" +#include "raslib/primitivetype.hh" +#include "ecw.hh" +#include "convertor.hh" +#include "convfactory.hh" + +#ifdef ECW +#include "ecwmemfs.hh" +#include "NCSECWClient.h" +#include "NCSErrors.h" + +NCSError memOpen(char *szFileName, void **ppClientData) + { + RMDBGENTER(5, RMDebug::module_conversion, "ECWMem", "memOpen(" << szFileName << ", fd)"); + MemoryFileSystem* myMem = new MemoryFileSystem(); + *ppClientData = (void*)myMem; + MemoryFileSystem::m_Error err = MemoryFileSystem::No_Error; + err = myMem->open(szFileName); + RMDBGEXIT(5, RMDebug::module_conversion, "ECWMem", "memOpen(" << szFileName << ", fd) " << err); + if (err == MemoryFileSystem::No_Error) + return NCS_SUCCESS; + else + return NCS_FILE_OPEN_FAILED; + } + +NCSError memClose(void *pClientData) + { + RMDBGENTER(5, RMDebug::module_conversion, "ECWMem", "memClose(fd)"); + MemoryFileSystem::m_Error err = MemoryFileSystem::No_Error; + err = ((MemoryFileSystem*)pClientData)->close(); + if (err == MemoryFileSystem::No_Error) + { + delete pClientData; + RMDBGEXIT(5, RMDebug::module_conversion, "ECWMem", "memClose(fd) OK"); + return NCS_SUCCESS; + } + else { + RMDBGEXIT(5, RMDebug::module_conversion, "ECWMem", "memClose(fd) Already closed"); + return NCS_FILE_CLOSE_ERROR; + } + } + +NCSError memRead(void *pClientData, void *pBuffer, UINT32 nLength) + { + RMDBGENTER(5, RMDebug::module_conversion, "ECWMem", "memRead(fd, buffer, " << nLength << ")"); + MemoryFileSystem::m_Error err = ((MemoryFileSystem*)pClientData)->read(pBuffer, nLength); + if (err == MemoryFileSystem::No_Error) + { + RMDBGEXIT(5, RMDebug::module_conversion, "ECWMem", "memRead(fd, buffer, " << nLength << ") OK"); + return NCS_SUCCESS; + } + else { + RMDBGEXIT(5, RMDebug::module_conversion, "ECWMem", "memRead(fd, buffer, " << nLength << ") ERROR"); + return NCS_FILE_SEEK_ERROR; + } + } + +NCSError memSeek(void *pClientData, UINT64 nOffset) + { + RMDBGENTER(5, RMDebug::module_conversion, "ECWMem", "memSeek(fd, " << nOffset << ")"); + MemoryFileSystem::m_Error err = ((MemoryFileSystem*)pClientData)->seek(nOffset); + if (err == MemoryFileSystem::No_Error) + { + RMDBGEXIT(5, RMDebug::module_conversion, "ECWMem", "memSeek(fd, " << nOffset << ") OK"); + return NCS_SUCCESS; + } + else { + RMDBGEXIT(5, RMDebug::module_conversion, "ECWMem", "memSeek(fd, " << nOffset << ") ERROR"); + return NCS_FILE_SEEK_ERROR; + } + } + +NCSError memTell(void *pClientData, UINT64 *pOffset) + { + RMDBGENTER(5, RMDebug::module_conversion, "ECWMem", "memTell(fd, " << *pOffset << ")"); + *pOffset = ((MemoryFileSystem*)pClientData)->tell(); + RMDBGEXIT(5, RMDebug::module_conversion, "ECWMem", "memTell(fd, " << *pOffset << ")"); + return NCS_SUCCESS; + } +#endif + +void +r_Conv_ECW::initECW() + { + RMDBGONCE(5, RMDebug::module_conversion, "r_Conv_ECW", "initECW()"); + if(params ==NULL) + { + params = new r_Parse_Params(2); + } + } + +r_Conv_ECW::r_Conv_ECW(const char* source, const r_Minterval& lengthordomain, const r_Type* tp) throw(r_Error) + : r_Convertor(source, lengthordomain, tp, true) + { + RMDBGONCE(5, RMDebug::module_conversion, "r_Conv_ECW", "r_Conv_ECW(source, " << lengthordomain << ", " << tp->name() << ")"); + initECW(); + } + +r_Conv_ECW::r_Conv_ECW(const char* source, const r_Minterval& lengthordomain, int tp) throw(r_Error) + : r_Convertor(source, lengthordomain, tp) + { + RMDBGONCE(5, RMDebug::module_conversion, "r_Conv_ECW", "r_Conv_ECW(source, " << lengthordomain << ", " << tp << ")"); + initECW(); + } + +r_convDesc& +r_Conv_ECW::convertFrom(const char* options) throw (r_Error) + { +#ifdef ECW + RMDBGENTER(5, RMDebug::module_conversion, "r_Conv_ECW", "convertFrom(" << ((options)? options : "NULL") << ")"); + int windowx = 1000; + int windowy = 1000; + params->add("windowx", &windowx, r_Parse_Params::param_type_int); + params->add("windowy", &windowy, r_Parse_Params::param_type_int); + params->process(options); + RMDBGMIDDLE(5, RMDebug::module_conversion, "r_Conv_ECW", "window x " << windowx); + RMDBGMIDDLE(5, RMDebug::module_conversion, "r_Conv_ECW", "window y " << windowy); + switch (desc.baseType) + { + case ctype_bool: + case ctype_char: + case ctype_uint8: + break; + case ctype_rgb: + break; + default: + RMInit::logOut << "r_Conv_ECW unknown base type!" << std::endl; + throw r_Error(COMPRESSIONFAILED); + } + NCSFileView *pNCSFileView = NULL; + NCSFileViewFileInfo *pNCSFileInfo = NULL; + + NCSError eError = NCS_SUCCESS; + eError = NCSecwSetIOCallbacks(memOpen, memClose, memRead, memSeek, memTell); + if (eError != NCS_SUCCESS) + { + RMInit::logOut << "Error = " << NCSGetErrorText(eError) << std::endl; + throw r_Error(COMPRESSIONFAILED); + } + UINT8 **p_p_output_line = NULL; + UINT8 *p_output_buffer = NULL; + UINT32 x_size = 0; + UINT32 y_size = 0; + UINT32 number_x = 0; + UINT32 number_y = 0; + UINT32 start_x = 0; + UINT32 start_y = 0; + UINT32 end_x = 0; + UINT32 end_y = 0; + UINT32 band = 0; + UINT32 nBands = 0; + MemoryFileSystem::memorySrc = desc.src; + MemoryFileSystem::memorySrcLength = desc.srcInterv[0].high() - desc.srcInterv[0].low() + 1; + eError = NCScbmOpenFileView((char*)MemoryFileSystem::memorySrcName, &pNCSFileView, NULL); + + if (eError != NCS_SUCCESS) + { + RMInit::logOut << "Error = " << NCSGetErrorText(eError) << std::endl; + throw r_Error(COMPRESSIONFAILED); + } + + NCScbmGetViewFileInfo(pNCSFileView, &pNCSFileInfo); + x_size = pNCSFileInfo->nSizeX; + y_size = pNCSFileInfo->nSizeY; + nBands = pNCSFileInfo->nBands; + RMDBGMIDDLE(5, RMDebug::module_conversion, "r_Conv_ECW", "image : " << x_size << " x " << y_size << ", " << nBands << " bands"); + + /* Have to set up the band list. Compatible with ER Mapper's method.*/ + /* In this example we always request all bands.*/ + UINT32* band_list = new UINT32[nBands]; + for( band = 0; band < nBands; band++ ) + band_list[band] = band; + size_t typeLength = nBands; + switch (desc.baseType) + { + case ctype_bool: + case ctype_char: + case ctype_uint8: + if (nBands != 1) + { + RMInit::logOut << "r_Conv_ECW conversion of base types bot supported" << std::endl; + throw r_Error(COMPRESSIONFAILED); + } + break; + case ctype_rgb: + if (nBands != 3) + { + RMInit::logOut << "r_Conv_ECW conversion of base types bot supported" << std::endl; + throw r_Error(COMPRESSIONFAILED); + } + break; + default: + RMInit::logOut << "r_Conv_ECW there is a really bad error in your compiler" << std::endl; + throw r_Error(10000); + break; + } + start_x = 0; + start_y = 0; + end_x = x_size - 1; + end_y = y_size - 1; + number_x = x_size; + number_y = y_size; + + windowx = number_x; + windowy = number_y; + + r_Minterval imageDomain(2); + imageDomain << r_Sinterval((r_Range)0, (r_Range)number_x - 1); + imageDomain << r_Sinterval((r_Range)0, (r_Range)number_y - 1); + RMDBGMIDDLE(5, RMDebug::module_conversion, "r_Conv_ECW", "image domain " << imageDomain << ", type length " << typeLength << " bands"); + char* image = (char*)mystore.storage_alloc(number_x * number_y * typeLength); + //char* image = new char[number_x * number_y * typeLength]; + memset(image, 0, number_x * number_y * typeLength); + r_Minterval maxDom(2); + maxDom << r_Sinterval((r_Range)0, (r_Range)1000 - 1); + maxDom << r_Sinterval((r_Range)0, (r_Range)1000 - 1); + r_MiterArea dom_iter(&maxDom, &imageDomain); + r_Minterval iterArea(2); + while (!dom_iter.isDone()) + { + iterArea = dom_iter.nextArea(); + start_x = iterArea[0].low(); + start_y = iterArea[1].low(); + end_x = iterArea[0].high(); + end_y = iterArea[1].high(); + number_x = iterArea[0].get_extent(); + number_y = iterArea[1].get_extent(); + RMDBGMIDDLE(5, RMDebug::module_conversion, "r_Conv_ECW", "current " << start_x << ":" << end_x << "," << start_y << ":" << end_y << " window " << number_x << " x " << number_y); + eError = NCScbmSetFileView(pNCSFileView, nBands, band_list, start_x, start_y, end_x, end_y, number_x, number_y); + if( eError != NCS_SUCCESS) + { + RMInit::logOut << "Error while setting file view to " << nBands << " bands, [" << start_x << ":" << end_x << "," << start_y << ":" << end_y << "], window size " << number_x << " x " << number_y << " pixel" << std::endl; + RMInit::logOut << "Error = " << NCSGetErrorText(eError) << std::endl; + NCScbmCloseFileViewEx(pNCSFileView, TRUE); + delete [] band_list; + mystore.storage_free(image); + throw r_Error(COMPRESSIONFAILED); + } + + p_output_buffer = new UINT8[number_x * nBands]; + p_p_output_line = new UINT8*[nBands]; + + for(band = 0; band < nBands; band++ ) + p_p_output_line[band] = p_output_buffer + (band * number_x); + + /* + ** Read each line of the compressed file + */ + for( UINT32 line = 0; line < number_y; line++ ) + { + NCSEcwReadStatus eReadStatus = NCScbmReadViewLineBIL( pNCSFileView, p_p_output_line); + if (eReadStatus != NCSECW_READ_OK) + { + RMInit::logOut << "Read line error at line " << line << std::endl; + RMInit::logOut << "Status code " << eReadStatus << std::endl; + NCScbmCloseFileViewEx(pNCSFileView, TRUE); + delete [] band_list; + delete [] p_p_output_line; + delete [] p_output_buffer; + mystore.storage_free(image); + throw r_Error(COMPRESSIONFAILED); + } + for (int b = 0; b < nBands; b++) + { + for (int l = 0; l < number_x; l++) + { + image[(l + iterArea[0].low()) * windowy * typeLength + (line + iterArea[1].low()) * typeLength + b] = p_p_output_line[b][l]; + } + } + } + delete [] p_p_output_line; + delete [] p_output_buffer; + RMDBGMIDDLE(5, RMDebug::module_conversion, "r_Conv_ECW", "read done"); + } + NCScbmCloseFileViewEx(pNCSFileView, TRUE); + delete [] band_list; + desc.dest = (char*)image; + desc.destInterv = imageDomain; + desc.destType = get_external_type(desc.baseType); + return desc; +#else + RMDBGENTER(5, RMDebug::module_conversion, "r_Conv_ECW", "convertFrom(" << options << ") NOT COMPILED"); + RMInit::logOut << "r_Conv_ECW::convertFrom(" << options << ") ecw support not compiled in" << std::endl; + throw r_Error(COMPRESSIONFAILED); +#endif + } + +r_convDesc& +r_Conv_ECW::convertTo(const char* options) throw (r_Error) + { + RMInit::logOut << "r_Conv_ECW::convertTo(" << options << ") compression not supported" << std::endl; + throw r_Error(COMPRESSIONFAILED); + } + +const char* +r_Conv_ECW::get_name() const + { + return get_name_from_data_format(r_ECW); + } + +r_Data_Format +r_Conv_ECW::get_data_format() const + { + return r_ECW; + } + +r_Convertor* +r_Conv_ECW::clone() const + { + return new r_Conv_ECW(desc.src, desc.srcInterv, desc.srcType); + } + |