//  Classes image typee      
//                    E.Aubourg , E. Lesquoy  01-03/95   
//                    Modifs R. Ansari   04/95

// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA

// $Id: cimage.cc,v 1.1.1.1 1999-11-26 16:37:09 ansari Exp $        


#include "machdefs.h"
#include <string.h>
#include <stdio.h>

#include "perrors.h"
#include "cimage.h"
#include "fct1dfit.h"
#include "histos.h"
#include "nbconst.h"
#include "utils.h"

/* ..............   Classe  Image<T>    ...............   */

//++
// Class 	Image<T>
// Lib 		Images++
// include	cimage.h
//
//
//	Classe descendant (heritier) de la classe *RzImage*, permettant
//	l'instantiation d'objets image avec un typage fort (entier, reel, ...)
//
//	Des objets de type "Image<uint_1>, Image<uint_2>, Image<int_2>, Image<int_4>"
//	(entier) et "Image<r_4>" (flottant) peuvent etre crees.
//	Des typedef (*ImageU1*, *ImageU2*, *ImageI2*, *ImageI4*, *ImageR4*) 
//	facilite l'utilisation de ces classes.
//--
//++
// Links	Parents
// RzImage
//--
//++
// Links	Descendants
// FitsImage<T>
//--
//++
// Links	Voir aussi
// DVList
//--

//++
// Titre	Constructeurs
//--

//++
// Image<T>(int sizx, sizy, int zero)
//	Creation d'une image de type "T", de taille "sizx*sizy" pixels.
//	Si "zero" non nul, tous les pixels de l'image sont mis a zero.
// Image<T>(char* flnm)
//	Cree une image a partir du fichier "flnm". Celui-ci doit etre 
//	au format "PPF" et cree par la methode "Save() ou "Write()".
//--

template <class T>
Image<T>::Image(int sizx, int sizy, int zero)
: RzImage(DataType((T)0), sizx, sizy), imagePtr( (T*) voidP )
{
  if (zero) Zero();
  END_CONSTRUCTOR
}

/* --Methode-- */
template <class T>
Image<T>::Image()
: RzImage(DataType((T)0)), imagePtr(0)
{
  END_CONSTRUCTOR
}


/* --Methode-- */
template <class T>
void Image<T>::Allocate(int sizx, int sizy, int zero, ImgVectP* pvpsh)
{
  RzImage::Allocate(DataType((T)0), sizx, sizy, pvpsh);
  imagePtr = (T*) voidP;
  if (!imagePtr) THROW(allocationErr);
  if (zero) Zero();
}

template <class T>
void Image<T>::SetPixels(int szx, int szy, T* pim)
{
  RzImage::SetPixels(DataType((T)0), szx, szy, pim);
  imagePtr = pim;
}

/* --Methode-- */
template <class T>
Image<T>::~Image()
{}


//++
// Image<T>(const Image<T>& src, int sharePixels)
//	Constructeur par copie. Fabrique une image identique a l'image "src".
//	Si "sharePixels" est non nul, le tableau des pixels est commun 
//	aux deux images ("src" et celle creee)
// Image<T>(const Image<T>& src, int orgx, int orgy, int sizx, int sizy)
//	Construit une image de type "T", a partir des pixels de l'image
//	"src" (du meme type), de taille "sizx*sizy" et de l'origine
//	"orgx, orgy" dans "src". Si "orgx" et/ou "orgy" sont negatifs,
//	la taille de la nouvelle image est automatiquement calculee 
//	pour contenir toute l'image source a partir de l'origine specifiee.
//	Genere l'exception "sizeMismatchErr" en cas d'incompatibilite 
//	taille/origine. 
//--

/* --Methode-- */
template <class T> 
Image<T>::Image(const Image<T>& src, int sharePixels)
: RzImage(src, sharePixels)
{
  imagePtr = (T*) voidP;
  if (!imagePtr) THROW(allocationErr);
  END_CONSTRUCTOR
}

/* --Methode-- */
template <class T> 
Image<T>::Image(const Image<T>& src, int orgx, int orgy, int sizx, int sizy)
:RzImage()
{
  // A optimiser...
  if (sizx < 0) sizx = src.XSize()-orgx;
  if (sizy < 0) sizy = src.YSize()-orgy;
  if (orgx+sizx > src.XSize() || orgy+sizy > src.YSize())
    THROW(sizeMismatchErr);

  Allocate(sizx, sizy);
  for (int i=0; i<sizx; i++)
    for (int j=0; j<sizy; j++)
      (*this)(i,j) = src(i+orgx, j+orgy);

  SetOrg(src.XOrg()+orgx, src.YOrg()+orgy);
  SetPxSize(src.XPxSize(), src.YPxSize());    
  END_CONSTRUCTOR
}

//++
// LaTeX 	Pour contrer un mauvais espacement des paragraphes de LaTeX
// \newpage
//--
//++
// Image<T>()
//	Creation d'une image de type "T" sans allocation du tableau des pixels.
//	Le tableau des pixels devra etre ensuite alloue par la methode "Allocate()"
//--

//++
// Image<T>(const RzImage& rzimg)
//	Permet de construire une image typee a partir d'une RzImage ("rzimg")
//	Le tableau des pixels est commun aux deux images.
//	Les pixels de l'image "rzimg" doivent etre du type "T", sinon 
//	l'exception "typeMismatchErr" est generee.
//--
/* --Methode-- */
template <class T>
Image<T>::Image(const RzImage& rzimg)
:RzImage(rzimg,1)
{

  if (rzimg.PixelType() != DataType((T)0))
    THROW(typeMismatchErr);
  imagePtr = (T*) voidP;
  if (!imagePtr) THROW(allocationErr);

  END_CONSTRUCTOR
}

//++
// void Allocate(int sizx, int sizy, int zero=1, ImgVectP* pvpsh=NULL)
//	Alloue le tableau des pixels.
//--
//++
// ~Image<T>
//	Destructeur. supprime le tableau des pixels en memoire si celui-ci
//	n'est pas utilise par d'autres objets image.
//--

/* --Methode-- */
template <class T> 
Image<T>::Image(char *flnm)
:RzImage(flnm)
{
  imagePtr = (T*) voidP;
  if (!imagePtr) THROW(allocationErr);

  END_CONSTRUCTOR
}


/* --Methode-- */
template <class T> 
void  Image<T>::ReadSelf(PInPersist& s)
{
  RzImage::ReadSelf(s);
  imagePtr = (T*) voidP;
}

//++
// Titre	Operateurs
//	Un grand nombre des operations pouvant etre effectuees sur un 
//	tableau de nombre ont ete defini pour les objets "Image<T>"
//	Dans les operations faisant intervenir deux images, l'exception
//	"sizeMismatchErr" est generee si les tailles (en X ou en Y) des 
//	deux images ne sont pas identiques.
//--

//++
// Image<T>& operator= (const Image<T>& rhs)
//	Copie le contenu (valeurs des pixels) de l'image "rhs".
//	Si l'image destination (membre gauche de =) n'a pas son 
//	tableau de pixels alloue, celui-ci est cree a une taille
//	identique a celle de "rhs"
// Image<T>& operator= (T val)
//	Met tous les pixels de l'image a la valeur "val"
//--

/* --Methode-- */
template <class T> 
Image<T>& Image<T>::operator = (const Image<T>& src)
{
  if (imagePtr) {
    if (siz_x != src.siz_x || siz_y != src.siz_y)
      THROW(sizeMismatchErr);
  } else
    Allocate(src.siz_x, src.siz_y);
  
  (RzImage)(*this) = (RzImage)src;
  return *this;
}

/* --Methode-- */
template <class T> 
Image<T>& Image<T>::operator = (T a)
{
  T* pDst = imagePtr;
  int nPix = siz_x * siz_y;

  for (int i=0; i<nPix; i++, pDst++)
    *pDst = a;

  return *this;
}

/* --Methode-- */
template <class T>
void Image<T>::Zero()
{
  memset(imagePtr,0,siz_x * siz_y * sizeof(T));
}

/* --Methode-- */
#if 0 // a la mort de RzImage
template <class T>
void Image<T>::Clear()
{
  if (imagePtr) {
    delete[] imagePtr;
    imagePtr = 0;
    siz_x = 0;
    siz_y = 0;
  }
}
#endif

/* --Methode-- */
template <class T> 
Image<T>& Image<T>::operator+= (Image<T> const& a)
{
  if (siz_x != a.siz_x || siz_y != a.siz_y)
    THROW(sizeMismatchErr);
  T* pSrc = a.imagePtr;
  T* pDst = imagePtr;
  int nPix = siz_x * siz_y;

  for (int i=0; i<nPix; i++, pSrc++, pDst++)
    *pDst = PutInRange((double)*pSrc + (double)*pDst, *pDst);

  return *this;
}


/* --Methode-- */
template <class T> 
Image<T>& Image<T>::operator-= (Image<T> const& a)
{
  if (siz_x != a.siz_x || siz_y != a.siz_y)
    THROW(sizeMismatchErr);
  T* pSrc = a.imagePtr;
  T* pDst = imagePtr;
  int nPix = siz_x * siz_y;

  for (int i=0; i<nPix; i++, pSrc++, pDst++)
    *pDst = PutInRange((double)*pDst - (double)*pSrc, *pDst);

  return *this;
}

/* --Methode-- */
template <class T> 
Image<T>& Image<T>::operator*= (Image<T> const& a)
{
  if (siz_x != a.siz_x || siz_y != a.siz_y)
    THROW(sizeMismatchErr);
  T* pSrc = a.imagePtr;
  T* pDst = imagePtr;
  int nPix = siz_x * siz_y;

  for (int i=0; i<nPix; i++, pSrc++, pDst++)
    *pDst = PutInRange((double)*pDst * (double)*pSrc, *pDst);

  return *this;
}

