diff --git a/Code/IO/otbImageFileReader.txx b/Code/IO/otbImageFileReader.txx index 4cf2763c5dfd5bd76304255f6aefce647a6b1097..04aa3e22dd01ed321c30efacb88fa91a45e60c06 100755 --- a/Code/IO/otbImageFileReader.txx +++ b/Code/IO/otbImageFileReader.txx @@ -128,21 +128,19 @@ ImageFileReader<TOutputImage> typedef itk::DefaultConvertPixelTraits< typename TOutputImage::IOPixelType > ConvertPixelTraits; - - if ( this->m_ImageIO->GetComponentTypeInfo() == typeid(ITK_TYPENAME ConvertPixelTraits::ComponentType) && (this->m_ImageIO->GetNumberOfComponents() == ConvertPixelTraits::GetNumberOfComponents())) { - itkDebugMacro(<< "No buffer conversion required."); + otbDebugMacro(<< "No buffer conversion required."); // allocate a buffer and have the ImageIO read directly into it this->m_ImageIO->Read(buffer); return; } else // a type conversion is necessary { - itkDebugMacro(<< "Buffer conversion required."); + otbDebugMacro(<< "Buffer conversion required."); // note: char is used here because the buffer is read in bytes // regardles of the actual type of the pixels. ImageRegionType region = output->GetBufferedRegion(); @@ -150,13 +148,13 @@ ImageFileReader<TOutputImage> // l'image (pas celle bufferis�d ans la cas du streaming ) char * loadBuffer = new char[this->m_ImageIO->GetImageSizeInBytes()]; - this->m_ImageIO->Read(loadBuffer); - - itkDebugMacro(<< "Buffer conversion required from: " + + otbDebugMacro(<< "Buffer conversion required from: " << this->m_ImageIO->GetComponentTypeInfo().name() << " to: " << typeid(ITK_TYPENAME ConvertPixelTraits::ComponentType).name()); + this->DoConvertBuffer(loadBuffer, region.GetNumberOfPixels()); delete [] loadBuffer; diff --git a/Code/IO/otbImageIOFactory.cxx b/Code/IO/otbImageIOFactory.cxx index 71552766b5e1ef56c706fba2afea2b20b1c8c26c..644e39e8d9fefebfb603949ccadb12d5c2d48bbf 100755 --- a/Code/IO/otbImageIOFactory.cxx +++ b/Code/IO/otbImageIOFactory.cxx @@ -8,6 +8,7 @@ #include "otbCAIImageIOFactory.h" #include "otbGDALImageIOFactory.h" +#include "otbONERAImageIOFactory.h" namespace otb { @@ -36,11 +37,13 @@ ImageIOFactory::RegisterBuiltInFactories() //For an SPOT5TIF image, if the user set only the directory, this image is read with CAI. //Otherwise, if the user set the name of the image ('IMAGERY.TIF') it read with GDAL. + // ONERA : New format for OTB + itk::ObjectFactoryBase::RegisterFactory( ONERAImageIOFactory::New() ); // GDAL : New format for OTB itk::ObjectFactoryBase::RegisterFactory( GDALImageIOFactory::New() ); // CAI : New format for OTB itk::ObjectFactoryBase::RegisterFactory( CAIImageIOFactory::New() ); - firstTime = false; + firstTime = false; } } diff --git a/Code/IO/otbONERAImageIO.cxx b/Code/IO/otbONERAImageIO.cxx index 9ff68f0ddbcaa0c099ca4b3eafddbf2b9add7d42..3053fc76bcd6106d54472864e3c660d4553353bd 100644 --- a/Code/IO/otbONERAImageIO.cxx +++ b/Code/IO/otbONERAImageIO.cxx @@ -30,9 +30,7 @@ ONERAImageIO::ONERAImageIO() { // By default set number of dimensions to two. this->SetNumberOfDimensions(2); - // By default set pixel type to scalar. m_PixelType = COMPLEX; - // By default set component type to float m_ComponentType = FLOAT; m_NbOctetPixel = 4; @@ -43,88 +41,175 @@ ONERAImageIO::ONERAImageIO() m_Origin[0] = 0.0; m_Origin[1] = 0.0; - m_currentfile = NULL; } ONERAImageIO::~ONERAImageIO() { + if( m_Datafile.is_open() ) + { + m_Datafile.close(); + } + if( m_Headerfile.is_open() ) + { + m_Headerfile.close(); + } } -bool ONERAImageIO::CanReadFile( const char* filename ) -{ - // First check the filename extension - std::ifstream file; - std::string fname(filename); - otbDebugMacro(<< "ONERAImageIO::CanReadFile()"); - if ( fname == "" ) +//GetExtension from uiig library. +static std::string +GetExtension( const std::string& filename ) { + + // This assumes that the final '.' in a file name is the delimiter + // for the file's extension type + const std::string::size_type it = filename.find_last_of( "." ); + + // This determines the file's type by creating a new string + // who's value is the extension of the input filename + // eg. "myimage.gif" has an extension of "gif" + std::string fileExt( filename, it+1, filename.length() ); + + return( fileExt ); +} + +//GetRootName from uiig library. +static std::string +GetRootName( const std::string& filename ) +{ + const std::string fileExt = GetExtension(filename); + + // Create a base filename + // i.e Image.ent --> Image + if( fileExt.length() > 0 ) { - otbDebugMacro(<< "No filename specified."); + const std::string::size_type it = filename.find_last_of( fileExt ); + std::string baseName( filename, 0, it-fileExt.length() ); + return( baseName ); } + //Default to return same as input when the extension is nothing (Analyze) + return( filename ); +} - bool extensionDescriptionFileFound = true; - bool extensionDataFileFound = false; - - std::string::size_type ONERAPos; - ONERAPos = fname.rfind(".DAT"); - if ((ONERAPos != std::string::npos) - && (ONERAPos == fname.length() - 4)) + +static std::string +GetHeaderFileName( const std::string & filename ) +{ + std::string ImageFileName = GetRootName(filename); + std::string fileExt = GetExtension(filename); + //If file was named xxx.img.gz then remove both the gz and the img endings. + if(fileExt.compare("ent")) { - extensionDataFileFound = true; + ImageFileName += ".ent"; + return( ImageFileName ); } + else + { + return(""); + } +} + +//Returns the base image filename. +static std::string GetImageFileName( const std::string& filename ) +{ + std::string fileExt = GetExtension(filename); + std::string ImageFileName = GetRootName(filename); - ONERAPos = fname.rfind(".dat"); - if ((ONERAPos != std::string::npos) - && (ONERAPos == fname.length() - 4)) + if(fileExt.compare("dat") ) { - extensionDataFileFound = true; + ImageFileName += ".dat"; + return( ImageFileName ); } + else + { + //uiig::Reporter* reporter = uiig::Reporter::getReporter(); + //std::string temp="Error, Can not determine compressed file image name. "; + //temp+=filename; + //reporter->setMessage( temp ); + return (""); + } +} +bool ONERAImageIO::CanReadFile( const char* FileNameToRead ) +{ + std::string filename(FileNameToRead); + std::string ext; + if( m_Datafile.is_open() ) + { + m_Datafile.close(); + } + if( m_Headerfile.is_open() ) + { + m_Headerfile.close(); + } - if( (!extensionDataFileFound) || (!extensionDescriptionFileFound) ) + // we check that the correction extension is given by the user + std::string filenameext = GetExtension(filename); + if(filenameext != std::string("ent") + && filenameext != std::string("dat") + ) { - itkDebugMacro(<<"The filename extension is not recognized"); return false; } + const std::string HeaderFileName = GetHeaderFileName(filename); + // + // Try to read ENT file + ext = GetExtension(HeaderFileName); + if(ext != std::string("ent") && ext != std::string("dat")) + { + return false; + } + m_Headerfile.open( HeaderFileName.c_str(), + std::ios::in ); + if( m_Headerfile.fail() ) + { + return false; + } - // Now check the content - std::ifstream inputStream; - file.open( filename, std::ios::in | std::ios::binary ); - if( inputStream.fail() ) +/* if( ! this->ReadBufferAsAscii( local_InputStream, + (void *)&(this->m_hdr), + sizeof(struct dsr) ) ) { return false; } +*/ + // try to read DAT file + const std::string ImageFileName = GetImageFileName(filename); + ext = GetExtension(ImageFileName); + if(ext != std::string("ent") && ext != std::string("dat")) + { + return false; + } + + m_Datafile.open( ImageFileName.c_str(), + std::ios::in | std::ios::binary ); + if( m_Datafile.fail() ) + { + return false; + } + //Read header of the DAT file this->m_ByteOrder = LittleEndian; - // Check to see if its a ONERA file - int magicNumber; - short NbCase; - - file.seekg(0, std::ios::beg ); - file.read((char*)(&magicNumber),4); - file.seekg(6, std::ios::beg ); - file.read((char*)(&NbCol),2); - otbDebugMacro(<< "Magic number Before magicNumber: " << magicNumber); - otbDebugMacro(<< "Magic number Before NbCase: " << NbCase); - + // Check magic_number + int magicNumber; + m_Datafile.seekg(0, std::ios::beg ); + m_Datafile.read((char*)(&magicNumber),4); + itk::ByteSwapper< int>::SwapFromSystemToLittleEndian(&magicNumber); - itk::ByteSwapper< short>::SwapFromSystemToLittleEndian(&NbCol); - - otbDebugMacro(<< "Magic number after : " << magicNumber); - otbDebugMacro(<< "Magic number after : " << NbCase); - file.close(); + otbDebugMacro(<< "Magic number : " << magicNumber); - return magicNumber == ONERA_MAGIC_NUMBER; + m_Datafile.close(); + return magicNumber == ONERA_MAGIC_NUMBER; } + // Used to print information about this object void ONERAImageIO::PrintSelf(std::ostream& os, itk::Indent indent) const { @@ -140,39 +225,71 @@ void ONERAImageIO::ReadVolume(void*) // Read image void ONERAImageIO::Read(void* buffer) { - std::ifstream file; + unsigned int dim; + const unsigned int dimensions = this->GetNumberOfDimensions(); + unsigned long numberOfPixels = 1; + for(dim=0; dim< dimensions; dim++ ) + { + numberOfPixels *= m_Dimensions[ dim ]; + } + + unsigned long step = this->GetNumberOfComponents(); + unsigned char * p = static_cast<unsigned char *>(buffer); + + int lNbLignes = this->GetIORegion().GetSize()[1]; + int lNbColonnes = this->GetIORegion().GetSize()[0]; + int lPremiereLigne = this->GetIORegion().GetIndex()[1] + 1; // [1... ] + int lPremiereColonne = this->GetIORegion().GetIndex()[0] + 1; // [1... ] + +// std::ifstream file; otbMsgDebugMacro( << "ONERAImageIO::Read() Start"); //read header information file: - this->OpenOneraDataFileForReading(file, m_FileName.c_str()); - int HeaderLength = ONERA_HEADER_LENGTH + 4 + 4*2* m_width; - - file.seekg(HeaderLength, std::ios::beg); - - if( !this->ReadBufferAsBinary( file, buffer, this->GetImageSizeInBytes()) ) +// this->OpenOneraDataFileForReading(file, m_FileName.c_str()); + + unsigned long numberOfBytesPerLines = 2* m_width * m_NbOctetPixel; + unsigned long headerLength = ONERA_HEADER_LENGTH + 4 + numberOfBytesPerLines; + unsigned long offset; + unsigned long numberOfBytesToBeRead = 2 * m_NbOctetPixel *lNbColonnes; + unsigned long numberOfBytesRead; + + char* value = new char[numberOfBytesToBeRead]; + unsigned long cpt = 0; + + + for(int LineNo = lPremiereLigne;LineNo <lPremiereLigne + lNbLignes; LineNo++ ) { - itkExceptionMacro(<<"Read failed: Wanted " << this->GetImageSizeInBytes() - << " bytes, but read " << file.gcount() << " bytes."); + offset = headerLength + numberOfBytesPerLines * LineNo; + offset += m_NbOctetPixel * lPremiereColonne; + m_Datafile.seekg(offset, std::ios::beg); + m_Datafile.read( static_cast<char *>( value ), numberOfBytesToBeRead ); + numberOfBytesRead = m_Datafile.gcount(); + if( numberOfBytesRead != numberOfBytesToBeRead ) + if( ( numberOfBytesRead != numberOfBytesToBeRead ) || m_Datafile.fail() ) + { + itkExceptionMacro(<<"ONERAImageIO::Read() Can Read the specified Region"); // read failed + } + + for( unsigned long i=0 ; i < numberOfBytesRead ; i = i+m_NbOctetPixel ) + { + memcpy((void*)(&(p[cpt])),(const void*)(&(value[i])),(size_t)(m_NbOctetPixel)); + cpt += m_NbOctetPixel; + } } //byte swapping depending on pixel type: if(this->GetComponentType() == FLOAT) { - itk::ByteSwapper<float>::SwapRangeFromSystemToBigEndian( - reinterpret_cast<float *>(buffer), - this->GetImageSizeInComponents() ); + itk::ByteSwapper<float>::SwapRangeFromSystemToLittleEndian( + reinterpret_cast<float *>(buffer),cpt); } - //closing file: - file.close(); - otbMsgDebugMacro( << "ONERAImageIO::Read() Finish"); } -bool ONERAImageIO::OpenOneraDataFileForReading(std::ifstream& os, - const char* filename) +bool ONERAImageIO::OpenOneraDataFileForReading(const char* filename) { // Make sure that we have a file to @@ -183,18 +300,18 @@ bool ONERAImageIO::OpenOneraDataFileForReading(std::ifstream& os, } // Close file from any previous image - if ( os.is_open() ) + if ( m_Datafile.is_open() ) { - os.close(); + m_Datafile.close(); } // Open the new file for reading otbDebugMacro(<< "Initialize: opening file " << filename); // Actually open the file - os.open( filename, std::ios::in | std::ios::binary ); + m_Datafile.open( filename, std::ios::in | std::ios::binary ); - if ( os.fail() ) + if ( m_Datafile.fail() ) { return false; } @@ -205,9 +322,7 @@ bool ONERAImageIO::OpenOneraDataFileForReading(std::ifstream& os, void ONERAImageIO::ReadImageInformation() { - std::ifstream file; - this->InternalReadImageInformation(file); - file.close(); + this->InternalReadImageInformation(m_Datafile); } @@ -216,25 +331,26 @@ void ONERAImageIO::ReadImageInformation() void ONERAImageIO::InternalReadImageInformation(std::ifstream& file) { //read .ent file (header) - if ( ! this->OpenOneraDataFileForReading(file, m_FileName.c_str()) ) + if ( ! this->OpenOneraDataFileForReading(m_FileName.c_str()) ) { itkExceptionMacro(<< "Cannot read requested file"); } // Find info... - float NbCol; - float NbRow; - - file.seekg(ONERA_FILE_ID_OFFSET + 4, std::ios::beg ); - file.read((char*)(&NbCol), 4); - file.read((char*)(&NbRow), 4); - itk::ByteSwapper<float>::SwapFromSystemToBigEndian(&NbCol); - itk::ByteSwapper<float>::SwapFromSystemToBigEndian(&NbRow); + short NbCol; + short NbRow; + + m_Datafile.seekg(6, std::ios::beg ); + m_Datafile.read((char*)(&NbCol),2); + otbDebugMacro(<< "Magic number Before NbCase: " << NbCol); + + itk::ByteSwapper< short>::SwapFromSystemToLittleEndian(&NbCol); - file.seekg(0, std::ios::end); + m_Datafile.seekg(0, std::ios::end); long gcountHead = static_cast<long>(ONERA_HEADER_LENGTH + 2*4*NbCol); - long gcount = static_cast<long>(file.tellg()); + long gcount = static_cast<long>(m_Datafile.tellg()); + // Set dim X,Y m_width = static_cast<int> ( NbCol ); diff --git a/Code/IO/otbONERAImageIO.h b/Code/IO/otbONERAImageIO.h index a68e488974781c2104d3583c05dcc7465fcbeeba..fcba33137be1130174c5de50a465056909d2c4fa 100644 --- a/Code/IO/otbONERAImageIO.h +++ b/Code/IO/otbONERAImageIO.h @@ -89,7 +89,7 @@ protected: /** Destructor.*/ ~ONERAImageIO(); - bool OpenOneraDataFileForReading(std::ifstream& os, const char* filename); + bool OpenOneraDataFileForReading(const char* filename); void InternalReadImageInformation(std::ifstream& file); void PrintSelf(std::ostream& os, itk::Indent indent) const; @@ -102,9 +102,9 @@ protected: int m_NbBands; /** Buffer*/ //float **pafimas; + std::ifstream m_Datafile; + std::ifstream m_Headerfile; - const char* m_currentfile; - private: ONERAImageIO(const Self&); //purposely not implemented void operator=(const Self&); //purposely not implemented