Commit 719c3c3e authored by Jordi Inglada's avatar Jordi Inglada
Browse files

Mega Wave format added

parent 132a5a96
......@@ -29,6 +29,7 @@
#include "otbLUMImageIOFactory.h"
#include "otbBSQImageIOFactory.h"
#include "otbRADImageIOFactory.h"
#include "otbMWImageIOFactory.h"
#ifdef OTB_COMPILE_JPEG2000
#include "otbJPEG2000ImageIOFactory.h"
......@@ -62,7 +63,10 @@ namespace otb
itk::MutexLockHolder<itk::SimpleMutexLock> mutexHolder( mutex );
if( firstTime )
{
// MegaWave format for OTB
itk::ObjectFactoryBase::RegisterFactory( MWImageIOFactory::New() );
// RAD Format for OTB
itk::ObjectFactoryBase::RegisterFactory( RADImageIOFactory::New() );
......
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "otbMWImageIO.h"
#include "itkByteSwapper.h"
#include <itksys/SystemTools.hxx>
#include <string.h> // for strncpy
#include "itkExceptionObject.h"
#include "otbMacro.h"
#include "itkMacro.h"
#include "otbSystem.h"
namespace otb
{
MWImageIO::MWImageIO()
{
// By default set number of dimensions to two.
this->SetNumberOfDimensions(2);
m_PixelType = SCALAR;
m_ComponentType = UCHAR;
if ( itk::ByteSwapper<char>::SystemIsLittleEndian() == true)
{
m_ByteOrder = LittleEndian;
}
else
{
m_ByteOrder = BigEndian;
}
m_FileByteOrder = BigEndian;
// Set default spacing to one
m_Spacing[0] = 1.0;
m_Spacing[1] = 1.0;
// Set default origin to zero
m_Origin[0] = 0.0;
m_Origin[1] = 0.0;
m_FlagWriteImageInformation = true;
m_Ncom = 0;
}
MWImageIO::~MWImageIO()
{
if( m_File.is_open() )
{
m_File.close();
}
}
bool MWImageIO::CanReadFile( const char* filename )
{
std::string lFileName(filename);
// Test the extension
std::string extension = GetExtension(filename);
if((extension!="img")&&(extension!=""))
{
return false;
}
if( System::IsADirName(lFileName) == true )
{
return false;
}
if( m_File.is_open() )
{
m_File.close();
}
std::fstream header_file;
header_file.open( filename, std::ios::in | std::ios::binary );
if( header_file.fail() )
{
otbMsgDevMacro(<<"MWImageIO::CanReadFile() failed header open ! " );
return false;
}
//Read header informations
bool lResult = InternalReadHeaderInformation(header_file,false);
header_file.close();
return (lResult);
}
// Used to print information about this object
void MWImageIO::PrintSelf(std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf(os, indent);
}
// Read a 3D image (or event more bands)... not implemented yet
void MWImageIO::ReadVolume(void*)
{
}
// Read image
void MWImageIO::Read(void* buffer)
{
char * p = static_cast<char *>(buffer);
int lNbLignes = this->GetIORegion().GetSize()[1];
int lNbColonnes = this->GetIORegion().GetSize()[0];
int lPremiereLigne = this->GetIORegion().GetIndex()[1] ; // [1... ]
int lPremiereColonne = this->GetIORegion().GetIndex()[0] ; // [1... ]
otbMsgDevMacro( <<" MWImageIO::Read() ");
otbMsgDevMacro( <<" Dimensions de l'image : "<<m_Dimensions[0]<<","<<m_Dimensions[1]);
otbMsgDevMacro( <<" Region lue (IORegion) : "<<this->GetIORegion());
otbMsgDevMacro( <<" Nb Of Components : "<<this->GetNumberOfComponents());
std::streamoff headerLength = static_cast<std::streamoff> (64*sizeof(char)) + static_cast<std::streamoff> (m_Ncom*sizeof(char));
std::streamoff numberOfBytesPerLines = static_cast<std::streamoff>(this->GetComponentSize() * m_Dimensions[0]);
std::streamoff offset;
std::streamsize numberOfBytesToBeRead = static_cast<std::streamsize>(this->GetComponentSize() * lNbColonnes);
std::streamsize numberOfBytesRead;
std::streamsize cpt = 0;
for(int LineNo = lPremiereLigne;LineNo <lPremiereLigne + lNbLignes; LineNo++ )
{
offset = headerLength + numberOfBytesPerLines * static_cast<std::streamoff>(LineNo);
offset += static_cast<std::streamoff>(this->GetComponentSize() * lPremiereColonne);
m_File.seekg(offset, std::ios::beg);
m_File.read( static_cast<char *>( p + cpt ), numberOfBytesToBeRead );
numberOfBytesRead = m_File.gcount();
#ifdef __APPLE_CC__
// fail() is broken in the Mac. It returns true when reaches eof().
if ( numberOfBytesRead != numberOfBytesToBeRead )
#else
if ( ( numberOfBytesRead != numberOfBytesToBeRead ) || m_File.fail() )
#endif
{
itkExceptionMacro(<<"MWImageIO::Read() Can Read the specified Region"); // read failed
}
cpt += numberOfBytesToBeRead;
}
unsigned long numberOfPixelsPerLines = lNbLignes * lNbColonnes;
// Swap bytes if necessary
if ( 0 ) {}
otbSwappFileToSystemMacro( float, FLOAT, buffer, numberOfPixelsPerLines )
else
{
itkExceptionMacro(<<"MWImageIO::Read() undefined component type! " );
}
}
void MWImageIO::ReadImageInformation()
{
if( m_File.is_open() )
{
m_File.close();
}
m_File.open( m_FileName.c_str(), std::ios::in | std::ios::binary );
if( m_File.fail() )
{
itkExceptionMacro(<<"MWImageIO::ReadImageInformation() failed header open ! " );
}
//Read header informations
InternalReadHeaderInformation(m_File,true);
otbMsgDebugMacro( <<"Driver to read: MW");
otbMsgDebugMacro( <<" Read file : "<< m_FileName);
otbMsgDebugMacro( <<" Size : "<<m_Dimensions[0]<<","<<m_Dimensions[1]);
otbMsgDebugMacro( <<" ComponentType : "<<this->GetComponentType() );
otbMsgDebugMacro( <<" NumberOfComponents : "<<this->GetNumberOfComponents());
otbMsgDebugMacro( <<" ComponentSize : "<<this->GetComponentSize());
otbMsgDebugMacro( <<" GetPixelSize : "<<this->GetPixelSize());
}
bool MWImageIO::InternalReadHeaderInformation(std::fstream & file, const bool reportError)
{
char * headerInformation = new char[64];
file.seekg(0, std::ios::beg );
file.read(headerInformation,64);
unsigned short NbCol(0);
unsigned short NbLig(0);
unsigned short Nbcom(0);
//Set file byte order
if( headerInformation[0] == *("R") || headerInformation[1] == *("I") )
{
m_FileByteOrder = BigEndian;
//Read image dimensions
Nbcom = (headerInformation[3]<<8) + headerInformation[2];
m_Ncom = Nbcom;
NbCol = (headerInformation[5]<<8) + headerInformation[4];
NbLig = (headerInformation[7]<<8) + headerInformation[6];
}
else if( headerInformation[0] == *("I") || headerInformation[1] == *("R") )
{
m_FileByteOrder = LittleEndian;
//Read image dimensions
Nbcom = (headerInformation[2]<<8) + headerInformation[3];
m_Ncom = Nbcom;
NbCol = (headerInformation[4]<<8) + headerInformation[5];
NbLig = (headerInformation[6]<<8) + headerInformation[7];
}
else
{
itkExceptionMacro(<< "MW : impossible to determine CodePix information of the image");
return false;
}
SetComponentType(FLOAT);
//Initialisation of image informations
m_Dimensions[0] = NbCol;
m_Dimensions[1] = NbLig;
this->SetNumberOfComponents(1);
this->SetFileTypeToBinary();
this->SetNumberOfDimensions(2);
delete[] headerInformation;
return(true);
}
bool MWImageIO::CanWriteFile( const char* filename )
{
std::string lFileName(filename);
std::string extension = GetExtension(filename);
if ((extension!="img")&&(extension!=""))
{
return false;
}
else if( System::IsADirName(lFileName) == true )
{
return false;
}
else
{
return true;
}
}
void MWImageIO::Write(const void* buffer)
{
if( m_FlagWriteImageInformation == true )
{
this->WriteImageInformation();
m_FlagWriteImageInformation = false;
}
unsigned long lNbLignes = this->GetIORegion().GetSize()[1];
unsigned long lNbColonnes = this->GetIORegion().GetSize()[0];
unsigned long lPremiereLigne = this->GetIORegion().GetIndex()[1] ; // [1... ]
int lPremiereColonne = this->GetIORegion().GetIndex()[0] ; // [1... ]
// Cas particuliers : on controle que si la r�gion � �crire est de la m�me dimension que l'image enti�re,
// on commence l'offset � 0 (lorsque que l'on est pas en "Streaming")
if( (lNbLignes == m_Dimensions[1]) && (lNbColonnes == m_Dimensions[0]))
{
otbMsgDevMacro(<<"Force l'offset de l'IORegion � 0");
lPremiereLigne = 0;
lPremiereColonne = 0;
}
otbMsgDevMacro( <<" MWImageIO::Write() ");
otbMsgDevMacro( <<" Dimensions de l'image : "<<m_Dimensions[0]<<","<<m_Dimensions[1]);
otbMsgDevMacro( <<" Region lue (IORegion) : "<<this->GetIORegion());
otbMsgDevMacro( <<" Nb Of Components : "<<this->GetNumberOfComponents());
otbMsgDevMacro( <<" GetComponentSize : "<<this->GetComponentSize());
std::streamoff numberOfBytesPerLines = this->GetComponentSize() * m_Dimensions[0];
std::streamoff headerLength = static_cast<std::streamoff> (64*sizeof(char)) + static_cast<std::streamoff> (m_Ncom*sizeof(char));
std::streamoff offset;
std::streamsize numberOfBytesToBeWrite = this->GetComponentSize() * lNbColonnes;
std::streamsize cpt = 0;
const char * p = static_cast<const char *>(buffer);
for(unsigned long LineNo = lPremiereLigne;LineNo <lPremiereLigne + lNbLignes; LineNo++ )
{
offset = headerLength + numberOfBytesPerLines * static_cast<std::streamoff>(LineNo);
offset += static_cast<std::streamoff>(this->GetComponentSize() * lPremiereColonne);
m_File.seekp(offset, std::ios::beg);
m_File.write( static_cast<const char *>( p + cpt ), numberOfBytesToBeWrite );
cpt += numberOfBytesToBeWrite;
}
}
void MWImageIO::WriteImageInformation()
{
if ( m_FileName == "" )
{
itkExceptionMacro(<<"A FileName must be specified.");
}
if( CanWriteFile(m_FileName.c_str()) == false)
{
itkExceptionMacro(<< "The file "<<m_FileName.c_str()<<" is not defined as a MW file");
}
// Close file from any previous image
if ( m_File.is_open() )
{
m_File.close();
}
// Open the new file for writing
// Actually open the file
m_File.open( m_FileName.c_str(), std::ios::out | std::ios::trunc | std::ios::binary );
if( m_File.fail() )
{
itkExceptionMacro(<< "Cannot write requested file "<<m_FileName.c_str()<<".");
}
//Writing header information
if( 0 ) {}
if( (this->GetComponentType() != FLOAT) )
{
itkExceptionMacro(<< "MegaWave fimage format only accepts FLOAT32 data type");
}
m_File.seekp(0, std::ios::beg );
char header[64];
std::string comments("Image written with otb mw_IO_factory");
m_Ncom = comments.length();
//Initialization to 0
for (unsigned int i =0; i<64; i++)
header[i] = static_cast<unsigned char>(0);
//Write image size and other information
unsigned short lNbComments = m_Ncom;
unsigned short lNbLignes = static_cast<unsigned short>(this->GetIORegion().GetSize()[1]);
unsigned short lNbColonnes =static_cast<unsigned short>( this->GetIORegion().GetSize()[0]);
unsigned short low,high;
if (m_ByteOrder == BigEndian)
{
header[0] = *("R");
header[1] = *("I");
ByteSplitting(lNbComments,low,high);
header[2] = static_cast<unsigned char>(low);
header[3] = static_cast<unsigned char>(high);
ByteSplitting(lNbColonnes,low,high);
header[4] = static_cast<unsigned char>(low);
header[5] = static_cast<unsigned char>(high);
ByteSplitting(lNbLignes,low,high);
header[6] = static_cast<unsigned char>(low);
header[7] = static_cast<unsigned char>(high);
}
else if (m_ByteOrder == LittleEndian)
{
header[0] = *("I");
header[1] = *("R");
ByteSplitting(lNbComments,low,high);
header[3] = static_cast<unsigned char>(low);
header[2] = static_cast<unsigned char>(high);
ByteSplitting(lNbColonnes,low,high);
header[5] = static_cast<unsigned char>(low);
header[4] = static_cast<unsigned char>(high);
ByteSplitting(lNbLignes,low,high);
header[7] = static_cast<unsigned char>(low);
header[6] = static_cast<unsigned char>(high);
}
else
{
itkExceptionMacro(<< "Unknown Byte order");
}
m_File.write(header,64);
m_File.write(comments.data(),36);
otbMsgDebugMacro( <<"Driver to write: MW");
otbMsgDebugMacro( <<" Write file : "<< m_FileName);
otbMsgDebugMacro( <<" Size : "<<m_Dimensions[0]<<","<<m_Dimensions[1]);
otbMsgDebugMacro( <<" Type Mw : "<<m_TypeMW);
otbMsgDebugMacro( <<" ComponentType : "<<this->GetComponentType() );
otbMsgDebugMacro( <<" NumberOfComponents : "<<this->GetNumberOfComponents());
otbMsgDebugMacro( <<" ComponentSize : "<<this->GetComponentSize());
otbMsgDebugMacro( <<" GetPixelSize : "<<this->GetPixelSize());
}
std::string MWImageIO::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() );
//If the extension has a "/" in it then this is not an extension and there are no extension.
std::string::size_type it2 = fileExt.find_last_of("/");
if ( it2!=std::string::npos )
{
std::string fileExt3("");
return( fileExt3 );
}
else
return( fileExt );
}
} // end namespace otb
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef __otbMWImageIO_h
#define __otbMWImageIO_h
#include "itkImageIOBase.h"
#include <fstream>
#include <string>
#include <vector>
namespace otb
{
/** \class MWImageIO
*
* \brief ImageIO object for reading (not writing) MW format images
*
* The streaming read is implemented.
*
* \ingroup IOFilters
*
*/
class ITK_EXPORT MWImageIO : public itk::ImageIOBase
{
public:
/** Standard class typedefs. */
typedef MWImageIO Self;
typedef itk::ImageIOBase Superclass;
typedef itk::SmartPointer<Self> Pointer;
/** Byte order typedef */
typedef Superclass::ByteOrder ByteOrder;
/** Method for creation through the object factory. */
itkNewMacro(Self);
/** Run-time type information (and related methods). */
itkTypeMacro(MWImageIO, itk::ImageIOBase);
/*-------- This part of the interface deals with reading data. ------ */
/** Determine the file type. Returns true if this ImageIO can read the
* file specified. */
virtual bool CanReadFile(const char*);
/** Determine the file type. Returns true if the ImageIO can stream read the specified file */
virtual bool CanStreamRead(){ return true; };
/** Set the spacing and dimention information for the set filename. */
virtual void ReadImageInformation();
/** Reads the data from disk into the memory buffer provided. */
virtual void Read(void* buffer);
/** Reads 3D data from multiple files assuming one slice per file. */
virtual void ReadVolume(void* buffer);
/*-------- This part of the interfaces deals with writing data. ----- */
/** Determine the file type. Returns true if this ImageIO can read the
* file specified. */
virtual bool CanWriteFile(const char*);
/** Determine the file type. Returns true if the ImageIO can stream write the specified file */
virtual bool CanStreamWrite() { return true; };
/** Writes the spacing and dimentions of the image.
* Assumes SetFileName has been called with a valid file name. */
virtual void WriteImageInformation();
/** Writes the data to disk from the memory buffer provided. Make sure
* that the IORegion has been set properly. */
virtual void Write(const void* buffer);
// JULIEN: NOT USED, NOT IMPLEMENTED
//void SampleImage(void* buffer,int XBegin, int YBegin, int SizeXRead, int SizeYRead, int XSample, int YSample);
protected:
/** Construtor.*/
MWImageIO();
/** Destructor.*/
~MWImageIO();
bool OpenOneraDataFileForReading(const char* filename);
bool OpenOneraHeaderFileForReading(const char* filename);
void InternalReadImageInformation();
bool OpenOneraDataFileForWriting(const char* filename);
bool OpenOneraHeaderFileForWriting(const char* filename);
void PrintSelf(std::ostream& os, itk::Indent indent) const;
private:
MWImageIO(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
/** Internal method to read filename extension */
std::string GetExtension( const std::string& filename );
/** Internal method to read header informations */
bool InternalReadHeaderInformation(std::fstream & file, const bool reportError);
inline void ByteSplitting(unsigned short a, unsigned short &low, unsigned short &high){
unsigned short b = 255;
low = a & b;
high = (a>>8) & b;
}
#define otbSwappFileOrderToSystemOrderMacro(StrongType, buffer, buffer_size) \
{ \
typedef itk::ByteSwapper< StrongType > InternalByteSwapperType; \
if ( m_ByteOrder != m_FileByteOrder ) \
{ \
if ( m_ByteOrder == LittleEndian ) \
{ \
InternalByteSwapperType::SwapRangeFromSystemToBigEndian( (StrongType *)buffer, buffer_size ); \
} \
else if ( m_ByteOrder == BigEndian ) \
{ \
InternalByteSwapperType::SwapRangeFromSystemToLittleEndian((StrongType *)buffer, buffer_size ); \
} \
} \
}
#define otbSwappFileToSystemMacro(StrongType, WeakType, buffer, buffer_size) \
else if ( this->GetComponentType() == WeakType ) \
{ \
otbSwappFileOrderToSystemOrderMacro( StrongType, buffer, buffer_size )\
}
bool m_FlagWriteImageInformation;
std::string m_TypeMW; //used for write
itk::ImageIOBase::ByteOrder m_FileByteOrder;
std::fstream m_File;
uint m_Ncom;
};
} // end namespace otb
#endif // __otbMWImageIO_h
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$