/* --Methode-- */
template <class T> 
Image<T>& Image<T>::operator/= (Image<T> const& a)
{
  if (siz_x != a.siz_x || siz_y != a.siz_y)
    THROW(sizeMismatchErr);
  T* pSrc = a.imagePtr;
  T* pDst = imagePtr;
  int nPix = siz_x * siz_y;

  for (int i=0; i<nPix; i++, pSrc++, pDst++)
    if (*pSrc)
      *pDst = PutInRange((double)*pDst / (double)*pSrc, *pDst);
    else *pDst = (T) MaxRange(*pDst);

  return *this;
}

//++
//  Image<T>& operator += -= *= /= (Image<T> const& rhs)
//	Ajoute (+=), soustrait(-=), multiplie(*=), divise(/=) les valeurs des pixels 
//	de l'image a gauche de l'operateur par les pixels correspondants
//	de l'image a droite de l'operateur ("rhs")
//  Image<T>& operator += -= *= /= (double crhs)
//	Ajoute (+=), soustrait(-=), multiplie(*=), divise(/=) les valeurs des pixels 
//	de l'image a gauche de l'operateur par la constante "crhs"
//--


/* --Methode-- */
template <class T> 
Image<T>& Image<T>::operator+= (double a)
{
  T* pDst = imagePtr;
  int nPix = siz_x * siz_y;

  for (int i=0; i<nPix; i++, pDst++)
    *pDst = PutInRange((double)*pDst + a, *pDst);

  return *this;
}

/* --Methode-- */
template <class T> 
Image<T>& Image<T>::operator-= (double a)
{
  T* pDst = imagePtr;
  int nPix = siz_x * siz_y;

  for (int i=0; i<nPix; i++, pDst++)
    *pDst = PutInRange((double)*pDst - a, *pDst);

  return *this;
}

/* --Methode-- */
template <class T> 
Image<T>& Image<T>::operator*= (double a)
{
  T* pDst = imagePtr;
  int nPix = siz_x * siz_y;

  for (int i=0; i<nPix; i++, pDst++)
    *pDst = PutInRange((double)*pDst * a, *pDst);

  return *this;
}


/* --Methode-- */
template <class T> 
Image<T>& Image<T>::operator/= (double a)
{
  T* pDst = imagePtr;
  int nPix = siz_x * siz_y;
  
  for (int i=0; i<nPix; i++, pDst++)
    *pDst = PutInRange((double)*pDst / a, *pDst);
  
  return *this;
}



//++
// Image<T> operator + - * / (Image<T> const& a, Image<T> const& b)
//	Ajoute, soustrait, multiplie, divise les pixels des deux 
//	images "a" et "b" et l'affecte a gauche de l'operateur egal.
// operator + - * / (Image<T> const& a, double cb)
//	Ajoute, soustrait, multiplie, divise le contenu de l'image "a"
//	par la constante "cb" et l'affecte a l'image a gauche de l'operateur = .
// 
//	Il est preferable d'utiliser dans la mesure du possible, les 
//	operateurs "+=", "-=", "*=", "/=" afin d'eviter des copies 
//	inutiles.
//
//	*Exemples:*
//| // Creation des images
//| ImageR4  ai(200,300), bi, ci;
//| // Tous les pixels a 238.5
//| ai = 238.5;
//| // Image bi meme taille, meme valeurs de pixels que ai
//| bi = ai;    
//| // On soustrait 13.2 a tous les pixels de ai
//| ai -= 13.2;
//| // Je divise bi par ai (pixel par pixel) qu'on affecte a bi
//| bi /= ai;
//| // On somme ai et bi (pixel par pixel) qu'on affecte a ci
//| ci = ai + bi; 
//--


/* --Methode-- */
template <class T>
Image<T> Image<T>::WhereNonZero()
{
  Image<T> c(*this);
  for (int i=0; i<XSize(); i++)
    for (int j=0; j<YSize(); j++)
      c(i,j) = c(i,j) ? 1 : 0;
  return c;
}

//++
// void PrintImage(ostream& os) const
//	Envoie le contenu de l'image (formatte, texte) sur le 
//	flot (stream) de sortie "os".
//	Attention: Ca peut faire beaucoup de ligne !
// void PrintImage() const
//	Appel a PrintImage(cout) - Sortie sur cout .
//--


/* --Methode-- */
template <class T>
void Image<T>::PrintImage(ostream& os) const
//  Impression de tout le contenu de l'image
{
#define PrPvLn 10
#define PrSize 6
int i,j,k,ido,ideb,ifin;
int siz_x,siz_y;

siz_x= XSize();
siz_y= YSize();

os << " Image::PrintImage: type pixel " ;
os << DataName(dataType) ;  
os << ", NbPix=("<<siz_x<<","<<siz_y<<") \n";  


/* segmentation avec des lignes de PrPvLn valeurs */

ido = (siz_x-1) / PrPvLn + 1;

char buff[256];

for(k=0;k<ido;k++)
  {
  ideb = k*PrPvLn;
  ifin = ideb + PrPvLn;
  if ( ifin >siz_x ) ifin =  siz_x ;
  sprintf(buff, "    ---- colonnes   %d   a   %d  ----\n",ideb,ifin-1);
  os << buff ;
  for(j=0; j<siz_y; j++)
    {
    sprintf(buff, "%3d - ",j);
    os << buff;
    for (i=ideb; i<ifin; i++)
      {
        os.width(PrSize);
// les uint_1 sont traites comme characteres par les ostream ...
        if (PixelType() == kuint_1) os << ((int)((*this)(i,j))) << " ";
        else os << (*this)(i,j) << " ";
      }
     os << endl;
     }
   }

 return;
}


//++
// Titre	Acces aux pixels
//--
//++
// T&  operator() (int x, int y)
//	Acces au pixel "(x,y)" de l'image (lecture/ecriture)
// T&  operator[] (int i)
//	Acces au pixel numero "i" de l'image (lecture/ecriture)
//
//| ImageU2 img(100,100);
//| int i,j,k;
//| // Remplissage de la moitie de l'image
//| for(k=0; k<100*50; k++)  img[k] = k%500;
//| img(50, 10); // Valeur du pixel (50, 10)
//
// T*  ImagePtr()
//	Renvoie un pointeur du type "T (uint_2, r_4, ...)" sur le
//	tableau des pixels de l'image. A n'utiliser que si un reelle
//	optimisation de l'acces aux pixels peut etre effectuee.
//--



//++
// Titre	Traitements simples
//--
//++
// int  CheckDyn(double min=-9.e19, double max=9.e19)
//	Cette methode retourne le nombre de pixels hors dynamique "( <min ou >max )"
//	Met a jour les donnees membres "min/maxPix nbNul/Sat".
//	Calcule aussi la moyenne et le sigma des pixels -> "moyPix, sigPix"
//	Implementation plus efficace de la methode "RzImage::CheckDyn()"
//--

/* --Methode-- */
template <class T>
int Image<T>::CheckDyn(double min, double max)

/*  Cette methode retourne le nombre de pixels hors dynamique    */
/* ds le pave ( <min ou >max )                                   */
/* Met a jour la structure image Min/MaxPix nbNul/Sat            */
/* Calcule aussi la moyenne et le sigma des pixels, met a jour   */
/* moypix et sigpix dans la structure                            */

{
T pixv=0;
double dv;

T minadu = PutInRange(min, pixv);
T maxadu = PutInRange(max, pixv);
T minpix = PutInRange(maxadu+1, pixv);
T maxpix = PutInRange(minadu-1, pixv);

double m = 0.;
double s = 0.;
int n9 = 0;
int n0 = 0;
int n = XSize()*YSize();
for(int i=0; i<n; i++) 
  {
  pixv = imagePtr[i];
  if (pixv <= maxadu && pixv >= minadu) 
    {  
    if (pixv < minpix)  minpix = pixv;
    else if (pixv > maxpix)  maxpix = pixv;  
    dv = (double)pixv;
    m += dv;  s += (dv*dv);
    }
  else 
    {  
    if (pixv > maxadu)  n9++;
    if (pixv < minadu)  n0++; 
    }
  }

nbNul = n0;
nbSat = n9;
minPix = minpix;
maxPix = maxpix;

n -= (n0+n9);
if (n > 0)
  { dv = (double)n;  m /= dv;  s = s/dv - m*m;
  if (s>0.)  s = sqrt(s);  else s = 0.;
  moyPix = m;  sigPix = s; }
else { moyPix = 0.;  sigPix = -1.; }

return(n0+n9);
}

//++
// SeuilBas(double seuil, double val)
//	Met les pixels en dessous du "seuil" (< seuil) a la valeur "val".
// SeuilBas(double seuil)
//	Met les pixels en dessous du "seuil" (< seuil) a zero
// SeuilHaut(double seuil, double val)
//	Met les pixels au dessus du "seuil" (> seuil) a la valeur "val".
// SeuilHaut(double seuil)
//	Met les pixels au dessus du "seuil" (> seuil) a zero
//--

/* --Methode-- */
template <class T>
void Image<T>::SeuilBas(double seuil, double val)

/*   Met a une valeur definie tous les pixels    */
/*   en dessous du seuil                         */

{
  if (!ImagePtr())   THROW(nullPtrErr);
  T* PtPix=ImagePtr();
  int nPix=XSize()*YSize();
  for(int i=0 ; i<nPix;i++,PtPix++) {if(*PtPix < (T) seuil) *PtPix = (T) val;};
}

/* --Methode-- */
template <class T>
void Image<T>::SeuilHaut(double seuil, double val)

/*   Met a une valeur definie tous les pixels    */
/*   en dessus du seuil                         */

{
  if (!ImagePtr())   THROW(nullPtrErr);
  T* PtPix=ImagePtr();
  int nPix=XSize()*YSize();
  for(int i=0 ; i<nPix;i++,PtPix++) {if(*PtPix > (T) seuil) *PtPix = (T) val;};
}

/* --Methode-- */
template <class T>
void Image<T>::SeuilBas(double seuil)
{
  SeuilBas(seuil,seuil);
}

