/* -*- mode: c++; c-basic-offset: 3 -*-
 *
 * PANDORE (PANTHEON Project)
 *
 * GREYC IMAGE
 * 6 Boulevard Maréchal Juin
 * F-14050 Caen Cedex France
 *
 * This file is free software. You can use it, distribute it
 * and/or modify it. However, the entire risk to the quality
 * and performance of this program is with you.
 *
 * Please email any bugs, comments, and/or additions to this file to:
 * pandore@greyc.ensicaen.fr
 * http://www.greyc.ensicaen.fr/EquipeImage/Pandore/
 */

/**
 * @author Jean-Baptiste  Hoock - 2005-07-26 
 */

/**
 * @file wedgewindow.cpp
 *
 * wedgewindow: creation of the two halves of a C^inf compactly supported 
 *              window 
 * wedgewindow: creer deux fenetres en utilisant un fenetrage de Meyer
 *
 * wedgewindow creates of the two halves of a C^inf compactly supported 
 * window 
 * ims: the input image of abscissae, the relevant ones from 0 to 1.
 * wl and wr are out images containing samples of the left, respectively
 * right half of the window
 *
 * Used in fct,fict and lowpass
 */

#include <math.h>
#include <float.h>

#include <pandore.h>
using namespace pandore; 	

#ifdef MAIN
#undef MAIN

//#include "arithmetic/pabs.cpp"
#include "arithmetic/pdiv.cpp"
#include "arithmetic/ppow.cpp"
#include "arithmetic/pmult.cpp"
#include "arithmetic/psqrt.cpp"	
#include "arithmetic/padd.cpp"

#define MAIN
#endif

 
Errc Wedgewindow(Img2dsf &ims, Img2dsf &wl, Img2dsf &wr)  {
//   Double epsilon=pow(2.0,-52.0);
    Double epsilon = FLT_EPSILON;

   //an absolute value smaller than epsilon is considered as null  
   Double coeff_l; //variable for the left window
   Double coeff_r; //variable for the right window
   register int y,x; //variable of loop
   
   //allocation
   Img2dsf temp0(ims.Size());
   Img2dsf temp1(ims.Size());
   Img2dsf normalisation(ims.Size());
        
   for (y=0;y<ims.Height();y++)
   for (x=0;x<ims.Width();x++)
   {
      (fabs(ims[y][x])<epsilon) ? temp0[y][x]=0 : temp0[y][x]=ims[y][x];
   }
   
   wl=0.0f;
   wr=0.0f;
     
   for (y=0;y<temp0.Height();y++)
   for (x=0;x<temp0.Width();x++)
   {
      if (temp0[y][x]<=0) {
	 wr[y][x]=1; 
	 continue;
      }
      if (temp0[y][x]>=1) {	
	 wl[y][x]=1;
	 continue;
      }

      //composee de MEYER (loi rond)
      coeff_l=(exp(1-1/(1-exp(1-1/(1-temp0[y][x])))));
      coeff_r=(exp(1-1/(1-exp(1-1/(temp0[y][x]))))); 
      wl[y][x]=(Img2dsf::ValueType)coeff_l;
      wr[y][x]=(Img2dsf::ValueType)coeff_r; 
   }
 
   //normalization
   PMult(wl,wl,temp1);
   PMult(wr,wr,normalisation);
   PAdd(temp1,normalisation,temp1);
   PSqrt(temp1,normalisation);
   PDiv(wl,normalisation,wl);
   PDiv(wr,normalisation,wr);
   
   //desallocation
   temp0.Delete();
   temp1.Delete();
   normalisation.Delete();
   
   return SUCCESS;
}

Errc Wedgewindow(Img1dsf &ims, Img1dsf &wl, Img1dsf &wr)  {
//    Double epsilon=pow(2.0,-52.0); 
    Double epsilon=FLT_EPSILON;

   //an absolute value smaller than epsilon is considered as null  
   Double coeff_l; //variable for the left window
   Double coeff_r; //variable for the right window
   register int x; //variable of loop
   
   //allocation
   Img1dsf temp0(ims.Size());
   Img1dsf temp1(ims.Size());
   Img1dsf normalisation(ims.Size());
        
   for (x=0;x<ims.Width();x++)
   {
      (fabs(ims[x])<epsilon) ? temp0[x]=0 : temp0[x]=ims[x];
   }
   
   wl=0.0f;
   wr=0.0f;
     
   for (x=0;x<temp0.Width();x++)
   {
      if (temp0[x]<=0) {
	 wr[x]=1; 
	 continue;
      }
      if (temp0[x]>=1) {	
	 wl[x]=1;
	 continue;
      }

      //composee de MEYER (loi rond)
      coeff_l=(exp(1-1/(1-exp(1-1/(1-temp0[x])))));
      coeff_r=(exp(1-1/(1-exp(1-1/(temp0[x]))))); 
      wl[x]=(Img1dsf::ValueType)coeff_l;
      wr[x]=(Img1dsf::ValueType)coeff_r; 
   }
 
   //normalization
   PMult(wl,wl,temp1);
   PMult(wr,wr,normalisation);
   PAdd(temp1,normalisation,temp1);
   PSqrt(temp1,normalisation);
   PDiv(wl,normalisation,wl);
   PDiv(wr,normalisation,wr);
   
   //desallocation
   temp0.Delete();
   temp1.Delete();
   normalisation.Delete();
   
   return SUCCESS;
}


#ifdef MAIN 
#define USAGE "USAGE : %s [-m mask] [im_in|-] [im_out1|-] [im_out2|]"
#define PARC 0 
#define FINC 1
#define FOUTC 2 
#define MASK 3 
	 
int main( int argc, char *argv[] ) {
   Errc result;              // The result code of the execution.
   Pobject* mask;            // The region map.
   Pobject* objin[FINC+1];   // The input objects;
   Pobject* objs[FINC+1];    // The source objects masked.
   Pobject* objout[FOUTC+1]; // The output object.
   Pobject* objd[FOUTC+1];   // The result object of the execution.
   char* parv[PARC+1];       // The input parameters.

   ReadArgs(argc,argv,PARC,FINC,FOUTC,&mask,objin,objs,objout,objd,parv,USAGE,MASK);
   if (objs[0]->Type() == Po_Img2dsf) { 
      Img2dsf* const ims=(Img2dsf*)objs[0];  
      objd[0]=new Img2dsf(ims->Size()); 
      Img2dsf* const wl=(Img2dsf*)objd[0]; 
      objd[1]=new Img2dsf(ims->Size()); 
      Img2dsf* const wr=(Img2dsf*)objd[1]; 
      result=Wedgewindow(*ims,*wl,*wr);
      goto end; 
   }
   else 
   if (objs[0]->Type() == Po_Img1dsf) { 
      Img1dsf* const ims=(Img1dsf*)objs[0];  
      objd[0]=new Img1dsf(ims->Size()); 
      Img1dsf* const wl=(Img1dsf*)objd[0]; 
      objd[1]=new Img1dsf(ims->Size()); 
      Img1dsf* const wr=(Img1dsf*)objd[1]; 
      result=Wedgewindow(*ims,*wl,*wr);
      goto end; 
   }
   else 
  {
     PrintErrorFormat(objin,FINC);
     result = FAILURE;
  }	

end:
  if (result)
	WriteArgs(argc,argv,PARC,FINC,FOUTC,&mask,objin,objs,objout,objd,MASK);
  Exit(result);
  return 0;
}
#endif
