//  Classes image heritant de TMatrix<T>
//                       R.Ansari, C.Magneville 07/2000    
// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA

#include "sopnamsp.h"
#include "machdefs.h"
#include <stdio.h>
#include <stdlib.h>
#include "pexceptions.h"
#include "datatype.h"
#include <typeinfo>

#define CIMAGE_CC_BFILE  // avoid extern template declarations 
#include "cimage.h"

/*!
   \class SOPHYA::Image
   \ingroup NTools
   This class specializes the Matrix class, for representing intensity 
   (or grey-level) images. It adds the possibility of defining pixel
   size and offset. The convention for the acces operator is also
   changed, compared to the matrix class.
*/

//! Default constructor - Pixel array not allocated
template <class T>
Image<T>::Image()
// Constructeur par defaut.
  : TMatrix<T>()
{
  SetOrg();
  SetPixelSize();
}

//! Constructor, with specification of the image size, pixel size and offsets
template <class T>
Image<T>::Image(sa_size_t sizx, sa_size_t sizy, r_8 szpx, r_8 szpy, r_8 orgx, r_8 orgy)
// Constructeur par defaut.
  : TMatrix<T>(sizy, sizx) 
{
  SetOrg(orgx, orgy);
  SetPixelSize(szpx, szpy);
}

//! Copy constructor
template <class T>
Image<T>::Image(const Image<T>& a)
  : TMatrix<T>(a)
{
  SetOrg(a.XOrg(), a.YOrg() );
  SetPixelSize(a.XPixSize(), a.YPixSize());
}


//! Copy constructor with possibility of duplicating the pixel array
/*!
  \param share : if true, the data is shared, duplicated if false.
*/
template <class T>
Image<T>::Image(const Image<T>& a, bool share)
  : TMatrix<T>(a, share)
{
  SetOrg(a.XOrg(), a.YOrg() );
  SetPixelSize(a.XPixSize(), a.YPixSize());
}

//! Destructor 
template <class T>
Image<T>::~Image()
{
}


// --------------------------------------------------------
//   Les objets delegues pour la gestion de persistance 
// --------------------------------------------------------
/*!
  \class SOPHYA::FIO_Image
  \ingroup Image
  Class for persistent management of Image

 */
///////////////////////////////////////////////////////////

//! Default constructor
template <class T>
FIO_Image<T>::FIO_Image()
  : FIO_TArray<T>()
{
}


//! Constructor from the file \b filename
template <class T>
FIO_Image<T>::FIO_Image(string const & filename) 
  : FIO_TArray<T>(filename) 
{
}

//! Constructor from the Image \b obj
template <class T>
FIO_Image<T>::FIO_Image(const Image<T> & obj) 
  : FIO_TArray<T>()
{ 
  this->dobj = new Image<T>(obj, true);
  this->ownobj=true; 
}

//! Connect with a Image \b obj
template <class T>
FIO_Image<T>::FIO_Image(Image<T> * obj) 
  : FIO_TArray<T>(obj)
{ 
}


//! Connect Image \b o
template <class T>
void FIO_Image<T>::SetDataObj(AnyDataObj & o)
{
  Image<T> * po = dynamic_cast< Image<T> * >(&o);
  if (po == NULL) {
    char buff[160];
    sprintf(buff,"FIO_Image<%s>::SetDataObj(%s) - Object type  error ! ",
	    DataTypeInfo<T>::getTypeName().c_str(), typeid(o).name());
    throw TypeMismatchExc(PExcLongMessage(buff));        
  }
  if (this->ownobj && this->dobj) delete this->dobj;
  this->dobj = po; this->ownobj = false;
} 

template <class T>
void FIO_Image<T>::ReadSelf(PInPersist& is)
{
  if (this->dobj == NULL) this->dobj = new Image<T>;
  Image<T> * img = dynamic_cast<Image<T> * > (this->dobj);
// On lit les 3 premiers uint_4
//  0: Numero de version,  1 : reserve
  uint_4 itab[3];
  is.Get(itab,3);

// Image<T> part data
  r_8 orgx, orgy;
  is.Get(orgx);
  is.Get(orgy);
  img->SetOrg(orgx, orgy);
  r_8 szx, szy;
  is.Get(szx);
  is.Get(szy);
  img->SetPixelSize(szx, szy);

// Reading the TArray part 
  FIO_TArray<T>::ReadSelf(is);
}

template <class T>
void FIO_Image<T>::WriteSelf(POutPersist& os) const
{
  if (this->dobj == NULL)   return;
  Image<T> * img = dynamic_cast<Image<T> * > (this->dobj);
//  On ecrit 3 uint_4 .... 
  uint_4 itab[3];
  itab[0] = 1;  // Numero de version a 1
  itab[1] = 0; 
  itab[2] = 0; 
  os.Put(itab,3);

// Image<T> part data
  os.Put(img->XOrg());
  os.Put(img->XOrg());
  os.Put(img->XPixSize());
  os.Put(img->YPixSize());

// Writing the TArray part 
  FIO_TArray<T>::WriteSelf(os);
}

///////////////////////////////////////////////////////////////
#ifdef __CXX_PRAGMA_TEMPLATES__
#pragma define_template Image<uint_1>
#pragma define_template Image<uint_2>
#pragma define_template Image<uint_4>
#pragma define_template Image<uint_8>
#pragma define_template Image<int_1>
#pragma define_template Image<int_2>
#pragma define_template Image<int_4>
#pragma define_template Image<int_8>
#pragma define_template Image<r_4>
#pragma define_template Image<r_8> 
#pragma define_template Image< complex<r_4> > 
#pragma define_template Image< complex<r_8> > 

#pragma define_template FIO_Image<uint_1>
#pragma define_template FIO_Image<uint_2>
#pragma define_template FIO_Image<uint_4>
#pragma define_template FIO_Image<uint_8>
#pragma define_template FIO_Image<int_1>
#pragma define_template FIO_Image<int_2>
#pragma define_template FIO_Image<int_4>
#pragma define_template FIO_Image<int_8>
#pragma define_template FIO_Image<r_4>
#pragma define_template FIO_Image<r_8>
#pragma define_template FIO_Image< complex<r_4> >
#pragma define_template FIO_Image< complex<r_8> >
#endif

#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
namespace SOPHYA {
template class Image<uint_1>;
template class Image<uint_2>;
template class Image<uint_4>;
template class Image<uint_8>;
template class Image<int_1>;
template class Image<int_2>;
template class Image<int_4>;
template class Image<int_8>;
template class Image<r_4>;
template class Image<r_8>;
template class Image< complex<r_4> >;
template class Image< complex<r_8> >;

template class FIO_Image<uint_1>;
template class FIO_Image<uint_2>;
template class FIO_Image<uint_4>;
template class FIO_Image<uint_8>;
template class FIO_Image<int_1>;
template class FIO_Image<int_2>;
template class FIO_Image<int_4>;
template class FIO_Image<int_8>;
template class FIO_Image<r_4>;
template class FIO_Image<r_8>;
template class FIO_Image< complex<r_4> >;
template class FIO_Image< complex<r_8> >;
}
#endif