/* --Methode-- */
template <class T>
void Image<T>::SeuilHaut(double seuil)
{
  SeuilHaut(seuil,seuil);
}

/* --Methode-- (cmv 23/09/96) */
template <class T>
//++
void Image<T>::HBinInt(int& nbin,float& xmin,float& xmax)
//
//	Valeur pour avoir un bin entier quand on fait un
//	histogramme 1D des pixels (pour les images entieres).
//--
{
if( PixelType()<kuint_2 || PixelType()>kint_4 ) return;
double binw = (xmax-xmin)/nbin;
binw = (double) ( (int)(binw+0.5) );
if( binw <= 0. ) binw = 1.;
xmin = (float) ( (int) xmin );
xmax = (float) ( (int) (xmax + binw) );
nbin = (int)( (xmax-xmin)/binw + 0.1 );
}

/* --Methode-- (cmv 23/09/96) */
template <class T>
//++
int Image<T>::EstimeFdSg(float& xbmax,float& sgbmax
             ,float nbsig,float frac,float lowbad,float highbad,int deb)
//
//	Pour donner une estimation  du fond de ciel et du sigma ciel.
//	Il est conseille de faire ceci sur une image partielle.
//	Une premiere estimation du fond et du sigma est faite en nettoyant
//	iterativement (cf MoySigmaIter).
//	Puis un histogramme est rempli et rebinne jusqu'a ce que son maximum
//	soit statistiquement significatif. Le fond et le sigma sont ensuite
//	calcules par les methodes `FitMax' et `EstimeWidthS' de la classe Histo.
//| xbmax = position du maximum
//| sgbmax = valeur du sigma
//| nbsig = dimensionnement de l'histo de depart en nombre
//|         de sigma autour de la valeur maximum
//| frac = valeur maximum principale / maximum secondaire a partir
//|        de laquelle on considere qu'elle a une signification
//|        statistique. 
//| lowbad,highbad = dynamique utile de l'image traitee
//| deb = niveau de debug
//| Return : 0 = OK, -1 = echec MoySigmaIter, -2 = echec FitMax,
//|                  -3 = echec FindWidth
//--
{
T pixv=0;
T minadu = PutInRange((double) lowbad , pixv);
T maxadu = PutInRange((double) highbad, pixv);
bool testl = (lowbad<highbad) ? true : false;
lowbad  = (float) minadu;  highbad = (float) maxadu;

if(deb<0) deb=0;
int envd = 0;
GetIntEnv("PDEBUG_FOND", envd);
if (deb < envd) deb = envd;

// moyenne et sigma bruts (iteratifs)
int rc;
float fd,sg;
rc = MoySigmaIter(fd,sg,lowbad,highbad,1,5,0.1,3.5,deb-1);
if(deb>0) cout<<"EstimeFdSg: MoySigmaIter rc="<<rc<<" fd="<<fd<<" sg="<<sg<<endl;
if(rc<=0) return -1;

// remplissage histogramme avec beaucoup de bins
int nbin;
float xmin,xmax;
xmin = fd - nbsig*sg; if(testl && xmin<lowbad ) xmin = lowbad;
xmax = fd + nbsig*sg; if(testl && xmax>highbad) xmax = highbad;
nbin = XSize()*YSize()/20; if(nbin>2000) nbin=2000;
Histo H(xmin,xmax,nbin);
for(int i=0;i<XSize()*YSize();i++) H.Add((float) (*this)[i],1.);

// redimensionnement de l'histo pour avoir une bonne signification stat.
for(;;) {
  float max1,max2;
  int imax1,imax2;
  rc = H.MaxiLocal(max1,imax1,max2,imax2);
  float rap = 1.;
  if( max1 != 0. ) rap = max2/max1;
  // if(nbin<100) H.Print(80);
  if(deb>1)
     cout<<"nbin="<<nbin
         <<"   maxloc="<<rc
         <<"   maxi="<<max1<<" imax="<<imax1<<" xmax="<<H.BinCenter(imax1)
         <<"   maxn="<<max2<<" imaxn="<<imax2<<" xmaxn="<<H.BinCenter(imax2)
         <<" -> "<<rap<<endl;
  if( rap<frac || nbin<=10 ) break;
  nbin = (int)(nbin/1.5);
  H.HRebin(nbin);
}
if(deb>1) { if(nbin<250) H.Print(80); else H.Print(80,-1.,1.,-1);}

TRY {
  xbmax = H.FitMax(2,0.5f,deb-2);
  if(deb>1) cout<<"H.FitMax = "<<xbmax<<endl;
} CATCHALL {
   if(deb) cout<< "Echec H.FitMax"<< endl;
   return(-2);
} ENDTRY

TRY {
  float sdroit = -2.;
  H.EstimeWidthS(0.5f,sgbmax,sdroit);
  if(sgbmax<=0.) sgbmax = H.FindWidth(0.5f,deb-2);
  sgbmax /= 2.36;
  if(deb>1) cout<<"H.FindWidth = "<<sgbmax<<" (droit="<<sdroit<<")"<<endl;
} CATCHALL {
   cout<< "Echec H.FindWidth"<< endl;
   return(-3);
} ENDTRY

return 0;
}

/* --Methode--  (cmv 23/09/96) */
template <class T>
//++
float Image<T>::FondCiel(int nbin,float bin_low,float bin_high
                         ,int degre,float frac,int modu,int deb)
//
//	Calcul du fond de ciel:
//	Remplissage d'un histogramme avec le contenu des pixels du pave,
//	recherche du bin contenant le maximum,
//	recheche des limites a frac% de chaque cote du maximum
//	et fit d'un polynome du 2sd ou 3ieme degre dans cette zone.
//| Input:
//|   nbin,bin_low,bin_high : definition de l'histogramme
//|   degre : degre du fit (2 ou 3)
//|   frac : definition de la zone de fit a frac% du maximum
//|   modu : on prend 1 px sur modu
//|   deb : debug flag
//| Output: renvoie le maximum de l'histogramme (fond de ciel)
//|         et update le membre protected fond (si succes)
//--
{
T pixv;

if(modu<=0) modu = 1;
if(frac<=0.) frac = 0.5;
if(degre<2 || degre>3) degre = 2;
if(deb>0)
  printf("Image::FondCiel: nbin=%d dyn=%g,%g deg=%d frac=%g modu=%d\n"
        ,nbin,bin_low,bin_high,degre,frac,modu);
if(nbin<=degre) THROW(inconsistentErr);

TRY {

  Histo tab(bin_low,bin_high,nbin);
  double sum = 0.;
  volatile int n = 0, nsum = 0;
  for(int i=0;i<XSize()*YSize();i++) {
    n++;
    if( n%modu != 0 ) continue;
    pixv = imagePtr[i];
    tab.Add( (float) pixv );
    sum += (double) pixv;
    nsum++;
  }
  if(deb>1) { int im = tab.IMax();
              tab.Print(80,1.,-1.,0,im-50,im+50); }

  float xf = 0.;
  // tout dans moins de degre bins
  if( tab.BinNonNul() <= degre ) {
    if(nsum<=0) THROW(inconsistentErr);
    xf = sum / (double) nsum;
    if(deb>0) printf("%d bins <= %d -> Succes Mean = %g\n"
                    ,tab.BinNonNul(),degre,xf);
    fond = xf;
    RETURN(xf);
  }

  TRY {
    xf = tab.FitMax(degre,frac,deb-1);
    if(deb>0) printf("Succes tab.FitMax = %g\n",xf);
    fond = xf;
    RETURN(xf);
  } CATCHALL {
    if(deb>0)
       printf("Echec tab.FitMax BinNonNul=%d\n",tab.BinNonNul());
    THROW(inconsistentErr);
  } ENDTRY

} CATCHALL {
   THROW_SAME;
} ENDTRY
}

/* --Methode-- (cmv 23/09/96) */
template <class T>
//++
float Image<T>::SigmaCiel(int nbin,float bin_low,float bin_high
                         ,float& means,float lowbad,float highbad
                         ,float nsig,int modu,int deb)
