diff --git a/Code/IO/otbJPEG2000ImageIO.cxx b/Code/IO/otbJPEG2000ImageIO.cxx index 94ecd0dd122a0ad2f2e271b465909b9268a19d34..b94c706fe385b96e06cfea6815d63a47cd6261ba 100644 --- a/Code/IO/otbJPEG2000ImageIO.cxx +++ b/Code/IO/otbJPEG2000ImageIO.cxx @@ -24,6 +24,8 @@ #include "itkTimeProbe.h" #include "itkMacro.h" +#include <deque> + extern "C" { #include "openjpeg.h" @@ -63,6 +65,10 @@ namespace otb class JPEG2000ReaderInternal { public: + typedef std::pair<unsigned int, opj_image_t *> CachedTileType; + typedef std::deque<CachedTileType> TileCacheType; + + JPEG2000ReaderInternal(); opj_codec_t* GetCodec(){return this->m_Codec; }; @@ -71,7 +77,11 @@ public: opj_stream_t* GetStream(){return this->m_Stream; }; opj_codestream_info_v2* GetCstrInfo(){return this->m_CstrInfo; }; - void Clean(); + bool LoadTileFromCache(unsigned int tileIndex); + + bool ReadTileFromFile(unsigned int tileIndex); + + void Clean(); int CanRead(); @@ -101,11 +111,17 @@ private: opj_image_t* m_Image; opj_stream_t* m_Stream; opj_codestream_info_v2* m_CstrInfo; + unsigned int m_CacheSizeInTiles; + TileCacheType m_Cache; int Initialize(); + void InsertTileInCache(unsigned int tileIndex,opj_image_t * tileData); + + void ClearCache(); }; + int JPEG2000ReaderInternal::Open(const char *filename) { this->Clean(); @@ -148,6 +164,9 @@ int JPEG2000ReaderInternal::Open(const char *filename) void JPEG2000ReaderInternal::Clean() { + // Clear the tile cache + this->ClearCache(); + // Close the byte stream if (this->m_Stream) { @@ -169,13 +188,6 @@ void JPEG2000ReaderInternal::Clean() } this->m_Codec = NULL; - // Destroy the image - if (this->m_Image) - { - otbopenjpeg_opj_image_destroy(this->m_Image); - } - this->m_Image = NULL; - // Destroy the codestream info if (this->m_CstrInfo) { @@ -207,6 +219,92 @@ void JPEG2000ReaderInternal::Clean() } + +void JPEG2000ReaderInternal::ClearCache() +{ + for(TileCacheType::iterator it = m_Cache.begin(); + it != m_Cache.end();++it) + { + CachedTileType erasedTile = *it; + + // Destroy the image + if (erasedTile.second) + { + //otbopenjpeg_opj_image_destroy(erasedTile.second); + } + erasedTile.second = NULL; + } + m_Cache.clear(); +} + +bool JPEG2000ReaderInternal::LoadTileFromCache(unsigned int tileIndex) +{ + for(TileCacheType::const_iterator it = m_Cache.begin(); + it != m_Cache.end();++it) + { + if(it->first == tileIndex) + { + this->m_Image = it->second; + std::cout<<"Tile "<<tileIndex<<" loaded from cache."<<std::endl; + return true; + } + } + return false; +} + +bool JPEG2000ReaderInternal::ReadTileFromFile(unsigned int tileIndex) +{ + bool success = otbopenjpeg_opj_get_decoded_tile(this->GetCodec(),this->GetStream(),this->GetImage(),tileIndex); + + + if(success) + { + std::cout<<"Tile "<<tileIndex<<" decoded from file"<<std::endl; + std::cout<<"Tile "<<this->GetImage()->x0<<" "<<this->GetImage()->y0<<" "<<this->GetImage()->x1<<" "<<this->GetImage()->y1<<std::endl; + InsertTileInCache(tileIndex,this->GetImage()); + } + + std::cout<<"Cache status: "; + + for(TileCacheType::const_iterator it = m_Cache.begin(); + it != m_Cache.end();++it) + { + std::cout<<it->first<<" "; + } + std::cout<<std::endl; + + return success; +} + +void JPEG2000ReaderInternal::InsertTileInCache(unsigned int tileIndex, opj_image_t * tileData) +{ + for(TileCacheType::const_iterator it = m_Cache.begin(); + it != m_Cache.end();++it) + { + if(it->first == tileIndex) + { + return; + } + } + std::cout<<"Registering new tile"<<std::endl; + if(m_Cache.size() >= m_CacheSizeInTiles) + { + CachedTileType erasedTile = *m_Cache.begin(); + + // Destroy the image + if (erasedTile.second) + { + otbopenjpeg_opj_image_destroy(erasedTile.second); + } + erasedTile.second = NULL; + + m_Cache.pop_front(); + } + + m_Cache.push_back(CachedTileType(tileIndex,tileData)); +} + + JPEG2000ReaderInternal::JPEG2000ReaderInternal() { this->m_Image = NULL; @@ -220,6 +318,9 @@ JPEG2000ReaderInternal::JPEG2000ReaderInternal() this->m_Precision = NULL; this->m_Signed = NULL; + this->m_Cache = TileCacheType(); + this->m_CacheSizeInTiles = 4; + this->Clean(); } @@ -369,6 +470,8 @@ int JPEG2000ReaderInternal::CanRead() else return 0; } + + JPEG2000ImageIO::JPEG2000ImageIO() { m_InternalReader = new JPEG2000ReaderInternal; @@ -471,12 +574,15 @@ void JPEG2000ImageIO::Read(void* buffer) // Decode tile need for (std::vector<unsigned int>::iterator itTile = tileList.begin(); itTile < tileList.end(); itTile++) { - - if (!otbopenjpeg_opj_get_decoded_tile(m_InternalReader->GetCodec(), m_InternalReader->GetStream(), - m_InternalReader->GetImage(), *itTile)) + // First, try to read from the Cache + if(!m_InternalReader->LoadTileFromCache(*itTile)) { - this->m_InternalReader->Clean(); + // If failed, try to read tile from file + if(!m_InternalReader->ReadTileFromFile(*itTile)) + { + this->m_InternalReader->Clean(); itkExceptionMacro(<< " otbopenjpeg failed to decode the desired tile "<< *itTile << "!"); + } } otbMsgDevMacro(<< " Tile " << *itTile << " is decoded."); @@ -576,7 +682,7 @@ void JPEG2000ImageIO::Read(void* buffer) chrono.Stop(); otbMsgDevMacro( << "JPEG2000ImageIO::Read took " << chrono.GetTotal() << " sec"); - m_InternalReader->Clean(); + //m_InternalReader->Clean(); } void JPEG2000ImageIO::ReadImageInformation() @@ -741,6 +847,7 @@ void JPEG2000ImageIO::ComputeOffsets( unsigned int &l_width_src, // Width of the unsigned int &l_start_offset_src // Offset where begin to read the data in the openjpeg decoded data in nb of pixel ) { + std::cout<<"Tile "<<m_InternalReader->GetImage()->x0<<" "<<m_InternalReader->GetImage()->y0<<" "<<m_InternalReader->GetImage()->x1<<" "<<m_InternalReader->GetImage()->y1<<std::endl; // Characteristics of the input buffer from openpjeg unsigned int l_x0_src = m_InternalReader->GetImage()->x0; unsigned int l_y0_src = m_InternalReader->GetImage()->y0;