//
//	Calcul du sigma du fond de ciel:
//	Remplissage d'un histogramme avec px-<px8> pour les pixels
//	entre lowbad et highbad (px=valeur du pixel etudie,
//	<px8>=moyenne des 8 pixels qui lui sont contigus).
//	Une premiere estimation du sigma (s1) et realisee en cherchant
//	la largeur a mi-hauteur de cet histogramme. Puis un fit non-lineaire
//	d'une gaussienne est effectue dans +/- nsig*s1
//| Input:
//|   nbin,bin_low,bin_high : definition de l'histogramme
//|   lowbad,highbad : limites des pixels a utiliser
//|   nsig : la zone de fit est definie a +/- nsig*sigma du maximum
//|   modu : on prend 1 px sur modu
//|   deb : debug flag
//| Output:
//|   means = moyenne fittee de l'histogramme (normalement -> 0)
//|   renvoie le sigma du fond de ciel
//|     et update le membre protected sigmaFond (si succes)
//--
{
T pixv=0;
T minadu = PutInRange((double) lowbad , pixv);
T maxadu = PutInRange((double) highbad, pixv);
volatile bool testl = (lowbad<highbad) ? true : false;

if(nbin<5) THROW(inconsistentErr);
if(nsig<=0.) nsig = 4.;
if(modu<=0) modu = 1;
means = 0.;
if(deb>0)
  cout << "SigmaCiel( nbin=" << nbin
       << ", bin_low=" << bin_low
       << ", bin_high=" << bin_high
       << ", lowbad=" << lowbad
       << ", highbad=" << highbad
       << ", nsig=" << nsig
       << ", modu=" << modu
       << ", deb=" << deb << endl;

// coeff pour corriger le sigma de (S-<S8>) par rapport au sigma de S
// sigma(S) = sigma(S-<S8>) * 1/sqrt(1+1/8) = 2*sqrt(2)/3
double coeff = 2.*Rac2/3.;

TRY {

  Histo tab(bin_low,bin_high,nbin);
  tab.Errors();

  int nmod = 0, nsum = 0;
  double sum= 0., sum2 = 0.;
  for(int j=1;j<YSize()-1;j++) for(int i=1;i<XSize()-1;i++) {
    nmod++;
    if( nmod%modu != 0 ) continue;
    pixv = (*this)(i,j);
    if ( testl && (pixv < minadu || pixv > maxadu) ) continue;
    double vp = (double) pixv;
    double pxv = 0.;
    volatile int n = 0;
    for(int j1=j-1;j1<=j+1;j1++) for(int i1=i-1;i1<=i+1;i1++) {
      if ( i1 == i && j1 == j ) continue;
      pixv = (*this)(i1,j1);
      if ( testl && (pixv < minadu || pixv > maxadu) ) continue;
      pxv += (double) pixv;
      n++;
    }
    if ( n != 8 ) continue;
    vp = vp - pxv/(double) n;
    tab.Add( (float) vp );
    nsum++;
    sum += vp;
    sum2 += vp*vp;
  }

  float ms = tab.BinCenter( tab.IMax() );
  volatile float sg = 0.;
  if( tab.BinNonNul() == 1 ) {
    if(deb>0) cout << tab.BinNonNul()
                   << " bins non nul dans l'histogramme" << endl;
    if(nsum<=1) THROW(inconsistentErr);
    sum /= (double) nsum;
    sum2 = sum2/(double) nsum - sum*sum;
    if(sum2<0.) THROW(inconsistentErr);
    means = sum;
    sum2 = sqrt(sum2) * coeff;
    sigmaFond = sum2;
    RETURN((float) sum2);
  } else {
    TRY {
      sg = tab.FindWidth(0.5,deb-1) / 2.36;
    } CATCHALL {
      THROW_SAME;
    } ENDTRY
  }
  double h = tab.VMax();
  if(deb>0) cout << "from histo: ms=" << ms 
                           << "  sg=" << sg
                           << "  h=" << h << endl;

  float xmin = ms - nsig*sg;
  float xmax = ms + nsig*sg;
  int imin = tab.FindBin(xmin);
  int imax = tab.FindBin(xmax);
  if( imax-imin+1 < 4 ) {imax++; imin--;}
  if(imin<0) imin=0;
  if(imax>=tab.NBins()) imax=tab.NBins()-1;
  int nb = imax-imin+1;
  if( nb < 4 ) THROW(inconsistentErr);
  if(deb>0) printf("xrange=[%g,%g] irange=[%d,%d] nb=%d\n"
                  ,xmin,xmax,imin,imax,nb);
  if(deb>2) tab.Print(80,1.,-1.,0,imin,imax);

  Gauss1DPol     myfunc;
  GeneralFit     myfit(&myfunc);
  GeneralFitData mydata(1,nb);
  for(int i=imin;i<=imax;i++) {
     float e = tab.Error(i);
     if( e <= 0. ) e = 1.;
     mydata.AddData1(tab.BinCenter(i),tab(i),e);
   }

  myfit.SetData(&mydata);
  myfit.SetParam(0,h,h/50.);
  myfit.SetParam(1,ms,sg/10.);
  myfit.SetParam(2,sg,sg/10.);
  myfit.SetBound(2,0.,sg*5.);
  int rc = myfit.Fit();
  if(rc<0) THROW(inconsistentErr);
  if(deb>1) myfit.PrintFit();

  means = myfit.GetParm(1);
  sum2 = myfit.GetParm(2) * coeff;
  sigmaFond = sum2;
  RETURN((float) sum2);

} CATCHALL {
   THROW_SAME;
} ENDTRY

}


/* --Methode-- (cmv 23/09/96) */
template <class T>
//++
int Image<T>::MoySigma(float& mean,float& sigma,float lowbad,float highbad,int modu)
//
//	Calcul de la moyenne (mean) et du sigma (sigma) dans un pave
//	en ne considerant que les pixels compris entre lowbad et highbad.
//	Seul 1 px sur modu est utilise.
//	La fonction retourne le nombre de pixels utilises pour le calcul.
//--
{
T pixv=0;
T minadu = PutInRange((double) lowbad , pixv);
T maxadu = PutInRange((double) highbad, pixv);
bool testl = (lowbad<highbad) ? true : false;

if(modu<=0) modu = 1;
mean = sigma = 0.;

int rc = 0, n = 0;
double m = 0., s = 0., mm, ss, v;

for(int j=0;j<YSize();j++) {
  mm = ss = 0.;
  for(int i=0;i<XSize();i++) {
    n++;
    if( n%modu != 0 ) continue;
    pixv = (*this)(i,j);
    if( testl && (pixv < minadu || pixv > maxadu) ) continue;
    v = (double) pixv;
    rc++;
    mm += v;
    ss += v*v;
  }
  m += mm;
  s += ss;
}

if(rc==0) return(-1);

m /= (double) rc;
s = s/(double) rc - m*m;
if(s<0.) return(-2);

mean  = (float) m;
sigma = (float) sqrt(s);

moyPix = mean;     // Mise a jour de la structure
sigPix = sigma;

return rc;
}

/* --Methode-- (cmv 23/09/96) */
template <class T>
//++
int Image<T>::MoySigmaIter(float& mean,float& sigma,float lowbad,float highbad
                          ,int modu,int nitermx,float perdiff,float scut,int deb)
//
//	Calcul de moyenne et sigma iterativement:
//| lowbad,highbad = dynamique permise pour la valeur
//|                  des pixels en ADU
//| modu = 1 px sur modu est utilise
//| nitermx = nombre maximum d'iterations permises
//| perdiff = condition d'arret en pourcent sur la variation du sigma
//| scut = coupure en nombre de sigma courant pour l'iteration suivante
//| mean = moyenne retournee
//| sigma = sigma retourne
//| return <= 0 probleme, sinon (>0) nombre de pixels utilises
//--
{
if( scut<=0. || nitermx<=0 || perdiff<=0. ) return 0;
if(modu<=0) modu = 1;
bool testl = (lowbad<highbad) ? true : false;

mean = sigma = 0.;
float sigmaold = 0;
float xmin = lowbad;
float xmax = highbad;
int rc = 0;

for(int it=0;it<nitermx;it++) {
  rc = MoySigma(mean,sigma,xmin,xmax,modu);
  if(deb>0) cout<<"MoySigmaIter mean="<<mean<<" sigma="<<sigma
                <<" npix="<<rc<<" entre "<<xmin<<","<<xmax<<endl;
  if( rc <= 0 || sigma<=0. ) return rc;
  if( it>=1 && fabs((double)(sigma-sigmaold))/sigma < perdiff ) break;
  xmin = mean - scut*sigma; if(testl && xmin<lowbad ) xmin = lowbad;
  xmax = mean + scut*sigma; if(testl && xmax>highbad) xmax = highbad;
  sigmaold = sigma;
}

return rc;
}

/* --Methode-- (cmv 23/09/96) */
template <class T>
//++
int Image<T>::FondSigmaCiel(float lowbad,float highbad,int pvsz
              ,float nbsig1,float nbsig2,float nbsig3
              ,float binsg,float frac,int modu,int deb)
//
//	Calcul automatique du fond de ciel et du sigma ciel en utilisant
//	les methodes precedentes et en calculant au mieux le binning.
//| lowbad,highbad: dynamoque utile de l'image (ADU)
//| pvsz : taille du pave a traiter (centre au milieu de l'image)
//| nbsig1 : pour EstimeFdSg  -> calcul sgbmax (def=3.5).
//| nbsig2 : pour FondCiel (histo entre X maxi +/- nbsig2*sgbmax
//|                        nbin = 2.*nbsig2*binsg) (def=5).
//| nbsig3 : pour SigmaCiel (histo entre 0 +/- nbsig3*sgbmax
//|                         nbin = 2.*nbsig3*binsg) (def=5).
//| binsg : taille du bin pour les histos de FondCiel et SigmaCiel
//|                        (def=0.33)
//| frac : pour EstimeFdSg(...,frac,...)  (def=0.33)
//--
{
if(pvsz<=0) pvsz = 100;
if(nbsig1<=0) nbsig1 = 3.5;
if(nbsig2<=0) nbsig2 = 5.0;
if(nbsig3<=0) nbsig3 = 5.0;
if(binsg<=0) binsg = 0.33; binsg = 1./binsg;
if(frac<=0.) frac = 0.33;
if(deb<0) deb=0;
int lpdb = (deb>=3) ? deb-2 : 0;
int envd = 0;
GetIntEnv("PDEBUG_FOND", envd);
if (lpdb < envd) lpdb = envd;
if (deb < envd) deb = envd;
float xbmax = 0., sgbmax = 0.;
int nbin,rc;
float xmin,xmax,binw,means;

// creation sous image
int pvsx = pvsz, pvsy = pvsz;
if( pvsx > XSize() ) pvsx = XSize();
if( pvsy > YSize() ) pvsy = YSize();
Image<T> *ssima = NULL;
bool cree = false;
if( pvsx == XSize() && pvsy == YSize() ) {
  ssima = this;
} else {
  int orgx = XSize()/2 - pvsx/2;  if( orgx < 0 ) orgx = 0;
  int orgy = YSize()/2 - pvsy/2;  if( orgy < 0 ) orgy = 0;
  if( orgx + pvsx > XSize() ) pvsx = XSize() - orgx;
  if( orgy + pvsy > YSize() ) pvsy = YSize() - orgy;
  ssima = new Image<T>(pvsx,pvsy);
  cree = true;
  CopieImageF(*ssima,*this,orgx,orgy,pvsx,pvsy,0,0,0.,0.);
}

// moyenne et sigma approches sur sous-image
rc = ssima->EstimeFdSg(xbmax,sgbmax,nbsig1,frac,lowbad,highbad,deb-1);
if( cree ) delete ssima;
if(rc<0) return -2;
fond = xbmax;
sigmaFond = sgbmax;

// bin entier... pas forcement necessaire.
xmin = xbmax - nbsig2*sgbmax;
xmax = xbmax + nbsig2*sgbmax;
nbin = (int)(2.*nbsig2*binsg); if(nbin<5) nbin=5;
binw = (xmax-xmin)/nbin;
if(deb>0) cout<<"bin auto: xmin="<<xmin<<" xmax="<<xmax
              <<" nbin="<<nbin<<" binw="<<binw<<endl;
HBinInt(nbin,xmin,xmax);
binw = (xmax-xmin)/nbin;
if(deb>0) cout<<"bin auto entier:  nbin="<<nbin<<" binw="<<binw
              <<" entre "<<xmin<<","<<xmax<<endl;

// Optimisation de modu
if( modu <= 0 ) {
  // 4 fois plus de pixels que dans le pre-pave
  int npv = 4*pvsz*pvsz;
  int nima = XSize()*YSize();
  if( npv >= nima || nima < 10000 ) modu = 1;
      else modu = (int)( (float) nima / (float) npv );
  if(deb) cout<<"modulo choisi a "<<modu<<endl;
}

// moyenne evoluee
TRY {
  fond = FondCiel(nbin,xmin,xmax,3,0.5,modu,lpdb);
  if(deb>0) cout <<"Fond de ciel = "<<fond<< endl;
} CATCHALL {
  if(deb>0) cout << "Echec FondCiel" << endl;
  return(-3);
} ENDTRY
  
// sigma evolue
TRY {
  float dyn = nbsig3*sgbmax;
  int nbins = (int) (2.*nbsig3*binsg);
  float binws = (2.*dyn)/nbins;
  sigmaFond = SigmaCiel(nbins,-dyn,dyn,means,lowbad,highbad,4.,modu,lpdb);
  if(deb>0) cout <<"Sigma fond de ciel = "<<sigmaFond
                <<" (ms="<<means<<") sur "<<nbins
                <<" bins de largeur "<<binws<< endl;
} CATCHALL {
  if(deb>0) cout << "Echec SigmaCiel" << endl;
  return(-4);
} ENDTRY

// Impression finale
if(deb) cout <<"ImgSigmaCiel: fond= "<<xbmax<<" / "<< fond
             <<"   sigma= "<<sgbmax<<" / "<<sigmaFond<<endl;

return 0;
}



/*  .......................................................  */
/*         Fonctions de copie d'images et de paves           */
/*  .......................................................  */


/* Nouvelle-Fonction */ 
template <class T2, class T1>
void CopieImageF(Image<T2>& copie, Image<T1> const& pim,
         int org_pim_x, int org_pim_y,            /* origine pave a copier */
         int pim_lpav_x, int pim_lpav_y,          /* largeur pave a copier */
         int org_copie_x, int org_copie_y,        /* origine copie         */
         double cutmin, double cutmax)            /* coupure pour max range*/

/* Copie d'une image (pim) ds l'autre (copie) a partir d'un  */
/* offset specifie en pixel                                  */
/* attention: pas d'offset -> org_x = org_y = 0              */
{
int i,j;
// int x,y;  $CHECK$ Reza 21/06/99 changement de methode de calcul des bornes
const T1* pt_pim;
T2* pt_copie;
double pim_pix;
int l_copie_x,l_copie_y;
int step_copie_x;
int step_pim_x;
int pim_siz_x, pim_siz_y;
// int copie_siz_x, copie_siz_y;  $CHECK$ Reza 21/06/99 changement de methode de calcul des bornes
int switch_copie;

pim_siz_x=pim.XSize();
pim_siz_y=pim.YSize();
if((org_pim_x < 0) || (org_pim_x > pim_siz_x))
  { cout<< "CopieImage_erreure : org_pim_x: " <<org_pim_x<<" < 0 ou > a "<<pim_siz_x<<endl;
    THROW(rangeCheckErr);}
if((org_pim_y < 0) || (org_pim_y > pim_siz_y))
  { cout<< "CopieImage_erreure : org_pim_y: " <<org_pim_y<<" < 0 ou > a "<<pim_siz_y<<endl;
    THROW(rangeCheckErr);}

if( (org_copie_x < 0) || (org_copie_x > copie.XSize()) )
  { cout<< "CopieImage_erreure : org_copie_x: " <<org_copie_x<<" < 0 ou > a "<< copie.XSize() << endl;
    THROW(rangeCheckErr);}
if( (org_copie_y < 0) || (org_copie_y > copie.YSize()) )
  { cout<< "CopieImage_erreure : org_copie_y: " <<org_copie_y<<" < 0 ou > a "<< copie.YSize() << endl;
    THROW(rangeCheckErr);}

/* $CHECK$ Reza 21/06/99  Changement de methode de calcul ------
$CHECK$ Reza 21/06/99 , je change la taille a copier en fonction de l'origine de copie 
copie_siz_x=copie.XSize()-org_copie_x;
copie_siz_y=copie.YSize()-org_copie_y;

x=pim_lpav_x;
if(x > (pim_siz_x-org_pim_x)) x=pim_siz_x-org_pim_x;
step_pim_x = pim_siz_x-x;

if(x < copie_siz_x)
  {
   l_copie_x=x;
   step_copie_x=copie_siz_x-x;
  }
else
  {
   l_copie_x=copie_siz_x;
   step_copie_x=0;
   step_pim_x=step_pim_x+x-copie_siz_x;
   }

if(org_copie_x  > 0 )
  {
  int x=copie_siz_x-org_copie_x;
  if(x < l_copie_x )
    {
     step_pim_x=step_pim_x+l_copie_x-x;
     l_copie_x=x;
     step_copie_x=org_copie_x;
    }
  else
    { 
     step_copie_x=copie_siz_x-l_copie_x;
    }
  }

y=pim_lpav_y;
if(y > (pim_siz_y-org_pim_y)) y=pim_siz_y-org_pim_y;

if(y < copie_siz_y)
  {
   l_copie_y=y;
  }
else
  {
   l_copie_y=copie_siz_y;
   }

*/

l_copie_x = copie.XSize()-org_copie_x;
l_copie_y = copie.YSize()-org_copie_y;
if ( pim_lpav_x > (pim.XSize()-org_pim_x) )  pim_lpav_x = pim.XSize()-org_pim_x;
if ( pim_lpav_y > (pim.YSize()-org_pim_y) )  pim_lpav_y = pim.YSize()-org_pim_y;
if ( (pim_lpav_x > 0) && (l_copie_x > pim_lpav_x) )  l_copie_x = pim_lpav_x;
if ( (pim_lpav_y > 0) && (l_copie_y > pim_lpav_y) )  l_copie_y = pim_lpav_y;
step_pim_x = pim.XSize()-l_copie_x;
step_copie_x = copie.XSize()-l_copie_x;

pt_pim  = pim.ImagePtr() + org_pim_y*pim.XSize() + org_pim_x;
pt_copie=copie.ImagePtr() + org_copie_y*copie.XSize() + org_copie_x;

switch((int)ConvType(*pt_pim,*pt_copie)) {
  case t_same: case t_up:
    switch_copie=0;
  break;
  case t_spe: case t_down:
    switch_copie=1;
  break;
}

if(cutmin < cutmax) switch_copie *= 2;

switch(switch_copie) {
  case 0:
    for (j=0; j< l_copie_y; j++)
      {
      for(i=0; i< l_copie_x; i++)
        {
        *pt_copie++ =(T2)*pt_pim++;
        }
      pt_pim   += step_pim_x;
      pt_copie += step_copie_x;
      }
  break;
  case 1:
    for (j=0; j< l_copie_y; j++)
      {
      for(i=0; i< l_copie_x; i++)
        {
        pim_pix = *pt_pim++;
        *pt_copie++ = PutInRange(pim_pix, *pt_copie);
        }
      pt_pim   += step_pim_x;
      pt_copie += step_copie_x;
      }
  break;
  case 2:
    for (j=0; j< l_copie_y; j++)
      {
      for(i=0; i< l_copie_x; i++)
        {
        pim_pix = *pt_pim++;
        *pt_copie++ = (T2)SharePix(pim_pix,*pt_copie,cutmin,cutmax);
        }
      pt_pim   += step_pim_x;
      pt_copie += step_copie_x;
      }
  break;
}

copie.SetOrg( pim.XOrg()+org_pim_x-org_copie_x, pim.YOrg()+org_pim_y-org_copie_y);
}


/* Nouvelle-Fonction */ 
template <class T2, class T1>
void CopieImage(Image<T2>& copie , Image<T1> const& pim)
{
if (!pim.ImagePtr())   THROW(nullPtrErr);
if (!copie.ImagePtr()) copie.Allocate(pim.XSize(),pim.YSize());

CopieImageF(copie, pim,0,0,pim.XSize(),pim.YSize(),0,0,0., 0.);
}

/* Nouvelle-Fonction */ 
template <class T2, class T1>
void CopieImage(Image<T2>& copie , Image<T1> const& pim,
                int org_pim_x    , int org_pim_y,
                int pim_lpav_x   , int pim_lpav_y,
                int org_copie_x  , int org_copie_y,
                double cutmin    , double cutmax )
{
if (!pim.ImagePtr())   THROW(nullPtrErr);
if (!copie.ImagePtr()) THROW(nullPtrErr);
copie.SetOrg( pim.XOrg()+org_pim_x-org_copie_x, pim.YOrg()+org_pim_y-org_copie_y);
// copie.SetOrg(org_pim_x,org_pim_y);

/* Reza 28/04/95 : Je protege pour le moment contre les pave en
dehors de l'image, mais je veux pouvoir copier des paves decale par
rapport aux bornes de l'image source  Re- CMV+Reza 30/09/96 */
/* $CHECK$ Reza 21/06/99 - Ca devrait etre OK  */
if ( (org_pim_x < 0) || (org_pim_y < 0) ||
     (org_pim_x >= pim.XSize() ) || (org_pim_y >= pim.YSize() ) ||
     ((org_pim_x+copie.XSize()) > pim.XSize()) ||
     ((org_pim_y+copie.YSize()) > pim.YSize()) ) copie.Zero(); 

if ( (org_pim_x >= pim.XSize()) || (org_pim_y >= pim.YSize()) ) {
  copie.SetOrg( pim.XOrg()+org_pim_x-org_copie_x, pim.YOrg()+org_pim_y-org_copie_y);
  return;
}   
// if ( (org_pim_x < 0) || (org_pim_y < 0) ||
//      (org_pim_x >= pim.XSize() ) || (org_pim_y >= pim.YSize() )) return;

int oox = org_pim_x;
int ooy = org_pim_y;
int ocx = org_copie_x;
int ocy = org_copie_y;
if (oox < 0)  { ocx -= oox;  oox = 0; }
if (ooy < 0)  { ocy -= ooy;  ooy = 0; }
/*  Fin de $CHECK$  */

// void CopieImageF(Image<T2>& copie, Image<T1> const& pim,
//         int org_pim_x, int org_pim_y,            /* origine pave a copier */
//         int pim_lpav_x, int pim_lpav_y,          /* largeur pave a copier */
//         int org_copie_x, int org_copie_y,        /* origine copie         */
//         double cutmin, double cutmax)            /* coupure pour max range*/

if((pim_lpav_x <= 0) || (pim_lpav_x > pim.XSize())) pim_lpav_x=pim.XSize();
if((pim_lpav_y <= 0) || (pim_lpav_y > pim.YSize())) pim_lpav_y=pim.YSize();
try {
  CopieImageF(copie, pim, oox, ooy, 
              pim_lpav_x, pim_lpav_y,
              ocx, ocy, cutmin,cutmax);
  }  catch(RangeCheckError) {
// $PLANCKCHECK$   if (merr != rangeCheckErr) THROW(merr);  // Re- $CHECK$ CMV+Reza 30/09/96
  } ENDTRY

copie.SetOrg( pim.XOrg()+org_pim_x-org_copie_x, pim.YOrg()+org_pim_y-org_copie_y);
}


/* Nouvelle-Fonction */ 
template <class T2, class T1>
void CopiePave ( Image<T2>& pave , Image<T1> const& pim,
                 float xc, float yc,
                 double cutmin, double cutmax) 
{
int ix, iy;

xc -= 0.5 * (float)(pave.XSize()-1);
yc -= 0.5 * (float)(pave.YSize()-1);
//  CopiePave tient compte de l'origine de l'image de depart   Reza 18/9/96
xc -= pim.XOrg();     yc -= pim.YOrg();

if ( xc >= 0.)  ix = (int)xc;
else ix = (int)(xc-1.0);
if ( yc >= 0.)  iy = (int)yc;
else iy = (int)(yc-1.0);
CopieImage(pave, pim, ix, iy, 0, 0, 0, 0, cutmin, cutmax ) ;
}


/* Nouvelle-Fonction */ 
template <class T>
void RzCopieImage(Image<T>& copie, RzImage const& pim,
                  int org_pim_x , int org_pim_y,
                  int pim_lpav_x, int pim_lpav_y,
                  int org_copie_x, int org_copie_y,
                  double cutmin , double cutmax)
{
  switch (pim.PixelType()) {
  case kuint_2: {
    ImageU2 src((RzImage&)pim);
    CopieImage(copie, src, org_pim_x , org_pim_y,
               pim_lpav_x, pim_lpav_y, org_copie_x, 
               org_copie_y, cutmin, cutmax );
    break;
    }
  case kint_2: {
    ImageI2 src((RzImage&)pim);
    CopieImage(copie, src, org_pim_x , org_pim_y,
               pim_lpav_x, pim_lpav_y, org_copie_x, 
               org_copie_y, cutmin, cutmax );
    break;
    }
  case kint_4: {
    ImageI4 src((RzImage&)pim);
    CopieImage(copie, src, org_pim_x , org_pim_y,
               pim_lpav_x, pim_lpav_y, org_copie_x, 
               org_copie_y, cutmin, cutmax );
    break;
    }
  case kr_4: {
    ImageR4 src((RzImage&)pim);
    CopieImage(copie, src, org_pim_x , org_pim_y,
               pim_lpav_x, pim_lpav_y, org_copie_x, 
               org_copie_y, cutmin, cutmax );
    break;
    }
  case kr_8:
  case kuint_4:
  case kuint_1:
  case kint_1:
    cerr << " RzCopieImage(...) / Error, Unsupported image type (kr_8/ kuint_4/ kuint_1/ kint_1) " 
         << (int)pim.PixelType() << "\n";
    break;
  default:
    cerr << " RzCopieImage(...) / Error, Unknown image type !" <<  (int)pim.PixelType() << "\n";
    break;
  } 
}


/* Nouvelle-Fonction */ 
template <class T>
void RzCopieImage(Image<T>& copie, RzImage const& pim)
{
  switch (pim.PixelType()) {
  case kuint_2: {
    ImageU2 src((RzImage&)pim);
    CopieImage(copie, src);
    break;
    }
  case kint_2: {
    ImageI2 src((RzImage&)pim);
    CopieImage(copie, src);
    break;
    }
  case kint_4: {
    ImageI4 src((RzImage&)pim);
    CopieImage(copie, src);
    break;
    }
  case kr_4: {
    ImageR4 src((RzImage&)pim);
    CopieImage(copie, src);
    break;
    }
  case kr_8:
  case kuint_4:
  case kuint_1:
  case kint_1:
    cerr << " RzCopieImage() / Error, Unsupported image type (kr_8/ kuint_4/ kuint_1/ kint_1) " 
         << (int)pim.PixelType() << "\n";
    break;
  default:
    cerr << " RzCopieImage() / Error, Unknown image type ! " <<  (int)pim.PixelType() << "\n";
    break;
  } 
}

/* Nouvelle-Fonction */ 
template <class T>
void RzCopiePave(Image<T> & pave, RzImage const & pim,
                 float xc, float yc, 
                 double cutmin, double cutmax) 
{
int ix, iy;

xc -= 0.5 * (float)(pave.XSize()-1);
yc -= 0.5 * (float)(pave.YSize()-1);
//  RzCopiePave tient compte de l'origine de l'image de depart   Reza 18/9/96
xc -= pim.XOrg();     yc -= pim.YOrg();

if ( xc >= 0.)  ix = (int)xc;
else ix = (int)(xc-1.0);
if ( yc >= 0.)  iy = (int)yc;
else iy = (int)(yc-1.0);

RzCopieImage(pave, pim, ix, iy, 0, 0, 0, 0, cutmin, cutmax) ;
}


/* Nouvelle-Fonction */ 
void RzPrintImage(RzImage & img)
{
switch (img.PixelType()) 
  {
  case kuint_1: 
    {
    ImageU1 src((RzImage&)img);
    cout << src ;
    break;
    }
  case kuint_2: 
    {
    ImageU2 src((RzImage&)img);
    cout << src ;
    break;
    }
  case kint_2: 
    {
    ImageI2 src((RzImage&)img);
    cout << src ;
    break;
    }
  case kint_4: 
    {
    ImageI4 src((RzImage&)img);
    cout << src ;
    break;
    }
  case kr_4: 
    {
    ImageR4 src((RzImage&)img);
    cout << src ;
    break;
    }
  case kr_8:
  case kuint_4:
  case kint_1:
    cerr << " RzPrintImage() / Error, Unsupported image type (kr_8/kuint_4/ kint_1) " 
         << (int)img.PixelType() << "\n";
    break;
  default:
    cerr << " RzPrintImage() / Error, Unknown image type " <<  (int)img.PixelType() << "\n";
    break;
  } 
}


// ********** INSTANCES
#if defined(__xlC) || defined(__aCC__)
void instancetempcimage(int n)
{
// #pragma define_template
/* Cette fonction sert uniquement a forcer le compilo a instancier les
  classes/fonctions template   */

int m = n-50;
ImageU1  iu1(n,n), xiu1(m,m);
ImageU2  iu2(n,n), xiu2(m,m);
ImageI2  ii2(n,n), xii2(m,m);
ImageI4  ii4(n,n), xii4(m,m);
ImageR4  ir4(n,n), xir4(m,m);
RzImage  rzi(kr_4, n, n);

cout << iu1;
cout << iu2;
cout << ii2;
cout << ii4;
cout << ir4;

CopieImageF(iu2, xiu2, 50, 50);
CopieImageF(iu2, xii2, 50, 50);
CopieImageF(iu2, xii4, 50, 50);
CopieImageF(iu2, xir4, 50, 50);
CopieImageF(ii2, xiu2, 50, 50);
CopieImageF(ii2, xii2, 50, 50);
CopieImageF(ii2, xii4, 50, 50);
CopieImageF(ii2, xir4, 50, 50);
CopieImageF(ii4, xiu2, 50, 50);
CopieImageF(ii4, xii2, 50, 50);
CopieImageF(ii4, xii4, 50, 50);
CopieImageF(ii4, xir4, 50, 50);
CopieImageF(ir4, xiu2, 50, 50);
CopieImageF(ir4, xii2, 50, 50);
CopieImageF(ir4, xii4, 50, 50);
CopieImageF(ir4, xir4, 50, 50);

CopieImage(iu2, xiu2);
CopieImage(iu2, xii2);
CopieImage(iu2, xii4);
CopieImage(iu2, xir4);
CopieImage(ii2, xiu2);
CopieImage(ii2, xii2);
CopieImage(ii2, xii4);
CopieImage(ii2, xir4);
CopieImage(ii4, xiu2);
CopieImage(ii4, xii2);
CopieImage(ii4, xii4);
CopieImage(ii4, xir4);
CopieImage(ir4, xiu2);
CopieImage(ir4, xii2);
CopieImage(ir4, xii4);
CopieImage(ir4, xir4);

CopieImage(iu2, xiu2, 50, 50);
CopieImage(iu2, xii2, 50, 50);
CopieImage(iu2, xii4, 50, 50);
CopieImage(iu2, xir4, 50, 50);
CopieImage(ii2, xiu2, 50, 50);
CopieImage(ii2, xii2, 50, 50);
CopieImage(ii2, xii4, 50, 50);
CopieImage(ii2, xir4, 50, 50);
CopieImage(ii4, xiu2, 50, 50);
CopieImage(ii4, xii2, 50, 50);
CopieImage(ii4, xii4, 50, 50);
CopieImage(ii4, xir4, 50, 50);
CopieImage(ir4, xiu2, 50, 50);
CopieImage(ir4, xii2, 50, 50);
CopieImage(ir4, xii4, 50, 50);
CopieImage(ir4, xir4, 50, 50);

CopiePave(iu2, xiu2, (float)25., (float)25.);
CopiePave(iu2, xii2, (float)25., (float)25.);
CopiePave(iu2, xii4, (float)25., (float)25.);
CopiePave(iu2, xir4, (float)25., (float)25.);
CopiePave(ii2, xiu2, (float)25., (float)25.);
CopiePave(ii2, xii2, (float)25., (float)25.);
CopiePave(ii2, xii4, (float)25., (float)25.);
CopiePave(ii2, xir4, (float)25., (float)25.);
CopiePave(ii4, xiu2, (float)25., (float)25.);
CopiePave(ii4, xii2, (float)25., (float)25.);
CopiePave(ii4, xii4, (float)25.,(float) 25.);
CopiePave(ii4, xir4, (float)25., (float)25.);
CopiePave(ir4, xiu2, (float)25., (float)25.);
CopiePave(ir4, xii2, (float)25., (float)25.);
CopiePave(ir4, xii4, (float)25., (float)25.);
CopiePave(ir4, xir4, (float)25., (float)25.);

RzCopieImage(iu2, rzi, 50, 50);
RzCopieImage(ii2, rzi, 50, 50);
RzCopieImage(ii4, rzi, 50, 50);
RzCopieImage(ir4, rzi, 50, 50);

RzCopieImage(iu2, rzi);
RzCopieImage(ii2, rzi);
RzCopieImage(ii4, rzi);
RzCopieImage(ir4, rzi);

RzCopiePave(iu2, rzi, (float)25., (float)25.);
RzCopiePave(ii2, rzi, (float)25., (float)25.);
RzCopiePave(ii4, rzi, (float)25., (float)25.);
RzCopiePave(ir4, rzi, (float)25., (float)25.);

return;
}

#endif

#ifdef __CXX_PRAGMA_TEMPLATES__
#pragma define_template Image<uint_1>
#pragma define_template Image<uint_2>
#pragma define_template Image<int_2>
#pragma define_template Image<int_4>
#pragma define_template Image<r_4>

// pour supprimer les message Warning: Unresolved:
//                                     __ls__XR7ostreamRC10Image__TUc

ostream& operator << (ostream& s, ImageU1 const& pim)
{
cout << "operator << (ostream, ImageU1) Not implemented ..." << endl;
return(s);
}

// CopieImageF
#pragma define_template CopieImageF < uint_1 , uint_1 >
#pragma define_template CopieImageF < uint_1 , uint_2 >
#pragma define_template CopieImageF < uint_1 , int_2 >
#pragma define_template CopieImageF < uint_1 , int_4 >
#pragma define_template CopieImageF < uint_1 , r_4 >

#pragma define_template CopieImageF < uint_2 , uint_2 >
#pragma define_template CopieImageF < uint_2 , int_2 >
#pragma define_template CopieImageF < uint_2 , int_4 >
#pragma define_template CopieImageF < uint_2 , r_4 >

#pragma define_template CopieImageF < int_2 , uint_2 >
#pragma define_template CopieImageF < int_2 , int_2 >
#pragma define_template CopieImageF < int_2 , int_4 >
#pragma define_template CopieImageF < int_2 , r_4 >

#pragma define_template CopieImageF < int_4 , uint_2 >
#pragma define_template CopieImageF < int_4 , int_2 >
#pragma define_template CopieImageF < int_4 , int_4 >
#pragma define_template CopieImageF < int_4 , r_4 >

#pragma define_template CopieImageF < r_4 , uint_2 >
#pragma define_template CopieImageF < r_4 , int_2 >
#pragma define_template CopieImageF < r_4 , int_4 >
#pragma define_template CopieImageF < r_4 , r_4 >

// CopieImage
#pragma define_template CopieImage < uint_2 , uint_2 >
#pragma define_template CopieImage < uint_2 , int_2 >
#pragma define_template CopieImage < uint_2 , int_4 >
#pragma define_template CopieImage < uint_2 , r_4 >

#pragma define_template CopieImage < int_2 , uint_2 >
#pragma define_template CopieImage < int_2 , int_2 >
#pragma define_template CopieImage < int_2 , int_4 >
#pragma define_template CopieImage < int_2 , r_4 >

#pragma define_template CopieImage < int_4 , uint_2 >
#pragma define_template CopieImage < int_4 , int_2 >
#pragma define_template CopieImage < int_4 , int_4 >
#pragma define_template CopieImage < int_4 , r_4 >

#pragma define_template CopieImage < r_4 , uint_2 >
#pragma define_template CopieImage < r_4 , int_2 >
#pragma define_template CopieImage < r_4 , int_4 >
#pragma define_template CopieImage < r_4 , r_4 >

// CopiePave
#pragma define_template CopiePave < uint_2 , uint_2 >
#pragma define_template CopiePave < uint_2 , int_2 >
#pragma define_template CopiePave < uint_2 , int_4 >
#pragma define_template CopiePave < uint_2 , r_4 >

#pragma define_template CopiePave < int_2 , uint_2 >
#pragma define_template CopiePave < int_2 , int_2 >
#pragma define_template CopiePave < int_2 , int_4 >
#pragma define_template CopiePave < int_2 , r_4 >

#pragma define_template CopiePave < int_4 , uint_2 >
#pragma define_template CopiePave < int_4 , int_2 >
#pragma define_template CopiePave < int_4 , int_4 >
#pragma define_template CopiePave < int_4 , r_4 >

#pragma define_template CopiePave < r_4 , uint_2 >
#pragma define_template CopiePave < r_4 , int_2 >
#pragma define_template CopiePave < r_4 , int_4 >
#pragma define_template CopiePave < r_4 , r_4 >

//RzCopieImage
#pragma define_template RzCopieImage < uint_2 >
#pragma define_template RzCopieImage < int_2 >
#pragma define_template RzCopieImage < int_4 >
#pragma define_template RzCopieImage < r_4 >

//RzCopiePave
#pragma define_template RzCopiePave < uint_2 >
#pragma define_template RzCopiePave < int_2 >
#pragma define_template RzCopiePave < int_4 >
#pragma define_template RzCopiePave < r_4 >


#endif


#if defined(ANSI_TEMPLATES) 
template class Image<uint_1>;
template class Image<uint_2>;
template class Image<int_2>;
template class Image<int_4>;
template class Image<r_4>;

#if !defined(__aCC__)     // HP - aCC a du mal avec les fonctions templates 

template void CopieImageF<uint_2, uint_2>(Image<uint_2>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
template void CopieImageF<uint_2,  int_2>(Image<uint_2>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
template void CopieImageF<uint_2,  int_4>(Image<uint_2>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
template void CopieImageF<uint_2,    r_4>(Image<uint_2>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
template void CopieImageF< int_2, uint_2>(Image< int_2>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
template void CopieImageF< int_2,  int_2>(Image< int_2>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
template void CopieImageF< int_2,  int_4>(Image< int_2>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
template void CopieImageF< int_2,    r_4>(Image< int_2>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
template void CopieImageF< int_4, uint_2>(Image< int_4>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
template void CopieImageF< int_4,  int_2>(Image< int_4>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
template void CopieImageF< int_4,  int_4>(Image< int_4>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
template void CopieImageF< int_4,    r_4>(Image< int_4>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
template void CopieImageF<   r_4, uint_2>(Image<   r_4>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
template void CopieImageF<   r_4,  int_2>(Image<   r_4>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
template void CopieImageF<   r_4,  int_4>(Image<   r_4>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
template void CopieImageF<   r_4,    r_4>(Image<   r_4>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);

template void CopieImage<uint_2, uint_2>(Image<uint_2>&, Image<uint_2> const&);
template void CopieImage<uint_2,  int_2>(Image<uint_2>&, Image< int_2> const&);
template void CopieImage<uint_2,  int_4>(Image<uint_2>&, Image< int_4> const&);
template void CopieImage<uint_2,    r_4>(Image<uint_2>&, Image<   r_4> const&);
template void CopieImage< int_2, uint_2>(Image< int_2>&, Image<uint_2> const&);
template void CopieImage< int_2,  int_2>(Image< int_2>&, Image< int_2> const&);
template void CopieImage< int_2,  int_4>(Image< int_2>&, Image< int_4> const&);
template void CopieImage< int_2,    r_4>(Image< int_2>&, Image<   r_4> const&);
template void CopieImage< int_4, uint_2>(Image< int_4>&, Image<uint_2> const&);
template void CopieImage< int_4,  int_2>(Image< int_4>&, Image< int_2> const&);
template void CopieImage< int_4,  int_4>(Image< int_4>&, Image< int_4> const&);
template void CopieImage< int_4,    r_4>(Image< int_4>&, Image<   r_4> const&);
template void CopieImage<   r_4, uint_2>(Image<   r_4>&, Image<uint_2> const&);
template void CopieImage<   r_4,  int_2>(Image<   r_4>&, Image< int_2> const&);
template void CopieImage<   r_4,  int_4>(Image<   r_4>&, Image< int_4> const&);
template void CopieImage<   r_4,    r_4>(Image<   r_4>&, Image<   r_4> const&);

template void CopieImage<uint_2, uint_2>(Image<uint_2>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
template void CopieImage<uint_2,  int_2>(Image<uint_2>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
template void CopieImage<uint_2,  int_4>(Image<uint_2>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
template void CopieImage<uint_2,    r_4>(Image<uint_2>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
template void CopieImage< int_2, uint_2>(Image< int_2>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
template void CopieImage< int_2,  int_2>(Image< int_2>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
template void CopieImage< int_2,  int_4>(Image< int_2>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
template void CopieImage< int_2,    r_4>(Image< int_2>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
template void CopieImage< int_4, uint_2>(Image< int_4>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
template void CopieImage< int_4,  int_2>(Image< int_4>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
template void CopieImage< int_4,  int_4>(Image< int_4>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
template void CopieImage< int_4,    r_4>(Image< int_4>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
template void CopieImage<   r_4, uint_2>(Image<   r_4>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
template void CopieImage<   r_4,  int_2>(Image<   r_4>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
template void CopieImage<   r_4,  int_4>(Image<   r_4>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
template void CopieImage<   r_4,    r_4>(Image<   r_4>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);

template void CopiePave<uint_2, uint_2>(Image<uint_2>&, Image<uint_2> const&, float, float, double, double);
template void CopiePave<uint_2,  int_2>(Image<uint_2>&, Image< int_2> const&, float, float, double, double);
template void CopiePave<uint_2,  int_4>(Image<uint_2>&, Image< int_4> const&, float, float, double, double);
template void CopiePave<uint_2,    r_4>(Image<uint_2>&, Image<   r_4> const&, float, float, double, double);
template void CopiePave< int_2, uint_2>(Image< int_2>&, Image<uint_2> const&, float, float, double, double);
template void CopiePave< int_2,  int_2>(Image< int_2>&, Image< int_2> const&, float, float, double, double);
template void CopiePave< int_2,  int_4>(Image< int_2>&, Image< int_4> const&, float, float, double, double);
template void CopiePave< int_2,    r_4>(Image< int_2>&, Image<   r_4> const&, float, float, double, double);
template void CopiePave< int_4, uint_2>(Image< int_4>&, Image<uint_2> const&, float, float, double, double);
template void CopiePave< int_4,  int_2>(Image< int_4>&, Image< int_2> const&, float, float, double, double);
template void CopiePave< int_4,  int_4>(Image< int_4>&, Image< int_4> const&, float, float, double, double);
template void CopiePave< int_4,    r_4>(Image< int_4>&, Image<   r_4> const&, float, float, double, double);
template void CopiePave<   r_4, uint_2>(Image<   r_4>&, Image<uint_2> const&, float, float, double, double);
template void CopiePave<   r_4,  int_2>(Image<   r_4>&, Image< int_2> const&, float, float, double, double);
template void CopiePave<   r_4,  int_4>(Image<   r_4>&, Image< int_4> const&, float, float, double, double);
template void CopiePave<   r_4,    r_4>(Image<   r_4>&, Image<   r_4> const&, float, float, double, double);


template void RzCopieImage<uint_2>(Image<uint_2> &, RzImage const &, int, int, int, int, int, int, double, double);
template void RzCopieImage< int_2>(Image< int_2> &, RzImage const &, int, int, int, int, int, int, double, double);
template void RzCopieImage< int_4>(Image< int_4> &, RzImage const &, int, int, int, int, int, int, double, double);
template void RzCopieImage<   r_4>(Image<   r_4> &, RzImage const &, int, int, int, int, int, int, double, double);

template void RzCopieImage<uint_2>(Image<uint_2> &, RzImage const &);
template void RzCopieImage< int_2>(Image< int_2> &, RzImage const &);
template void RzCopieImage< int_4>(Image< int_4> &, RzImage const &);
template void RzCopieImage<   r_4>(Image<   r_4> &, RzImage const &);

template void RzCopiePave<uint_2>(Image<uint_2> &, RzImage const &, float, float, double, double);
template void RzCopiePave< int_2>(Image< int_2> &, RzImage const &, float, float, double, double);
template void RzCopiePave< int_4>(Image< int_4> &, RzImage const &, float, float, double, double);
template void RzCopiePave<   r_4>(Image<   r_4> &, RzImage const &, float, float, double, double);

#endif   // Pb avec HP aCC

#endif


#ifdef __GNU_TEMPLATES__
template class Image<bool>;
template class Image<uint_1>;
template class Image<uint_2>;
template class Image<int_2>;
template class Image<int_4>;
template class Image<r_4>;


template void CopieImageF(Image<uint_2>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
template void CopieImageF(Image<uint_2>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
template void CopieImageF(Image<uint_2>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
template void CopieImageF(Image<uint_2>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
template void CopieImageF(Image< int_2>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
template void CopieImageF(Image< int_2>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
template void CopieImageF(Image< int_2>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
template void CopieImageF(Image< int_2>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
template void CopieImageF(Image< int_4>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
template void CopieImageF(Image< int_4>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
template void CopieImageF(Image< int_4>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
template void CopieImageF(Image< int_4>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
template void CopieImageF(Image<   r_4>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
template void CopieImageF(Image<   r_4>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
template void CopieImageF(Image<   r_4>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
template void CopieImageF(Image<   r_4>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);

template void CopieImage(Image<uint_2>&, Image<uint_2> const&);
template void CopieImage(Image<uint_2>&, Image< int_2> const&);
template void CopieImage(Image<uint_2>&, Image< int_4> const&);
template void CopieImage(Image<uint_2>&, Image<   r_4> const&);
template void CopieImage(Image< int_2>&, Image<uint_2> const&);
template void CopieImage(Image< int_2>&, Image< int_2> const&);
template void CopieImage(Image< int_2>&, Image< int_4> const&);
template void CopieImage(Image< int_2>&, Image<   r_4> const&);
template void CopieImage(Image< int_4>&, Image<uint_2> const&);
template void CopieImage(Image< int_4>&, Image< int_2> const&);
template void CopieImage(Image< int_4>&, Image< int_4> const&);
template void CopieImage(Image< int_4>&, Image<   r_4> const&);
template void CopieImage(Image<   r_4>&, Image<uint_2> const&);
template void CopieImage(Image<   r_4>&, Image< int_2> const&);
template void CopieImage(Image<   r_4>&, Image< int_4> const&);
template void CopieImage(Image<   r_4>&, Image<   r_4> const&);

template void CopieImage(Image<uint_2>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
template void CopieImage(Image<uint_2>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
template void CopieImage(Image<uint_2>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
template void CopieImage(Image<uint_2>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
template void CopieImage(Image< int_2>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
template void CopieImage(Image< int_2>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
template void CopieImage(Image< int_2>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
template void CopieImage(Image< int_2>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
template void CopieImage(Image< int_4>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
template void CopieImage(Image< int_4>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
template void CopieImage(Image< int_4>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
template void CopieImage(Image< int_4>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);
template void CopieImage(Image<   r_4>&, Image<uint_2> const&, int, int, int, int, int, int, double, double);
template void CopieImage(Image<   r_4>&, Image< int_2> const&, int, int, int, int, int, int, double, double);
template void CopieImage(Image<   r_4>&, Image< int_4> const&, int, int, int, int, int, int, double, double);
template void CopieImage(Image<   r_4>&, Image<   r_4> const&, int, int, int, int, int, int, double, double);

template void CopiePave(Image<uint_2>&, Image<uint_2> const&, float, float, double, double);
template void CopiePave(Image<uint_2>&, Image< int_2> const&, float, float, double, double);
template void CopiePave(Image<uint_2>&, Image< int_4> const&, float, float, double, double);
template void CopiePave(Image<uint_2>&, Image<   r_4> const&, float, float, double, double);
template void CopiePave(Image< int_2>&, Image<uint_2> const&, float, float, double, double);
template void CopiePave(Image< int_2>&, Image< int_2> const&, float, float, double, double);
template void CopiePave(Image< int_2>&, Image< int_4> const&, float, float, double, double);
template void CopiePave(Image< int_2>&, Image<   r_4> const&, float, float, double, double);
template void CopiePave(Image< int_4>&, Image<uint_2> const&, float, float, double, double);
template void CopiePave(Image< int_4>&, Image< int_2> const&, float, float, double, double);
template void CopiePave(Image< int_4>&, Image< int_4> const&, float, float, double, double);
template void CopiePave(Image< int_4>&, Image<   r_4> const&, float, float, double, double);
template void CopiePave(Image<   r_4>&, Image<uint_2> const&, float, float, double, double);
template void CopiePave(Image<   r_4>&, Image< int_2> const&, float, float, double, double);
template void CopiePave(Image<   r_4>&, Image< int_4> const&, float, float, double, double);
template void CopiePave(Image<   r_4>&, Image<   r_4> const&, float, float, double, double);


template void RzCopieImage(Image<uint_2> &, RzImage const &, int, int, int, int, int, int, double, double);
template void RzCopieImage(Image< int_2> &, RzImage const &, int, int, int, int, int, int, double, double);
template void RzCopieImage(Image< int_4> &, RzImage const &, int, int, int, int, int, int, double, double);
template void RzCopieImage(Image<   r_4> &, RzImage const &, int, int, int, int, int, int, double, double);

template void RzCopieImage(Image<uint_2> &, RzImage const &);
template void RzCopieImage(Image< int_2> &, RzImage const &);
template void RzCopieImage(Image< int_4> &, RzImage const &);
template void RzCopieImage(Image<   r_4> &, RzImage const &);

template void RzCopiePave(Image<uint_2> &, RzImage const &, float, float, double, double);
template void RzCopiePave(Image< int_2> &, RzImage const &, float, float, double, double);
template void RzCopiePave(Image< int_4> &, RzImage const &, float, float, double, double);
template void RzCopiePave(Image<   r_4> &, RzImage const &, float, float, double, double);

#endif

